Skip to main content
The FFmpeg API lets you transcode, trim, convert, and otherwise process video and audio files entirely on the server. You provide a source URL and an FFmpeg command; MADIAD Hub fetches the file, runs the job, and makes the output available to download. There is no binary upload — input files must be reachable over HTTPS. The API returns a job_id immediately; processing is asynchronous, so you poll for status and then download the result.
FFmpeg jobs require a paid plan. The Trial plan includes 0 FFmpeg minutes per month. Upgrade to Starter or higher to unlock the feature.

How a job works

1

Submit

POST to /v1/ffmpeg/jobs with one or more source URLs and an FFmpeg command. The API validates the command, reserves quota, and queues the job. You receive a job_id.
2

Poll

GET /v1/ffmpeg/jobs/:id until status is finished.
3

Download

GET /v1/ffmpeg/jobs/:id/result to stream the processed file.

Submit a job

POST /v1/ffmpeg/jobs
Authorization: Bearer $MADIAD_API_KEY
Content-Type: application/json

Request body

FieldTypeRequiredDescription
file_urlstringOne of file_url / file_urlsA single HTTPS source URL
file_urlsstring[]One of file_url / file_urlsMultiple HTTPS source URLs (e.g. for mixing tracks)
full_commandstringYesThe complete FFmpeg command string (see Command rules)
output_extensionstringYesContainer/format for the output (see Allowed extensions)

Response

{
  "job_id": "ffj_01HZX9G4P6R8S0T2V4W6X8Y0Z2",
  "status": "queued"
}

Poll status

GET /v1/ffmpeg/jobs/:id
Authorization: Bearer $MADIAD_API_KEY

Response

{
  "job_id": "ffj_01HZX9G4P6R8S0T2V4W6X8Y0Z2",
  "status": "processing",
  "duration_sec": null
}
duration_sec is null until the job finishes; it is populated with the actual output duration once complete.
status valueMeaning
queuedJob is waiting to run
processingJob is running
finishedOutput is ready to download
failedJob failed; retry with a corrected command

Download the result

Once status is finished, stream the output file:
GET /v1/ffmpeg/jobs/:id/result
Authorization: Bearer $MADIAD_API_KEY
The response is a binary stream with Content-Disposition: attachment. Pipe it to a file or buffer it in memory.

Command rules

The full_command field must satisfy all of the following rules. Requests that fail validation return 400 invalid_request before any quota is consumed.
RuleDetail
Starts with ffmpegThe command must begin with the literal word ffmpeg
Contains {input} placeholderUse {input} for a single source, or {input0}, {input1}, … for multiple sources
Contains {output} placeholderMADIAD Hub substitutes the output path at run time
Maximum length4,000 characters
No shell metacharactersCharacters ;, |, &, $, `, <, > are blocked
No destructive tokens$(, rm, rmdir, mkfs, dd are blocked
Newlines in the command are converted to spaces automatically, so you can paste multi-line commands directly.

Allowed output extensions

output_extension must be one of the following values (without a leading dot):
CategoryValues
Videomp4, mov, webm, mkv, gif
Audiomp3, wav, m4a, aac, ogg
Imagejpg, png
Any other value returns 400 invalid_request.

Quota and billing

FFmpeg usage is measured in FFmpeg minutes. In v1, every job costs a flat 1 minute, regardless of the actual output duration. The quota is reserved at submit time and refunded automatically if the job fails to queue. Monthly limits by plan:
PlanFFmpeg minutes / month
Trial0 (not available)
Starter30
Growth150
Business500
CustomUnlimited
When you exhaust your monthly allowance, the API returns 429 quota_exceeded. Usage resets on the first day of each calendar month (UTC).

Authentication and rate limits

All FFmpeg endpoints use the same API-key Bearer authentication as the rest of MADIAD Hub — see Authentication. The rate limit is 120 requests per minute per account across all FFmpeg endpoints. Exceeding this returns 429 with a Retry-After header indicating how long to wait.

Job ownership

Jobs are private to the account that created them. Polling or downloading a job that belongs to another account returns 404 not_found — there is no cross-account access.

Errors

HTTP statusCodeWhen
400invalid_requestMissing or non-HTTPS URL, command fails validation, unsupported output_extension
404not_foundUnknown job ID, or the job belongs to a different account
429quota_exceededMonthly FFmpeg minutes exhausted
429rate_limitedMore than 120 requests/minute; back off and retry after Retry-After seconds
502upstream_errorResult not available yet, or processing failed

Worked example

1. Submit: convert an MP4 to a web-optimized WebM

curl -X POST https://api.madiad.com/v1/ffmpeg/jobs \
  -H "Authorization: Bearer $MADIAD_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "file_url": "https://cdn.example.com/raw/interview.mp4",
        "full_command": "ffmpeg -i {input} -c:v libvpx-vp9 -crf 33 -b:v 0 -c:a libopus {output}",
        "output_extension": "webm"
      }'

2. Poll until finished

curl https://api.madiad.com/v1/ffmpeg/jobs/ffj_01HZX9G4P6R8S0T2V4W6X8Y0Z2 \
  -H "Authorization: Bearer $MADIAD_API_KEY"
# Keep polling until "status": "finished"

3. Download the result

curl https://api.madiad.com/v1/ffmpeg/jobs/ffj_01HZX9G4P6R8S0T2V4W6X8Y0Z2/result \
  -H "Authorization: Bearer $MADIAD_API_KEY" \
  --output interview.webm