jpjp9292 commited on
Commit
5f28806
โ€ข
1 Parent(s): 864798c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +289 -86
app.py CHANGED
@@ -1,105 +1,105 @@
1
 
2
- import streamlit as st
3
- import yt_dlp
4
- import os
5
- from pathlib import Path
6
 
7
- # Set page config
8
- st.set_page_config(page_title="YouTube Video Downloader", page_icon="๐Ÿ“บ")
9
 
10
- # Set the title of the app
11
- st.title("YouTube Video Downloader ๐Ÿ“บ")
12
 
13
- # Create output directory if it doesn't exist
14
- output_dir = Path("downloads")
15
- output_dir.mkdir(exist_ok=True)
16
 
17
- # Input field for YouTube video URL
18
- video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...")
19
 
20
- # Function to download video
21
- def download_video(url):
22
- try:
23
- ydl_opts = {
24
- 'format': 'bestvideo+bestaudio/best',
25
- 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
26
- 'merge_output_format': 'webm',
27
- # Add these options to mimic browser behavior
28
- 'quiet': True,
29
- 'no_warnings': True,
30
- 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
31
- 'referer': 'https://www.youtube.com/',
32
- 'cookiefile': 'youtube.com_cookies.txt', # ์ฟ ํ‚ค ํŒŒ์ผ ์‚ฌ์šฉ
33
- 'socket_timeout': 30,
34
- 'http_chunk_size': 10485760, # 10MB
35
- }
36
 
37
- # Progress placeholder
38
- progress_bar = st.progress(0)
39
- status_text = st.empty()
40
 
41
- def progress_hook(d):
42
- if d['status'] == 'downloading':
43
- try:
44
- progress = d['downloaded_bytes'] / d['total_bytes']
45
- progress_bar.progress(progress)
46
- status_text.text(f"Downloading: {progress:.1%}")
47
- except:
48
- status_text.text("Downloading... (size unknown)")
49
- elif d['status'] == 'finished':
50
- progress_bar.progress(1.0)
51
- status_text.text("Processing...")
52
 
53
- ydl_opts['progress_hooks'] = [progress_hook]
54
 
55
- with yt_dlp.YoutubeDL(ydl_opts) as ydl:
56
- info = ydl.extract_info(url, download=True)
57
- filename = ydl.prepare_filename(info)
58
- return filename
59
 
60
- except Exception as e:
61
- st.error(f"An error occurred: {str(e)}")
62
- return None
63
 
64
- # Download button
65
- if st.button("Download"):
66
- if video_url:
67
- try:
68
- with st.spinner("Preparing download..."):
69
- downloaded_file_path = download_video(video_url)
70
 
71
- if downloaded_file_path and os.path.exists(downloaded_file_path):
72
- with open(downloaded_file_path, 'rb') as file:
73
- st.download_button(
74
- label="Click here to download",
75
- data=file,
76
- file_name=os.path.basename(downloaded_file_path),
77
- mime="application/octet-stream"
78
- )
79
- st.success("โœ… Download ready!")
80
- else:
81
- st.error("โŒ Download failed. Please try again.")
82
- except Exception as e:
83
- st.error(f"โŒ An error occurred: {str(e)}")
84
- else:
85
- st.warning("โš ๏ธ Please enter a valid YouTube URL.")
86
 
87
- # Help section
88
- with st.expander("โ„น๏ธ Help & Troubleshooting"):
89
- st.markdown("""
90
- **If you're experiencing download issues:**
91
 
92
- 1. Cookie Authentication Method:
93
- - Install a browser extension like "Get cookies.txt"
94
- - Visit YouTube and ensure you're logged in
95
- - Export cookies to 'youtube.com_cookies.txt'
96
- - Place the file in the same directory as this app
97
 
98
- 2. Alternative Solutions:
99
- - Try different videos
100
- - Check if the video is public/not age-restricted
101
- - Try again later if YouTube is blocking requests
102
- """)
103
 
104
 
105
  # import streamlit as st
@@ -210,3 +210,206 @@ with st.expander("โ„น๏ธ Help & Troubleshooting"):
210
  # 3. Try a different video
211
  # 4. Try again later if YouTube is blocking requests
212
  # """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
 
2
+ # import streamlit as st
3
+ # import yt_dlp
4
+ # import os
5
+ # from pathlib import Path
6
 
