File size: 1,624 Bytes
4e32180
 
 
 
 
 
 
 
 
 
00151c0
 
 
 
 
 
 
 
 
4e32180
 
 
 
00151c0
4e32180
00151c0
 
 
4e32180
 
 
 
 
 
 
00151c0
4e32180
 
 
 
 
00151c0
4e32180
 
 
 
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
import subprocess
import tempfile
import os
import gradio as gr


def compress_video(video_path, crf=28, max_width=1280):
    if video_path is None:
        return None

    base = os.path.splitext(os.path.basename(video_path))[0]
    out_path = os.path.join(tempfile.gettempdir(), f"compressed_{base}.mp4")

    # Probe for an audio stream; GIFs and some clips have none.
    probe = subprocess.run(
        ["ffprobe", "-v", "error", "-select_streams", "a", "-show_entries", "stream=index", "-of", "csv=p=0", video_path],
        capture_output=True, text=True,
    )
    has_audio = bool(probe.stdout.strip())

    cmd = [
        "ffmpeg", "-y", "-i", video_path,
        "-vf", f"scale='min({max_width},iw)':-2",
        "-c:v", "libx264", "-crf", str(crf), "-preset", "slower", "-pix_fmt", "yuv420p",
    ]
    cmd += ["-c:a", "aac", "-b:a", "128k"] if has_audio else ["-an"]
    cmd += ["-movflags", "+faststart", out_path]

    subprocess.run(cmd, check=True, capture_output=True)
    return out_path


demo = gr.Interface(
    fn=compress_video,
    inputs=[
        gr.File(label="Input video or GIF", file_types=["video", ".gif"], type="filepath"),
        gr.Slider(18, 35, value=28, step=1, label="CRF (higher = smaller file, lower quality)"),
        gr.Slider(480, 1920, value=1280, step=10, label="Max width (px)"),
    ],
    outputs=gr.Video(label="Compressed video"),
    title="Video Compressor (ffmpeg)",
    description="Server-side H.264 re-encode to shrink file size. Accepts video files and GIFs. Runs entirely on the HF Space, no local processing.",
)

if __name__ == "__main__":
    demo.launch()