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()