import gradio as gr import subprocess import os from pathlib import Path import tempfile import json # Comprehensive format support VIDEO_FORMATS = [ "mp4", "avi", "mkv", "mov", "wmv", "flv", "webm", "m4v", "mpg", "mpeg", "3gp", "ogv", "ts", "vob", "divx", "f4v", "asf", "rm", "rmvb" ] AUDIO_FORMATS = [ "mp3", "wav", "aac", "flac", "ogg", "m4a", "wma", "opus", "aiff", "alac", "ape", "ac3", "dts", "amr", "mka", "tta", "wv" ] IMAGE_FORMATS = [ "jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "webp", "svg", "ico", "heic", "heif", "raw", "cr2", "nef", "psd", "eps" ] DOCUMENT_FORMATS = [ "pdf", "txt", "doc", "docx", "rtf", "odt", "html", "md" ] ALL_FORMATS = sorted(set(VIDEO_FORMATS + AUDIO_FORMATS + IMAGE_FORMATS + DOCUMENT_FORMATS)) def get_file_info(file_path): """Get detailed information about the uploaded file.""" if not file_path: return "š *Upload a file to see details*" try: file_size = os.path.getsize(file_path) file_ext = Path(file_path).suffix.lower().replace(".", "") size_mb = file_size / (1024 * 1024) info = f""" š **File Information** - **Name:** {Path(file_path).name} - **Format:** {file_ext.upper()} - **Size:** {size_mb:.2f} MB """ # Try to get media info using ffprobe try: result = subprocess.run( ["ffprobe", "-v", "quiet", "-print_format", "json", "-show_format", "-show_streams", file_path], capture_output=True, text=True, timeout=10 ) if result.returncode == 0: data = json.loads(result.stdout) if "format" in data: duration = data["format"].get("duration", "N/A") if duration != "N/A": info += f"\n- **Duration:** {float(duration):.2f} seconds" if "streams" in data: for stream in data["streams"]: if stream["codec_type"] == "video": info += f"\n- **Video Codec:** {stream.get('codec_name', 'N/A')}" info += f"\n- **Resolution:** {stream.get('width', 'N/A')}x{stream.get('height', 'N/A')}" break for stream in data["streams"]: if stream["codec_type"] == "audio": info += f"\n- **Audio Codec:** {stream.get('codec_name', 'N/A')}" info += f"\n- **Sample Rate:** {stream.get('sample_rate', 'N/A')} Hz" break except Exception as e: info += f"\n\n*Could not retrieve detailed media info*" return info except Exception as e: return f"ā Error reading file: {str(e)}" def convert_media(input_file, output_format, quality="high", resolution=None): """ Convert media file to specified format. Args: input_file: Path to input file output_format: Desired output format quality: Quality setting (high, medium, low) resolution: Optional resolution for video (e.g., "1920x1080") """ if not input_file: raise gr.Error("ā Please upload a file first!") if not output_format: raise gr.Error("ā Please select an output format!") # Create temporary output file output_file = tempfile.NamedTemporaryFile( delete=False, suffix=f".{output_format}" ).name try: # Build ffmpeg command based on format and quality cmd = ["ffmpeg", "-i", input_file, "-y"] # Quality settings if quality == "high": if output_format in VIDEO_FORMATS: cmd.extend(["-crf", "18", "-preset", "slow"]) elif output_format in AUDIO_FORMATS: cmd.extend(["-b:a", "320k"]) elif quality == "medium": if output_format in VIDEO_FORMATS: cmd.extend(["-crf", "23", "-preset", "medium"]) elif output_format in AUDIO_FORMATS: cmd.extend(["-b:a", "192k"]) else: # low if output_format in VIDEO_FORMATS: cmd.extend(["-crf", "28", "-preset", "fast"]) elif output_format in AUDIO_FORMATS: cmd.extend(["-b:a", "128k"]) # Resolution settings for video if resolution and output_format in VIDEO_FORMATS: cmd.extend(["-s", resolution]) # Format-specific settings if output_format == "mp3": cmd.extend(["-codec:a", "libmp3lame"]) elif output_format == "aac": cmd.extend(["-codec:a", "aac"]) elif output_format == "flac": cmd.extend(["-codec:a", "flac"]) elif output_format == "opus": cmd.extend(["-codec:a", "libopus"]) elif output_format == "webm": cmd.extend(["-codec:v", "libvpx-vp9", "-codec:a", "libopus"]) elif output_format == "mp4": cmd.extend(["-codec:v", "libx264", "-codec:a", "aac"]) elif output_format == "wav": cmd.extend(["-codec:a", "pcm_s16le"]) elif output_format in IMAGE_FORMATS: # For image conversion, just specify format pass cmd.append(output_file) # Execute conversion result = subprocess.run( cmd, capture_output=True, text=True, timeout=300 # 5 minute timeout ) if result.returncode != 0: raise Exception(f"Conversion failed: {result.stderr}") # Verify output file exists and has content if not os.path.exists(output_file) or os.path.getsize(output_file) == 0: raise Exception("Conversion produced empty file") output_size = os.path.getsize(output_file) / (1024 * 1024) return output_file, f"ā **Conversion Successful!**\n\nConverted to **{output_format.upper()}** format with **{quality}** quality.\n\nš¦ Output size: **{output_size:.2f} MB**" except subprocess.TimeoutExpired: if os.path.exists(output_file): os.unlink(output_file) raise gr.Error("ā±ļø Conversion timed out. File may be too large or complex.") except Exception as e: if os.path.exists(output_file): os.unlink(output_file) raise gr.Error(f"ā Conversion failed: {str(e)}") def update_format_suggestions(input_file): """Update suggested formats based on input file type.""" if not input_file: return gr.Dropdown(choices=ALL_FORMATS, value="mp4") file_ext = Path(input_file).suffix.lower().replace(".", "") # Suggest related formats if file_ext in VIDEO_FORMATS: suggested = ["mp4", "webm", "avi", "mkv", "mov", "gif"] elif file_ext in AUDIO_FORMATS: suggested = ["mp3", "wav", "aac", "flac", "ogg", "m4a"] elif file_ext in IMAGE_FORMATS: suggested = ["jpg", "png", "webp", "gif", "bmp", "tiff"] else: suggested = ["mp4", "mp3", "jpg", "png"] # Add all formats but prioritize suggested ones all_choices = suggested + [f for f in ALL_FORMATS if f not in suggested] return gr.Dropdown(choices=all_choices, value=suggested[0]) # Custom CSS for better UI/UX custom_css = """ .main-container { max-width: 1400px; margin: 0 auto; } .header-section { text-align: center; padding: 2rem 1rem; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 12px; margin-bottom: 2rem; color: white; } .header-section h1 { font-size: 2.5rem; margin-bottom: 0.5rem; font-weight: 700; } .header-section p { font-size: 1.1rem; opacity: 0.95; } .conversion-panel { background: rgba(255, 255, 255, 0.05); border-radius: 12px; padding: 1.5rem; margin-bottom: 1rem; } .info-box { background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); border-radius: 8px; padding: 1rem; margin: 1rem 0; } .status-success { color: #10b981; font-weight: 600; } .status-error { color: #ef4444; font-weight: 600; } footer { text-align: center; padding: 2rem; margin-top: 2rem; opacity: 0.8; } .format-badge { display: inline-block; padding: 0.25rem 0.75rem; background: #667eea; color: white; border-radius: 20px; font-size: 0.875rem; margin: 0.25rem; } .feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 1rem; margin: 1rem 0; } .feature-item { background: rgba(102, 126, 234, 0.1); padding: 1rem; border-radius: 8px; text-align: center; } """ # Build the Gradio interface with gr.Blocks(fill_height=True) as demo: gr.HTML("""
Convert any media file to any format ⢠Support for 60+ formats ⢠Professional quality
⨠Built with anycoder