Muktibhuyan commited on
Commit
7a16d12
Β·
verified Β·
1 Parent(s): ca78672

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -165
app.py CHANGED
@@ -6,6 +6,7 @@ import shutil
6
  from pathlib import Path
7
  import re
8
  import uuid
 
9
  session_data = {}
10
 
11
  class YouTubeDownloader:
@@ -20,33 +21,90 @@ class YouTubeDownloader:
20
  return youtube_regex.match(url) is not None
21
 
22
  def format_video_info(self, video_info):
23
- """Format video information into a readable report"""
24
  if not video_info:
25
  return "❌ No video information available."
26
-
27
- # Format duration
28
  duration = video_info.get('duration', 0)
29
  duration_str = f"{duration//3600}:{(duration%3600)//60:02d}:{duration%60:02d}" if duration else "Unknown"
30
-
31
- # Format upload date
32
  upload_date = video_info.get('upload_date', '')
33
- if upload_date and len(upload_date) == 8:
34
- formatted_date = f"{upload_date[:4]}-{upload_date[4:6]}-{upload_date[6:8]}"
35
- else:
36
- formatted_date = upload_date or "Unknown"
37
-
38
- # Format numbers
39
  def format_number(num):
40
  if num >= 1_000_000:
41
  return f"{num/1_000_000:.1f}M"
42
  elif num >= 1_000:
43
  return f"{num/1_000:.1f}K"
44
- else:
45
- return str(num)
46
-
47
- # Build the report
48
- report = f"""
49
- πŸ“Ή VIDEO ANALYSIS REPORT
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  {'='*50}
51
 
52
  πŸ“ BASIC INFORMATION:
@@ -67,166 +125,45 @@ class YouTubeDownloader:
67
  β€’ Tags: {', '.join(video_info.get('tags', [])[:10]) or 'None'}
68
  {('β€’ More tags...' if len(video_info.get('tags', [])) > 10 else '')}
69
 
70
- πŸ“– DESCRIPTION:
71
  {video_info.get('description', 'No description available')[:500]}
72
  {'...' if len(video_info.get('description', '')) > 500 else ''}
73
 
 
 
 
 
 
 
 
 
74
  πŸ”— VIDEO URL:
75
  {video_info.get('webpage_url', 'Unknown')}
76
- """
77
-
78
  return report.strip()
79
 
80
- def get_video_info(self, url, progress=gr.Progress(), cookiefile=None):
81
- if not url or not url.strip():
82
- return None, "❌ Please enter a YouTube URL"
83
-
84
- if not self.is_valid_youtube_url(url):
85
- return None, "❌ Invalid YouTube URL. Please enter a valid YouTube video URL"
86
-
87
  try:
88
- progress(0.2, desc="Fetching video information...")
89
- ydl_opts = {
90
- 'noplaylist': True,
91
- 'extract_flat': False,
92
- }
93
- if cookiefile:
94
- ydl_opts['cookiefile'] = cookiefile
95
-
96
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
97
- try:
98
- info = ydl.extract_info(url, download=False)
99
- video_info = {
100
- 'title': info.get('title', 'Unknown'),
101
- 'description': info.get('description', 'No description available'),
102
- 'duration': info.get('duration', 0),
103
- 'view_count': info.get('view_count', 0),
104
- 'like_count': info.get('like_count', 0),
105
- 'comment_count': info.get('comment_count', 0),
106
- 'upload_date': info.get('upload_date', ''),
107
- 'uploader': info.get('uploader', 'Unknown'),
108
- 'channel': info.get('channel', 'Unknown'),
109
- 'channel_followers': info.get('channel_follower_count', 0),
110
- 'tags': info.get('tags', []),
111
- 'categories': info.get('categories', []),
112
- 'thumbnail': info.get('thumbnail', ''),
113
- 'webpage_url': info.get('webpage_url', url)
114
- }
115
- progress(1.0, desc="Information retrieved!")
116
- return video_info, "βœ… Video information retrieved successfully"
117
- except yt_dlp.DownloadError as e:
118
- error_msg = str(e)
119
- if "Video unavailable" in error_msg:
120
- return None, "❌ Video is unavailable or private"
121
- elif "age-restricted" in error_msg.lower():
122
- return None, "❌ Video is age-restricted"
123
- else:
124
- return None, f"❌ Failed to get video info: {error_msg}"
125
  except Exception as e:
126
- return None, f"❌ An unexpected error occurred: {str(e)}"
127
-
128
- def download_video(self, url, progress=gr.Progress(), cookiefile=None):
129
- if not url or not url.strip():
130
- return None, "❌ Please enter a YouTube URL"
131
-
132
- if not self.is_valid_youtube_url(url):
133
- return None, "❌ Invalid YouTube URL. Please enter a valid YouTube video URL"
134
-
135
- try:
136
- progress(0.1, desc="Initializing download...")
137
- ydl_opts = {
138
- 'format': 'best[ext=mp4]/best',
139
- 'outtmpl': os.path.join(self.download_dir, '%(title)s.%(ext)s'),
140
- 'noplaylist': True,
141
- }
142
- if cookiefile:
143
- ydl_opts['cookiefile'] = cookiefile
144
-
145
- progress(0.3, desc="Fetching video information...")
146
- with yt_dlp.YoutubeDL(ydl_opts) as ydl:
147
- try:
148
- info = ydl.extract_info(url, download=False)
149
- video_title = info.get('title', 'Unknown')
150
- duration = info.get('duration', 0)
151
- progress(0.5, desc=f"Downloading: {video_title[:50]}...")
152
- ydl.download([url])
153
- progress(0.9, desc="Finalizing download...")
154
- downloaded_files = list(Path(self.download_dir).glob('*'))
155
- if downloaded_files:
156
- downloaded_file = downloaded_files[0]
157
- file_size = downloaded_file.stat().st_size / (1024 * 1024)
158
- progress(1.0, desc="Download completed!")
159
- success_message = f"βœ… Successfully downloaded: {video_title}\n"
160
- success_message += f"πŸ“ File size: {file_size:.1f} MB\n"
161
- success_message += f"⏱️ Duration: {duration//60}:{duration%60:02d}" if duration else ""
162
- return str(downloaded_file), success_message
163
- else:
164
- return None, "❌ Download completed but file not found"
165
- except yt_dlp.DownloadError as e:
166
- error_msg = str(e)
167
- if "Video unavailable" in error_msg:
168
- return None, "❌ Video is unavailable or private"
169
- elif "age-restricted" in error_msg.lower():
170
- return None, "❌ Video is age-restricted and cannot be downloaded"
171
- elif "copyright" in error_msg.lower():
172
- return None, "❌ Video cannot be downloaded due to copyright restrictions"
173
- else:
174
- return None, f"❌ Download failed: {error_msg}"
175
- except Exception as e:
176
- return None, f"❌ An unexpected error occurred: {str(e)}"
177
-
178
- def cleanup(self):
179
- try:
180
- shutil.rmtree(self.download_dir, ignore_errors=True)
181
- except:
182
- pass
183
 
184
  downloader = YouTubeDownloader()
185
 
