API DocsProcessing

Media Processing

Transform your uploaded files using the full power of FFmpeg through simple HTTP requests. Whether you’re converting formats, resizing videos, extracting audio, or creating complex multi-media workflows, this guide takes you from basic to advanced processing techniques.

Input Options

Each input’s file_path can be either an uploaded file (dir_id/filename) from the File Management workflow, or a direct HTTPS URL. URLs are automatically imported before processing.

Learning Path: Simple to Advanced

1

🎬 Basic Operations

Format conversion, simple transformations

2

⚙️ Intermediate

Filters, quality settings, multi-output

3

🚀 Advanced

Complex filters, multi-input workflows

The Processing Request

All processing happens through POST /ffmpeg/process with a JSON task definition:

const response = await fetch('https://api.ffmpeg-api.com/ffmpeg/process', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    task: {
      inputs: [{ file_path: 'dir_123/input.mp4' }],
      outputs: [{ file: 'output.mp4' }]
    }
  })
})
 
const result = await response.json()

Task Structure Overview

Required Fields
inputs[] → Array of input files with their file_path
inputs[].file_path → Either dir_id/filename (uploaded file) or an HTTPS URL
outputs[] → Array of output specifications with file names
Optional Fields
inputs[].options[] → FFmpeg options applied before input
outputs[].options[] → FFmpeg options for output
outputs[].maps[] → Stream mapping for complex workflows
filter_complex → Advanced filter graphs for multi-input processing
output_dir_id → Target directory for outputs (see below)

Directory Handling

When using URL inputs, the API needs to know where to store imported files and outputs:

Directory Resolution (in priority order)
1. Explicit: If output_dir_id is provided, use that directory
2. Inferred: If any input uses dir_id/filename format, use that directory
3. Auto-create: For URL-only inputs without output_dir_id, a temporary directory is created automatically

Example with mixed inputs:

const task = {
  inputs: [
    { file_path: 'dir_abc123/my-logo.png' },  // Uploaded watermark
    { file_path: 'https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4' }
  ],
  filter_complex: '[1:v][0:v]overlay=10:10[out]',
  outputs: [{ file: 'watermarked.mp4', maps: ['[out]', '1:a'] }]
  // Directory inferred from the uploaded file's dir_id
}

Example with explicit output directory:

const task = {
  inputs: [
    { file_path: 'https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4' }
  ],
  outputs: [{ file: 'thumbnail.jpg', options: ['-vframes', '1', '-ss', '5'] }],
  output_dir_id: 'dir_abc123'  // Explicit target directory
}
🔍

Important Constraints: For uploaded files, all must be from the same directory. Output filenames cannot conflict with input filenames. Files must not exceed your plan’s maximum size limit. URL inputs must be HTTPS and publicly accessible.

Sync vs Async Processing

FFmpeg API offers two ways to process files:

🚀 Synchronous (default)

Use POST /ffmpeg/process

  • • Returns results immediately
  • • Best for quick tasks (under 2 min)
  • • Simple request/response flow

⏳ Asynchronous

Use POST /ffmpeg/process/async

  • • Returns job_id immediately
  • • Best for long-running tasks
  • • Poll status or use webhooks

Async Processing Example

// 1. Submit async job
const submitRes = await fetch('https://api.ffmpeg-api.com/ffmpeg/process/async', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    task: {
      inputs: [{ file_path: 'dir_123/large-video.mp4' }],
      outputs: [{ file: 'converted.mp4', options: ['-crf', '23'] }]
    },
    webhook_url: 'https://yoursite.com/webhook' // optional
  })
})
 
const { job_id } = await submitRes.json()
console.log('Job submitted:', job_id)
 
// 2. Poll for status (or wait for webhook)
const statusRes = await fetch(`https://api.ffmpeg-api.com/job/${job_id}`, {
  headers: { 'Authorization': 'Basic YOUR_API_KEY' }
})
 
const status = await statusRes.json()
// status.status: 'pending' | 'processing' | 'completed' | 'failed'
💡

Webhooks: If you provide a webhook_url, we’ll POST the results to your server when the job completes. Must be HTTPS and publicly accessible.

See the API Reference for full endpoint details.

Understanding the Response

Successful processing returns detailed results and usage information:

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

📁 Result Files

file_name → Output filename
size_bytes → File size in bytes
download_url → Direct download link

📊 Usage Stats

time_sec → Processing time
gb_sec → Billing units consumed
input_size_gb → Input file sizes
output_size_gb → Output file sizes

🎬 Level 1: Basic Operations

Start with simple, single-input transformations:

Format Conversion

Convert a GIF to MP4 (uploaded file):

const task = {
  inputs: [
    { file_path: 'dir_123/animation.gif' }
  ],
  outputs: [
    { file: 'animation.mp4' }
  ]
}

Process from URL

Convert directly from a URL (no upload needed):

const task = {
  inputs: [
    { file_path: 'https://download.blender.org/peach/bigbuckbunny_movies/BigBuckBunny_320x180.mp4' }
  ],
  outputs: [
    { file: 'compressed.mp4', options: ['-crf', '28'] }
  ]
}
// A temporary directory is auto-created for outputs

Quality Control

Compress a video with specific quality settings:

const task = {
  inputs: [
    { file_path: 'dir_123/large-video.mp4' }
  ],
  outputs: [
    {
      file: 'compressed.mp4',
      options: ['-crf', '28', '-preset', 'medium']
    }
  ]
}

Extract Audio

Pull audio track from a video:

