API DocsRequest

Requests overview

Most operations use JSON requests and Basic Auth. The typical flow is:

  1. Create a file to obtain an upload URL
  2. Upload the file bytes
  3. Submit a processing task referencing file_path

See also: Quick Start, File Management, and Processing.

Input Object

  • options: Array of FFmpeg input options applied before the input file
    • Format: ["-option", "value", "-another_option", "value"]
    • Examples: ["-ss", "00:00:10"] (seek to 10 seconds), ["-t", "30"] (duration of 30 seconds)
  • file: Filename that exactly matches the uploaded file parameter name

Output Object

  • options: Array of FFmpeg output options applied to the output file
    • Format: ["-option", "value", "-another_option", "value"]
    • Examples: ["-c:v", "libx264", "-crf", "23"] (H.264 codec with quality 23)
  • file: Desired output filename (will be available for download)
  • maps: (Optional) Array of stream mapping specifiers
    • Format: ["input_index:stream_type:stream_index"]
    • Examples: ["0:v"] (video from first input), ["1:a:2"] (third audio track from second input)
    • Can also reference filter outputs: ["[filter_label]"]

Filter Complex

  • filter_complex: (Optional) FFmpeg filter graph for advanced video/audio processing
    • Used for operations like scaling, overlay, concatenation, side-by-side videos
    • Filter outputs can be referenced in output maps using labels like [out]
    • Example: "[0:v]scale=1920:1080[v1];[1:v]scale=1920:1080[v2];[v1][v2]hstack[out]"

Example Requests (JSON workflow)

Basic GIF to MP4 Conversion

Request Data:

  • File: input.gif (your GIF file)
  • Command: {"inputs":[{"options":[],"file":"input.gif"}],"outputs":[{"options":[],"file":"output.mp4"}]}

Examples:

  • curl
# 1) Get an upload URL
curl -sS -X POST https://api.ffmpeg-api.com/file \
  -H 'Authorization: Basic YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"file_name":"input.gif"}'
 
# (capture $UPLOAD_URL and $FILE_PATH from the response)
 
# 2) Upload the bytes
curl -X PUT "$UPLOAD_URL" --data-binary @./input.gif
 
# 3) Process with file_path
curl -sS -X POST https://api.ffmpeg-api.com/ffmpeg/process \
  -H 'Authorization: Basic YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"task":{"inputs":[{"file_path":"'$FILE_PATH'"}],"outputs":[{"file":"output.mp4"}]}}'
  • JavaScript (Node)
const res = await fetch('https://api.ffmpeg-api.com/file', {
  method: 'POST',
  headers: { Authorization: `Basic ${API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ file_name: 'input.gif' })
});
const { file, upload } = await res.json();
await fetch(upload.url, { method: 'PUT', body: fs.readFileSync('./input.gif') });
await fetch('https://api.ffmpeg-api.com/ffmpeg/process', {
  method: 'POST',
  headers: { Authorization: `Basic ${API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ task: { inputs: [{ file_path: file.file_path }], outputs: [{ file: 'output.mp4' }] } })
});

Video with Custom Options

Request Data:

  • File: video.mp4 (your video file)
  • Command: {"inputs":[{"options":["-ss","00:00:10","-t","30"],"file":"video.mp4"}],"outputs":[{"options":["-c:v","libx264","-crf","23"],"file":"output.mp4"}]}

Examples:

  • curl
# 1) Get an upload URL
curl -sS -X POST https://api.ffmpeg-api.com/file \
  -H 'Authorization: Basic YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"file_name":"video.mp4"}'
 
# 2) Upload
curl -X PUT "$UPLOAD_URL" --data-binary @./video.mp4
 
# 3) Process with input trimming and quality options
curl -sS -X POST https://api.ffmpeg-api.com/ffmpeg/process \
  -H 'Authorization: Basic YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"task":{"inputs":[{"file_path":"'$FILE_PATH'","options":["-ss","00:00:10","-t","30"]}],"outputs":[{"file":"output.mp4","options":["-c:v","libx264","-crf","23"]}]}}'
  • JavaScript (Node)
const fileRes = await fetch('https://api.ffmpeg-api.com/file', {
  method: 'POST',
  headers: { Authorization: `Basic ${API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ file_name: 'video.mp4' })
});
const { file, upload } = await fileRes.json();
await fetch(upload.url, { method: 'PUT', body: fs.readFileSync('./video.mp4') });
await fetch('https://api.ffmpeg-api.com/ffmpeg/process', {
  method: 'POST',
  headers: { Authorization: `Basic ${API_KEY}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ task: { inputs: [{ file_path: file.file_path, options: ['-ss','00:00:10','-t','30'] }], outputs: [{ file: 'output.mp4', options: ['-c:v','libx264','-crf','23'] }] } })
});

