Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
|
| 2 |
import gradio as gr
|
| 3 |
import yt_dlp
|
| 4 |
import os
|
|
@@ -18,6 +17,64 @@ class YouTubeDownloader:
|
|
| 18 |
)
|
| 19 |
return youtube_regex.match(url) is not None
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
def get_video_info(self, url, progress=gr.Progress(), cookiefile=None):
|
| 22 |
if not url or not url.strip():
|
| 23 |
return None, "β Please enter a YouTube URL"
|
|
@@ -132,12 +189,12 @@ def create_interface():
|
|
| 132 |
status_output = gr.Textbox(label="Download Status")
|
| 133 |
file_output = gr.File(label="Downloaded Video", visible=False)
|
| 134 |
analysis_btn = gr.Button("Show Analysis Results", visible=False)
|
| 135 |
-
analysis_output = gr.Textbox(label="Video Analysis Results", visible=False)
|
| 136 |
video_info_state = gr.State(value=None)
|
| 137 |
|
| 138 |
def handle_download(url, cookies_path):
|
| 139 |
if not url or not url.strip():
|
| 140 |
-
return "Please enter a YouTube URL", gr.File(visible=False), gr.Button(visible=False), None
|
| 141 |
|
| 142 |
cookiefile = cookies_path.strip() if cookies_path and os.path.exists(cookies_path.strip()) else None
|
| 143 |
video_info, info_message = downloader.get_video_info(url, cookiefile=cookiefile)
|
|
@@ -146,20 +203,21 @@ def create_interface():
|
|
| 146 |
|
| 147 |
if file_path and video_info:
|
| 148 |
success_message = f"{download_message}\n\nVideo downloaded successfully! Click 'Show Analysis Results' to see detailed information."
|
| 149 |
-
return success_message, gr.File(value=file_path, visible=True), gr.Button(visible=True), video_info
|
| 150 |
elif file_path:
|
| 151 |
-
return f"{download_message}\n\nVideo downloaded but analysis data unavailable.", gr.File(value=file_path, visible=True), gr.Button(visible=False), None
|
| 152 |
else:
|
| 153 |
-
return f"β Download failed:\n{download_message}", gr.File(visible=False), gr.Button(visible=False), None
|
| 154 |
|
| 155 |
def show_analysis(video_info):
|
| 156 |
if video_info:
|
| 157 |
-
|
| 158 |
-
|
|
|
|
| 159 |
|
| 160 |
-
download_btn.click(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, video_info_state])
|
| 161 |
analysis_btn.click(show_analysis, inputs=[video_info_state], outputs=[analysis_output])
|
| 162 |
-
url_input.submit(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, video_info_state])
|
| 163 |
|
| 164 |
return demo
|
| 165 |
|
|
@@ -167,4 +225,4 @@ if __name__ == "__main__":
|
|
| 167 |
demo = create_interface()
|
| 168 |
import atexit
|
| 169 |
atexit.register(downloader.cleanup)
|
| 170 |
-
demo.launch()
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import yt_dlp
|
| 3 |
import os
|
|
|
|
| 17 |
)
|
| 18 |
return youtube_regex.match(url) is not None
|
| 19 |
|
| 20 |
+
def format_video_info(self, video_info):
|
| 21 |
+
"""Format video information into a readable report"""
|
| 22 |
+
if not video_info:
|
| 23 |
+
return "β No video information available."
|
| 24 |
+
|
| 25 |
+
# Format duration
|
| 26 |
+
duration = video_info.get('duration', 0)
|
| 27 |
+
duration_str = f"{duration//3600}:{(duration%3600)//60:02d}:{duration%60:02d}" if duration else "Unknown"
|
| 28 |
+
|
| 29 |
+
# Format upload date
|
| 30 |
+
upload_date = video_info.get('upload_date', '')
|
| 31 |
+
if upload_date and len(upload_date) == 8:
|
| 32 |
+
formatted_date = f"{upload_date[:4]}-{upload_date[4:6]}-{upload_date[6:8]}"
|
| 33 |
+
else:
|
| 34 |
+
formatted_date = upload_date or "Unknown"
|
| 35 |
+
|
| 36 |
+
# Format numbers
|
| 37 |
+
def format_number(num):
|
| 38 |
+
if num >= 1_000_000:
|
| 39 |
+
return f"{num/1_000_000:.1f}M"
|
| 40 |
+
elif num >= 1_000:
|
| 41 |
+
return f"{num/1_000:.1f}K"
|
| 42 |
+
else:
|
| 43 |
+
return str(num)
|
| 44 |
+
|
| 45 |
+
# Build the report
|
| 46 |
+
report = f"""
|
| 47 |
+
πΉ VIDEO ANALYSIS REPORT
|
| 48 |
+
{'='*50}
|
| 49 |
+
|
| 50 |
+
π BASIC INFORMATION:
|
| 51 |
+
β’ Title: {video_info.get('title', 'Unknown')}
|
| 52 |
+
β’ Channel: {video_info.get('channel', 'Unknown')}
|
| 53 |
+
β’ Uploader: {video_info.get('uploader', 'Unknown')}
|
| 54 |
+
β’ Upload Date: {formatted_date}
|
| 55 |
+
β’ Duration: {duration_str}
|
| 56 |
+
|
| 57 |
+
π STATISTICS:
|
| 58 |
+
β’ Views: {format_number(video_info.get('view_count', 0))}
|
| 59 |
+
β’ Likes: {format_number(video_info.get('like_count', 0))}
|
| 60 |
+
β’ Comments: {format_number(video_info.get('comment_count', 0))}
|
| 61 |
+
β’ Channel Followers: {format_number(video_info.get('channel_followers', 0))}
|
| 62 |
+
|
| 63 |
+
π·οΈ CATEGORIES & TAGS:
|
| 64 |
+
β’ Categories: {', '.join(video_info.get('categories', [])) or 'None'}
|
| 65 |
+
β’ Tags: {', '.join(video_info.get('tags', [])[:10]) or 'None'}
|
| 66 |
+
{('β’ More tags...' if len(video_info.get('tags', [])) > 10 else '')}
|
| 67 |
+
|
| 68 |
+
π DESCRIPTION:
|
| 69 |
+
{video_info.get('description', 'No description available')[:500]}
|
| 70 |
+
{'...' if len(video_info.get('description', '')) > 500 else ''}
|
| 71 |
+
|
| 72 |
+
π VIDEO URL:
|
| 73 |
+
{video_info.get('webpage_url', 'Unknown')}
|
| 74 |
+
"""
|
| 75 |
+
|
| 76 |
+
return report.strip()
|
| 77 |
+
|
| 78 |
def get_video_info(self, url, progress=gr.Progress(), cookiefile=None):
|
| 79 |
if not url or not url.strip():
|
| 80 |
return None, "β Please enter a YouTube URL"
|
|
|
|
| 189 |
status_output = gr.Textbox(label="Download Status")
|
| 190 |
file_output = gr.File(label="Downloaded Video", visible=False)
|
| 191 |
analysis_btn = gr.Button("Show Analysis Results", visible=False)
|
| 192 |
+
analysis_output = gr.Textbox(label="Video Analysis Results", visible=False, lines=20)
|
| 193 |
video_info_state = gr.State(value=None)
|
| 194 |
|
| 195 |
def handle_download(url, cookies_path):
|
| 196 |
if not url or not url.strip():
|
| 197 |
+
return "Please enter a YouTube URL", gr.File(visible=False), gr.Button(visible=False), gr.Textbox(visible=False), None
|
| 198 |
|
| 199 |
cookiefile = cookies_path.strip() if cookies_path and os.path.exists(cookies_path.strip()) else None
|
| 200 |
video_info, info_message = downloader.get_video_info(url, cookiefile=cookiefile)
|
|
|
|
| 203 |
|
| 204 |
if file_path and video_info:
|
| 205 |
success_message = f"{download_message}\n\nVideo downloaded successfully! Click 'Show Analysis Results' to see detailed information."
|
| 206 |
+
return success_message, gr.File(value=file_path, visible=True), gr.Button(visible=True), gr.Textbox(visible=False), video_info
|
| 207 |
elif file_path:
|
| 208 |
+
return f"{download_message}\n\nVideo downloaded but analysis data unavailable.", gr.File(value=file_path, visible=True), gr.Button(visible=False), gr.Textbox(visible=False), None
|
| 209 |
else:
|
| 210 |
+
return f"β Download failed:\n{download_message}", gr.File(visible=False), gr.Button(visible=False), gr.Textbox(visible=False), None
|
| 211 |
|
| 212 |
def show_analysis(video_info):
|
| 213 |
if video_info:
|
| 214 |
+
analysis_report = downloader.format_video_info(video_info)
|
| 215 |
+
return gr.Textbox(value=analysis_report, visible=True)
|
| 216 |
+
return gr.Textbox(value="β No analysis data available.", visible=True)
|
| 217 |
|
| 218 |
+
download_btn.click(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, analysis_output, video_info_state])
|
| 219 |
analysis_btn.click(show_analysis, inputs=[video_info_state], outputs=[analysis_output])
|
| 220 |
+
url_input.submit(handle_download, inputs=[url_input, cookies_input], outputs=[status_output, file_output, analysis_btn, analysis_output, video_info_state])
|
| 221 |
|
| 222 |
return demo
|
| 223 |
|
|
|
|
| 225 |
demo = create_interface()
|
| 226 |
import atexit
|
| 227 |
atexit.register(downloader.cleanup)
|
| 228 |
+
demo.launch()
|