jpjp9292's picture
Update app.py
5119228 verified
raw
history blame
16.1 kB
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
# """)