Multiple Input Files

Request Data:

  • Files: video.mp4, audio.mp3
  • Command: {"inputs":[{"options":[],"file":"video.mp4"},{"options":[],"file":"audio.mp3"}],"outputs":[{"options":["-c:v","copy","-c:a","aac"],"file":"output.mp4"}]}

Examples:

  • curl
# 1) Get upload URLs for both files
curl -sS -X POST https://api.ffmpeg-api.com/file -H 'Authorization: Basic YOUR_API_KEY' -H 'Content-Type: application/json' -d '{"file_name":"video.mp4"}'
curl -sS -X POST https://api.ffmpeg-api.com/file -H 'Authorization: Basic YOUR_API_KEY' -H 'Content-Type: application/json' -d '{"file_name":"audio.mp3"}'
 
# 2) Upload each file
curl -X PUT "$UPLOAD_URL_VIDEO" --data-binary @./video.mp4
curl -X PUT "$UPLOAD_URL_AUDIO" --data-binary @./audio.mp3
 
# 3) Process by referencing both file_paths from step 1
curl -sS -X POST https://api.ffmpeg-api.com/ffmpeg/process \
  -H 'Authorization: Basic YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"task":{"inputs":[{"file_path":"'$FILE_PATH_VIDEO'"},{"file_path":"'$FILE_PATH_AUDIO'"}],"outputs":[{"file":"output.mp4","options":["-c:v","copy","-c:a","aac"]}]}}'
  • JavaScript (Node)
const v = await fetch('https://api.ffmpeg-api.com/file', { method:'POST', headers:{ Authorization:`Basic ${API_KEY}`, 'Content-Type':'application/json' }, body: JSON.stringify({ file_name:'video.mp4' }) }).then(r=>r.json());
const a = await fetch('https://api.ffmpeg-api.com/file', { method:'POST', headers:{ Authorization:`Basic ${API_KEY}`, 'Content-Type':'application/json' }, body: JSON.stringify({ file_name:'audio.mp3' }) }).then(r=>r.json());
await fetch(v.upload.url, { method:'PUT', body: fs.readFileSync('./video.mp4') });
await fetch(a.upload.url, { method:'PUT', body: fs.readFileSync('./audio.mp3') });
await fetch('https://api.ffmpeg-api.com/ffmpeg/process', {
  method:'POST',
  headers:{ Authorization:`Basic ${API_KEY}`, 'Content-Type':'application/json' },
  body: JSON.stringify({ task: { inputs: [ { file_path: v.file.file_path }, { file_path: a.file.file_path } ], outputs: [ { file:'output.mp4', options:['-c:v','copy','-c:a','aac'] } ] } })
});

Stream Mapping with Maps

Extract specific streams from inputs into separate output files:

Request Data:

  • File: movie.mkv (contains multiple video and audio tracks)
  • Command: Extract video-only and specific audio track
{
  "inputs": [{"file": "movie.mkv", "options": []}],
  "outputs": [
    {
      "options": ["-c:v", "libx264", "-crf", "23"],
      "file": "video_only.mp4",
      "maps": ["0:v:0"]
    },
    {
      "options": ["-c:a", "aac", "-b:a", "128k"],
      "file": "audio_track2.m4a",
      "maps": ["0:a:1"]
    }
  ]
}

Filter Complex for Side-by-Side Video

Combine two videos side by side using filter_complex:

Request Data:

  • Files: left_video.mp4, right_video.mp4
  • Command: Scale both videos and place them side by side
{
  "task": {
    "inputs": [
      {"file_path": "<file_path_left>", "options": []},
      {"file_path": "<file_path_right>", "options": []}
    ],
    "filter_complex": "[0:v]scale=960:540[left];[1:v]scale=960:540[right];[left][right]hstack[out]",
    "outputs": [
      {
        "file": "side_by_side.mp4",
        "options": ["-c:v", "libx264", "-preset", "medium"],
        "maps": ["[out]"]
      }
    ]
  }
}

Advanced Options Usage

Trimming and Quality Control:

{
  "inputs": [
    {
      "file": "input.mp4",
      "options": ["-ss", "00:01:30", "-t", "00:02:00"]
    }
  ],
  "outputs": [
    {
      "file": "trimmed_high_quality.mp4",
      "options": [
        "-c:v", "libx264",
        "-crf", "18",
        "-preset", "slow",
        "-c:a", "aac",
        "-b:a", "192k"
      ]
    }
  ]
}