7
+ # # Set page config
8
+ # st.set_page_config(page_title="YouTube Video Downloader", page_icon="๐Ÿ“บ")
9
 
10
+ # # Set the title of the app
11
+ # st.title("YouTube Video Downloader ๐Ÿ“บ")
12
 
13
+ # # Create output directory if it doesn't exist
14
+ # output_dir = Path("downloads")
15
+ # output_dir.mkdir(exist_ok=True)
16
 
17
+ # # Input field for YouTube video URL
18
+ # video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...")
19
 
20
+ # # Function to download video
21
+ # def download_video(url):
22
+ # try:
23
+ # ydl_opts = {
24
+ # 'format': 'bestvideo+bestaudio/best',
25
+ # 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
26
+ # 'merge_output_format': 'webm',
27
+ # # Add these options to mimic browser behavior
28
+ # 'quiet': True,
29
+ # 'no_warnings': True,
30
+ # 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
31
+ # 'referer': 'https://www.youtube.com/',
32
+ # 'cookiefile': 'youtube.com_cookies.txt', # ์ฟ ํ‚ค ํŒŒ์ผ ์‚ฌ์šฉ
33
+ # 'socket_timeout': 30,
34
+ # 'http_chunk_size': 10485760, # 10MB
35
+ # }
36
 
37
+ # # Progress placeholder
38
+ # progress_bar = st.progress(0)
39
+ # status_text = st.empty()
40
 
41
+ # def progress_hook(d):
42
+ # if d['status'] == 'downloading':
43
+ # try:
44
+ # progress = d['downloaded_bytes'] / d['total_bytes']
45
+ # progress_bar.progress(progress)
46
+ # status_text.text(f"Downloading: {progress:.1%}")
47
+ # except:
48
+ # status_text.text("Downloading... (size unknown)")
49
+ # elif d['status'] == 'finished':
50
+ # progress_bar.progress(1.0)
51
+ # status_text.text("Processing...")
52
 
53
+ # ydl_opts['progress_hooks'] = [progress_hook]
54
 
55
+ # with yt_dlp.YoutubeDL(ydl_opts) as ydl:
56
+ # info = ydl.extract_info(url, download=True)
57
+ # filename = ydl.prepare_filename(info)
58
+ # return filename
59
 
60
+ # except Exception as e:
61
+ # st.error(f"An error occurred: {str(e)}")
62
+ # return None
63
 
64
+ # # Download button
65
+ # if st.button("Download"):
66
+ # if video_url:
67
+ # try:
68
+ # with st.spinner("Preparing download..."):
69
+ # downloaded_file_path = download_video(video_url)
70
 
71
+ # if downloaded_file_path and os.path.exists(downloaded_file_path):
72
+ # with open(downloaded_file_path, 'rb') as file:
73
+ # st.download_button(
74
+ # label="Click here to download",
75
+ # data=file,
76
+ # file_name=os.path.basename(downloaded_file_path),
77
+ # mime="application/octet-stream"
78
+ # )
79
+ # st.success("โœ… Download ready!")
80
+ # else:
81
+ # st.error("โŒ Download failed. Please try again.")
82
+ # except Exception as e:
83
+ # st.error(f"โŒ An error occurred: {str(e)}")
84
+ # else:
85
+ # st.warning("โš ๏ธ Please enter a valid YouTube URL.")
86
 
87
+ # # Help section
88
+ # with st.expander("โ„น๏ธ Help & Troubleshooting"):
89
+ # st.markdown("""
90
+ # **If you're experiencing download issues:**
91
 
92
+ # 1. Cookie Authentication Method:
93
+ # - Install a browser extension like "Get cookies.txt"
94
+ # - Visit YouTube and ensure you're logged in
95
+ # - Export cookies to 'youtube.com_cookies.txt'
96
+ # - Place the file in the same directory as this app
97
 
98
+ # 2. Alternative Solutions:
99
+ # - Try different videos
100
+ # - Check if the video is public/not age-restricted
101
+ # - Try again later if YouTube is blocking requests
102
+ # """)
103
 
104
 
105
  # import streamlit as st
 
210
  # 3. Try a different video
211
  # 4. Try again later if YouTube is blocking requests
212
  # """)
