Video compression often starts with a single FFmpeg command. In an automation workflow, you also need to submit the job, wait for it, handle failures, and pass the result to the next step.
This walkthrough uses the FFHub community node to do that in n8n. FFmpeg runs on FFHub's infrastructure, so you don't need to install it on your n8n server.
Disclosure: I'm the developer of FFHub. It is a hosted service that requires an account and API key. The n8n node source code is available under the MIT license; using the hosted service is separate from the node's license.
What we'll build
Create this sequence of nodes:
Manual Trigger → FFHub (Create Task) → FFHub (Wait for Completion) → IF
├─ true: use output URL
└─ false: inspect error
The first FFHub node submits the command and returns a task ID. The second polls that task until it succeeds or fails. The IF node decides what to do with the result.
1. Install the node and add credentials
On a self-hosted n8n instance with community nodes enabled:
- Open Settings → Community nodes → Install.
- Enter
@ffhub/n8n-nodes-ffhub. This walkthrough uses version 0.2.1. - In your FFHub dashboard, create an API key.
- In n8n, create FFHub API credentials with that key. Keep the default API Base URL:
https://api.ffhub.io/v1. - Select those credentials in both FFHub nodes.
You'll also need a direct HTTPS URL to a video you can use. It must be accessible to the remote processing service. A local file path, a YouTube watch page, or a storage sharing page is not a direct media URL.
n8n Cloud: npm publication alone does not make a community node available in the Cloud node picker. If this package is unavailable on your instance, the alternative is an integration through n8n's built-in HTTP Request node and the FFHub API. The steps below use the community node.
2. Submit a compression command
Add a Manual Trigger, then an FFHub node with operation Create Task.
Paste this into FFmpeg Command, replacing the placeholder input URL with your own direct video URL:
ffmpeg -i https://example.com/input.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k -movflags +faststart output.mp4
The command encodes video as H.264 and audio as AAC:
-
-crf 28selects a quality level. Lower values generally preserve more detail and produce larger files; higher values trade quality for smaller files. -
-preset fastcontrols the encoding speed/compression tradeoff. -
-b:a 128ksets the audio bitrate. -
-movflags +faststartmoves MP4 metadata to the beginning of the file to help playback begin before the entire file downloads.
This is a starting point, not a guaranteed size reduction. An already heavily compressed input might not become smaller. Compare the output's size and visual quality before choosing settings for your workflow.
3. Wait using the returned task ID
Connect a second FFHub node and choose Wait for Completion. Set Task ID to this n8n expression:
{{ $json.task_id }}
Version 0.2.1 defaults to a 5-second polling interval and a 600-second timeout. Adjust the timeout to suit your files.
A timeout while waiting does not by itself establish that the remote job failed. Keep the original task ID so you can check it later with Get Task instead of blindly submitting another conversion.
4. Check success before using the output
Add an IF node after Wait for Completion. Configure a string condition:
- Value:
{{ $json.status }} - Operation: is equal to
- Compare with:
succeeded
On the true branch, access the first output file URL with:
{{ $json.outputs[0].url }}
Pass it to a downstream step that accepts a URL. To download the actual bytes in n8n, use an HTTP Request node with method GET, this expression as the URL, and response format File. You can then connect a storage upload node appropriate to your destination.
On the false branch, inspect the task's status and error fields. Wait for Completion returns on failure too: execution reaching the next node is not evidence of a successful conversion. HTTP errors and polling timeouts also need n8n's execution error handling.
Another example: extract an MP3
Keep the same task-submission and polling sequence, but replace the command:
ffmpeg -i https://example.com/input.mp4 -vn -c:a libmp3lame -q:a 2 output.mp3
Here, -vn disables video output, and -q:a 2 selects variable-bitrate MP3 audio quality. This example requires an input with an audio track.
Before automating a batch
Start with one short video. Confirm that FFHub can fetch the input, the task reaches succeeded, the output URL downloads correctly, and the result meets your quality requirements. Then replace Manual Trigger with the event source your workflow needs.
You can find the package on npm and the implementation and setup instructions on GitHub.
Which video-processing step would you want to automate in n8n: compression, audio extraction, thumbnails, or something else?
Top comments (0)