jpjp9292 commited on
Commit
5d05675
·
verified ·
1 Parent(s): 8d8cc5c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +93 -568
app.py CHANGED
@@ -1,585 +1,110 @@
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
-
24
- # ydl_opts = {
25
- # 'format': 'bestvideo+bestaudio/best',
26
- # 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
27
- # 'merge_output_format': 'webm',
28
- # 'quiet': False, # Change to False to see more detailed error output
29
- # 'no_warnings': False,
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', # Ensure this file path is correct
33
- # 'socket_timeout': 30,
34
- # 'http_chunk_size': 10485760, # 10MB
35
- # 'retries': 10, # Increase retry attempts
36
- # 'headers': {
37
- # 'Accept-Language': 'en-US,en;q=0.9',
38
- # 'Accept-Encoding': 'gzip, deflate, br',
39
- # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
40
- # 'Upgrade-Insecure-Requests': '1',
41
- # }
42
- # }
43
-
44
- # # Progress placeholder
45
- # progress_bar = st.progress(0)
46
- # status_text = st.empty()
47
-
48
- # def progress_hook(d):
49
- # if d['status'] == 'downloading':
50
- # try:
51
- # progress = d['downloaded_bytes'] / d['total_bytes']
52
- # progress_bar.progress(progress)
53
- # status_text.text(f"Downloading: {progress:.1%}")
54
- # except:
55
- # status_text.text("Downloading... (size unknown)")
56
- # elif d['status'] == 'finished':
57
- # progress_bar.progress(1.0)
58
- # status_text.text("Processing...")
59
-
60
- # ydl_opts['progress_hooks'] = [progress_hook]
61
-
62
- # with yt_dlp.YoutubeDL(ydl_opts) as ydl:
63
- # info = ydl.extract_info(url, download=True)
64
- # filename = ydl.prepare_filename(info)
65
- # return filename
66
-
67
- # except Exception as e:
68
- # st.error(f"An error occurred: {str(e)}")
69
- # return None
70
-
71
- # # Download button
72
- # if st.button("Download"):
73
- # if video_url:
74
- # try:
75
- # with st.spinner("Preparing download..."):
76
- # downloaded_file_path = download_video(video_url)
77
-
78
- # if downloaded_file_path and os.path.exists(downloaded_file_path):
79
- # with open(downloaded_file_path, 'rb') as file:
80
- # st.download_button(
81
- # label="Click here to download",
82
- # data=file,
83
- # file_name=os.path.basename(downloaded_file_path),
84
- # mime="application/octet-stream"
85
- # )
86
- # st.success("✅ Download ready!")
87
- # else:
88
- # st.error("❌ Download failed. Please try again.")
89
- # except Exception as e:
90
- # st.error(f"❌ An error occurred: {str(e)}")
91
- # else:
92
- # st.warning("⚠️ Please enter a valid YouTube URL.")
93
-
94
- # # Help section
95
- # with st.expander("ℹ️ Help & Troubleshooting"):
96
- # st.markdown("""
97
- # **If you're experiencing download issues:**
98
-
99
- # 1. Cookie Authentication Method:
100
- # - Install a browser extension like "Get cookies.txt"
101
- # - Visit YouTube and ensure you're logged in
102
- # - Export cookies to 'youtube.com_cookies.txt'
103
- # - Place the file in the same directory as this app
104
-
105
- # 2. Alternative Solutions:
106
- # - Try different videos
107
- # - Check if the video is public/not age-restricted
108
- # - Try again later if YouTube is blocking requests
109
- # """)
110
-
111
-
112
- # import streamlit as st
113
- # import yt_dlp
114
- # import os
115
- # from pathlib import Path
116
- # import time
117
- # from datetime import datetime
118
- # import json
119
-
120
- # # Set page config
121
- # st.set_page_config(page_title="YouTube Video Downloader", page_icon="📺", layout="wide")
122
-
123
- # # Set the title of the app
124
- # st.title("YouTube Video Downloader 📺")
125
-
126
- # # Create output directory if it doesn't exist
127
- # output_dir = Path("downloads")
128
- # output_dir.mkdir(exist_ok=True)
129
-
130
- # # Authentication settings
131
- # AUTH_CONFIG = {
132
- # 'COOKIES_FILE': 'youtube.com_cookies.txt',
133
- # 'TOKEN_FILE': 'auth_token.json'
134
- # }
135
-
136
- # def load_auth_token():
137
- # try:
138
- # if os.path.exists(AUTH_CONFIG['TOKEN_FILE']):
139
- # with open(AUTH_CONFIG['TOKEN_FILE'], 'r') as f:
140
- # data = json.load(f)
141
- # if datetime.fromisoformat(data['expires']) > datetime.now():
142
- # return data['token']
143
- # except Exception:
144
- # pass
145
- # return None
146
-
147
- # def save_auth_token(token):
148
- # with open(AUTH_CONFIG['TOKEN_FILE'], 'w') as f:
149
- # json.dump({
150
- # 'token': token,
151
- # 'expires': (datetime.now().isoformat())
152
- # }, f)
153
-
154
- # def setup_ydl_options(has_cookies):
155
- # opts = {
156
- # 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
157
- # 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
158
- # 'merge_output_format': 'mp4',
159
- # 'quiet': True,
160
- # 'no_warnings': True,
161
- # 'extract_flat': False,
162
- # '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',
163
- # 'referer': 'https://www.youtube.com/',
164
- # 'http_chunk_size': 10485760,
165
- # 'retries': 3,
166
- # 'file_access_retries': 3,
167
- # 'fragment_retries': 3,
168
- # 'skip_unavailable_fragments': True,
169
- # 'abort_on_unavailable_fragment': False,
170
- # }
171
-
172
- # # Add cookies file if available
173
- # if has_cookies:
174
- # opts['cookiefile'] = AUTH_CONFIG['COOKIES_FILE']
175
-
176
- # # Add authentication token if available
177
- # token = load_auth_token()
178
- # if token:
179
- # opts['headers'] = {
180
- # 'Authorization': f'Bearer {token}'
181
- # }
182
-
183
- # return opts
184
-
185
- # def download_video(url, progress_callback):
186
- # max_retries = 3
187
- # retry_count = 0
188
-
189
- # while retry_count < max_retries:
190
- # try:
191
- # has_cookies = os.path.exists(AUTH_CONFIG['COOKIES_FILE'])
192
- # ydl_opts = setup_ydl_options(has_cookies)
193
-
194
- # # Add progress hooks
195
- # def progress_hook(d):
196
- # if d['status'] == 'downloading':
197
- # try:
198
- # progress = d['downloaded_bytes'] / d['total_bytes']
199
- # progress_callback(progress, f"Downloading: {progress:.1%}")
200
- # except:
201
- # progress_callback(0, "Downloading... (size unknown)")
202
- # elif d['status'] == 'finished':
203
- # progress_callback(1.0, "Processing...")
204
-
205
- # ydl_opts['progress_hooks'] = [progress_hook]
206
-
207
- # with yt_dlp.YoutubeDL(ydl_opts) as ydl:
208
- # info = ydl.extract_info(url, download=True)
209
- # filename = ydl.prepare_filename(info)
210
- # return filename, None
211
-
212
- # except yt_dlp.utils.ExtractorError as e:
213
- # if "Sign in to confirm you're not a bot" in str(e):
214
- # retry_count += 1
215
- # if retry_count < max_retries:
216
- # time.sleep(5) # Wait before retry
217
- # continue
218
- # return None, "Bot detection triggered. Please try again later or use authentication."
219
- # return None, f"Video extraction failed: {str(e)}"
220
-
221
- # except Exception as e:
222
- # return None, f"Download failed: {str(e)}"
223
-
224
- # return None, "Maximum retries reached. Please try again later."
225
-
226
- # # Main UI
227
- # col1, col2 = st.columns([2, 1])
228
-
229
- # with col1:
230
- # video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...")
231
-
232
- # if st.button("Download", type="primary"):
233
- # if video_url:
234
- # progress_bar = st.progress(0)
235
- # status_text = st.empty()
236
-
237
- # def update_progress(progress, status):
238
- # progress_bar.progress(progress)
239
- # status_text.text(status)
240
-
241
- # downloaded_file, error = download_video(video_url, update_progress)
242
-
243
- # if downloaded_file and os.path.exists(downloaded_file):
244
- # with open(downloaded_file, 'rb') as file:
245
- # st.download_button(
246
- # label="⬇️ Download Video",
247
- # data=file,
248
- # file_name=os.path.basename(downloaded_file),
249
- # mime="video/mp4"
250
- # )
251
- # st.success("✅ Download ready!")
252
- # else:
253
- # st.error(f"❌ {error}")
254
- # else:
255
- # st.warning("⚠️ Please enter a valid YouTube URL.")
256
-
257
- # with col2:
258
- # with st.expander("⚙️ Settings & Information"):
259
- # st.markdown("""
260
- # **Authentication Status:**
261
- # """)
262
-
263
- # if os.path.exists(AUTH_CONFIG['COOKIES_FILE']):
264
- # st.success("✅ Cookie authentication available")
265
- # else:
266
- # st.warning("""
267
- # ⚠️ No cookie authentication configured
268
-
269
- # To enable cookie authentication:
270
- # 1. Export cookies from your browser
271
- # 2. Save as 'youtube.com_cookies.txt' in the app directory
272
- # """)
273
-
274
- # st.markdown("""
275
- # **Download Options:**
276
- # - Videos are downloaded in best available quality
277
- # - Format: MP4 (when available)
278
- # - Automatic quality selection
279
- # """)
280
-
281
- # with st.expander("❓ Help & Troubleshooting"):
282
- # st.markdown("""
283
- # **Common Issues & Solutions:**
284
-
285
- # 1. **Bot Detection:**
286
- # - The app implements automatic retries
287
- # - Use cookie authentication for better success rate
288
- # - Wait a few minutes between attempts
289
-
290
- # 2. **Download Fails:**
291
- # - Verify the video is public
292
- # - Check your internet connection
293
- # - Try a different video
294
- # - Clear browser cache and cookies
295
-
296
- # 3. **Quality Issues:**
297
- # - The app automatically selects the best available quality
298
- # - Some videos may have quality restrictions
299
- # - Premium content may require authentication
300
-
301
- # **Need More Help?**
302
- # - Check if the video is available in your region
303
- # - Verify YouTube's terms of service
304
- # - Consider using cookie authentication
305
- # """)
306
-
307
-
308
  import streamlit as st