186
- def create_interface():
187
- with gr.Blocks(title="YouTube Video Downloader & Analyzer") as demo:
188
- url_input = gr.Textbox(label="YouTube URL", placeholder="https://www.youtube.com/watch?v=...")
189
- cookies_input = gr.File(label="Upload cookies.txt (optional)", type="filepath", file_types=[".txt"])
190
- download_btn = gr.Button("Download Video")
191
- status_output = gr.Textbox(label="Download Status")
192
- file_output = gr.File(label="Downloaded Video", visible=False)
193
- analysis_btn = gr.Button("Show Analysis Results", visible=False)
194
- analysis_output = gr.Textbox(label="Video Analysis Results", visible=False, lines=20)
195
- video_info_state = gr.Textbox(value=False)
196
-
197
-
198
- def handle_download(url, cookies_path):
199
- if not url or not url.strip():
200
- return "Please enter a YouTube URL", gr.File(visible=False), gr.Button(visible=False), None
201
-
202
- cookiefile = cookies_path.strip() if cookies_path and os.path.exists(cookies_path.strip()) else None
203
- video_info, info_message = downloader.get_video_info(url, cookiefile=cookiefile)
204
- file_path, download_message = downloader.download_video(url, cookiefile=cookiefile)
205
- print(f"[DEBUG] Download message: {download_message}")
206
-
207
- if file_path and video_info:
208
- success_message = f"{download_message}\n\nVideo downloaded successfully! Click 'Show Analysis Results' to see detailed information."
209
- return success_message, gr.File(value=file_path, visible=True), gr.Button(visible=True), gr.State(video_info)
210
- elif file_path:
211
- return f"{download_message}\n\nVideo downloaded but analysis data unavailable.", gr.File(value=file_path, visible=True), gr.Button(visible=False), gr.State("")
212
- else:
213
- return f"❌ Download failed:\n{download_message}", gr.File(visible=False), gr.Button(visible=False), gr.State(None)
214
-
215
- def show_analysis(video_info):
216
- print("[DEBUG] Received session_id:", session_id)
217
- video_info = session_data.get(session_id)
218
- if video_info:
219
- return downloader.format_video_info(video_info), gr.Textbox(visible=True)
220
- return "❌ No analysis data available.", gr.Textbox(visible=True)
221
-
222
- download_btn.click(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, video_info_state])
223
- analysis_btn.click(show_analysis, inputs=[video_info_state], outputs=[analysis_output])
224
- url_input.submit(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, video_info_state])
225
-
226
- return demo
227
 
228
  if __name__ == "__main__":
229
- demo = create_interface()
230
- import atexit
231
- atexit.register(downloader.cleanup)
232
- demo.launch()
 
6
  from pathlib import Path
7
  import re
8
  import uuid
9
+
10
  session_data = {}
11
 
12
  class YouTubeDownloader:
 
21
  return youtube_regex.match(url) is not None
22
 
23
  def format_video_info(self, video_info):
 
24
  if not video_info:
25
  return "❌ No video information available."
26
+
 
27
  duration = video_info.get('duration', 0)
28
  duration_str = f"{duration//3600}:{(duration%3600)//60:02d}:{duration%60:02d}" if duration else "Unknown"
 
 
29
  upload_date = video_info.get('upload_date', '')
30
+ formatted_date = f"{upload_date[:4]}-{upload_date[4:6]}-{upload_date[6:8]}" if len(upload_date) == 8 else upload_date or "Unknown"
31
+
 
 
 
 
32
  def format_number(num):
33
  if num >= 1_000_000:
34
  return f"{num/1_000_000:.1f}M"
35
  elif num >= 1_000:
36
  return f"{num/1_000:.1f}K"
