"""YT Proxy — lightweight YouTube downloader for Mazinger Dubber.""" import os import tempfile import gradio as gr import yt_dlp def download_video(url: str) -> str: """Download a YouTube video and return the local file path.""" if not url or not url.strip(): raise gr.Error("Please provide a YouTube URL.") tmp_dir = tempfile.mkdtemp(prefix="yt_proxy_") output_template = os.path.join(tmp_dir, "%(title).50s.%(ext)s") ydl_opts = { "format": "bestvideo[height<=720][ext=mp4]+bestaudio[ext=m4a]/best[height<=720][ext=mp4]/best", "outtmpl": output_template, "merge_output_format": "mp4", "quiet": True, "no_warnings": True, } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=True) filename = ydl.prepare_filename(info) # yt-dlp may change extension after merge if not os.path.exists(filename): for f in os.listdir(tmp_dir): filename = os.path.join(tmp_dir, f) break return filename except Exception as e: raise gr.Error(f"Download failed: {e}") def download_audio(url: str) -> str: """Download audio only from a YouTube video.""" if not url or not url.strip(): raise gr.Error("Please provide a YouTube URL.") tmp_dir = tempfile.mkdtemp(prefix="yt_proxy_") output_template = os.path.join(tmp_dir, "%(title).50s.%(ext)s") ydl_opts = { "format": "bestaudio/best", "outtmpl": output_template, "postprocessors": [{ "key": "FFmpegExtractAudio", "preferredcodec": "mp3", "preferredquality": "192", }], "quiet": True, "no_warnings": True, } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(url, download=True) # Find the output file (may have .mp3 extension after postprocessing) for f in os.listdir(tmp_dir): return os.path.join(tmp_dir, f) raise gr.Error("No output file found.") except gr.Error: raise except Exception as e: raise gr.Error(f"Download failed: {e}") with gr.Blocks(title="YT Proxy") as demo: gr.Markdown("## YT Proxy\nDownload YouTube videos/audio. Used by Mazinger Dubber.") url_input = gr.Textbox(label="YouTube URL", placeholder="https://youtube.com/watch?v=...") with gr.Row(): video_btn = gr.Button("Download Video (MP4)") audio_btn = gr.Button("Download Audio (MP3)") output_file = gr.File(label="Downloaded file") video_btn.click(fn=download_video, inputs=url_input, outputs=output_file, api_name="download_video") audio_btn.click(fn=download_audio, inputs=url_input, outputs=output_file, api_name="download_audio") demo.queue().launch()