# FFmpeg

Run your exact FFmpeg commands on distributed GPU infrastructure.

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:

```bash
# 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

````

```bash
# 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
````

```bash
# 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
```

```bash
# 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:

```bash
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:

```bash
# 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](/guides/process-files-from-s3) and [write output to S3](/guides/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:

```bash
ittybit ffmpeg -i input.mov -c:v libx264 output.mp4 --local
```

```bash
ittybit ffmpeg -i https://example.com/video.mp4 -c:v libx264 output.mp4 --local
```

```bash
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.
