Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| import os | |
| from utils import download_media_from_url, convert_media | |
| def handle_url_input(url): | |
| """Downloads media from a URL and returns the path.""" | |
| if not url: | |
| raise gr.Error("Please enter a valid URL") | |
| try: | |
| gr.Info("Attempting download... This may take a few seconds.") | |
| file_path = download_media_from_url(url) | |
| return file_path, file_path # Return to state and video preview | |
| except Exception as e: | |
| # Friendly error message for common issues | |
| error_msg = str(e) | |
| if "403" in error_msg or "Forbidden" in error_msg: | |
| raise gr.Error("Access denied (403). The site might be blocking automated downloads from this server IP.") | |
| elif "Video unavailable" in error_msg: | |
| raise gr.Error("Video not found. It might be private or deleted.") | |
| else: | |
| raise gr.Error(f"Download failed: {error_msg}") | |
| def handle_file_upload(file): | |
| """Handles direct file upload.""" | |
| if not file: | |
| return None, None | |
| return file, file | |
| def process_conversion(input_path, target_format): | |
| """Orchestrates the conversion process.""" | |
| if not input_path: | |
| raise gr.Error("No media file selected. Please upload a file or enter a URL.") | |
| gr.Info(f"Converting to {target_format}...") | |
| try: | |
| output_path, is_audio = convert_media(input_path, target_format) | |
| # Return logic: (Video_Component, Audio_Component, File_Download_Component) | |
| if is_audio: | |
| return { | |
| video_output: gr.Video(visible=False), | |
| audio_output: gr.Audio(value=output_path, visible=True), | |
| file_output: gr.File(value=output_path, visible=True) | |
| } | |
| else: | |
| return { | |
| video_output: gr.Video(value=output_path, visible=True), | |
| audio_output: gr.Audio(visible=False), | |
| file_output: gr.File(value=output_path, visible=True) | |
| } | |
| except Exception as e: | |
| raise gr.Error(f"Conversion failed: {str(e)}") | |
| # --- Gradio 6 Application Definition --- | |
| with gr.Blocks( | |
| title="Universal Media Converter", | |
| theme=gr.themes.Soft(), | |
| footer_links=[ | |
| {"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}, | |
| {"label": "yt-dlp Documentation", "url": "https://github.com/yt-dlp/yt-dlp"} | |
| ] | |
| ) as demo: | |
| # State to hold the path of the currently loaded file | |
| current_file_state = gr.State() | |
| with gr.Row(): | |
| gr.Markdown( | |
| """ | |
| # 🔄 Universal Media Converter | |
| [Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder) | |
| Robust downloader and converter for Twitter/X, YouTube, TikTok, and more. | |
| """ | |
| ) | |
| with gr.Row(): | |
| with gr.Column(scale=1): | |
| with gr.Tabs(): | |
| with gr.Tab("🔗 From URL"): | |
| gr.Markdown("Paste a link from X (Twitter), YouTube, or TikTok.") | |
| url_input = gr.Textbox( | |
| label="Paste URL", | |
| placeholder="https://x.com/user/status/...", | |
| show_label=False | |
| ) | |
| url_btn = gr.Button("Fetch Media", variant="primary") | |
| with gr.Tab("📁 Upload File"): | |
| upload_input = gr.File( | |
| label="Drop Video File", | |
| file_types=["video", "audio"], | |
| type="filepath" | |
| ) | |
| # Preview of the input | |
| input_preview = gr.Video(label="Input Preview", interactive=False) | |
| with gr.Column(scale=1): | |
| gr.Markdown("### Conversion Settings") | |
| target_format = gr.Dropdown( | |
| choices=[ | |
| "MP4", "WEBM", "GIF", "AVI", "MOV", "MKV", # Video | |
| "MP3", "WAV", "FLAC", "AAC", "OGG" # Audio | |
| ], | |
| value="MP4", | |
| label="Target Format", | |
| info="Select output format" | |
| ) | |
| convert_btn = gr.Button("🚀 Convert Now", variant="secondary", size="lg") | |
| # Output Area | |
| gr.Markdown("### Result") | |
| video_output = gr.Video(label="Video Output", visible=False) | |
| audio_output = gr.Audio(label="Audio Output", visible=False) | |
| file_output = gr.File(label="Download Converted File") | |
| # --- Event Listeners --- | |
| url_btn.click( | |
| fn=handle_url_input, | |
| inputs=[url_input], | |
| outputs=[current_file_state, input_preview], | |
| api_visibility="public" | |
| ) | |
| upload_input.upload( | |
| fn=handle_file_upload, | |
| inputs=[upload_input], | |
| outputs=[current_file_state, input_preview], | |
| api_visibility="public" | |
| ) | |
| convert_btn.click( | |
| fn=process_conversion, | |
| inputs=[current_file_state, target_format], | |
| outputs=[video_output, audio_output, file_output], | |
| api_visibility="public" | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch() |