FFmpeg Editor API
Process and transform media using your own FFmpeg command safely on our infrastructure. Submit a job with your media and a command template, then poll the job until it finishes and download the result.
Endpoint
POST /api/uploadposts/ffmpeg/jobs/upload
Headers
| Name | Value | Description |
|---|---|---|
| Authorization | Apikey your-api-key-here | Your API key for authentication. |
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| file | File (binary) | Yes | Media file to process. |
| full_command | String | Yes | FFmpeg command template that MUST use {input} and {output} placeholders. Example: ffmpeg -y -i {input} -c:v libx264 -crf 23 {output} |
| output_extension | String | Yes | Desired output file extension (e.g., mp4, wav, mp3, mov, webm). |
Note: If the duration of the input media cannot be detected, the system assumes 60 seconds for quota calculation.
Command Template Rules
For security and reliability, only safe FFmpeg commands are accepted.
- Use placeholders:
{input}(or indexed{input0},{input1}, …) for input files and{output}for the output file; do not hardcode filenames. The first input can be referenced as{input}or{input0}. - Allowed pattern starts with
ffmpegand may include typical flags (e.g.,-y,-i,-c:v,-c:a,-r,-b:v, filters, etc.). - Blocked characters/constructs to prevent command injection:
;,|,&,$,\``,$(, newlines, carriage returns, and destructive commands likerm/rmdir`. - If validation fails, the API returns 400 Bad Request with a helpful message.
Responses
- 202 Accepted (job created)
{
"success": true,
"job_id": "a97bbb5a-139b-46ca-b893-6e8d303d5934",
"status": "PENDING"
}
Check Job Status
Poll the job until it finishes.
GET /api/uploadposts/ffmpeg/jobs/{job_id}
Example response:
{
"job_id": "a97bbb5a-139b-46ca-b893-6e8d303d5934",
"status": "FINISHED",
"duration_seconds": 120,
"output_extension": "mp4"
}
Statuses: PENDING, PROCESSING, FINISHED, ERROR.
Download Result
When status is FINISHED, download the processed file.
GET /api/uploadposts/ffmpeg/jobs/{job_id}/download
Response headers include the appropriate Content-Type and a Content-Disposition attachment filename (e.g., output.mp4, output.wav). The response body is the binary media.
Example: Convert to MP4 (H.264)
curl \
-H 'Authorization: Apikey your-api-key-here' \
-F 'file=@/path/to/input.mov' \
-F 'full_command=ffmpeg -y -i {input} -c:v libx264 -preset medium -crf 23 -c:a aac -b:a 128k {output}' \
-F 'output_extension=mp4' \
-X POST https://api.upload-post.com/api/uploadposts/ffmpeg/jobs/upload
Example: Extract Audio to WAV
curl \
-H 'Authorization: Apikey your-api-key-here' \
-F 'file=@/path/to/input.mp4' \
-F 'full_command=ffmpeg -y -i {input} -vn -acodec pcm_s16le -ar 44100 -ac 2 {output}' \
-F 'output_extension=wav' \
-X POST https://api.upload-post.com/api/uploadposts/ffmpeg/jobs/upload
Concatenate/Merge multiple videos (NEW)
The API now supports multiple input files for operations like concatenation. You can use placeholders {input0}, {input1}, {input2}, etc., in full_command.
Option A: Send multiple URLs (JSON endpoint)
curl -X POST https://api.upload-post.com/api/uploadposts/ffmpeg/jobs \
-H 'Content-Type: application/json' \
-H 'Authorization: Apikey your-api-key-here' \
-d '{
"files": [
"https://tu-cdn.com/video1.mp4",
"https://tu-cdn.com/video2.mp4",
"https://tu-cdn.com/video3.mp4"
],
"full_command": "ffmpeg -y -hide_banner -i {input0} -i {input1} -i {input2} -filter_complex \"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]\" -map \"[outv]\" -map \"[outa]\" -c:v h264_nvenc -preset p5 -cq 23 -c:a aac -b:a 128k {output}",
"output_extension": "mp4",
"publish": true
}'
Option B: Upload multiple files (multipart/form-data)
curl -X POST https://api.upload-post.com/api/uploadposts/ffmpeg/jobs/upload \
-H 'Authorization: Apikey your-api-key-here' \
-F "file=@/ruta/video1.mp4" \
-F "file1=@/ruta/video2.mp4" \
-F "file2=@/ruta/video3.mp4" \
-F 'full_command=ffmpeg -y -hide_banner -i {input0} -i {input1} -i {input2} -filter_complex "[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" -c:v h264_nvenc -preset p5 -cq 23 -c:a aac -b:a 128k {output}' \
-F "output_extension=mp4" \
-F "publish=true"
Concatenation examples
Simple concatenation (2 videos):
{
"files": ["https://cdn.com/part1.mp4", "https://cdn.com/part2.mp4"],
"full_command": "ffmpeg -y -i {input0} -i {input1} -filter_complex \"[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]\" -map \"[v]\" -map \"[a]\" -c:v h264_nvenc -cq 23 -c:a aac {output}",
"output_extension": "mp4"
}
Concatenation with re-encoding (multiple videos):
{
"files": [
"https://cdn.com/intro.mp4",
"https://cdn.com/contenido.mp4",
"https://cdn.com/outro.mp4"
],
"full_command": "ffmpeg -y -hwaccel cuda -i {input0} -i {input1} -i {input2} -filter_complex \"[0:v][0:a][1:v][1:a][2:v][2:a]concat=n=3:v=1:a=1[outv][outa]\" -map \"[outv]\" -map \"[outa]\" -c:v h264_nvenc -preset p5 -rc vbr -cq 23 -b:v 4M -c:a aac -b:a 128k {output}",
"output_extension": "mp4"
}
Using the concat demuxer (no re-encoding — faster but requires identical formats):
First create a text file with the list of videos, upload it as file and the videos as file1, file2, etc.:
# Create list (concat-list.txt)
echo "file '/work/.../in-src-0'" > concat-list.txt
echo "file '/work/.../in-src-1'" >> concat-list.txt
echo "file '/work/.../in-src-2'" >> concat-list.txt
# Note: For this method you'll need to adjust paths in the command or use the filter_complex method above
Important: The
{input}placeholder still works as before (points to the first file). For multiple inputs, use{input0},{input1},{input2}, etc.
Limitation: The predefined presets (
h264_social,hevc_social,copy_mux) andffmpeg_argsonly support a single file. For multiple inputs, you must usefull_command.
Quotas by Plan (minutes of media/month)
| Plan | Minutes/Month |
|---|---|
| free | 30 |
| basic | 300 |
| professional | 1000 |
| advanced | 3000 |
| business | 10000 |
Resets on the 1st of each month at 00:00 UTC.
Errors
- 400 Bad Request: Invalid or unsafe FFmpeg command, missing parameters.
- 401 Unauthorized: Invalid or expired API key.
- 404 Not Found: Job not found.
- 429 Too Many Requests: Monthly quota exceeded (response includes current usage when applicable).
- 500 Internal Server Error: Processing error.
Notes
- Jobs are asynchronous; always poll the job status before attempting to download the output.
- Quota checks use detected media duration to ensure fair usage across plans.