File size: 5,052 Bytes
d83b57c
 
 
 
76e6c8b
d83b57c
 
79a696c
d83b57c
 
 
 
1dc23c5
d83b57c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c841491
d83b57c
 
 
 
76e6c8b
 
c841491
1dc23c5
 
 
 
 
 
 
 
 
 
 
 
 
76e6c8b
d83b57c
 
 
76e6c8b
 
 
 
 
 
 
 
c841491
 
 
adf3f37
c841491
ff1aced
c841491
 
 
 
 
 
 
e0d1f98
c841491
d83b57c
 
c841491
d83b57c
 
c841491
 
d83b57c
c841491
1dc23c5
 
 
 
d83b57c
 
 
1dc23c5
d83b57c
 
 
 
 
c1e1ec2
d83b57c
 
 
c841491
 
 
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
import os
import subprocess
import uuid
import glob
import shutil
import gradio as gr

os.system("chmod +x ffmpeg")
# Set default acceleration and extra encoding options.
accel = 'auto'
extra = '-crf 63 -c:v libx264'  # default extra settings

# Fixed upload and conversion folders.
UPLOAD_FOLDER = 'uploads'
CONVERTED_FOLDER = 'converted'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(CONVERTED_FOLDER, exist_ok=True)

# Helper function to configure audio options.
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.
    """
    # Determine output filename based on whether only audio is desired.
    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

    # Handle optional downscale first
    if downscale and not audio_only:
        downscaled_path = os.path.join(UPLOAD_FOLDER, f"downscaled_{uuid.uuid4()}.mp4")
        downscale_cmd = ['ffmpeg', '-hwaccel', accel, '-y', '-i', input_path,
                         '-vf', 'scale=144:-2', '-c:v', 'libx264', '-preset', 'ultrafast', '-crf', '40',
                         '-c:a', 'copy', downscaled_path]
        try:
            subprocess.run(downscale_cmd, check=True)
        except subprocess.CalledProcessError as e:
            return f"An error occurred during downscaling: {e}", None
        input_path = downscaled_path  # Use this for next pass

    # Now do the final encode
    ffmpeg_cmd = ['./ffmpeg', '-hwaccel', accel, '-y', '-i', input_path] + extra.split()

    if faster:
        ffmpeg_cmd.extend(['-preset', 'ultrafast'])

    if audio_only:
        ffmpeg_cmd.extend(['-vn'])
    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

# Create the 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 (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()