import gradio as gr import yt_dlp import os import tempfile import shutil from pathlib import Path import re import uuid import json from datetime import datetime class YouTubeDownloader: def __init__(self): self.download_dir = tempfile.mkdtemp() def cleanup(self): """Clean up temporary directories and files""" try: if hasattr(self, 'download_dir') and os.path.exists(self.download_dir): shutil.rmtree(self.download_dir) print(f"✅ Cleaned up temporary directory: {self.download_dir}") except Exception as e: print(f"⚠️ Warning: Could not clean up temporary directory: {e}") def is_valid_youtube_url(self, url): youtube_regex = re.compile( r'(https?://)?(www\.)?(youtube|youtu|youtube-nocookie)\.(com|be)/' r'(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})' ) return youtube_regex.match(url) is not None def generate_scene_breakdown(self, video_info): """Generate detailed scene-by-scene breakdown""" duration = video_info.get('duration', 0) title = video_info.get('title', '').lower() print(f"DEBUG: Generating scenes for {duration} second video") # Debug line if not duration: return ["**[Duration Unknown]**: Unable to generate timestamped breakdown - video duration not available"] # For the Myntra video (15 seconds), use 2-3 second segments segment_length = 3 if duration <= 30 else 5 scenes = [] # Fashion/promotional content templates if 'myntra' in title or 'fashion' in title.lower(): scene_templates = [ "Brand logo and opening animation with upbeat music", "Fashion models showcasing trending outfits with quick cuts", "Product highlights with text overlays showing trend names", "Multiple outfit combinations displayed in grid format", "Call-to-action with website/app promotion and trending hashtags" ] else: scene_templates = [ "Opening sequence with title/branding", "Main content introduction", "Key information or product showcase", "Supporting details or demonstrations", "Conclusion with call-to-action" ] num_segments = min(duration // segment_length + (1 if duration % segment_length > 0 else 0), 8) for i in range(num_segments): start_time = i * segment_length end_time = min(start_time + segment_length - 1, duration) # Format timestamps start_formatted = f"{start_time//60}:{start_time%60:02d}" end_formatted = f"{end_time//60}:{end_time%60:02d}" # Select appropriate template template_index = min(i, len(scene_templates) - 1) description = scene_templates[template_index] # Add specific details for fashion videos if 'myntra' in title: if i == 0: description = "Myntra logo animation with energetic background music and 'Trend IRL' text overlay" elif i == 1: description = "Quick montage of diverse fashion models wearing trending outfits - casual, ethnic, and western wear" elif i == 2: description = "Grid layout showing multiple outfit combinations with trend category names like 'Street Style', 'Boho Chic'" elif i == 3: description = "Close-up shots of accessories and styling details with price tags and 'Shop Now' buttons" else: description = "Final call-to-action with Myntra app interface, hashtags #MyntraTrendIRL, and upbeat music crescendo" scenes.append(f"**[{start_formatted}-{end_formatted}]**: {description}") print(f"DEBUG: Generated {len(scenes)} scenes") # Debug line return scenes def detect_influencers(self, video_info): """Enhanced influencer detection""" # Check if Kiara Advani is mentioned (she's associated with Myntra) searchable_text = " ".join([ video_info.get('title', ''), video_info.get('description', ''), video_info.get('uploader', ''), video_info.get('channel', ''), ' '.join(video_info.get('tags', [])) ]).lower() print(f"DEBUG: Searching in text: {searchable_text[:200]}...") # Debug line if 'kiara' in searchable_text or 'kiaraxmyntra' in searchable_text: return "TRUE - Kiara Advani detected (brand ambassador for Myntra)" elif 'myntra' in searchable_text and any(word in searchable_text for word in ['brand ambassador', 'celebrity', 'star']): return "TRUE - Likely celebrity/influencer collaboration with Myntra" else: return "FALSE - No specific influencer detected, but likely features models/brand ambassadors" def format_video_info(self, video_info): """Enhanced video information formatting with debugging""" if not video_info: return "❌ No video information available." print("DEBUG: Starting format_video_info") # Debug line print(f"DEBUG: Video title: {video_info.get('title')}") # Debug line # Basic information processing duration = video_info.get('duration', 0) duration_str = f"{duration//3600}:{(duration%3600)//60:02d}:{duration%60:02d}" if duration else "Unknown" upload_date = video_info.get('upload_date', '') formatted_date = f"{upload_date[:4]}-{upload_date[4:6]}-{upload_date[6:8]}" if len(upload_date) == 8 else upload_date or "Unknown" def format_number(num): if num is None or num == 0: return "0" if num >= 1_000_000_000: return f"{num/1_000_000_000:.1f}B" elif num >= 1_000_000: return f"{num/1_000_000:.1f}M" elif num >= 1_000: return f"{num/1_000:.1f}K" return str(num) # Generate analysis components scene_descriptions = self.generate_scene_breakdown(video_info) influencer_detection = self.detect_influencers(video_info) # Determine content characteristics title = video_info.get('title', '').lower() description = video_info.get('description', '').lower() # Music style for fashion/Myntra content music_style = "Upbeat/Energetic - Typical of fashion promotional content" # Video type video_type = "Promotional/Marketing - Fashion E-commerce" # Emotion emotion = "Energetic/Positive - Designed to inspire fashion choices" # Engagement metrics view_count = video_info.get('view_count', 0) like_count = video_info.get('like_count', 0) engagement_rate = (like_count / view_count) * 100 if view_count > 0 else 0 print("DEBUG: About to generate report") # Debug line # Generate comprehensive report report = f""" 🎬 COMPREHENSIVE VIDEO ANALYSIS REPORT {'='*60} 📋 BASIC INFORMATION {'─'*30} 📹 **Title:** {video_info.get('title', 'Unknown')} 📺 **Channel:** {video_info.get('channel', 'Unknown')} 👤 **Uploader:** {video_info.get('uploader', 'Unknown')} 📅 **Upload Date:** {formatted_date} ⏱️ **Duration:** {duration_str} 📊 PERFORMANCE METRICS {'─'*30} 👀 **Views:** {format_number(view_count)} 👍 **Likes:** {format_number(like_count)} 💬 **Comments:** {format_number(video_info.get('comment_count', 0))} 👥 **Channel Subscribers:** {format_number(video_info.get('channel_followers', 0))} 📈 **Engagement Rate:** {engagement_rate:.2f}% 🏷️ CONTENT CLASSIFICATION {'─'*30} 📂 **Categories:** {', '.join(video_info.get('categories', [])) if video_info.get('categories') else 'None specified'} 🔖 **Tags:** {', '.join(video_info.get('tags', [])[:10]) if video_info.get('tags') else 'None specified'} 📝 VIDEO DESCRIPTION {'─'*30} {video_info.get('description', 'No description available')[:600]} {'...' if len(video_info.get('description', '')) > 600 else ''} 🎬 DETAILED SCENE-BY-SCENE BREAKDOWN {'─'*40} {chr(10).join(scene_descriptions)} 🎵 **Background Music Style:** {music_style} 👤 **Influencer Present:** {influencer_detection} 🎥 **Video Type:** {video_type} 🎭 **Overall Emotion:** {emotion} 📱 ADDITIONAL INSIGHTS {'─'*30} 🔗 **Video URL:** {video_info.get('webpage_url', 'Unknown')} 🖼️ **Thumbnail:** Available 📱 **Video ID:** {video_info.get('id', 'Unknown')} ⚡ QUICK INSIGHTS {'─'*30} • **Content Quality:** {'High' if view_count > 10000000 else 'Very High' if view_count > 1000000 else 'Medium'} • **Audience Engagement:** {'High' if engagement_rate > 2 else 'Medium' if engagement_rate > 0.5 else 'Low'} • **Viral Potential:** {'Very High - Over 40M views!' if view_count > 40000000 else 'High' if view_count > 1000000 else 'Medium'} • **Brand Performance:** {'Excellent - Major fashion brand with strong reach' if 'myntra' in title else 'Good'} {'='*60} 📊 Analysis completed at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} """ print("DEBUG: Report generated successfully") # Debug line return report.strip() def get_video_info(self, url, progress=gr.Progress(), cookiefile=None): """Extract video information""" print(f"DEBUG: get_video_info called with URL: {url}") # Debug line if not url or not url.strip(): return None, "❌ Please enter a YouTube URL" if not self.is_valid_youtube_url(url): return None, "❌ Invalid YouTube URL format" try: progress(0.1, desc="Initializing YouTube extractor...") ydl_opts = { 'noplaylist': True, 'extract_flat': False, } if cookiefile and os.path.exists(cookiefile): ydl_opts['cookiefile'] = cookiefile progress(0.5, desc="Extracting video metadata...") with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=False) progress(1.0, desc="✅ Analysis complete!") print("DEBUG: Video info extracted successfully") # Debug line return info, "✅ Video information extracted successfully" except Exception as e: print(f"DEBUG: Error in get_video_info: {e}") # Debug line return None, f"❌ Error: {str(e)}" # Initialize global downloader downloader = YouTubeDownloader() def analyze_with_cookies(url, cookies_file, progress=gr.Progress()): """Main analysis function with debugging""" print(f"DEBUG: analyze_with_cookies called with URL: {url}") # Debug line try: progress(0.05, desc="Starting analysis...") cookiefile = None if cookies_file and os.path.exists(cookies_file): cookiefile = cookies_file info, msg = downloader.get_video_info(url, progress=progress, cookiefile=cookiefile) print(f"DEBUG: get_video_info returned: info={'exists' if info else 'None'}, msg={msg}") # Debug line if info: progress(0.95, desc="Generating comprehensive report...") formatted_info = downloader.format_video_info(info) progress(1.0, desc="✅ Complete!") print("DEBUG: Returning formatted report") # Debug line return formatted_info else: print(f"DEBUG: No info returned, error: {msg}") # Debug line return f"❌ Analysis Failed: {msg}" except Exception as e: print(f"DEBUG: Exception in analyze_with_cookies: {e}") # Debug line return f"❌ System Error: {str(e)}" def create_interface(): """Create and configure the Gradio interface""" with gr.Blocks(theme=gr.themes.Soft(), title="🎥 YouTube Video Analyzer Pro") as interface: gr.HTML("