const task = {
  inputs: [
    { file_path: 'dir_123/movie.mp4' }
  ],
  outputs: [
    {
      file: 'soundtrack.mp3',
      options: ['-vn', '-acodec', 'mp3', '-ab', '192k']
    }
  ]
}

💡 Quick Reference: Common Output Options

Video Quality:
  • -crf 18 → High quality
  • -crf 23 → Good quality (default)
  • -crf 28 → Compressed
Audio Extraction:
  • -vn → No video
  • -acodec mp3 → MP3 format
  • -ab 192k → Audio bitrate

⚙️ Level 2: Intermediate Processing

Resize and Crop Videos

Resize to specific dimensions:

const task = {
  inputs: [
    { file_path: 'dir_123/fullhd-video.mp4' }
  ],
  outputs: [
    {
      file: 'mobile-video.mp4',
      options: [
        '-vf', 'scale=640:360',
        '-crf', '25'
      ]
    }
  ]
}

Trim Video Segments

Extract a 30-second clip starting at 1 minute:

const task = {
  inputs: [
    {
      file_path: 'dir_123/long-video.mp4',
      options: ['-ss', '60', '-t', '30']
    }
  ],
  outputs: [
    {
      file: 'highlight.mp4',
      options: ['-c:v', 'libx264', '-crf', '23']
    }
  ]
}

Multiple Output Files

Generate different versions from one input:

const task = {
  inputs: [
    { file_path: 'dir_123/source.mp4' }
  ],
  outputs: [
    {
      file: 'web-version.mp4',
      options: ['-vf', 'scale=1280:720', '-crf', '25']
    },
    {
      file: 'mobile-version.mp4',
      options: ['-vf', 'scale=640:360', '-crf', '28']
    },
    {
      file: 'audio-only.mp3',
      options: ['-vn', '-acodec', 'mp3']
    }
  ]
}

🚀 Level 3: Advanced Workflows

Multi-Input Processing

Combine separate video and audio:

const task = {
  inputs: [
    { file_path: 'dir_123/video.mp4' },
    { file_path: 'dir_123/audio.wav' }
  ],
  outputs: [
    {
      file: 'final.mp4',
      options: ['-c:v', 'copy', '-c:a', 'aac']
    }
  ]
}

Side-by-Side Video Comparison

Create split-screen view of two videos:

const task = {
  inputs: [
    { file_path: 'dir_123/before.mp4' },
    { file_path: 'dir_123/after.mp4' }
  ],
  filter_complex: '[0:v]scale=640:360[left];[1:v]scale=640:360[right];[left][right]hstack[out]',
  outputs: [
    {
      file: 'comparison.mp4',
      options: ['-c:v', 'libx264', '-crf', '23'],
      maps: ['[out]']
    }
  ]
}

Picture-in-Picture Overlay

Overlay a small video on top of a larger one:

const task = {
  inputs: [
    { file_path: 'dir_123/main-video.mp4' },
    { file_path: 'dir_123/overlay.mp4' }
  ],
  filter_complex: '[1:v]scale=320:180[overlay];[0:v][overlay]overlay=W-w-10:H-h-10[out]',
  outputs: [
    {
      file: 'picture-in-picture.mp4',
      options: ['-c:v', 'libx264', '-crf', '23'],
      maps: ['[out]', '0:a']
    }
  ]
}

Watermark Application

Add a logo watermark to a video:

const task = {
  inputs: [
    { file_path: 'dir_123/video.mp4' },
    { file_path: 'dir_123/logo.png' }
  ],
  filter_complex: '[0:v][1:v]overlay=W-w-10:10[out]',
  outputs: [
    {
      file: 'branded-video.mp4',
      options: ['-c:v', 'libx264', '-crf', '23'],
      maps: ['[out]', '0:a']
    }
  ]
}

Understanding Filter Complex

For advanced operations, filter_complex lets you create sophisticated processing pipelines:

// Filter syntax breakdown:
[0:v]scale=640:360[scaled];

│ │ │

Input Filter Output Label

Input References

  • [0:v] → Video from first input
  • [1:a] → Audio from second input
  • [2:v:0] → First video track from third input

Common Filters

  • scale=W:H → Resize video
  • hstack → Side-by-side layout
  • overlay=X:Y → Position overlay

Error Handling & Troubleshooting

❌ Error 400: “Invalid task format”

Check your task structure:

  • Ensure inputs and outputs are arrays
  • Verify all file_path values are strings
  • Options arrays should contain strings only
  • Output filenames must not conflict with inputs

❌ Error 500: “FFmpeg processing failed”

FFmpeg couldn’t process your command. Common causes:

  • Invalid FFmpeg options or syntax
  • Incompatible input/output formats
  • Complex filter syntax errors
  • Insufficient processing resources for large files

❌ Error 403: “File size exceeds plan limit”

One or more files exceed your plan’s maximum file size:

  • Free & Starter plans: 500 MB per file
  • Pro plan: 1 GB per file
  • Growth plan: 5 GB per file
  • Consider compressing large files or upgrading your plan

Example error: “File ‘video.mp4’ size (750.25 MB) exceeds plan (starter) max file size limit of 500 MB. See https://ffmpeg-api.com/pricing for more details.”

❌ Error 404: “File not found”

Referenced files don’t exist:

  • Verify file_path matches upload response exactly
  • Ensure all files are in the same directory
  • Check that files were successfully uploaded
  • List directory contents to confirm file presence

What’s Next?

Need more FFmpeg options? Check the Advanced Usage guide for comprehensive FFmpeg command reference and edge cases.