Multiple Output Formats:

{
  "inputs": [{"file": "source.mp4", "options": []}],
  "outputs": [
    {
      "file": "compressed.mp4",
      "options": ["-c:v", "libx264", "-crf", "28", "-c:a", "aac"]
    },
    {
      "file": "thumbnail.jpg",
      "options": ["-vf", "scale=320:240", "-vframes", "1", "-ss", "00:00:05"]
    }
  ]
}

File Upload Guidelines

ℹ️

File parameter names in the request must exactly match the file field in your command’s inputs.

File Upload Requirements

  1. Parameter names: Must match the file field in your command inputs
  2. File paths: Any accessible file path (implementation depends on your tool/language)
  3. Multiple files: Upload all files referenced in your command’s inputs

File Size Limits

  • Maximum file size: 100MB per file (will be increased in the future)

Response Format

Success Response

{
  "ok": true,
  "result": [
    {
      "file_name": "output.mp4",
      "size_bytes": 104897,
      "download_url": "https://.../output.mp4?..."
    }
  ],
  "usage": { "time_sec": 12.5, "input_size_gb": 0.098, "output_size_gb": 0.015, "gb_sec": 1.4125 }
}

Response Fields:

  • ok: Boolean indicating request success
  • result: Array of output files
  • result[].file: Signed URL to download the processed file (valid for 1 hour)
  • result[].size: File size in bytes

Error Response

{
  "ok": false,
  "error": "Error message describing what went wrong"
}

Best Practices

⚠️

Always validate your FFmpeg command locally before sending it to the API to avoid unnecessary usage charges.

Error Prevention

  1. Check file formats: Ensure input files are in supported formats
  2. Validate paths: Use absolute paths for file uploads
  3. Test commands: Validate FFmpeg syntax before API calls
  4. Handle timeouts: Implement retry logic for large file processing

Language-Specific Examples

Python (requests)

Basic conversion:

import requests
import json
 
files = {
    'input.gif': open('/path/to/file.gif', 'rb'),
    'command': (None, json.dumps({
        "inputs": [{"options": [], "file": "input.gif"}],
        "outputs": [{"options": [], "file": "output.mp4"}]
    }))
}
 
headers = {
    'Authorization': 'Basic YOUR_AUTH_KEY_HERE'
}
 
response = requests.post(
    'https://api.ffmpeg-api.com/ffmpeg/run',
    files=files,
    headers=headers
)
 
result = response.json()
if result['ok']:
    output_url = result['result'][0]['file']
    print(f"Download your file: {output_url}")

Advanced example with stream mapping:

import requests
import json
 
# Extract audio track and create thumbnail
command = {
    "inputs": [
        {
            "file": "movie.mp4",
            "options": []
        }
    ],
    "outputs": [
        {
            "file": "audio_only.m4a",
            "options": ["-c:a", "aac", "-b:a", "128k"],
            "maps": ["0:a:0"]
        },
        {
            "file": "thumbnail.jpg",
            "options": ["-vf", "scale=320:240", "-vframes", "1", "-ss", "00:00:10"],
            "maps": ["0:v:0"]
        }
    ]
}
 
files = {
    'movie.mp4': open('/path/to/movie.mp4', 'rb'),
    'command': (None, json.dumps(command))
}
 
response = requests.post(
    'https://api.ffmpeg-api.com/ffmpeg/run',
    files=files,
    headers={'Authorization': 'Basic YOUR_AUTH_KEY_HERE'}
)
 
result = response.json()
if result['ok']:
    for output in result['result']:
        print(f"Download: {output['file']} ({output['size']} bytes)")

JavaScript (Node.js)

Basic conversion:

const FormData = require('form-data');
const fs = require('fs');
const fetch = require('node-fetch');
 
const form = new FormData();
form.append('input.gif', fs.createReadStream('/path/to/file.gif'));
form.append('command', JSON.stringify({
    inputs: [{ options: [], file: 'input.gif' }],
    outputs: [{ options: [], file: 'output.mp4' }]
}));
 
const response = await fetch('https://api.ffmpeg-api.com/ffmpeg/run', {
    method: 'POST',
    headers: {
        'Authorization': 'Basic YOUR_AUTH_KEY_HERE',
        ...form.getHeaders()
    },
    body: form
});
 
const result = await response.json();
if (result.ok) {
    const outputUrl = result.result[0].file;
    console.log(`Download your file: ${outputUrl}`);
}