309
  import yt_dlp
310
  import os
311
  from pathlib import Path
312
- import time
313
- import random
314
- from datetime import datetime
315
- import json
316
- import requests
317
- import http.cookiejar as cookielib
318
 
319
  # Set page config
320
- st.set_page_config(page_title="YouTube Video Downloader", page_icon="📺", layout="wide")
321
- st.title("YouTube Video Downloader 📺")
322
 
323
- # Constants and Configurations
324
- class Config:
325
- OUTPUT_DIR = Path("downloads")
326
- COOKIES_FILE = 'youtube.com_cookies.txt'
327
- TOKEN_FILE = 'auth_token.json'
328
- MAX_RETRIES = 5
329
- RETRY_DELAYS = [3, 5, 10, 15, 30] # Progressive delays in seconds
330
-
331
- # 미리 정의된 User-Agent 목록
332
- USER_AGENTS = [
333
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
334
- 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2.1 Safari/605.1.15',
335
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0',
336
- 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
337
- 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Edge/120.0.0.0 Safari/537.36'
338
- ]
339
-
340
- HEADERS_POOL = [
341
- {
342
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
343
- 'Accept-Language': 'en-US,en;q=0.5',
344
- 'DNT': '1',
345
- 'Connection': 'keep-alive',
346
- 'Upgrade-Insecure-Requests': '1',
347
- },
348
- {
349
- 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
350
- 'Accept-Language': 'en-US,en;q=0.9',
351
- 'DNT': '1',
352
- 'Connection': 'keep-alive',
353
- }
354
- ]
355
-
356
- # Create output directory
357
- Config.OUTPUT_DIR.mkdir(exist_ok=True)
358
-
359
- # Session management
360
- class SessionManager:
361
- @staticmethod
362
- def create_cookie_jar():
363
- return cookielib.MozillaCookieJar(Config.COOKIES_FILE)
364
-
365
- @staticmethod
366
- def get_random_headers():
367
- headers = random.choice(Config.HEADERS_POOL).copy()
368
- headers['User-Agent'] = random.choice(Config.USER_AGENTS)
369
- return headers
370
-
371
- @staticmethod
372
- def get_session():
373
- session = requests.Session()
374
- if os.path.exists(Config.COOKIES_FILE):
375
- session.cookies = SessionManager.create_cookie_jar()
376
- session.cookies.load(ignore_discard=True, ignore_expires=True)
377
- session.headers.update(SessionManager.get_random_headers())
378
- return session
379
-
380
- def get_download_options(session_headers=None):
381
- """Enhanced download options with stronger anti-bot measures"""
382
- options = {
383
- 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best',
384
- 'outtmpl': str(Config.OUTPUT_DIR / '%(title)s.%(ext)s'),
385
- 'merge_output_format': 'mp4',
386
- 'quiet': True,
387
- 'no_warnings': True,
388
- 'extract_flat': False,
389
- 'nocheckcertificate': True,
390
- 'http_chunk_size': random.randint(10000000, 15000000),
391
- 'retries': Config.MAX_RETRIES,
392
- 'file_access_retries': 3,
393
- 'fragment_retries': 3,
394
- 'skip_unavailable_fragments': True,
395
- 'abort_on_unavailable_fragment': False,
396
- # 추가된 옵션들
397
- 'sleep_interval': random.randint(1, 3), # 요청 사이의 랜덤 대기 시간
398
- 'max_sleep_interval': 5,
399
- 'sleep_interval_requests': 1,
400
- 'socket_timeout': 30,
401
- 'geo_bypass': True, # 지역 제한 우회 시도
402
- 'geo_bypass_country': 'US', # 미국 서버 사용
403
- }
404
-
405
- if os.path.exists(Config.COOKIES_FILE):
406
- options['cookiefile'] = Config.COOKIES_FILE
407
- options['cookiesfrombrowser'] = ('chrome',) # 크롬 브라우저 쿠키 사용
408
-
409
- if session_headers:
410
- options['headers'] = session_headers
411
-
412
- return options
413
-
414
- def download_with_retry(url, progress_callback):
415
- """Enhanced download function with improved retry logic"""
416
- session = None
417
- for attempt in range(Config.MAX_RETRIES):
418
- try:
419
- if not session:
420
- session = SessionManager.get_session()
421
-
422
- # 매 시도마다 새로운 헤더 사용
423
- session.headers.update(SessionManager.get_random_headers())
424
- ydl_opts = get_download_options(session.headers)
425
-
426
- def progress_hook(d):
427
- if d['status'] == 'downloading':
428
- try:
429
- progress = d['downloaded_bytes'] / d['total_bytes']
430
- progress_callback(progress, f"Downloading: {progress:.1%}")
431
- except:
432
- progress_callback(-1, f"Downloading... (Attempt {attempt + 1}/{Config.MAX_RETRIES})")
433
- elif d['status'] == 'finished':
434
- progress_callback(1.0, "Processing...")
435
-
436
- ydl_opts['progress_hooks'] = [progress_hook]
437
-
438
- # 비디오 정보 먼저 확인
439
- with yt_dlp.YoutubeDL(ydl_opts) as ydl:
440
- try:
441
- info = ydl.extract_info(url, download=False)
442
- if not info:
443
- return None, "Failed to extract video information"
444
-
445
- # 실제 다운로드 진행
446
- info = ydl.extract_info(url, download=True)
447
- filename = ydl.prepare_filename(info)
448
- return filename, None
449
-
450
- except yt_dlp.utils.ExtractorError as e:
451
- if "Sign in to confirm you're not a bot" in str(e):
452
- # 봇 감지시 더 긴 대기 시간 적용
453
- delay = Config.RETRY_DELAYS[min(attempt, len(Config.RETRY_DELAYS)-1)] * 2
454
- progress_callback(-1, f"Bot detection... Waiting {delay}s (Attempt {attempt + 1}/{Config.MAX_RETRIES})")
455
- time.sleep(delay)
456
-
457
- # 세션 리셋
458
- session = None
459
- continue
460
-
461
- if "Video unavailable" in str(e):
462
- # 다른 지역에서 시도
463
- ydl_opts['geo_bypass_country'] = random.choice(['US', 'GB', 'JP', 'KR', 'DE'])
464
- continue
465
-
466
- raise e
467
-
468
- except Exception as e:
469
- error_msg = str(e)
470
- if attempt < Config.MAX_RETRIES - 1:
471
- delay = Config.RETRY_DELAYS[attempt]
472
- progress_callback(-1, f"Error: {error_msg}\nRetrying in {delay}s... ({attempt + 1}/{Config.MAX_RETRIES})")
473
- time.sleep(delay)
474
- continue
475
- return None, f"Download failed after {Config.MAX_RETRIES} attempts: {error_msg}"
476
-
477
- return None, "Maximum retries reached. Please try again later."
478
 
 
 
 
479
 
 
 
