RandomPersonRR's picture
Update app.py
6567ae9 verified
raw
history blame
4.36 kB
import os
import asyncio
import subprocess
import uuid
import glob
import shutil
import gradio as gr
accel = 'auto'
video_extra = ['-crf', '63', '-c:v', 'libx264', '-preset', 'ultrafast', '-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):
process = await asyncio.create_subprocess_exec(
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
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):
if use_mp3:
# Directly compress audio to MP3 with video untouched or skipped
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 # No video output in this case
# Non-MP3 path: split streams
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 WAV
await run_subprocess([
'ffmpeg', '-y', '-i', input_path, '-ac', '1', '-ar', '8000', audio_wav
])
# Compress with fdkaac
await run_subprocess([
'fdkaac', '-b', '1k', '-C', '-f', '2', '-G', '1', '-w', '8000',
'-o', audio_output, audio_wav
])
# Video compression
video_cmd = ['ffmpeg', '-y', '-hwaccel', accel, '-i', input_path, *video_extra, '-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', '-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() as demo:
gr.Markdown("## Low Quality Video Inator")
gr.Markdown("Upload a video or use a YouTube URL and adjust the options below.")
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(label="Downscale Video (144p)", value=False)
faster = gr.Checkbox(label="Faster Conversion", value=False)
with gr.Row():
use_mp3 = gr.Checkbox(label="Use MP3 (skips video compression)", value=False)
audio_only = gr.Checkbox(label="Only Audio", value=False)
convert_button = gr.Button("Convert")
gr.Markdown("### Preview")
video_preview = gr.Video()
gr.Markdown("### Download")
file_download = gr.File()
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()