# import streamlit as st # import yt_dlp # import os # from pathlib import Path # # Set page config # st.set_page_config(page_title="YouTube Video Downloader", page_icon="πŸ“Ί") # # Set the title of the app # st.title("YouTube Video Downloader πŸ“Ί") # # Create output directory if it doesn't exist # output_dir = Path("downloads") # output_dir.mkdir(exist_ok=True) # # Input field for YouTube video URL # video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...") # # Function to download video # def download_video(url): # try: # ydl_opts = { # 'format': 'bestvideo+bestaudio/best', # 'outtmpl': str(output_dir / '%(title)s.%(ext)s'), # 'merge_output_format': 'webm', # 'quiet': False, # Change to False to see more detailed error output # 'no_warnings': False, # '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', # 'referer': 'https://www.youtube.com/', # 'cookiefile': 'youtube.com_cookies.txt', # Ensure this file path is correct # 'socket_timeout': 30, # 'http_chunk_size': 10485760, # 10MB # 'retries': 10, # Increase retry attempts # 'headers': { # 'Accept-Language': 'en-US,en;q=0.9', # 'Accept-Encoding': 'gzip, deflate, br', # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', # 'Upgrade-Insecure-Requests': '1', # } # } # # Progress placeholder # progress_bar = st.progress(0) # status_text = st.empty() # def progress_hook(d): # if d['status'] == 'downloading': # try: # progress = d['downloaded_bytes'] / d['total_bytes'] # progress_bar.progress(progress) # status_text.text(f"Downloading: {progress:.1%}") # except: # status_text.text("Downloading... (size unknown)") # elif d['status'] == 'finished': # progress_bar.progress(1.0) # status_text.text("Processing...") # ydl_opts['progress_hooks'] = [progress_hook] # with yt_dlp.YoutubeDL(ydl_opts) as ydl: # info = ydl.extract_info(url, download=True) # filename = ydl.prepare_filename(info) # return filename # except Exception as e: # st.error(f"An error occurred: {str(e)}") # return None # # Download button # if st.button("Download"): # if video_url: # try: # with st.spinner("Preparing download..."): # downloaded_file_path = download_video(video_url) # if downloaded_file_path and os.path.exists(downloaded_file_path): # with open(downloaded_file_path, 'rb') as file: # st.download_button( # label="Click here to download", # data=file, # file_name=os.path.basename(downloaded_file_path), # mime="application/octet-stream" # ) # st.success("βœ… Download ready!") # else: # st.error("❌ Download failed. Please try again.") # except Exception as e: # st.error(f"❌ An error occurred: {str(e)}") # else: # st.warning("⚠️ Please enter a valid YouTube URL.") # # Help section # with st.expander("ℹ️ Help & Troubleshooting"): # st.markdown(""" # **If you're experiencing download issues:** # 1. Cookie Authentication Method: # - Install a browser extension like "Get cookies.txt" # - Visit YouTube and ensure you're logged in # - Export cookies to 'youtube.com_cookies.txt' # - Place the file in the same directory as this app # 2. Alternative Solutions: # - Try different videos # - Check if the video is public/not age-restricted # - Try again later if YouTube is blocking requests # """) import streamlit as st import yt_dlp import os from pathlib import Path # Set page config st.set_page_config(page_title="YouTube Video Downloader", page_icon="πŸ“Ί") # Set the title of the app st.title("YouTube Video Downloader πŸ“Ί") # Create output directory if it doesn't exist output_dir = Path("downloads") output_dir.mkdir(exist_ok=True) # Check if cookies file exists COOKIES_FILE = 'youtube.com_cookies.txt' has_cookies = os.path.exists(COOKIES_FILE) if has_cookies: st.success("βœ… Cookie file detected") else: st.warning("⚠️ No cookie file found - Some videos might be restricted") # Input field for YouTube video URL video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...") def download_video(url): try: ydl_opts = { 'format': 'bestvideo+bestaudio/best', 'outtmpl': str(output_dir / '%(title)s.%(ext)s'), 'merge_output_format': 'webm', 'quiet': True, 'no_warnings': True, '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', 'referer': 'https://www.youtube.com/', 'http_chunk_size': 10485760 } # Add cookies file if available if has_cookies: ydl_opts['cookiefile'] = COOKIES_FILE # Progress placeholder progress_bar = st.progress(0) status_text = st.empty() def progress_hook(d): if d['status'] == 'downloading': try: progress = d['downloaded_bytes'] / d['total_bytes'] progress_bar.progress(progress) status_text.text(f"Downloading: {progress:.1%}") except: status_text.text("Downloading... (size unknown)") elif d['status'] == 'finished': progress_bar.progress(1.0) status_text.text("Processing...") ydl_opts['progress_hooks'] = [progress_hook] with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=True) filename = ydl.prepare_filename(info) return filename except Exception as e: st.error(f"An error occurred: {str(e)}") return None # Download button if st.button("Download"): if video_url: try: with st.spinner("Preparing download..."): downloaded_file_path = download_video(video_url) if downloaded_file_path and os.path.exists(downloaded_file_path): with open(downloaded_file_path, 'rb') as file: st.download_button( label="Click here to download", data=file, file_name=os.path.basename(downloaded_file_path), mime="application/octet-stream" ) st.success("βœ… Download ready!") else: st.error("❌ Download failed. Please try again.") except Exception as e: st.error(f"❌ An error occurred: {str(e)}") else: st.warning("⚠️ Please enter a valid YouTube URL.") # Help section with st.expander("ℹ️ Help & Information"): st.markdown(""" **About Cookie Authentication:** - This app uses cookie authentication to bypass YouTube's bot detection - Cookies help the app behave like a logged-in browser - No personal data is stored or transmitted **If downloads fail:** 1. Check if the video is public 2. Verify the URL is correct 3. Try a different video 4. Try again later if YouTube is blocking requests """) # import streamlit as st # import yt_dlp # import os # from pathlib import Path # from http.cookiejar import MozillaCookieJar # import random # import time # # Constants # COOKIES_FILE = 'youtube.com_cookies.txt' # OUTPUT_DIR = Path("downloads") # # Set page config # st.set_page_config(page_title="YouTube Video Downloader", page_icon="πŸ“Ί") # st.title("YouTube Video Downloader πŸ“Ί") # # Create output directory if it doesn't exist # OUTPUT_DIR.mkdir(exist_ok=True) # def get_random_user_agent(): # """랜덀 User-Agent 생성""" # user_agents = [ # 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', # 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0', # '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', # 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0' # ] # return random.choice(user_agents) # def validate_cookies(): # """μΏ ν‚€ 파일 μœ νš¨μ„± 검사""" # if not os.path.exists(COOKIES_FILE): # return False, "Cookie file not found" # try: # cookie_jar = MozillaCookieJar(COOKIES_FILE) # cookie_jar.load() # return True, "Cookies loaded successfully" # except Exception as e: # return False, f"Cookie error: {str(e)}" # def download_with_retry(url, ydl_opts, max_retries=3, delay=5): # """μž¬μ‹œλ„ 둜직이 ν¬ν•¨λœ λ‹€μš΄λ‘œλ“œ ν•¨μˆ˜""" # last_error = None # for attempt in range(max_retries): # try: # # 맀 μ‹œλ„λ§ˆλ‹€ μƒˆλ‘œμš΄ User-Agent μ‚¬μš© # ydl_opts['headers']['User-Agent'] = get_random_user_agent() # with yt_dlp.YoutubeDL(ydl_opts) as ydl: # info = ydl.extract_info(url, download=True) # filename = ydl.prepare_filename(info) # return filename, info # except yt_dlp.utils.DownloadError as e: # last_error = e # if "Sign in to confirm you're not a bot" in str(e): # if attempt < max_retries - 1: # st.warning(f"Bot detection encountered. Retrying in {delay} seconds... (Attempt {attempt + 1}/{max_retries})") # time.sleep(delay) # delay *= 2 # μ§€μˆ˜ λ°±μ˜€ν”„ # continue # elif "HTTP Error 429" in str(e): # if attempt < max_retries - 1: # st.warning(f"Rate limit detected. Waiting {delay} seconds... (Attempt {attempt + 1}/{max_retries})") # time.sleep(delay * 2) # 레이트 λ¦¬λ°‹μ˜ 경우 더 κΈ΄ λŒ€κΈ° μ‹œκ°„ # continue # except Exception as e: # last_error = e # if attempt < max_retries - 1: # st.warning(f"Error occurred. Retrying... (Attempt {attempt + 1}/{max_retries})") # time.sleep(delay) # continue # # λͺ¨λ“  μž¬μ‹œλ„ μ‹€νŒ¨ ν›„ # raise last_error or Exception("Download failed after all retries") # def download_video(url): # try: # ydl_opts = { # 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', # 'outtmpl': str(OUTPUT_DIR / '%(title)s.%(ext)s'), # 'merge_output_format': 'mp4', # # μΏ ν‚€ μ„€μ • # 'cookiefile': COOKIES_FILE, # # ν–₯μƒλœ μ˜΅μ…˜ # 'quiet': True, # 'no_warnings': True, # 'extract_flat': False, # 'socket_timeout': 30, # 'retries': 10, # 'fragment_retries': 10, # # ν–₯μƒλœ 헀더 # 'headers': { # 'User-Agent': get_random_user_agent(), # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', # 'Accept-Language': 'en-US,en;q=0.5', # 'Accept-Encoding': 'gzip, deflate, br', # 'Connection': 'keep-alive', # 'Upgrade-Insecure-Requests': '1', # 'Sec-Fetch-Dest': 'document', # 'Sec-Fetch-Mode': 'navigate', # 'Sec-Fetch-Site': 'none', # 'Sec-Fetch-User': '?1', # 'DNT': '1', # 'Sec-GPC': '1', # 'Pragma': 'no-cache', # 'Cache-Control': 'no-cache', # }, # # μΆ”κ°€ μ˜΅μ…˜ # 'age_limit': None, # 'geo_bypass': True, # 'geo_bypass_country': 'US', # 'sleep_interval': 2, # 'max_sleep_interval': 5, # } # # 진행 상황 ν‘œμ‹œ # progress_bar = st.progress(0) # status_text = st.empty() # def progress_hook(d): # if d['status'] == 'downloading': # try: # progress = d['downloaded_bytes'] / d['total_bytes'] # progress_bar.progress(progress) # status_text.text(f"Downloading: {progress:.1%} | Speed: {d.get('speed_str', 'N/A')} | ETA: {d.get('eta_str', 'N/A')}") # except: # status_text.text(f"Downloading... Speed: {d.get('speed_str', 'N/A')}") # elif d['status'] == 'finished': # progress_bar.progress(1.0) # status_text.text("Processing downloaded files...") # ydl_opts['progress_hooks'] = [progress_hook] # return download_with_retry(url, ydl_opts) # except Exception as e: # raise Exception(f"Download error: {str(e)}") # # μΏ ν‚€ μƒνƒœ 확인 # cookie_valid, cookie_message = validate_cookies() # if not cookie_valid: # st.warning(f"⚠️ Cookie Issue: {cookie_message}") # else: # st.success("βœ… Cookies loaded successfully") # # λΉ„λ””μ˜€ URL μž…λ ₯ # video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...") # # λ‹€μš΄λ‘œλ“œ λ²„νŠΌ # if st.button("Download Video"): # if not video_url: # st.warning("⚠️ Please enter a valid YouTube URL.") # elif not cookie_valid: # st.error("❌ Cannot proceed without valid cookies.") # else: # try: # with st.spinner("Preparing download..."): # downloaded_file_path, video_info = download_video(video_url) # if downloaded_file_path and os.path.exists(downloaded_file_path): # file_size = os.path.getsize(downloaded_file_path) # st.info(f""" # **Download Complete!** # - File: {os.path.basename(downloaded_file_path)} # - Size: {file_size / (1024*1024):.1f} MB # """) # with open(downloaded_file_path, 'rb') as file: # st.download_button( # label="πŸ’Ύ Download Video", # data=file, # file_name=os.path.basename(downloaded_file_path), # mime="video/mp4" # ) # else: # st.error("❌ Download failed. Please try again.") # except Exception as e: # st.error(f"❌ {str(e)}") # # Help μ„Ήμ…˜ # with st.expander("ℹ️ Troubleshooting Guide"): # st.markdown(f""" # **Current Status:** # - Cookie File: {'βœ… Found' if os.path.exists(COOKIES_FILE) else '❌ Not Found'} # - Cookie Validity: {'βœ… Valid' if cookie_valid else '❌ Invalid'} # **Common Issues:** # 1. Bot Detection: # - The app will automatically retry with different settings # - Each retry uses a random User-Agent and headers # 2. Cookie Problems: # - Current cookie file: {COOKIES_FILE} # - Make sure the cookie file is up to date # - Export fresh cookies when issues persist # 3. Download Fails: # - Try again after a few minutes # - Check if the video is available in your region # - Verify that the video is public # """)