480
 
481
- # UI Components
482
- def render_main_ui():
483
- col1, col2 = st.columns([2, 1])
484
-
485
- with col1:
486
- video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...")
487
 
488
- if st.button("Download", type="primary"):
489
- if video_url:
490
- progress_bar = st.progress(0)
491
- status_text = st.empty()
492
-
493
- def update_progress(progress, status):
494
- if progress >= 0:
495
- progress_bar.progress(progress)
496
- status_text.text(status)
497
-
498
- downloaded_file, error = download_with_retry(video_url, update_progress)
499
-
500
- if downloaded_file and os.path.exists(downloaded_file):
501
- with open(downloaded_file, 'rb') as file:
502
- st.download_button(
503
- label="⬇️ Download Video",
504
- data=file,
505
- file_name=os.path.basename(downloaded_file),
506
- mime="video/mp4"
507
- )
508
- st.success("✅ Download completed successfully!")
509
- else:
510
- st.error(f"❌ {error}")
511
- else:
512
- st.warning("⚠️ Please enter a valid YouTube URL.")
513
-
514
- with col2:
515
- render_settings_panel()
516
 
517
- def render_settings_panel():
518
- with st.expander("⚙️ Settings & Information"):
519
- st.markdown("**Authentication Status:**")
520
 
521
- if os.path.exists(Config.COOKIES_FILE):
522
- st.success("✅ Cookie authentication active")
523
- if st.button("Remove Cookie File"):
524
  try:
