How to run FFmpeg in a cloud sandbox
Install Ubuntu's ffmpeg package in a microVM, upload the media, run ffmpeg or ffprobe, and download the output file.
On Runtime you pay for the CPU an encode burns, and nothing for the minutes around it. A 2 vCPU, 4 GiB sandbox with both CPUs encoding costs $0.08 an hour, so ten minutes of full-load x264 work costs about $0.013, and the same sandbox waiting for the next upload costs $0.03125 an hour (pricing). Each job runs in its own Firecracker microVM, which matters for media: a malformed file uploaded by a stranger is parsed on a machine that holds nothing else. Ubuntu 24.04 shipped FFmpeg 6.1.1 on 25 September 2026.
Transcode an upload to web-ready MP4
TypeScriptimport { writeFile } from "node:fs/promises";import { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ diskMiB: 8192, timeoutSeconds: 3600 });await sbx.exec("sudo apt-get update -qq && sudo apt-get install -y -qq ffmpeg", { check: true, timeoutMs: 600_000,});await sbx.files.upload("./talk.mov", "/workspace/in.mov");await sbx.exec( [ "ffmpeg", "-hide_banner", "-y", "-i", "in.mov", "-c:v", "libx264", "-preset", "medium", "-crf", "23", "-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "128k", "-movflags", "+faststart", "out.mp4", ], { check: true, timeoutMs: 3_000_000, onStderr: (text) => process.stderr.write(text) },);await sbx.exec(["ffmpeg", "-y", "-ss", "5", "-i", "out.mp4", "-frames:v", "1", "poster.jpg"], { check: true,});await writeFile("out.mp4", await sbx.files.read("/workspace/out.mp4"));await writeFile("poster.jpg", await sbx.files.read("/workspace/poster.jpg"));Pythonimport sysfrom withruntime import Sandboxwith Sandbox.create(disk_mib=8192, timeout_seconds=3600) as sbx: sbx.exec("sudo apt-get update -qq && sudo apt-get install -y -qq ffmpeg", check=True, timeout_ms=600_000) sbx.files.upload("talk.mov", "/workspace/in.mov") sbx.exec(["ffmpeg", "-hide_banner", "-y", "-i", "in.mov", "-c:v", "libx264", "-preset", "medium", "-crf", "23", "-pix_fmt", "yuv420p", "-c:a", "aac", "-b:a", "128k", "-movflags", "+faststart", "out.mp4"], check=True, timeout_ms=3_000_000, on_stderr=sys.stderr.write) sbx.exec(["ffmpeg", "-y", "-ss", "5", "-i", "out.mp4", "-frames:v", "1", "poster.jpg"], check=True) sbx.files.download("/workspace/out.mp4", "out.mp4") sbx.files.download("/workspace/poster.jpg", "poster.jpg")- The command is an array, so it runs without a shell: a file name a user chose cannot inject shell syntax.
- FFmpeg writes progress to stderr, which
onStderrstreams as it happens. +faststartmoves the MP4's index to the front of the file, per FFmpeg's format documentation, so a browser can start playing before the download ends.- Uploads and downloads move in parallel 1 MiB chunks, each checked by SHA-256, and resume after a dropped connection. There is no file size limit beyond the sandbox's disk.
Read a file's streams as JSON
ffprobe comes with the package. Its JSON writer gives an agent the codec,
duration, resolution and bitrate without parsing text:
TypeScriptimport { Sandbox } from "withruntime";await using sbx = await Sandbox.create({ image: "ffmpeg" });await sbx.files.upload("./clip.mkv", "/workspace/clip.mkv");const probe = await sbx.exec( ["ffprobe", "-v", "error", "-of", "json", "-show_format", "-show_streams", "clip.mkv"], { check: true },);const info = JSON.parse(probe.stdout) as { format: { duration: string }; streams: { codec_type: string; codec_name: string; width?: number }[];};console.log( info.format.duration, info.streams.map((s) => `${s.codec_type}:${s.codec_name}`),);Encoders in Ubuntu's build
Ubuntu 24.04's libavcodec60, the library behind its ffmpeg, depends on
these codec libraries, per packages.ubuntu.com on 25 September 2026:
| Library | Use it for | Name in ffmpeg |
|---|---|---|
libx264-164 |
H.264 video, the widest playback | -c:v libx264 |
libx265-199 |
H.265/HEVC video | -c:v libx265 |
libvpx9 |
VP8 and VP9 video for WebM | -c:v libvpx-vp9 |
libsvtav1enc1 |
AV1 encoding | -c:v libsvtav1 |
libdav1d7 |
AV1 decoding | (decoder) |
libopus0 |
Opus audio | -c:a libopus |
libmp3lame0 |
MP3 audio | -c:a libmp3lame |
Run ffmpeg -hide_banner -encoders in a sandbox for the full list.
Encodes run on CPUs
Runtime sandboxes have no GPUs, so NVENC and other hardware encoders are not available; every encoder above runs on the CPU. Two ways to go faster:
- Paid sandboxes can ask for more
vcputhan the trial's two; x264 spreads its work across threads. The bill follows the CPU actually used, not the cores reserved. - Many files at once: give each its own sandbox. A paid account runs 100 at once to start with, and the trial runs eight.
TypeScriptimport { Sandbox } from "withruntime";const files = ["a.mov", "b.mov", "c.mov"];await Promise.all( files.map(async (name) => { await using sbx = await Sandbox.create({ image: "ffmpeg", diskMiB: 8192 }); await sbx.files.upload(`./${name}`, `/workspace/${name}`); await sbx.exec(["ffmpeg", "-y", "-i", name, "-c:v", "libx264", "-crf", "23", "out.mp4"], { check: true, timeoutMs: 3_000_000, }); await sbx.files.download("/workspace/out.mp4", `./${name}.mp4`); }),);Start every sandbox with FFmpeg installed
The samples above that say image: "ffmpeg" use this custom image:
TypeScriptimport { Runtime } from "withruntime";const runtime = new Runtime();await runtime.images.build({ name: "ffmpeg", recipe: { apt: ["ffmpeg"] } });Pythonfrom withruntime import RuntimeRuntime().images.build(name="ffmpeg", recipe={"apt": ["ffmpeg"]})Building is free and uses no trial hours; the free trial stores three images free.
Disk and time
| Limit | What to set |
|---|---|
| Disk | Input, output and FFmpeg itself share it; the default 4 GiB had about 2.5 GiB free on 24 September 2026, the trial allows 10 GiB |
| Disk speed | Bursts to about 250 MB/s for up to 30 seconds, then about 40 MB/s |
| One command | 60 seconds by default, up to 24 hours with timeoutMs |
| Sandbox lifetime | timeoutSeconds, at most an hour ahead; extend moves it, or keepAlive holds it while your process runs |
For media that arrives from users, turn the sandbox's internet off after the install so a crafted file cannot call out (turn off sandbox internet). To generate images or thumbnails in other formats, see ImageMagick in a sandbox. Document and PDF pipelines are in document conversion, and batch jobs across many sandboxes in AI data pipelines.
Sources
- FFmpeg formats documentation (
movflagsandfaststart), https://ffmpeg.org/ffmpeg-formats.html, read 25 September 2026 - Ubuntu 24.04 ffmpeg and libavcodec60 packages, https://packages.ubuntu.com/noble/ffmpeg and https://packages.ubuntu.com/noble/libavcodec60, read 25 September 2026
Facts on this page were checked on 25 September 2026.