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=...") | |
# Format selection | |
format_option = st.selectbox( | |
"Select Format:", | |
options=[ | |
"Best Quality (Video + Audio)", | |
"Audio Only (Best Quality)", | |
"720p", | |
"480p", | |
"360p" | |
] | |
) | |
def get_format_options(selection): | |
if selection == "Best Quality (Video + Audio)": | |
return { | |
'format': 'best', # Changed from bestvideo+bestaudio to best | |
'merge_output_format': 'mp4' | |
} | |
elif selection == "Audio Only (Best Quality)": | |
return { | |
'format': 'bestaudio/best', | |
'postprocessors': [{ | |
'key': 'FFmpegExtractAudio', | |
'preferredcodec': 'mp3', | |
}] | |
} | |
elif selection == "720p": | |
return { | |
'format': 'best[height<=720]', # Simplified format selection | |
'merge_output_format': 'mp4' | |
} | |
elif selection == "480p": | |
return { | |
'format': 'best[height<=480]', | |
'merge_output_format': 'mp4' | |
} | |
elif selection == "360p": | |
return { | |
'format': 'best[height<=360]', | |
'merge_output_format': 'mp4' | |
} | |
def download_video(url, format_selection): | |
try: | |
format_opts = get_format_options(format_selection) | |
ydl_opts = { | |
'outtmpl': str(output_dir / '%(title)s.%(ext)s'), | |
'quiet': True, | |
'no_warnings': True, | |
# Enhanced options to bypass restrictions | |
'nocheckcertificate': True, | |
'ignoreerrors': True, | |
'no_color': True, | |
'noprogress': 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', # 10MB chunks for better reliability | |
} | |
# Update options with format-specific settings | |
ydl_opts.update(format_opts) | |
# 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=False) | |
filename = ydl.prepare_filename(info) | |
ydl.download([url]) | |
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, format_option) | |
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.") | |
# Add help section | |
with st.expander("ℹ️ Help"): | |
st.markdown(""" | |
**How to use:** | |
1. Paste a YouTube video URL in the input field | |
2. Select your preferred format | |
3. Click the Download button | |
4. Wait for the download to complete | |
5. Click the download button that appears | |
**Note:** Some videos might be restricted due to YouTube's policies. | |
""") |