|
|
|
import os |
|
import subprocess |
|
import uuid |
|
import glob |
|
import shutil |
|
import gradio as gr |
|
|
|
|
|
accel = 'auto' |
|
extra = '-crf 63 -c:v libx264' |
|
|
|
|
|
UPLOAD_FOLDER = 'uploads' |
|
CONVERTED_FOLDER = 'converted' |
|
os.makedirs(UPLOAD_FOLDER, exist_ok=True) |
|
os.makedirs(CONVERTED_FOLDER, exist_ok=True) |
|
|
|
|
|
def configure_audio(cmd_list, use_mp3): |
|
if use_mp3: |
|
cmd_list.extend(['-c:a', 'libmp3lame', '-b:a', '8k', '-ar', '24k', '-ac', '1']) |
|
else: |
|
cmd_list.extend(['-c:a', 'aac', '-b:a', '1k', '-ar', '8k', '-ac', '1']) |
|
|
|
def convert_video(use_youtube, youtube_url, video_file, downscale, faster, use_mp3, audio_only): |
|
""" |
|
Converts a video either from a YouTube URL or an uploaded file. |
|
Returns a tuple (preview_file, download_file) with the output path. |
|
""" |
|
|
|
if audio_only: |
|
output_filename = f"{uuid.uuid4()}.mp3" if use_mp3 else f"{uuid.uuid4()}.aac" |
|
else: |
|
output_filename = f"{uuid.uuid4()}.mp4" |
|
output_path = os.path.join(CONVERTED_FOLDER, output_filename) |
|
|
|
if use_youtube: |
|
if not youtube_url: |
|
return "Error: YouTube URL is required.", None |
|
|
|
|
|
quality = 'worstaudio' if audio_only and downscale else ( |
|
'worstvideo+worstaudio' if downscale else 'b') |
|
|
|
yt_uuid = str(uuid.uuid4()) |
|
yt_input_filename = yt_uuid + ".%(ext)s" |
|
yt_input_path = os.path.join(UPLOAD_FOLDER, yt_input_filename) |
|
yt_dlp_cmd = ['yt-dlp', '-o', yt_input_path, '-f', quality, youtube_url] |
|
try: |
|
subprocess.run(yt_dlp_cmd, check=True) |
|
except subprocess.CalledProcessError as e: |
|
return f"An error occurred during YouTube download: {e}", None |
|
|
|
|
|
pattern = os.path.join(UPLOAD_FOLDER, yt_uuid + ".*") |
|
downloaded_files = glob.glob(pattern) |
|
if not downloaded_files: |
|
return "Failed to download YouTube video.", None |
|
input_path = downloaded_files[0] |
|
else: |
|
|
|
if not video_file: |
|
return "Error: No video file provided.", None |
|
|
|
if os.path.exists(video_file): |
|
ext = os.path.splitext(video_file)[1] |
|
input_filename = f"{uuid.uuid4()}{ext}" |
|
input_path = os.path.join(UPLOAD_FOLDER, input_filename) |
|
|
|
shutil.copy2(video_file, input_path) |
|
else: |
|
|
|
input_path = video_file |
|
|
|
|
|
ffmpeg_cmd = ['ffmpeg', '-hwaccel', accel, '-y', '-i', input_path] + extra.split() |
|
|
|
if downscale: |
|
ffmpeg_cmd.extend(['-vf', 'scale=144:-2']) |
|
if faster: |
|
ffmpeg_cmd.extend(['-preset', 'ultrafast']) |
|
|
|
if audio_only: |
|
ffmpeg_cmd.extend(['-vn']) |
|
configure_audio(ffmpeg_cmd, use_mp3) |
|
else: |
|
configure_audio(ffmpeg_cmd, use_mp3) |
|
|
|
ffmpeg_cmd.append(output_path) |
|
|
|
try: |
|
subprocess.run(ffmpeg_cmd, check=True) |
|
except subprocess.CalledProcessError as e: |
|
return f"An error occurred during conversion: {e}", None |
|
|
|
|
|
return output_path, output_path |
|
|
|
|
|
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 (almost never works)", value=False) |
|
youtube_url = gr.Textbox(label="YouTube URL", placeholder="Enter YouTube URL here") |
|
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 (more pixelated)", value=False) |
|
with gr.Row(): |
|
use_mp3 = gr.Checkbox(label="Use MP3 (video audio compression)", value=False) |
|
audio_only = gr.Checkbox(label="Only Audio (no video)", value=False) |
|
|
|
convert_button = gr.Button("Convert Video") |
|
|
|
gr.Markdown("### Preview Converted Video") |
|
video_preview = gr.Video(label="Converted Video") |
|
gr.Markdown("### Download Converted Video") |
|
file_download = gr.File(label="Download Video") |
|
|
|
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() |