LearnIntegrationsn8n Automation

n8n + FFmpegAPI

This guide walks you through a minimal but complete n8n workflow:

  • Upload a file to FFmpeg API
  • Run a processing task (e.g., convert to MP4 or change codec/CRF)
  • Download the result and store it (Filesystem, S3, Google Drive, etc.)

No prior experience with FFmpeg or n8n required.

💡

You’ll need an FFmpeg API key. In production, never hardcode secrets; store them in environment variables or n8n Credentials.

What you’ll build

An n8n workflow triggered by a manual run or a Webhook:

  1. Get an upload URL from our API

  2. Upload the input file bytes to the returned pre‑signed URL

  3. Start an FFmpeg processing task

  4. Download the result and save it

Overview diagram

API endpoints used

  • POST /file → returns { upload.url, file.file_path }
  • PUT upload.url → uploads your bytes
  • POST /ffmpeg/process → starts a task and returns the result with download URLs

See also: Quick Start, Processing, Examples.

Prepare credentials in n8n

Use n8n’s Credentials to store your API key as FFMPEG_API_KEY.

  • Create a new Environment Variable or Generic Credential in n8n
  • Name: FFMPEG_API_KEY
  • Value: your live API key (found in Dashboard)

Build the workflow step by step

1) Trigger node

  • Add a Manual Trigger (for tests) or a Webhook node (for automation)
  • If using Webhook, set HTTP Method to POST and expect a file URL or base64 input in the payload

2) Get upload URL (HTTP Request)

  • Add an HTTP Request node named Get Upload URL
  • Method: POST
  • URL: https://api.ffmpeg-api.com/file
  • Headers:
    • Authorization: Basic {{$env.FFMPEG_API_KEY}}
    • Content-Type: application/json
  • Body: JSON

Body JSON (if you already know the filename):

{
  "file_name": "input.mp4"
}

Expected response shape:

{
  "file": { "file_path": "<dir>/input.mp4" },
  "upload": { "url": "https://...presigned-url..." }
}

3) Upload bytes (Binary upload)

There are two common patterns for getting the input bytes into n8n:

  • If you have a public file URL: add an HTTP Request node to GET the file with Download enabled → a binary property (e.g., data) becomes available
  • If your trigger contains base64: use Move Binary Data to create a binary property from base64

Now add another HTTP Request node named Upload to Presigned URL:

  • Method: PUT
  • URL: ={{$json["upload"]["url"]}} (use the expression editor to reference the previous node’s output)
  • Send: Binary
  • Binary Property: data (or the property you created)
  • Do not set Authorization headers; presigned URLs typically do not require them

4) Start processing (HTTP Request)

Add an HTTP Request node named Start Processing:

  • Method: POST
  • URL: https://api.ffmpeg-api.com/ffmpeg/process
  • Headers:
    • Authorization: Basic {{$env.FFMPEG_API_KEY}}
    • Content-Type: application/json
  • Body: JSON

Minimal body example that re-encodes input to MP4 with a target quality:

{
  "task": {
    "inputs": [{ "file_path": "={{$json["file"]["file_path"]}}" }],
    "outputs": [
      { "file": "output.mp4", "options": ["-c:v", "libx264", "-crf", "23"] }
    ]
  }
}

Response contains the completed result with download URLs.

5) Download the result

Use the first result’s download_url from the previous step:

  • Add HTTP Request node named Download Result
  • Method: GET
  • URL: ={{$json["result"][0]["download_url"]}}
  • Download: true (to store as binary)
  • Binary Property: result

6) Save the file

Choose any storage node. Common options:

  • Write Binary File (local n8n host)
  • S3: set credentials, bucket, and Binary Property = result
  • Google Drive: use Upload with Binary Property = result

Common variations

  • Multiple outputs: add more outputs entries in the process body
  • Different formats: change encoder and extension (e.g., libx265 + output.hevc.mp4)
  • Thumbnails or GIFs: use -vf scale, fps, or palette filters; see Recipes

Troubleshooting

⚠️

If you see 401/403 errors, verify the Authorization header, and ensure your API key is present in n8n credentials as FFMPEG_API_KEY.

  • Upload PUT fails: ensure you are sending Binary data and not JSON
  • Task stuck in queued: try smaller inputs or verify your plan limits
  • Download empty: confirm status is completed and pick the correct result[index]

Full example payloads

Request to /ffmpeg/process:

{
  "task": {
    "inputs": [
      { "file_path": "<dir>/input.mp4" }
    ],
    "outputs": [
      { "file": "output.mp4", "options": ["-c:v", "libx264", "-crf", "23"] }
    ]
  }
}

Example completed task response:

{
  "status": "completed",
  "result": [
    {
      "file": "output.mp4",
      "download_url": "https://..."
    }
  ]
}

Next steps

  • Add a Webhook trigger to accept file URLs from your app
  • Add branching (IF node) to pick different FFmpeg options per input size
  • Chain follow‑up steps: notify via Slack/Email with result link