Spaces:
Runtime error
Runtime error
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 | |
# 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 | |
# """) |