Spaces:
Sleeping
Sleeping
import gradio as gr | |
import yt_dlp | |
import os | |
import tempfile | |
import shutil | |
from pathlib import Path | |
import re | |
import uuid | |
session_data = {} | |
class YouTubeDownloader: | |
def __init__(self): | |
self.download_dir = tempfile.mkdtemp() | |
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 format_video_info(self, video_info): | |
if not video_info: | |
return "β No video information available." | |
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 >= 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) | |
scene_descriptions = [] | |
if duration: | |
chunk = 3 | |
for start in range(0, duration, chunk): | |
end = min(start + chunk - 1, duration) | |
description = f"Visual segment from {start}s to {end}s. (e.g., close-up, presenter talks, etc.)" | |
scene_descriptions.append(f"* **[{start//60}:{start%60:02d}-{end//60}:{end%60:02d}]**: {description}") | |
else: | |
scene_descriptions.append("* No timestamped breakdown available.") | |
tags = ' '.join(video_info.get('tags', [])).lower() | |
title = video_info.get('title', '').lower() | |
description_text = video_info.get('description', '').lower() | |
channel = video_info.get('channel', '').lower() | |
if any(word in description_text for word in ['calm music', 'soft', 'soothing']): | |
music_style = "Calm" | |
elif any(word in description_text for word in ['energetic', 'upbeat', 'lively']): | |
music_style = "Upbeat" | |
elif "music" not in description_text: | |
music_style = "No music" | |
else: | |
music_style = "Unknown" | |
known_names = [ | |
"Kartik Aaryan", "Virat Kohli", "Deepika Padukone", "Alia Bhatt", "Ranveer Singh", | |
"MrBeast", "PewDiePie", "CarryMinati", "Prajakta Koli", "Bhuvan Bam", | |
"Amitabh Bachchan", "Katrina Kaif", "Salman Khan", "Kiara Advani", | |
"Kylie Jenner", "Shahrukh Khan", "Ananya Pandey", "Ashish Chanchlani", | |
"Sundar Pichai", "Elon Musk", "Taylor Swift", "Janhvi Kapoor" | |
] | |
metadata = " ".join([ | |
video_info.get('title', ''), | |
video_info.get('description', ''), | |
video_info.get('uploader', ''), | |
video_info.get('channel', ''), | |
' '.join(video_info.get('tags', [])) | |
]).lower() | |
matched = [name for name in known_names if any(part in metadata for part in name.lower().split())] | |
if matched: | |
influencer_note = f"Yes, known influencer/celebrity detected: {', '.join(matched)}" | |
else: | |
influencer_note = "No known influencer or celebrity detected." | |
if any(word in metadata for word in ["actor", "brand ambassador", "featured", "with", "hosted by"]): | |
influencer_note += " (Someone might be featured β check visually)" | |
if "review" in title or "demo" in title or "how to" in title: | |
video_type = "Educational" | |
elif "ad" in title or "promo" in title or "launch" in title: | |
video_type = "Promotional" | |
elif "funny" in title or "challenge" in title: | |
video_type = "Entertainment" | |
else: | |
video_type = "Informational" | |
if any(word in description_text for word in ['excited', 'amazing', 'love']): | |
emotion = "Positive" | |
elif any(word in description_text for word in ['calm', 'soothing']): | |
emotion = "Neutral" | |
elif any(word in description_text for word in ['warning', 'serious']): | |
emotion = "Serious" | |
else: | |
emotion = "Neutral" | |
report = f"""πΉ VIDEO ANALYSIS REPORT | |
{'='*50} | |
π BASIC INFORMATION: | |
β’ 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} | |
π STATISTICS: | |
β’ Views: {format_number(video_info.get('view_count', 0))} | |
β’ Likes: {format_number(video_info.get('like_count', 0))} | |
β’ Comments: {format_number(video_info.get('comment_count', 0))} | |
β’ Channel Followers: {format_number(video_info.get('channel_followers', 0))} | |
π·οΈ CATEGORIES & TAGS: | |
β’ Categories: {', '.join(video_info.get('categories', [])) or 'None'} | |
β’ Tags: {', '.join(video_info.get('tags', [])[:10]) or 'None'} | |
{('β’ More tags...' if len(video_info.get('tags', [])) > 10 else '')} | |
π DESCRIPTION (first 500 chars): | |
{video_info.get('description', 'No description available')[:500]} | |
{'...' if len(video_info.get('description', '')) > 500 else ''} | |
π¬ SCENE-BY-SCENE BREAKDOWN: | |
{chr(10).join(scene_descriptions)} | |
π΅ BACKGROUND MUSIC STYLE: {music_style} | |
π€ INFLUENCER PRESENT: {influencer_note} | |
π₯ VIDEO TYPE: {video_type} | |
π OVERALL EMOTION: {emotion} | |
π VIDEO URL: | |
{video_info.get('webpage_url', 'Unknown')} | |
""" | |
return report.strip() | |
def get_video_info(self, url): | |
ydl_opts = { | |
'noplaylist': True, | |
'extract_flat': False, | |
} | |
try: | |
with yt_dlp.YoutubeDL(ydl_opts) as ydl: | |
info = ydl.extract_info(url, download=False) | |
return info, "β Info retrieved" | |
except Exception as e: | |
return None, f"β {str(e)}" | |
downloader = YouTubeDownloader() | |
def analyze(url): | |
info, msg = downloader.get_video_info(url) | |
if info: | |
return downloader.format_video_info(info) | |
else: | |
return msg | |
demo = gr.Interface(fn=analyze, inputs=gr.Textbox(label="YouTube URL"), outputs="text", title="YouTube Analyzer with Scene Breakdown") | |
if __name__ == "__main__": | |
demo.launch() | |