FFmpeg

View Markdown

We love FFmpeg. It’s probably the best piece of software in the world. It handles every codec, every container, every edge case. If it involves video, audio, or images, FFmpeg can do it.

But running it in production at scale is a nightmare.

The pain of running FFmpeg yourself

FFmpeg can’t change the physics of moving large files across networks, suddenly make user-generated uploads trustworthy, or solve the computer science and infrastructure problems of running long processes reliably at scale. Those are your problems.

  • Long-running encodes tie up your servers for minutes or hours. A single 4K transcode can peg a CPU for 15 minutes.
  • Server timeouts kill jobs mid-encode. Your HTTP gateway, load balancer, or serverless runtime doesn’t care that you’re 90% done.
  • Memory and disk fill up without warning. A 2-hour lecture at 4K needs tens of gigabytes of scratch space.
  • Error handling is cryptic. FFmpeg exits with code 1 and a wall of stderr. Good luck building retry logic around that.
  • Scaling means provisioning machines, managing queues, handling failures, and writing all the glue code to move files in and out.
  • Codec edge cases surface at scale. That one user’s screen recording with a variable frame rate, or the phone video with rotation metadata your pipeline ignores.

You end up building a media processing platform just to run one command.

One prefix, full FFmpeg

Ittybit runs your exact FFmpeg commands. No abstraction layer, no simplified flags, no subset of features. Your existing FFmpeg knowledge transfers directly:

# ffmpeg
ffmpeg -i input.mov -c:v libx264 -crf 23 output.mp4

# ittybit

ittybit ffmpeg -i input.mov -c:v libx264 -crf 23 output.mp4
# ffmpeg
ffmpeg -i input.mp4 -c:v libx265 -crf 28 -preset medium output.mkv

# ittybit
ittybit ffmpeg -i input.mp4 -c:v libx265 -crf 28 -preset medium output.mkv
# ffmpeg
ffmpeg -i input.mov -ss 5 -frames:v 1 frame.png

# ittybit
ittybit ffmpeg -i input.mov -ss 5 -frames:v 1 frame.png
# ffmpeg
ffmpeg -i input.mov \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920" \
  -c:v libx264 -preset slow -crf 23 \
  output.mp4

# ittybit
ittybit ffmpeg -i input.mov \
  -vf "scale=1080:1920:force_original_aspect_ratio=increase,crop=1080:1920" \
  -c:v libx264 -preset slow -crf 23 \
  output.mp4

Same arguments. Same codecs. Same filters. Ittybit handles everything around the encode: fetching the input, running the command, capturing structured output, and delivering the result.

What ittybit handles

When you run ittybit ffmpeg, the CLI:

  1. Uploads the source file (or fetches it from a URL or S3)
  2. Runs your FFmpeg command on managed infrastructure with GPU acceleration. No timeouts, no disk limits, no orphaned processes
  3. Streams structured JSONL progress events back to your terminal or application
  4. Downloads the output to your local machine or writes it to S3

Transient failures are retried automatically with exponential backoff. Unrecoverable errors return immediately with a structured error response including a kind field and an actionable message, not a wall of FFmpeg stderr.

Structured output

FFmpeg writes progress to stderr in a format designed for humans squinting at a terminal. Ittybit gives you machine-readable JSONL instead. Every event has a type, a timestamp, and structured metadata: progress percentage, current frame, output file size, codec info.

Pipe it into jq, feed it to a webhook, or parse it in your application:

ittybit ffmpeg -i input.mov -c:v libx264 output.mp4 --json

Output files are probed automatically. The response includes duration, codecs, bitrate, resolution, and file size. No need to run a separate ffprobe step.

S3 and URL compatible

Inputs and outputs work with local files, URLs, and S3-compatible storage:

# URL input
ittybit ffmpeg -i https://example.com/video.mp4 -c:v libx264 output.mp4

# S3 input and output
ittybit ffmpeg -i s3://my-bucket/input.mov -c:v libx264 output.mp4 \
  -o s3://my-bucket/output.mp4 --connection my-bucket

Configure a connection once and reference it by name. See process files from S3 and write output to S3 for setup.

Process files in parallel

Submit thousands of files at once and they process concurrently across the fleet. No provisioning, no capacity planning, no queue management. Ittybit handles scheduling, retries, and scaling automatically.

When you’re not processing, you’re not paying. No idle instances, no reserved capacity.

Local mode

If you have FFmpeg installed, you can process files locally without an API key or network calls:

ittybit ffmpeg -i input.mov -c:v libx264 output.mp4 --local
ittybit ffmpeg -i https://example.com/video.mp4 -c:v libx264 output.mp4 --local
ittybit ffmpeg -i s3://my-bucket/input.mov -c:v libx264 output.mp4 --local \
  --connection my-bucket

Same commands and same structured output. The only difference is where the processing runs.

It’s super useful for local development and testing. Add --debug for full JSONL log lines.