525
- os.remove(Config.COOKIES_FILE)
526
- st.rerun()
527
- except Exception as e:
528
- st.error(f"Failed to remove cookie file: {str(e)}")
529
- else:
530
- st.warning("""
531
- ⚠️ No cookie authentication configured
532
-
533
- To enable cookie authentication:
534
- 1. Install a browser extension to export cookies
535
- 2. Export cookies from YouTube (while logged in)
536
- 3. Save as 'youtube.com_cookies.txt' in the app directory
537
- """)
538
-
539
- # Cookie file uploader
540
- uploaded_file = st.file_uploader("Upload Cookie File", type=['txt'])
541
- if uploaded_file is not None:
542
- try:
543
- with open(Config.COOKIES_FILE, 'wb') as f:
544
- f.write(uploaded_file.getvalue())
545
- st.success("✅ Cookie file uploaded successfully!")
546
- st.rerun()
547
- except Exception as e:
548
- st.error(f"Failed to save cookie file: {str(e)}")
549
-
550
- def render_help_section():
551
- with st.expander("❓ Help & Troubleshooting"):
552
- st.markdown("""
553
- **Common Issues & Solutions:**
554
-
555
- 1. **Bot Detection Issues:**
556
- - The app now implements multiple retry strategies
557
- - Uses random delays between attempts
558
- - Rotates User-Agents automatically
559
- - Uses cookie authentication when available
560
-
561
- 2. **Download Problems:**
562
- - Check if the video is public and available
563
- - Verify your internet connection
564
- - Try uploading a fresh cookie file
565
- - Clear browser cache and try again
566
-
567
- 3. **Quality Settings:**
568
- - Automatically selects best available quality
569
- - Prioritizes MP4 format when available
570
- - Handles premium content with proper authentication
571
 
572
- **Need More Help?**
573
- - Make sure you're using an up-to-date browser
574
- - Check if the video is available in your region
575
- - Consider using a VPN if region-blocked
576
- - Ensure your cookie file is recent and valid
577
- """)
578
-
579
- # Main App
580
- def main():
581
- render_main_ui()
582
- render_help_section()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
 
