import os import asyncio import subprocess import uuid import glob import shutil import gradio as gr # Make sure fdkaac is executable (only needed once, but harmless) os.system("chmod +x fdkaac") # Locate binaries and check existence ffmpeg_path = shutil.which("ffmpeg") yt_dlp_path = shutil.which("yt-dlp") fdkaac_path = os.path.abspath("./fdkaac") print("[DEBUG] Detected Paths:") print("FFmpeg:", ffmpeg_path) print("yt-dlp:", yt_dlp_path) print("fdkaac:", fdkaac_path) if not ffmpeg_path: raise FileNotFoundError("FFmpeg not found in PATH.") if not yt_dlp_path: raise FileNotFoundError("yt-dlp not found in PATH.") if not os.path.isfile(fdkaac_path): raise FileNotFoundError("fdkaac binary not found in current directory.") 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): print(f"\n[DEBUG] Running command:\n{' '.join(cmd)}\n") process = await asyncio.create_subprocess_exec( *cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, env=os.environ.copy() # Inherit full environment for safety ) 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: output_path = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp3") ffmpeg_cmd = [ ffmpeg_path, '-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 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") await run_subprocess([ ffmpeg_path, '-y', '-i', input_path, '-ac', '1', '-ar', '8000', audio_wav ]) await run_subprocess([ fdkaac_path, '-b', '1k', '-C', '-f', '2', '-G', '1', '-w', '8000', '-o', audio_output, audio_wav ]) video_cmd = [ ffmpeg_path, '-y', '-hwaccel', accel, '-i', input_path, *video_base_opts, '-an', video_output ] if faster: video_cmd.extend(['-preset', 'ultrafast']) await run_subprocess(video_cmd) return audio_output, video_output async def process_conversion(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only): try: if use_youtube: yt_uuid = str(uuid.uuid4()) yt_out = os.path.join(UPLOAD_FOLDER, yt_uuid + ".%(ext)s") yt_cmd = [yt_dlp_path, '-o', yt_out, '-f', '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)[1] input_path = os.path.join(UPLOAD_FOLDER, f"{uuid.uuid4()}{ext}") shutil.copy2(video_file, input_path) audio_out, video_out = await convert_video_task(input_path, downscale, faster, use_mp3) if audio_only: return audio_out, audio_out return video_out or audio_out, video_out or audio_out except Exception as e: return str(e), None def convert_video(*args): return asyncio.run(process_conversion(*args)) # Gradio Interface with gr.Blocks(theme=gr.themes.Default(primary_hue="rose")) as demo: gr.Markdown(""" # 🎥 **Low Quality Video Inator** Welcome to your personal bad-video-making machine. Upload a video or paste a YouTube URL below, then tweak the settings to ruin your video (on purpose). """) 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()