Spaces:
Running
Running
| 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() | |