213
+
214
+
215
+ import streamlit as st
216
+ import yt_dlp
217
+ import os
218
+ from pathlib import Path
219
+ import json
220
+ from http.cookiejar import MozillaCookieJar
221
+ from datetime import datetime
222
+
223
+ # Constants
224
+ COOKIES_FILE = 'youtube.com_cookies.txt'
225
+ OUTPUT_DIR = Path("downloads")
226
+
227
+ # Set page config
228
+ st.set_page_config(page_title="YouTube Video Downloader", page_icon="๐Ÿ“บ")
229
+ st.title("YouTube Video Downloader ๐Ÿ“บ")
230
+
231
+ # Create output directory if it doesn't exist
232
+ OUTPUT_DIR.mkdir(exist_ok=True)
233
+
234
+ def validate_cookies():
235
+ """์ฟ ํ‚ค ํŒŒ์ผ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ"""
236
+ if not os.path.exists(COOKIES_FILE):
237
+ return False, "Cookie file not found"
238
+
239
+ try:
240
+ cookie_jar = MozillaCookieJar(COOKIES_FILE)
241
+ cookie_jar.load()
242
+
243
+ # Check for essential YouTube cookies
244
+ essential_cookies = ['CONSENT', 'LOGIN_INFO', 'PREF']
245
+ found_cookies = [cookie.name for cookie in cookie_jar]
246
+
247
+ missing_cookies = [cookie for cookie in essential_cookies if cookie not in found_cookies]
248
+ if missing_cookies:
249
+ return False, f"Missing essential cookies: {', '.join(missing_cookies)}"
250
+
251
+ return True, "Cookies valid"
252
+ except Exception as e:
253
+ return False, f"Cookie validation error: {str(e)}"
254
+
255
+ def get_video_info(url):
256
+ """๋™์˜์ƒ ์ •๋ณด ๋ฏธ๋ฆฌ๋ณด๊ธฐ ์ถ”์ถœ"""
257
+ ydl_opts = {
258
+ 'quiet': True,
259
+ 'no_warnings': True,
260
+ 'extract_flat': True,
261
+ 'cookiefile': COOKIES_FILE,
262
+ }
263
+
264
+ try:
265
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
266
+ return ydl.extract_info(url, download=False)
267
+ except Exception as e:
268
+ return None
269
+
270
+ def download_video(url):
271
+ try:
272
+ ydl_opts = {
273
+ 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', # Prefer MP4
274
+ 'outtmpl': str(OUTPUT_DIR / '%(title)s.%(ext)s'),
275
+ 'merge_output_format': 'mp4',
276
+
277
+ # Cookie and authentication settings
278
+ 'cookiefile': COOKIES_FILE,
279
+ 'cookiesfrombrowser': ('chrome',), # Also try to get cookies from Chrome
280
+
281
+ # Enhanced options
282
+ 'quiet': True,
283
+ 'no_warnings': True,
284
+ 'extract_flat': False,
285
+ 'socket_timeout': 30,
286
+ 'retries': 10,
287
+ 'fragment_retries': 10,
288
+ 'file_access_retries': 10,
289
+
290
+ # Headers
291
+ 'headers': {
292
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
293
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
294
+ 'Accept-Language': 'en-us,en;q=0.5',
295
+ 'Accept-Encoding': 'gzip,deflate',
296
+ 'DNT': '1',
297
+ 'Upgrade-Insecure-Requests': '1',
298
+ },
299
+
300
+ # Additional options
301
+ 'age_limit': None, # Try to bypass age restriction
302
+ 'geo_bypass': True,
303
+ 'geo_bypass_country': 'US',
304
+ }
305
+
306
+ # Progress tracking
307
+ progress_bar = st.progress(0)
308
+ status_text = st.empty()
309
+
310
+ def progress_hook(d):
311
+ if d['status'] == 'downloading':
312
+ try:
313
+ progress = d['downloaded_bytes'] / d['total_bytes']
314
+ progress_bar.progress(progress)
315
+ status_text.text(f"Downloading: {progress:.1%} | Speed: {d.get('speed_str', 'N/A')} | ETA: {d.get('eta_str', 'N/A')}")
316
+ except:
317
+ status_text.text(f"Downloading... Size: {d.get('total_bytes_str', 'unknown')} | Speed: {d.get('speed_str', 'N/A')}")
318
+ elif d['status'] == 'finished':
319
+ progress_bar.progress(1.0)
320
+ status_text.text("Processing downloaded files...")
321
+
322
+ ydl_opts['progress_hooks'] = [progress_hook]
323
+
324
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
325
+ info = ydl.extract_info(url, download=True)
326
+ filename = ydl.prepare_filename(info)
327
+ return filename, info
328
+
329
+ except yt_dlp.utils.DownloadError as e:
330
+ if "Sign in to confirm your age" in str(e):
331
+ raise Exception("This video requires age verification. Please ensure you're logged in through the cookies file.")
332
+ elif "The uploader has not made this video available in your country" in str(e):
333
+ raise Exception("This video is not available in your country. Try using a VPN.")
334
+ else:
335
+ raise Exception(f"Download error: {str(e)}")
336
+ except Exception as e:
337
+ raise Exception(f"An unexpected error occurred: {str(e)}")
338
+
339
+ # Check cookie status at startup
340
+ cookie_valid, cookie_message = validate_cookies()
341
+ if not cookie_valid:
342
+ st.warning(f"โš ๏ธ Cookie Issue: {cookie_message}")
343
+ else:
344
+ st.success("โœ… Cookies loaded successfully")
345
+
346
+ # Video URL input
347
+ video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...")
348
+
349
+ # Preview button
350
+ if video_url and st.button("Preview Video Info"):
351
+ with st.spinner("Fetching video information..."):
352
+ info = get_video_info(video_url)
353
+ if info:
354
+ st.write("**Video Information:**")
355
+ st.write(f"Title: {info.get('title', 'N/A')}")
356
+ st.write(f"Duration: {info.get('duration_string', 'N/A')}")
357
+ st.write(f"View Count: {info.get('view_count', 'N/A'):,}")
358
+ st.write(f"Upload Date: {info.get('upload_date', 'N/A')}")
359
+
360
+ # Download button
361
+ if st.button("Download Video"):
362
+ if not video_url:
363
+ st.warning("โš ๏ธ Please enter a valid YouTube URL.")
364
+ elif not cookie_valid:
365
+ st.error("โŒ Cannot proceed without valid cookies. Please check your cookie file.")
366
+ else:
367
+ try:
368
+ with st.spinner("Preparing download..."):
369
+ downloaded_file_path, video_info = download_video(video_url)
370
+
371
+ if downloaded_file_path and os.path.exists(downloaded_file_path):
372
+ # Add file info
373
+ file_size = os.path.getsize(downloaded_file_path)
374
+ st.info(f"""
375
+ **Download Complete!**
376
+ - File: {os.path.basename(downloaded_file_path)}
377
+ - Size: {file_size / (1024*1024):.1f} MB
378
+ - Format: {video_info.get('format', 'N/A')}
379
+ - Resolution: {video_info.get('resolution', 'N/A')}
380
+ """)
381
+
382
+ with open(downloaded_file_path, 'rb') as file:
383
+ st.download_button(
384
+ label="๐Ÿ’พ Download Video",
385
+ data=file,
386
+ file_name=os.path.basename(downloaded_file_path),
387
+ mime="video/mp4"
388
+ )
389
+ else:
390
+ st.error("โŒ Download failed. Please try again.")
391
+ except Exception as e:
392
+ st.error(f"โŒ {str(e)}")
393
+
394
+ # Enhanced help section
395
+ with st.expander("โ„น๏ธ Help & Cookie Information"):
396
+ st.markdown("""
397
+ **Cookie File Status:**
398
+ - Location: `youtube.com_cookies.txt`
399
+ - Valid: {'โœ…' if cookie_valid else 'โŒ'}
400
+ - Message: {cookie_message}
401
+
402
+ **Common Issues:**
403
+ 1. Age-Restricted Videos:
404
+ - Ensure you're logged into YouTube when exporting cookies
405
+ - The cookie file must contain valid authentication tokens
406
+
407
+ 2. Region-Restricted Content:
408
+ - The app attempts to bypass region restrictions automatically
409
+ - Consider using a VPN if download fails
410
+
411
+ 3. Cookie-Related Problems:
412
+ - Use a browser extension (e.g., "Get cookies.txt") to export cookies
413
+ - Make sure you're logged into YouTube before exporting
414
+ - Cookie file must be in Mozilla/Netscape format
415
+ """)