37
+ return str(num)
38
+
39
+ scene_descriptions = []
40
+ if duration:
41
+ chunk = 3
42
+ for start in range(0, duration, chunk):
43
+ end = min(start + chunk - 1, duration)
44
+ description = f"Visual segment from {start}s to {end}s. (e.g., close-up, presenter talks, etc.)"
45
+ scene_descriptions.append(f"* **[{start//60}:{start%60:02d}-{end//60}:{end%60:02d}]**: {description}")
46
+ else:
47
+ scene_descriptions.append("* No timestamped breakdown available.")
48
+
49
+ tags = ' '.join(video_info.get('tags', [])).lower()
50
+ title = video_info.get('title', '').lower()
51
+ description_text = video_info.get('description', '').lower()
52
+ channel = video_info.get('channel', '').lower()
53
+
54
+ if any(word in description_text for word in ['calm music', 'soft', 'soothing']):
55
+ music_style = "Calm"
56
+ elif any(word in description_text for word in ['energetic', 'upbeat', 'lively']):
57
+ music_style = "Upbeat"
58
+ elif "music" not in description_text:
59
+ music_style = "No music"
60
+ else:
61
+ music_style = "Unknown"
62
+
63
+ known_names = [
64
+ "Kartik Aaryan", "Virat Kohli", "Deepika Padukone", "Alia Bhatt", "Ranveer Singh",
65
+ "MrBeast", "PewDiePie", "CarryMinati", "Prajakta Koli", "Bhuvan Bam",
66
+ "Amitabh Bachchan", "Katrina Kaif", "Salman Khan", "Kiara Advani",
67
+ "Kylie Jenner", "Shahrukh Khan", "Ananya Pandey", "Ashish Chanchlani",
68
+ "Sundar Pichai", "Elon Musk", "Taylor Swift", "Janhvi Kapoor"
69
+ ]
70
+
71
+ metadata = " ".join([
72
+ video_info.get('title', ''),
73
+ video_info.get('description', ''),
74
+ video_info.get('uploader', ''),
75
+ video_info.get('channel', ''),
76
+ ' '.join(video_info.get('tags', []))
77
+ ]).lower()
78
+
79
+ matched = [name for name in known_names if any(part in metadata for part in name.lower().split())]
80
+
81
+ if matched:
82
+ influencer_note = f"Yes, known influencer/celebrity detected: {', '.join(matched)}"
83
+ else:
84
+ influencer_note = "No known influencer or celebrity detected."
85
+
86
+ if any(word in metadata for word in ["actor", "brand ambassador", "featured", "with", "hosted by"]):
87
+ influencer_note += " (Someone might be featured β€” check visually)"
88
+
89
+ if "review" in title or "demo" in title or "how to" in title:
90
+ video_type = "Educational"
91
+ elif "ad" in title or "promo" in title or "launch" in title:
92
+ video_type = "Promotional"
93
+ elif "funny" in title or "challenge" in title:
94
+ video_type = "Entertainment"
95
+ else:
96
+ video_type = "Informational"
97
+
98
+ if any(word in description_text for word in ['excited', 'amazing', 'love']):
99
+ emotion = "Positive"
100
+ elif any(word in description_text for word in ['calm', 'soothing']):
101
+ emotion = "Neutral"
102
+ elif any(word in description_text for word in ['warning', 'serious']):
103
+ emotion = "Serious"
104
+ else:
105
+ emotion = "Neutral"
106
+
107
+ report = f"""πŸ“Ή VIDEO ANALYSIS REPORT
108
  {'='*50}
109
 
110
  πŸ“ BASIC INFORMATION:
 
125
  β€’ Tags: {', '.join(video_info.get('tags', [])[:10]) or 'None'}
126
  {('β€’ More tags...' if len(video_info.get('tags', [])) > 10 else '')}
127
 
128
+ πŸ“– DESCRIPTION (first 500 chars):
129
  {video_info.get('description', 'No description available')[:500]}
130
  {'...' if len(video_info.get('description', '')) > 500 else ''}
131
 
132
+ 🎬 SCENE-BY-SCENE BREAKDOWN:
133
+ {chr(10).join(scene_descriptions)}
134
+
135
+ 🎡 BACKGROUND MUSIC STYLE: {music_style}
136
+ πŸ‘€ INFLUENCER PRESENT: {influencer_note}
137
+ πŸŽ₯ VIDEO TYPE: {video_type}
138
+ 🎭 OVERALL EMOTION: {emotion}
139
+
140
  πŸ”— VIDEO URL:
141
  {video_info.get('webpage_url', 'Unknown')}
142
+ """
 
143
  return report.strip()
144
 
145
+ def get_video_info(self, url):
146
+ ydl_opts = {
147
+ 'noplaylist': True,
148
+ 'extract_flat': False,
149
+ }
 
 
150
  try:
 
 
 
 
 
 
 
 
151
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
152
+ info = ydl.extract_info(url, download=False)
153
+ return info, "βœ… Info retrieved"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
  except Exception as e:
155
+ return None, f"❌ {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
 
157
  downloader = YouTubeDownloader()
158
 
159
+ def analyze(url):
160
+ info, msg = downloader.get_video_info(url)
161
+ if info:
162
+ return downloader.format_video_info(info)
163
+ else:
164
+ return msg
165
+
166
+ demo = gr.Interface(fn=analyze, inputs=gr.Textbox(label="YouTube URL"), outputs="text", title="YouTube Analyzer with Scene Breakdown")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  if __name__ == "__main__":
169
+ demo.launch()