YT-DL / main.py
Hanzo03's picture
Add extractor arguments for YouTube in download_media function; create packages.txt for dependencies
2f555aa
Raw
History Blame Contribute Delete
5.74 kB
import os
import uuid
import logging
from pathlib import Path
import subprocess
import gradio as gr
import yt_dlp
# --- Logging Setup ---
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
logging.getLogger("urllib3").setLevel(logging.WARNING)
logging.getLogger("httpx").setLevel(logging.WARNING)
logger = logging.getLogger(__name__)
# --- Load YouTube cookies from HF Secrets ---
if "YOUTUBE_COOKIES" in os.environ:
with open("/tmp/cookies.txt", "w", encoding="utf-8") as f:
f.write(os.environ["YOUTUBE_COOKIES"])
def download_media(url: str, format_choice: str, progress=gr.Progress()):
if not url:
raise gr.Error("Please enter a valid YouTube URL.")
logger.info(f"New download request. URL: {url}, Format: {format_choice}")
# Unique session folder
session_id = str(uuid.uuid4())
out_dir = Path("/tmp/downloads") / session_id
out_dir.mkdir(parents=True, exist_ok=True)
logger.info(f"Created temporary directory: {out_dir}")
def progress_hook(d):
if d["status"] == "downloading":
total = d.get("total_bytes") or d.get("total_bytes_estimate", 0)
downloaded = d.get("downloaded_bytes", 0)
if total > 0:
progress(downloaded / total, desc="Downloading...")
elif d["status"] == "finished":
progress(1.0, desc="Processing with ffmpeg...")
try:
# --- Step 1: Extract Video Info ---
info_opts = {
"quiet": False,
"verbose": True,
"no_warnings": False,
"cookiefile": "/tmp/cookies.txt"
if os.path.exists("/tmp/cookies.txt")
else None,
"extractor_retries": 10,
"skip_download": True,
"noplaylist": True,
"extractor_args": {
"youtube": {
"player_skip": ["webpage", "configs"],
}
},
}
with yt_dlp.YoutubeDL(info_opts) as ydl:
logger.info("Extracting video information...")
info_dict = ydl.extract_info(
url,
download=False,
process=False
)
formats = info_dict.get("formats", [])
logger.info("----- AVAILABLE FORMATS -----")
for f in formats:
logger.info(
f"ID: {f.get('format_id')} | "
f"EXT: {f.get('ext')} | "
f"RES: {f.get('resolution')} | "
f"VCODEC: {f.get('vcodec')} | "
f"ACODEC: {f.get('acodec')}"
)
logger.info("-----------------------------")
# --- Step 2: Download Options ---
download_opts = {
"outtmpl": str(out_dir / "%(title)s.%(ext)s"),
"progress_hooks": [progress_hook],
"quiet": True,
"no_warnings": True,
"cookiefile": "/tmp/cookies.txt"
if os.path.exists("/tmp/cookies.txt")
else None,
"extractor_retries": 5,
"extractor_args": {
"youtube": {
"player_skip": ["webpage", "configs"],
}
},
}
# --- Audio Download ---
if format_choice == "Audio (MP3)":
download_opts.update({
"format": "bestaudio/best",
"postprocessors": [{
"key": "FFmpegExtractAudio",
"preferredcodec": "mp3",
"preferredquality": "192",
}],
})
# --- Video Download ---
else:
download_opts.update({
"format": "bestvideo+bestaudio/best",
"merge_output_format": "mp4",
})
logger.info(
f"Downloading using selector: {download_opts['format']}"
)
with yt_dlp.YoutubeDL(download_opts) as ydl:
ydl.download([url])
logger.info("Download completed successfully.")
downloaded_files = list(out_dir.glob("*"))
if downloaded_files:
logger.info(f"Downloaded file: {downloaded_files[0]}")
return str(downloaded_files[0])
raise gr.Error("Download failed: No file generated.")
except Exception as e:
logger.error(
f"yt-dlp exception: {str(e)}",
exc_info=True
)
raise gr.Error(
f"Download failed.\n\nError:\n{str(e)}"
)
# --- Theme ---
custom_theme = gr.themes.Monochrome(
font=[
gr.themes.GoogleFont("Inter"),
"ui-sans-serif",
"system-ui",
"sans-serif",
]
)
# --- UI ---
with gr.Blocks(
title="YouTube Downloader",
theme=custom_theme
) as app:
gr.Markdown("# YouTube Cloud Downloader")
gr.Markdown(
"Download YouTube videos or audio directly."
)
url_input = gr.Textbox(
label="YouTube URL",
placeholder="https://www.youtube.com/watch?v=..."
)
format_input = gr.Radio(
choices=[
"Video (MP4)",
"Audio (MP3)"
],
label="Format",
value="Video (MP4)"
)
download_btn = gr.Button(
"Download",
variant="primary",
size="lg"
)
output_file = gr.File(
label="Downloaded File"
)
download_btn.click(
fn=download_media,
inputs=[url_input, format_input],
outputs=output_file
)
# --- Launch ---
if __name__ == "__main__":
app.launch(
server_name="0.0.0.0",
server_port=7860
)