Spaces:
Sleeping
Sleeping
File size: 6,437 Bytes
d83b57c 6567ae9 d83b57c 76e6c8b d83b57c f4a8b85 3328834 d83b57c 6eeced8 d83b57c 2297f9b 7be90a2 6567ae9 ded38ea 2297f9b 6567ae9 c841491 4280e2f 6567ae9 6eeced8 f4a8b85 6eeced8 7be90a2 f4a8b85 f699201 6eeced8 f4a8b85 6eeced8 f4a8b85 6eeced8 6567ae9 6eeced8 6567ae9 6eeced8 6567ae9 6eeced8 3ab04ba 6eeced8 7f4c045 6eeced8 7f4c045 6eeced8 7f4c045 6eeced8 c841491 f4a8b85 6eeced8 7be90a2 6eeced8 7be90a2 6eeced8 c841491 6eeced8 de205c3 6eeced8 de205c3 6eeced8 de205c3 6eeced8 de205c3 4280e2f 6eeced8 de205c3 d83b57c 6eeced8 55f9dd1 6eeced8 55f9dd1 6eeced8 6567ae9 d83b57c de205c3 6eeced8 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 161 162 163 164 165 166 167 168 |
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:
env["LD_LIBRARY_PATH"] = os.path.abspath("./") + ":" + env.get("LD_LIBRARY_PATH", "")
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:
raise subprocess.CalledProcessError(process.returncode, cmd, stderr.decode())
return stdout.decode(), stderr.decode()
async def convert_video_task(input_path, downscale, faster, use_mp3, audio_only, custom_bitrate, video_bitrate, progress):
if use_mp3:
progress.update(1, desc="Converting audio to MP3...")
output_audio = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp3")
cmd = [
'ffmpeg', '-y', '-i', input_path, '-vn',
'-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1',
output_audio
]
await run_subprocess(cmd)
if audio_only:
return output_audio, None
# embed into video
progress.update(1, desc="Making the video quality lower...")
output_video = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
cmd = ['ffmpeg', '-y', '-hwaccel', accel, '-i', input_path]
if custom_bitrate:
cmd += ['-b:v', f"{int(video_bitrate)}k"]
else:
cmd += video_base_opts
if faster:
cmd += ['-preset', 'ultrafast']
cmd += ['-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24000', '-ac', '1', output_video]
await run_subprocess(cmd)
return None, output_video
# split
progress.update(1, desc="Splitting Audio and Video...")
audio_wav = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.wav")
await run_subprocess(['ffmpeg','-y','-i',input_path,'-ac','1','-ar','8000',audio_wav])
# AAC encode
progress.update(1, desc="Converting audio to AAC which is lower quality...")
audio_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.m4a")
await run_subprocess([ './fdkaac','-b','1k','-C','-f','2','-G','1','-w','8000','-o',audio_output,audio_wav ], use_fdkaac=True)
# video
progress.update(1, desc="Making the video quality lower...")
video_output = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
cmd = ['ffmpeg','-y','-hwaccel',accel,'-i',input_path]
if downscale:
cmd += ['-vf','scale=-2:144']
if custom_bitrate:
cmd += ['-b:v',f"{int(video_bitrate)}k"]
else:
cmd += video_base_opts
if faster:
cmd += ['-preset','ultrafast']
cmd += ['-an',video_output]
await run_subprocess(cmd)
if audio_only:
return audio_output, None
# merge
progress.update(1, desc="Mixing audio and video together...")
merged = os.path.join(CONVERTED_FOLDER, f"{uuid.uuid4()}.mp4")
await run_subprocess(['ffmpeg','-y','-i',video_output,'-i',audio_output,'-c','copy',merged])
# cleanup
for f in (audio_wav, audio_output, video_output):
try: os.remove(f)
except: pass
return None, merged
async def process_conversion(use_youtube, youtube_url, video_file, downscale, faster,
use_mp3, audio_only, custom_bitrate, video_bitrate,
progress=gr.Progress()):
with progress.tqdm(total=5) as pbar:
# Step 1: fetch
if use_youtube:
pbar.update(1, desc="Downloading video...")
yt_uuid = uuid.uuid4().hex
out = os.path.join(UPLOAD_FOLDER, yt_uuid + ".%(ext)s")
await run_subprocess(['yt-dlp','-o',out,'-f','b',youtube_url])
files = glob.glob(os.path.join(UPLOAD_FOLDER, yt_uuid + ".*"))
if not files: return "Download failed.", None
input_path = files[0]
else:
pbar.update(1, desc="Preparing input video...")
fname = video_file.name
ext = os.path.splitext(fname)[1]
input_path = os.path.join(UPLOAD_FOLDER, uuid.uuid4().hex + ext)
shutil.copy2(fname, input_path)
# Step 2–5: convert
if use_mp3:
pbar.update(1, desc="Converting audio to MP3...")
else:
pbar.update(1, desc="Converting audio to AAC which is lower quality...")
audio_out, video_out = await convert_video_task(
input_path, downscale, faster, use_mp3, audio_only,
custom_bitrate, video_bitrate, pbar
)
# final update
pbar.update(1, desc="Finalizing...")
if audio_only:
return audio_out, audio_out
return video_out, video_out
# Build UI
with gr.Blocks(theme=gr.themes.Default(primary_hue="rose")) as demo:
gr.Markdown("# Low Quality Video Inator")
with gr.Row():
use_youtube = gr.Checkbox(label="Use YouTube URL", value=False)
youtube_url = gr.Textbox(label="YouTube URL")
video_file = gr.File(label="Upload Video")
with gr.Row():
downscale = gr.Checkbox("Downscale Video to 144p", value=False)
faster = gr.Checkbox("Faster Compression", value=False)
with gr.Row():
use_mp3 = gr.Checkbox("Use MP3 Audio", value=False)
audio_only = gr.Checkbox("Audio Only", value=False)
with gr.Row():
custom_bitrate = gr.Checkbox("Custom Video Bitrate", value=False)
video_bitrate = gr.Number(label="Bitrate (kbps)", visible=False)
custom_bitrate.change(lambda x: gr.update(visible=x), custom_bitrate, video_bitrate)
convert_button = gr.Button("Convert Now", variant="primary")
video_preview = gr.Video()
file_download = gr.File()
convert_button.click(
process_conversion,
inputs=[use_youtube, youtube_url, video_file,
downscale, faster, use_mp3, audio_only,
custom_bitrate, video_bitrate],
outputs=[video_preview, file_download]
)
demo.launch() |