# 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', # # Add these options to mimic browser behavior # '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/', # 'cookiefile': 'youtube.com_cookies.txt', # 쿠키 파일 사용 # 'socket_timeout': 30, # 'http_chunk_size': 10485760, # 10MB # } # # 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 import json from http.cookiejar import MozillaCookieJar from datetime import datetime # 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 validate_cookies(): """쿠키 파일 유효성 검사""" if not os.path.exists(COOKIES_FILE): return False, "Cookie file not found" try: cookie_jar = MozillaCookieJar(COOKIES_FILE) cookie_jar.load() # Check for essential YouTube cookies essential_cookies = ['CONSENT', 'LOGIN_INFO', 'PREF'] found_cookies = [cookie.name for cookie in cookie_jar] missing_cookies = [cookie for cookie in essential_cookies if cookie not in found_cookies] if missing_cookies: return False, f"Missing essential cookies: {', '.join(missing_cookies)}" return True, "Cookies valid" except Exception as e: return False, f"Cookie validation error: {str(e)}" def get_video_info(url): """동영상 정보 미리보기 추출""" ydl_opts = { 'quiet': True, 'no_warnings': True, 'extract_flat': True, 'cookiefile': COOKIES_FILE, } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: return ydl.extract_info(url, download=False) except Exception as e: return None def download_video(url): try: ydl_opts = { 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', # Prefer MP4 'outtmpl': str(OUTPUT_DIR / '%(title)s.%(ext)s'), 'merge_output_format': 'mp4', # Cookie and authentication settings 'cookiefile': COOKIES_FILE, 'cookiesfrombrowser': ('chrome',), # Also try to get cookies from Chrome # Enhanced options 'quiet': True, 'no_warnings': True, 'extract_flat': False, 'socket_timeout': 30, 'retries': 10, 'fragment_retries': 10, 'file_access_retries': 10, # Headers 'headers': { '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', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en-us,en;q=0.5', 'Accept-Encoding': 'gzip,deflate', 'DNT': '1', 'Upgrade-Insecure-Requests': '1', }, # Additional options 'age_limit': None, # Try to bypass age restriction 'geo_bypass': True, 'geo_bypass_country': 'US', } # Progress tracking 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... Size: {d.get('total_bytes_str', 'unknown')} | 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] 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: if "Sign in to confirm your age" in str(e): raise Exception("This video requires age verification. Please ensure you're logged in through the cookies file.") elif "The uploader has not made this video available in your country" in str(e): raise Exception("This video is not available in your country. Try using a VPN.") else: raise Exception(f"Download error: {str(e)}") except Exception as e: raise Exception(f"An unexpected error occurred: {str(e)}") # Check cookie status at startup cookie_valid, cookie_message = validate_cookies() if not cookie_valid: st.warning(f"⚠️ Cookie Issue: {cookie_message}") else: st.success("✅ Cookies loaded successfully") # Video URL input video_url = st.text_input("Enter YouTube Video URL:", placeholder="https://www.youtube.com/watch?v=...") # Preview button if video_url and st.button("Preview Video Info"): with st.spinner("Fetching video information..."): info = get_video_info(video_url) if info: st.write("**Video Information:**") st.write(f"Title: {info.get('title', 'N/A')}") st.write(f"Duration: {info.get('duration_string', 'N/A')}") st.write(f"View Count: {info.get('view_count', 'N/A'):,}") st.write(f"Upload Date: {info.get('upload_date', 'N/A')}") # Download button 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. Please check your cookie file.") 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): # Add file info 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 - Format: {video_info.get('format', 'N/A')} - Resolution: {video_info.get('resolution', 'N/A')} """) 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)}") # Enhanced help section with st.expander("ℹ️ Help & Cookie Information"): st.markdown(""" **Cookie File Status:** - Location: `youtube.com_cookies.txt` - Valid: {'✅' if cookie_valid else '❌'} - Message: {cookie_message} **Common Issues:** 1. Age-Restricted Videos: - Ensure you're logged into YouTube when exporting cookies - The cookie file must contain valid authentication tokens 2. Region-Restricted Content: - The app attempts to bypass region restrictions automatically - Consider using a VPN if download fails 3. Cookie-Related Problems: - Use a browser extension (e.g., "Get cookies.txt") to export cookies - Make sure you're logged into YouTube before exporting - Cookie file must be in Mozilla/Netscape format """)