import os import asyncio import subprocess import uuid import glob import shutil import gradio as gr os.system("chmod +x ./fdkaac") # Ensure fdkaac is executable accel = 'auto' video_base_opts = ['-crf', '63', '-c:v', 'libx264', '-tune', 'zerolatency'] UPLOAD_FOLDER = 'uploads' CONVERTED_FOLDER = 'converted' os.makedirs(UPLOAD_FOLDER, exist_ok=True) os.makedirs(CONVERTED_FOLDER, exist_ok=True) async def run_subprocess(cmd, use_fdkaac=False): env = os.environ.copy() if use_fdkaac: # Add your fdkaac lib path here if needed: env["LD_LIBRARY_PATH"] = os.path.abspath("./") + ":" + env.get("LD_LIBRARY_PATH", "") print(f"[DEBUG] Running command:\n{' '.join(cmd)}\n") process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, env=env ) stdout, stderr = await process.communicate() if process.returncode != 0: print(f"[ERROR] Command failed:\n{stderr.decode()}\n") raise subprocess.CalledProcessError(process.returncode, cmd, stderr.decode()) print(f"[DEBUG] Command succeeded:\n{stdout.decode()}\n") return stdout.decode(), stderr.decode() async def convert_video_task(input_path, downscale, faster, use_mp3): if use_mp3: # MP3 audio only, no splitting output_path = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp3") ffmpeg_cmd = [ 'ffmpeg', '-y', '-i', input_path, '-vn', '-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1', output_path ] await run_subprocess(ffmpeg_cmd) return output_path, None # Paths for audio and video audio_wav = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.wav") audio_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.m4a") video_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4") # Extract mono 8kHz WAV audio await run_subprocess([ 'ffmpeg', '-y', '-i', input_path, '-ac', '1', '-ar', '8000', audio_wav ]) # Compress WAV to AAC with fdkaac await run_subprocess([ './fdkaac', '-b', '1k', '-C', '-f', '2', '-G', '1', '-w', '8000', '-o', audio_output, audio_wav ], use_fdkaac=True) # Compress video with extreme low quality, no audio video_cmd = [ 'ffmpeg', '-y', '-hwaccel', accel, '-i', input_path, *video_base_opts, '-an', video_output ] if faster: video_cmd.extend(['-preset', 'ultrafast']) await run_subprocess(video_cmd) # Merge video + audio into final mp4 container merged_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4") await run_subprocess([ 'ffmpeg', '-y', '-i', video_output, '-i', audio_output, '-c', 'copy', merged_output ]) # Cleanup intermediate files for f in [audio_wav, audio_output, video_output]: try: os.remove(f) except FileNotFoundError: pass return audio_output, merged_output async def process_conversion(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only): try: if use_youtube: if not youtube_url: return "Error: YouTube URL required.", None yt_uuid = str(uuid.uuid4()) yt_out = os.path.join(UPLOAD_FOLDER, yt_uuid + ".%(ext)s") yt_cmd = ['yt-dlp', '-o', yt_out, '-f', "\"best[protocol*=m3u8][format_id*=tv]/best[format_id*=tv]/b\"", youtube_url] await run_subprocess(yt_cmd) pattern = os.path.join(UPLOAD_FOLDER, yt_uuid + ".*") files = glob.glob(pattern) if not files: return "Download failed.", None input_path = files[0] else: if not video_file: return "No video provided.", None ext = os.path.splitext(video_file.name)[1] input_path = os.path.join(UPLOAD_FOLDER, f"{uuid.uuid4()}{ext}") shutil.copy2(video_file.name, input_path) audio_out, video_out = await convert_video_task(input_path, downscale, faster, use_mp3) if audio_only: return audio_out, audio_out else: return video_out, video_out except Exception as e: return f"Error: {str(e)}", None def convert_video(*args): return asyncio.run(process_conversion(*args)) with gr.Blocks(theme=gr.themes.Default(primary_hue="rose")) as demo: gr.Markdown(""" # 🎥 **Low Quality Video Inator** Upload a video or paste a YouTube URL below then play around with the settings to see which one you like the best. Note: YouTube never works """) with gr.Group(): with gr.Row(): use_youtube = gr.Checkbox(label="🔗 Use YouTube URL (experimental)", value=False) youtube_url = gr.Textbox(label="YouTube URL", placeholder="Paste YouTube URL here") video_file = gr.File(label="📁 Upload Video File") gr.Markdown("### ⚙️ **Conversion Settings**") with gr.Group(): with gr.Row(): downscale = gr.Checkbox(label="Downscale Video to 144p", value=False) faster = gr.Checkbox(label="Faster Video Compression", value=False) with gr.Row(): use_mp3 = gr.Checkbox(label="Use MP3 Audio", value=False) audio_only = gr.Checkbox(label="Audio Only", value=False) convert_button = gr.Button("Convert Now", variant="primary") gr.Markdown("### **Conversion Preview**") video_preview = gr.Video(label="Preview Output (if applicable)") gr.Markdown("### **Download Your Masterpiece**") file_download = gr.File(label="Download Result") convert_button.click( convert_video, inputs=[use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only], outputs=[video_preview, file_download] ) demo.launch()