584
- if __name__ == "__main__":
585
- main()
 
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
 
24
+ ydl_opts = {
25
+ 'format': 'bestvideo+bestaudio/best',
26
+ 'outtmpl': str(output_dir / '%(title)s.%(ext)s'),
27
+ 'merge_output_format': 'webm',
28
+ 'quiet': False, # Change to False to see more detailed error output
29
+ 'no_warnings': False,
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', # Ensure this file path is correct
33
+ 'socket_timeout': 30,
34
+ 'http_chunk_size': 10485760, # 10MB
35
+ 'retries': 10, # Increase retry attempts
36
+ 'headers': {
37
+ 'Accept-Language': 'en-US,en;q=0.9',
38
+ 'Accept-Encoding': 'gzip, deflate, br',
39
+ 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
40
+ 'Upgrade-Insecure-Requests': '1',
41
+ }
42
+ }
 
 
 
 
 
 
 
 
 
43
 
44
+ # Progress placeholder
45
+ progress_bar = st.progress(0)
46
+ status_text = st.empty()
47
 
48
+ def progress_hook(d):
49
+ if d['status'] == 'downloading':
 
50
  try:
51
+ progress = d['downloaded_bytes'] / d['total_bytes']
52
+ progress_bar.progress(progress)
53
+ status_text.text(f"Downloading: {progress:.1%}")
54
+ except:
55
+ status_text.text("Downloading... (size unknown)")
56
+ elif d['status'] == 'finished':
57
+ progress_bar.progress(1.0)
58
+ status_text.text("Processing...")
59
+
60
+ ydl_opts['progress_hooks'] = [progress_hook]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
 
