Muktibhuyan's picture
Update app.py
cc59b3b verified
raw
history blame
13.6 kB
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("<h1>πŸŽ₯ YouTube Video Analyzer Pro</h1>")
with gr.Row():
url_input = gr.Textbox(
label="πŸ”— YouTube URL",
placeholder="Paste your YouTube video URL here...",
value="https://www.youtube.com/watch?v=o6zYartcwx4" # Pre-filled for testing
)
cookies_input = gr.File(
label="πŸͺ Upload cookies.txt (Optional)",
file_types=[".txt"],
type="filepath"
)
analyze_btn = gr.Button("πŸ” Analyze Video", variant="primary")
output = gr.Textbox(
label="πŸ“Š Analysis Report",
lines=30,
show_copy_button=True
)
analyze_btn.click(
fn=analyze_with_cookies,
inputs=[url_input, cookies_input],
outputs=output,
show_progress=True
)
return interface
if __name__ == "__main__":
demo = create_interface()
import atexit
atexit.register(downloader.cleanup)
demo.launch(debug=True, show_error=True)