Side-by-side video with filter_complex:

const FormData = require('form-data');
const fs = require('fs');
const fetch = require('node-fetch');
 
// Create side-by-side video using filter_complex
const command = {
    inputs: [
        { file: 'video1.mp4', options: [] },
        { file: 'video2.mp4', options: [] }
    ],
    filter_complex: '[0:v]scale=640:360[left];[1:v]scale=640:360[right];[left][right]hstack[out]',
    outputs: [
        {
            file: 'combined.mp4',
            options: ['-c:v', 'libx264', '-preset', 'medium', '-crf', '23'],
            maps: ['[out]']
        }
    ]
};
 
const form = new FormData();
form.append('video1.mp4', fs.createReadStream('/path/to/video1.mp4'));
form.append('video2.mp4', fs.createReadStream('/path/to/video2.mp4'));
form.append('command', JSON.stringify(command));
 
const response = await fetch('https://api.ffmpeg-api.com/ffmpeg/run', {
    method: 'POST',
    headers: {
        'Authorization': 'Basic YOUR_AUTH_KEY_HERE',
        ...form.getHeaders()
    },
    body: form
});
 
const result = await response.json();
if (result.ok) {
    console.log(`Combined video: ${result.result[0].file}`);
}

PHP

Basic conversion:

<?php
$ch = curl_init();
 
$postFields = [
    'input.gif' => new CURLFile('/path/to/file.gif'),
    'command' => json_encode([
        'inputs' => [['options' => [], 'file' => 'input.gif']],
        'outputs' => [['options' => [], 'file' => 'output.mp4']]
    ])
];
 
curl_setopt($ch, CURLOPT_URL, 'https://api.ffmpeg-api.com/ffmpeg/run');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Basic YOUR_AUTH_KEY_HERE'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
$response = curl_exec($ch);
$result = json_decode($response, true);
 
if ($result['ok']) {
    $outputUrl = $result['result'][0]['file'];
    echo "Download your file: " . $outputUrl;
}
curl_close($ch);
?>

Advanced example with stream mapping:

<?php
// Extract specific audio and video streams
$command = [
    'inputs' => [
        ['file' => 'movie.mkv', 'options' => []]
    ],
    'outputs' => [
        [
            'file' => 'video_only.mp4',
            'options' => ['-c:v', 'libx264', '-crf', '23'],
            'maps' => ['0:v:0']
        ],
        [
            'file' => 'audio_only.aac',
            'options' => ['-c:a', 'aac', '-b:a', '128k'],
            'maps' => ['0:a:1']
        ]
    ]
];
 
$ch = curl_init();
$postFields = [
    'movie.mkv' => new CURLFile('/path/to/movie.mkv'),
    'command' => json_encode($command)
];
 
curl_setopt($ch, CURLOPT_URL, 'https://api.ffmpeg-api.com/ffmpeg/run');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: Basic YOUR_AUTH_KEY_HERE'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
$response = curl_exec($ch);
$result = json_decode($response, true);
 
if ($result['ok']) {
    foreach ($result['result'] as $output) {
        echo "Download: " . $output['file'] . " (" . $output['size'] . " bytes)\n";
    }
}
curl_close($ch);
?>

Other Tools

HTTPie:

Basic conversion:

http --form POST https://api.ffmpeg-api.com/ffmpeg/run \
    'Authorization:Basic YOUR_AUTH_KEY_HERE' \
    input.gif@/path/to/file.gif \
    command='{"inputs":[{"options":[],"file":"input.gif"}],"outputs":[{"options":[],"file":"output.mp4"}]}'

Video overlay with filter_complex:

http --form POST https://api.ffmpeg-api.com/ffmpeg/run \
    'Authorization:Basic YOUR_AUTH_KEY_HERE' \
    background.mp4@/path/to/background.mp4 \
    overlay.png@/path/to/overlay.png \
    command='{"inputs":[{"file":"background.mp4","options":[]},{"file":"overlay.png","options":["-loop","1"]}],"filter_complex":"[1:v]scale=200:100[ovrl];[0:v][ovrl]overlay=10:10[out]","outputs":[{"file":"result.mp4","options":["-c:v","libx264","-t","10"],"maps":["[out]"]}]}'

Postman:

  • Method: POST
  • URL: https://api.ffmpeg-api.com/ffmpeg/run
  • Headers: Authorization: Basic YOUR_AUTH_KEY_HERE
  • Body: form-data with file upload and command field
ℹ️

For more examples and use cases, check out our FFmpeg recipes section.