62
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
63
+ info = ydl.extract_info(url, download=True)
64
+ filename = ydl.prepare_filename(info)
65
+ return filename
66
+
67
+ except Exception as e:
68
+ st.error(f"An error occurred: {str(e)}")
69
+ return None
70
+
71
+ # Download button
72
+ if st.button("Download"):
73
+ if video_url:
74
+ try:
75
+ with st.spinner("Preparing download..."):
76
+ downloaded_file_path = download_video(video_url)
77
+
78
+ if downloaded_file_path and os.path.exists(downloaded_file_path):
79
+ with open(downloaded_file_path, 'rb') as file:
80
+ st.download_button(
81
+ label="Click here to download",
82
+ data=file,
83
+ file_name=os.path.basename(downloaded_file_path),
84
+ mime="application/octet-stream"
85
+ )
86
+ st.success("✅ Download ready!")
87
+ else:
88
+ st.error("❌ Download failed. Please try again.")
89
+ except Exception as e:
90
+ st.error(f"❌ An error occurred: {str(e)}")
91
+ else:
92
+ st.warning("⚠️ Please enter a valid YouTube URL.")
93
+
94
+ # Help section
95
+ with st.expander("ℹ️ Help & Troubleshooting"):
96
+ st.markdown("""
97
+ **If you're experiencing download issues:**
98
+
99
+ 1. Cookie Authentication Method:
100
+ - Install a browser extension like "Get cookies.txt"
101
+ - Visit YouTube and ensure you're logged in
102
+ - Export cookies to 'youtube.com_cookies.txt'
103
+ - Place the file in the same directory as this app
104
+
105
+ 2. Alternative Solutions:
106
+ - Try different videos
107
+ - Check if the video is public/not age-restricted
108
+ - Try again later if YouTube is blocking requests
109
+ """)
110