File size: 5,895 Bytes
d83b57c 6567ae9 d83b57c 76e6c8b d83b57c 7be90a2 3328834 d83b57c f699201 d83b57c 2297f9b 7be90a2 2297f9b 6567ae9 ded38ea 2297f9b 6567ae9 ded38ea 6567ae9 ded38ea 6567ae9 c841491 6567ae9 7be90a2 6567ae9 f699201 7be90a2 f699201 6567ae9 f699201 6567ae9 7be90a2 6567ae9 7be90a2 6567ae9 7be90a2 6567ae9 7be90a2 6567ae9 7be90a2 ded38ea 2297f9b 6567ae9 7be90a2 f699201 7be90a2 f699201 d83b57c 6567ae9 c841491 7be90a2 c841491 6567ae9 1dc23c5 6567ae9 7be90a2 6567ae9 54cf621 6567ae9 7be90a2 6567ae9 7be90a2 6567ae9 7be90a2 6567ae9 7be90a2 d83b57c 6567ae9 d83b57c 55f9dd1 074254a 54cf621 55f9dd1 6567ae9 d83b57c 6567ae9 d83b57c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
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() |