Making API Requests
The FFmpeg API accepts requests to process media files using FFmpeg commands. All requests are made to the main endpoint with file uploads and command parameters.
Endpoint
POST https://api.ffmpeg-api.com/ffmpeg/run
Request Format
The API uses multipart/form-data
for file uploads and accepts the following parameters:
Required Parameters
Parameter | Type | Description |
---|---|---|
command | JSON string | FFmpeg command structure with inputs and outputs |
File uploads | File | Media files referenced in the command |
Headers
Key | Value | Required |
---|---|---|
Authorization | Basic <Your Auth Key> | Yes |
Content-Type | multipart/form-data | Automatically set by curl |
Command Structure
The command
parameter must be a JSON string with the following structure:
{
"inputs": [
{
"options": [],
"file": "input_filename"
}
],
"outputs": [
{
"options": [],
"file": "output_filename",
"maps": []
}
],
"filter_complex": "optional_filter_graph"
}
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)
- Format:
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)
- Format:
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]"]
- Format:
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
Basic GIF to MP4 Conversion
Request Data:
- File:
input.gif
(your GIF file) - Command:
{"inputs":[{"options":[],"file":"input.gif"}],"outputs":[{"options":[],"file":"output.mp4"}]}
cURL Example:
curl -F "input.gif=@/path/to/your/file.gif" \
https://api.ffmpeg-api.com/ffmpeg/run \
-H 'Authorization: Basic YOUR_AUTH_KEY_HERE' \
-F 'command={"inputs":[{"options":[],"file":"input.gif"}],"outputs":[{"options":[],"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"}]}
cURL Example:
curl -F "video.mp4=@/path/to/video.mp4" \
https://api.ffmpeg-api.com/ffmpeg/run \
-H 'Authorization: Basic YOUR_AUTH_KEY_HERE' \
-F 'command={"inputs":[{"options":["-ss","00:00:10","-t","30"],"file":"video.mp4"}],"outputs":[{"options":["-c:v","libx264","-crf","23"],"file":"output.mp4"}]}'
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"}]}
cURL Example:
curl -F "video.mp4=@/path/to/video.mp4" \
-F "audio.mp3=@/path/to/audio.mp3" \
https://api.ffmpeg-api.com/ffmpeg/run \
-H 'Authorization: Basic YOUR_AUTH_KEY_HERE' \
-F 'command={"inputs":[{"options":[],"file":"video.mp4"},{"options":[],"file":"audio.mp3"}],"outputs":[{"options":["-c:v","copy","-c:a","aac"],"file":"output.mp4"}]}'
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
{
"inputs": [
{"file": "left_video.mp4", "options": []},
{"file": "right_video.mp4", "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
- Parameter names: Must match the
file
field in your command inputs - File paths: Any accessible file path (implementation depends on your tool/language)
- 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": "https://.../output.mp4?...",
"size": 104897
}
]
}
Response Fields:
ok
: Boolean indicating request successresult
: Array of output filesresult[].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
- Check file formats: Ensure input files are in supported formats
- Validate paths: Use absolute paths for file uploads
- Test commands: Validate FFmpeg syntax before API calls
- 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.