Hosted FFmpeg API, $0.01 a compute minute

Run any ffmpeg command over HTTP

Send your input URLs and the arguments you already tested in your terminal. We run them on ffmpeg 8.1 on a fresh machine with 4 vCPUs and 12 GiB of memory, ready in 1.87 seconds at the median, and hand back a URL for every output. You pay $0.01 per compute minute, with no servers, binaries or job queue of your own.

  • Any filter graph
  • Up to 20 outputs per job
  • 10 minutes per job
in.mp416:9, as uploaded
out.mp49:16

How it maps

Your terminal command, as JSON

This is the exact command behind the clip above. The same three parts show up in every request.

your terminal
$ ffmpeg -i in.mp4 \
  -filter_complex "[0:v]scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,boxblur=24:2[bg];[0:v]scale=720:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2" \
  -c:a copy out.mp4

job folder, after the run

  • in.mp4downloaded from inputs
  • out.mp4written by ffmpeg, uploaded to outputs
POST /v1/ffmpeg
{
  "inputs": {
    "in.mp4": "https://your.app/landscape.mp4"
  },
  "args": [
    "-i", "in.mp4",
    "-filter_complex",
    "[0:v]scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,boxblur=24:2[bg];[0:v]scale=720:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2",
    "-c:a", "copy",
    "out.mp4"
  ],
  "outputs": ["out.mp4"]
}
  • in.mp4

    Each input is a name and a URL. We download it into the job folder under that name before ffmpeg starts.

  • args

    Your arguments go to ffmpeg 8.1 exactly as written, with no shell in between, so quoting can't bite you.

  • out.mp4

    Every file listed in outputs is uploaded when ffmpeg exits and comes back as a URL that works for 7 days.

Quick start

Send it from any language

curl "https://api.reelsdk.com/v1/ffmpeg" \
  -H "Authorization: Bearer $REELSDK_KEY" \
  --json '{
    "inputs": { "in.mp4": "https://your.app/landscape.mp4" },
    "args": [
      "-i", "in.mp4", "-filter_complex",
      "[0:v]scale=720:1280:force_original_aspect_ratio=increase,crop=720:1280,boxblur=24:2[bg];[0:v]scale=720:-2[fg];[bg][fg]overlay=(W-w)/2:(H-h)/2",
      "-c:a", "copy", "out.mp4"
    ],
    "outputs": ["out.mp4"]
  }'
200 OK
{
  "job": {
    "id": "job_dhodzdoc9is0j8ht9lgm",
    "op": "ffmpeg",
    "status": "succeeded",
    "stage": null,
    "created_at": "2026-10-26T09:12:40.318Z",
    "finished_at": "2026-10-26T09:12:52.904Z",
    "outputs": {
      "out.mp4": "https://api.reelsdk.com/f/out/job_dhodzdoc9is0j8ht9lgm/out.mp4"
    },
    "result": null,
    "duration_s": 10.053,
    "error": null,
    "usage": {
      "output_seconds": 10.053,
      "audio_seconds": 0,
      "tts_characters": 0,
      "images": 0
    },
    "poll_url": "https://api.reelsdk.com/v1/jobs/job_dhodzdoc9is0j8ht9lgm"
  }
}

Each name in outputs comes back as its own URL, kept for 7 days.

The sandbox

Everything ffmpeg can do, inside one folder

Each job runs on its own machine, and your command reads and writes only inside its job folder. These are all the rules.

What a raw ffmpeg job can and can't do
WorksBlocked
FilesNames from inputs and anything your command writes in the job folderAbsolute paths, .. and ~
NetworkRemote files listed in inputs, downloaded before ffmpeg startsURLs and protocols such as http:, tcp: or concat: inside args
FiltersEvery filter in ffmpeg 8.1: filter_complex, drawtext, subtitles, xfade, loudnorm and the restmovie and amovie
FormatsCommon video, audio, image and subtitle formats, plus concat and lavfi when you force them with -fThe tee muxer and glob patterns
OptionsCodecs, bitrates, seeking, mapping, metadata and two-pass logs in the job folderFilter scripts, presets files and hardware devices

Fonts in /usr/share/fonts/reelapi/

  • Anton-Regular.ttf
  • BebasNeue-Regular.ttf
  • Montserrat-Black.ttf
  • Montserrat-ExtraBold.ttf
  • Poppins-Bold.ttf
  • Poppins-ExtraBold.ttf
  • Poppins-Black.ttf

Plus Noto Sans Bold for Japanese, Chinese, Korean, Arabic, Hebrew, Thai, Devanagari, Lao, Myanmar.

Use one in drawtext

"-vf", "drawtext=fontfile=/usr/share/fonts/reelapi/Anton-Regular.ttf:text='SALE':fontsize=120:fontcolor=white:x=(w-tw)/2:y=h*0.7"

What you control

