Runtime

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 onStderr streams as it happens.
  • +faststart moves 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 vcpu than 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

Facts on this page were checked on 25 September 2026.