import gradio as gr from yt_dlp import YoutubeDL import os import tempfile import shutil from pathlib import Path def download_for_browser(url, mode='audio', quality='high'): if not url: return None, "Please enter a valid URL" # Create temporary directory that persists until file is served temp_dir = Path(tempfile.mkdtemp()) try: # Configure download options opts = { 'format': 'bestaudio/best' if mode == 'audio' else 'bestvideo+bestaudio/best', 'outtmpl': str(temp_dir / '%(title)s.%(ext)s'), 'restrictfilenames': True, 'windowsfilenames': True, 'quiet': True, 'no_warnings': True } # Add format-specific options if mode == 'audio': opts.update({ 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '320' if quality == 'high' else '192', }], 'prefer_ffmpeg': True, 'keepvideo': False }) else: opts.update({ 'format': 'bestvideo+bestaudio/best' if quality == 'high' else 'best[height<=720]', 'merge_output_format': 'mp4' }) # Download file with YoutubeDL(opts) as ydl: info = ydl.extract_info(url, download=True) # Find downloaded file files = list(temp_dir.glob('*')) if not files: return None, "Download failed - no files found" download_file = files[0] if not download_file.exists(): return None, f"File not found after download: {download_file.name}" # Return file while it exists in temp directory return str(download_file), f"Successfully converted: {download_file.name}" except Exception as e: if temp_dir.exists(): shutil.rmtree(temp_dir) return None, f"Error during download: {str(e)}" def create_browser_ui(): with gr.Blocks(title="YouTube Downloader", theme=gr.themes.Soft()) as demo: gr.Markdown("## YouTube Downloader") with gr.Row(): url_input = gr.Textbox( label="YouTube URL", placeholder="https://youtube.com/watch?v=...", scale=2 ) with gr.Row(): with gr.Column(scale=1): mode_input = gr.Radio( choices=["audio", "video"], value="audio", label="Format" ) quality_input = gr.Radio( choices=["high", "medium"], value="high", label="Quality" ) download_button = gr.Button("Convert", variant="primary") with gr.Column(scale=2): status_text = gr.Textbox(label="Converting Status", interactive=False) output_file = gr.File(label="Download to your device ...") download_button.click( fn=download_for_browser, inputs=[url_input, mode_input, quality_input], outputs=[output_file, status_text] ) return demo demo = create_browser_ui() demo.launch( share=False, debug=True, show_error=True )