A real ffmpeg, without running one

  • Your command, unchanged

    Send args as an array, or paste the whole command as one string and we split it like a shell would. A leading ffmpeg is dropped for you.

  • Up to 20 output files

    List what your command writes in outputs and each file comes back as a URL. Leave it out and the last argument is used.

  • A fresh machine every job

    Each job gets its own machine with 4 vCPUs, 12 GiB of memory and 20 GB of disk. It's ready in 1.87 seconds at the median, 2.48 at p90.

  • Runs up to 10 minutes

    Set timeout_s from 1 to 600. The call waits 60 seconds for the result by default, up to 300 with ?wait=, then hands you a poll_url.

  • Fonts already installed

    Point drawtext or subtitles at /usr/share/fonts/reelapi/ for seven display faces and Noto Sans in nine scripts.

  • Errors that say what broke

    A blocked argument is a 400 that names it, like args[3]. When ffmpeg fails you get 422 FFMPEG_FAILED with its last meaningful line of output.

Specs

FFmpeg API specs

reelsdk hosted FFmpeg API specifications
EndpointPOST /v1/ffmpeg
ffmpeg8.1 on Alpine Linux, a fresh machine per job
Machine4 vCPUs, 12 GiB memory, 20 GB disk
Start-upMachine ready in 1.87 s at the median, 2.48 s at p90
InputsNamed files fetched from URLs, 500 MB each and 1 GB per job, media up to 15 minutes
ArgumentsAn array of up to 1,000 strings, or one string of up to 65,536 characters
Outputs1 to 20 files, each returned as a URL that works for 7 days
Time limittimeout_s from 1 to 600 seconds, 600 by default
FontsAnton, Bebas Neue, Montserrat, Poppins and Noto Sans in /usr/share/fonts/reelapi/
DeliveryWait up to 300 s, poll the job, or get a webhook signed with HMAC-SHA256
Price$0.01 per compute minute

Pricing

One cent per compute minute

Billed on compute rather than output length, because the output of a raw command can be anything.

$0.01per compute minute

No subscription or minimum. Prepaid credit, and your first $1 is free.

Prefer a ready-made pipeline?

Captions and slideshows are priced by the finished video instead: $0.02 per output minute, with transcription, timing and styling done for you. See captions and slideshows.

Use cases

What people run on it

  1. 01

    Reframe landscape to vertical

    Turn 16:9 footage into 9:16 clips with a blurred fill, like the example above, or crop to a face-safe centre.

  2. 02

    Thumbnails and GIF previews

    Pull a poster frame, a contact sheet and a short GIF out of one upload in a single job with several outputs.

  3. 03

    Join clips and fix the audio

    Concatenate files, crossfade scenes with xfade, level speech with loudnorm or pull the audio track out as MP3.

  4. 04

    Watermarks and burned-in subtitles

    Overlay a logo, stamp text with drawtext or burn an SRT or ASS file into the picture with the bundled fonts.

FAQ

FFmpeg API questions

Why can't I run ffmpeg in my serverless function?

A static ffmpeg binary is about 80 MB before it loads a single frame. Supabase Edge Functions give you 256 MB of memory and 2 seconds of CPU per request, Cloudflare Workers give you 128 MB, and neither can start a subprocess. Vercel functions cap request bodies at 4.5 MB, so most videos can't even be posted to them. Sending the job to reelsdk over HTTPS sidesteps all of it.

How much does it cost?

$0.01 per minute of compute time. Raw ffmpeg is billed on compute rather than output length because the output can be anything: a clip, an audio track or a folder of thumbnails. There's no subscription or minimum; you use prepaid credit and your first $1 is free.

Which arguments are blocked?

Anything that reaches outside the job folder: URLs and network protocols inside args, absolute paths, .. segments, the movie and amovie filters, the tee muxer, glob patterns, filter scripts, presets files and hardware devices. Remote files go in inputs instead. A blocked argument returns a 400 that names its position, like args[3].

How do I get the output files?

The create call waits up to 60 seconds and returns the finished job with a URL per output. Add ?wait=300 to wait longer. If the job is still running you get a 202 with a poll_url, or pass a webhook_url and we POST the finished job to you, signed with HMAC-SHA256, with up to 3 attempts. URLs work for 7 days.

Which fonts can drawtext use?

Anton, Bebas Neue, Montserrat Black and ExtraBold, and Poppins Bold, ExtraBold and Black, plus Noto Sans for Japanese, Chinese, Korean, Arabic, Hebrew, Thai, Devanagari, Lao and Myanmar. They live in /usr/share/fonts/reelapi/, the one absolute path fontfile and fontsdir may use.

What are the limits per key?

3 jobs at once and 500 a day, 20 GiB of uploads a day, inputs up to 500 MB each and 1 GB per job, media up to 15 minutes and up to 10 minutes of run time per job.

Ready to build?

Run your first command in a minute

Sign up and create an API key in a minute. Your first $1 of compute is on us, then it's a cent a minute.

Moonlit lake with a lit cabin under the mountains