Originally published at ffmpeg-micro.com.
Most n8n users who want FFmpeg reach for the Execute Command node first. Makes sense. You've got a shell, you know the command, you just want to run ffmpeg -i input.mp4 output.webm and move on.
Then you hit the wall. n8n Cloud doesn't support Execute Command at all. Self-hosted? You need FFmpeg installed on the same machine, and the Execute Command node is a security risk that most production setups lock down. Even when it works, you're stuck managing FFmpeg versions, codecs, and disk space on your n8n server.
There's a better way. Use the HTTP Request node to call an FFmpeg API instead.
Why the Execute Command node breaks in production
The Execute Command node runs arbitrary shell commands on the n8n host machine. For video processing, that means:
- n8n Cloud users are locked out. The Execute Command node isn't available on n8n Cloud. If you're on Cloud, you literally can't run FFmpeg this way.
- Self-hosted setups need FFmpeg installed. You need to install FFmpeg on the same server, keep it updated, and make sure the right codecs are compiled in.
- Security exposure. Any workflow with Execute Command can run any shell command. Most teams disable it in production or restrict it behind environment flags.
- Resource contention. Video processing is CPU-heavy. Running FFmpeg on the same machine as n8n means your workflows compete with video jobs for CPU and memory.
None of these problems exist when you call an external API.
The HTTP Request node approach
Instead of running FFmpeg locally, send an HTTP request to a cloud FFmpeg service. The video gets processed on remote infrastructure, and n8n just orchestrates the workflow.
FFmpeg Micro is one such service. One POST request starts a transcode job. You poll for completion, then grab a download link. All through standard HTTP calls that work on n8n Cloud and self-hosted alike.
Step-by-step: convert a video in n8n
Here's the complete setup. Three HTTP Request nodes: start the job, wait for it to finish, get the download URL.
1. Start the transcode job
Add an HTTP Request node with these settings:
- Method: POST
-
URL:
https://api.ffmpeg-micro.com/v1/transcodes -
Authentication: Predefined Credential Type > Header Auth
- Name:
Authorization - Value:
Bearer YOUR_API_KEY
- Name:
- Body Content Type: JSON
- JSON Body:
{
"inputs": [
{ "url": "https://example.com/my-video.mp4" }
],
"outputFormat": "mp4",
"preset": {
"quality": "high",
"resolution": "1080p"
}
}
The inputs array takes public URLs or GCS URLs from the upload flow. outputFormat accepts mp4, webm, or mov. The preset object handles quality and resolution without writing raw FFmpeg flags.
This returns a job object with an id and status: "queued".
2. Poll until complete
Add a second HTTP Request node inside a loop (or use n8n's Wait node with a 10-second delay):
- Method: GET
-
URL:
https://api.ffmpeg-micro.com/v1/transcodes/{{ $json.id }} - Authentication: Same Header Auth credential
The response includes a status field. When it changes from queued to processing to completed, you're done. If it returns failed, the error_message field tells you what went wrong.
A simple approach: add a Wait node (10 seconds), then an IF node that checks {{ $json.status }} != "completed". Loop back to the Wait node if it's still processing.
3. Download the result
Once the job status is completed, grab the signed download URL:
- Method: GET
-
URL:
https://api.ffmpeg-micro.com/v1/transcodes/{{ $json.id }}/download - Authentication: Same Header Auth credential
This returns a url field with a signed HTTPS link valid for 10 minutes. Use another HTTP Request node to download the file, or pass the URL to the next step in your workflow (upload to S3, send via email, post to Slack).
Using advanced FFmpeg options
The preset system covers common operations, but you can also pass raw FFmpeg flags through the options array. This is useful for specific codec settings, bitrate control, or audio extraction.
Convert to WebM with a specific CRF value:
{
"inputs": [
{ "url": "https://example.com/input.mp4" }
],
"outputFormat": "webm",
"options": [
{ "option": "-c:v", "argument": "libvpx-vp9" },
{ "option": "-crf", "argument": "30" },
{ "option": "-b:v", "argument": "0" }
]
}
Extract audio only:
{
"inputs": [
{ "url": "https://example.com/video.mp4" }
],
"outputFormat": "mp4",
"options": [
{ "option": "-vn", "argument": "" },
{ "option": "-c:a", "argument": "aac" },
{ "option": "-b:a", "argument": "128k" }
]
}
These JSON bodies go straight into the HTTP Request node. No FFmpeg installation, no command-line syntax to debug.
Uploading local files from n8n
If your workflow generates video files (screen recordings, camera uploads, files from other nodes), you need to upload them before transcoding. FFmpeg Micro uses a 3-step upload flow:
Get a presigned URL: POST to
/v1/upload/presigned-urlwith the filename, content type, and file size. The response includes anuploadUrl.Upload the file: PUT the raw file bytes to the presigned URL. This goes directly to Google Cloud Storage, not through the API server.
Confirm the upload: POST to
/v1/upload/confirmwith the filename and file size. The response includes agcsUrlthat you pass to the transcode endpoint.
In n8n, each step is one HTTP Request node. The presigned URL upload is fast because n8n streams directly to cloud storage.
Common pitfalls
Using the wrong content type. The transcode endpoint needs Content-Type: application/json. n8n's HTTP Request node sets this automatically when you choose JSON body, but double-check if you're building the request manually.
Forgetting to poll. Transcode jobs are async. The POST request returns immediately with status: "queued". You need the polling loop to know when the output is ready.
Hardcoding the download URL. The signed download URL expires after 10 minutes. Always call the /download endpoint fresh when you need the file. Don't store the signed URL for later use.
Using options and preset together. If you include both in the request body, options takes priority and preset is ignored. Pick one approach per request.
FAQ
Can I use this on n8n Cloud?
Yes. The HTTP Request node works on n8n Cloud with no restrictions. That's the whole point. You don't need Execute Command, and you don't need FFmpeg installed anywhere.
What video formats does the API accept?
MP4, WebM, AVI, QuickTime (MOV), and MKV for video. MP3, WAV, FLAC, and AAC for audio. You can also pass public URLs to files hosted anywhere.
How long does a transcode take?
It depends on file size and complexity. A 1-minute 1080p video typically processes in 10-30 seconds. Longer videos or complex operations (multi-input compositions, H.265 encoding) take proportionally longer.
Is there a free tier?
FFmpeg Micro has a free tier with 10 minutes of processing per month. Enough to test your workflow and process a handful of videos. Paid plans start when you need more volume.
What if the job fails?
The job status changes to failed and the error_message field explains what went wrong. Common causes: unsupported input format, corrupted source file, or incompatible FFmpeg options. Check the error, fix the input, and retry.
Top comments (0)