n8n Video Processing: The Complete Guide

February 14, 2026 · RenderIO

n8n can automate everything except video processing

n8n connects APIs, transforms data, and automates workflows. It handles HTTP requests, file operations, database queries, and hundreds of integrations. But it can't run FFmpeg.

If your workflow involves video, you hit a wall. n8n Cloud doesn't give you shell access. You can't install binaries. The Execute Command node doesn't exist in the cloud version. (For a focused explanation of why this happens and the exact workaround, see n8n + FFmpeg: the cloud fix.)

The fix: use the HTTP Request node to call a video processing API. Send your FFmpeg command to RenderIO, get back processed files.

This guide shows you how to set up video processing in any n8n workflow, from a single conversion to a full batch pipeline.

Why n8n can't process video natively

n8n Cloud runs in a sandboxed environment. Each workflow execution has limited CPU, memory, and no filesystem access beyond temporary data. Even n8n self-hosted on a small VPS doesn't have the resources for video encoding.

Video processing is CPU-intensive. A 5-minute H.264 encode can consume 100% of a core for 3-8 minutes. Running that inside an n8n workflow would block all other executions.

The right architecture: offload video processing to a dedicated service and use n8n for orchestration.

The fastest path: RenderIO's official n8n node

RenderIO has a partner-verified community node available on the n8n marketplace. It wraps the entire API into a native n8n node with a visual interface — no HTTP Request configuration needed.

The node supports:

  • Run commands: Execute single, chained, or parallel FFmpeg commands

  • File management: Store, upload, retrieve, and delete media files

  • Presets: Use reusable FFmpeg templates from a searchable dropdown

  • Auth: OAuth2 (recommended for n8n Cloud) or API key

Install it from Settings → Community Nodes → search "renderio".

For most workflows, the native node is the quickest way to get started. The rest of this guide covers the HTTP Request approach for cases where you need full control over the API calls.

The building blocks of n8n video processing

Every n8n video processing workflow uses three components:

  1. Trigger node: Starts the workflow (webhook, schedule, file upload, etc.)

  2. HTTP Request node: Sends the FFmpeg command to RenderIO

  3. HTTP Request node: Polls for the result (or use a webhook)

If you're using the native RenderIO node, the RenderIO node replaces both HTTP Request nodes above. You still need the trigger and the polling or webhook pattern to check for completion.

That's it. Three nodes for any video operation.

Setting up your first workflow

Step 1: Configure credentials

In n8n, create a Header Auth credential:

  • Name: RenderIO API

  • Header Name: X-API-KEY

  • Header Value: ffsk_your_api_key

You'll use this credential in every HTTP Request node.

Step 2: Submit the FFmpeg command

Add an HTTP Request node with these settings:

  • Method: POST

  • URL: https://renderio.dev/api/v1/run-ffmpeg-command

  • Authentication: Header Auth (select your RenderIO credential)

  • Body Content Type: JSON

  • Body Parameters:

{
  "ffmpeg_command": "-i {{in_video}} -c:v libx264 -preset fast -crf 22 -c:a aac {{out_video}}",
  "input_files": {
    "in_video": "{{ $json.videoUrl }}"
  },
  "output_files": {
    "out_video": "processed.mp4"
  }
}

The {{ $json.videoUrl }} expression pulls the input URL from the previous node's output. Adjust this based on your trigger.

Watch the braces: n8n expressions use double braces {{ }}, while RenderIO placeholders use single braces {{in_video}}. They look similar but do different things. The n8n expression {{ $json.videoUrl }} gets replaced by n8n before the request is sent. The RenderIO placeholder {{in_video}} gets replaced by the API server when it builds the FFmpeg command. Don't mix them up.

Step 3: Wait for processing

Add a Wait node set to 5 seconds.

Then add another HTTP Request node:

  • Method: GET

  • URL: https://renderio.dev/api/v1/commands/{{ $('Submit FFmpeg').item.json.command_id }}

  • Authentication: Header Auth (RenderIO credential)

Step 4: Check if complete

Add an IF node:

  • Condition: {{ $json.status }} equals completed

True branch: Continue to your next step (download, upload, notify, etc.) False branch: Loop back to the Wait node (add a Loop node or use a simple back-connection)

Step 5: Use the result

The completed response includes output_files with download URLs. Pass these to your next nodes: upload to S3, post to Slack, update a database, trigger another workflow.

Complete workflow: Convert uploaded videos

Here's a practical workflow that watches a webhook for new video URLs, converts them to MP4, and sends a Slack notification:

Node 1: Webhook Trigger

  • Path: /video-upload

  • HTTP Method: POST

  • Expects body: { "videoUrl": "https://..." }

Node 2: Submit FFmpeg (HTTP Request)

{
  "ffmpeg_command": "-i {{in_video}} -c:v libx264 -crf 22 -c:a aac {{out_video}}",
  "input_files": { "in_video": "{{ $json.videoUrl }}" },
  "output_files": { "out_video": "converted.mp4" }
}

Node 3: Wait (5 seconds)

Node 4: Check Status (HTTP Request)

  • GET https://renderio.dev/api/v1/commands/{{ $('Submit FFmpeg').item.json.command_id }}

Node 5: IF (status === "SUCCESS")

True → Node 6: Slack (send message with download URL)

False → Loop back to Node 3

This entire workflow takes 5 minutes to build. It handles any video format as input and produces a web-ready MP4.

Webhook-based completion (skip the polling loop)

Polling works, but there's a cleaner approach. Instead of looping back to check status every 5 seconds, you can tell RenderIO to ping you when the job finishes.

The idea: submit the FFmpeg command with a webhook_url pointing back to an n8n webhook. When processing completes, RenderIO sends a POST to that URL with the result.

Workflow A — Submit and forget:

  1. Webhook Trigger (receives the initial request)

  2. HTTP Request: POST to RenderIO with webhook_url set to your completion webhook

  3. Respond to Webhook: Return { "status": "processing" } immediately

Workflow B — Handle completion:

  1. Webhook Trigger at path /video-complete

  2. The incoming payload has command_id, status, and output_files

  3. Continue with your downstream logic (upload, notify, etc.)

{
  "ffmpeg_command": "-i {{in_video}} -c:v libx264 -crf 22 -c:a aac {{out_video}}",
  "input_files": { "in_video": "{{ $json.videoUrl }}" },
  "output_files": { "out_video": "converted.mp4" },
  "webhook_url": "https://your-n8n-instance.app.n8n.cloud/webhook/video-complete"
}

Why bother? Polling loops consume n8n executions. Each loop iteration counts toward your execution limit. Webhooks use one execution for the submit and one for the callback. For high-volume workflows, that difference adds up fast.

Common FFmpeg commands for n8n workflows

Here are the FFmpeg commands you'll use most in n8n. For the full list, check the FFmpeg cheat sheet. The Python, Node.js, and curl guides show these same commands called directly from code if you want to skip n8n for simpler pipelines.

Convert to MP4 (universal):

-i {{in_video}} -c:v libx264 -crf 22 -c:a aac {{out_video}}

Resize to 720p:

-i {{in_video}} -vf scale=-2:720 -c:v libx264 -crf 23 {{out_video}}

Compress for email/chat:

-i {{in_video}} -c:v libx264 -crf 28 -preset slow -c:a aac -b:a 96k {{out_video}}

Extract audio:

-i {{in_video}} -vn -acodec libmp3lame -q:a 2 {{out_audio}}

Generate thumbnail:

-i {{in_video}} -ss 00:00:05 -vframes 1 -q:v 2 {{out_thumb}}

TikTok format (1080x1920):

-i {{in_video}} -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2:black" -c:v libx264 -crf 23 -c:a aac {{out_video}}

Dynamic commands with expressions

n8n's expression engine lets you build FFmpeg commands dynamically. For example, resize video in n8n based on a variable:

-i {{in_video}} -vf scale=-2:{{ $json.targetHeight }} -c:v libx264 -crf 23 {{out_video}}

Or trim based on timestamps from a database:

-i {{in_video}} -ss {{ $json.startTime }} -t {{ $json.duration }} -c copy {{out_video}}

This makes your workflows adaptable. The same workflow handles different operations based on input parameters.

Error handling

Getting the happy path right is easy. The real work is handling failures gracefully. Here's what to cover:

HTTP Request errors

Use n8n's "Continue on Fail" option on the submit node. In the next node, check if {{ $json.error }} exists. If it does, route to an error handler (a Slack message or a row in a Google Sheet for retry later).

Common causes: expired API key, malformed JSON body, RenderIO returning a 429 (rate limit). For rate limits, add a Wait node and retry.

Processing failures

The status check returns "status": "FAILED" with an error message when something goes wrong server-side. Typical culprits:

  • Bad input URL: the file doesn't exist or needs authentication. Double-check that your source URLs are publicly accessible or use signed URLs with enough expiry time.

  • Invalid FFmpeg flags: a typo in the filter chain, or using a filter that doesn't exist. Test your command locally first with ffmpeg -i test.mp4 ... before putting it in n8n.

  • Unsupported codec: asking for a codec that's not compiled into the FFmpeg build. Stick with libx264/libx265/aac and you're fine.

IF: {{ $('Check Status').item.json.status }} equals "FAILED"
  → Send error notification with {{ $json.error }}
  → Log to error tracking sheet

Timeout protection

Without a timeout, a failed polling loop runs forever (or until n8n kills it). Add a counter using the Function node:

const attempts = ($json.pollCount || 0) + 1;
if (attempts > 60) {
  return { status: 'timeout', message: 'Processing exceeded 5 minutes' };
}
return { pollCount: attempts, ...$json };

Route the timeout case to an alert. Sixty iterations at 5-second intervals gives you 5 minutes, enough for most videos under 10 minutes long.

Complete workflow: Batch process a folder

Here's a more advanced pattern. Say you have a Google Drive folder where your team drops raw videos. You want to convert them all to 720p MP4 and move them to a "Processed" folder.

Node 1: Schedule Trigger — runs every hour

Node 2: Google Drive — List files in the "Raw Videos" folder

Node 3: Split In Batches — process 5 at a time (keeps API usage predictable)

Node 4: HTTP Request — submit FFmpeg command for each file:

{
  "ffmpeg_command": "-i {{in_video}} -vf scale=-2:720 -c:v libx264 -crf 23 -c:a aac {{out_video}}",
  "input_files": { "in_video": "{{ $json.webContentLink }}" },
  "output_files": { "out_video": "{{ $json.name }}" }
}

Node 5: Wait (10 seconds)

Node 6: Check Status — GET the command status

Node 7: IF — completed? Route accordingly.

Node 8: Google Drive — Upload to "Processed" folder

Node 9: Google Drive — Move original to "Archive" folder

This pattern works for any source: S3 buckets, Dropbox folders, Airtable records with video URLs. Swap the trigger and storage nodes and the core processing stays the same.

For more batch patterns, see the n8n batch video processing guide.

Common mistakes

Using the wrong node for polling. The Loop node in n8n works, but the back-connection approach (drawing a connector from the IF false output back to the Wait node) is simpler for status polling. The Loop node is better for iterating over arrays.

Forgetting movflags +faststart. If you're producing MP4s for web playback, add -movflags +faststart to your FFmpeg command. Without it, the browser has to download the entire file before playing. This is an FFmpeg thing, not an n8n thing, but it trips people up.

Hardcoding wait times. A 5-second wait works for short clips. A 30-minute video might take 2-3 minutes. Start with short waits and let the polling loop handle it. That's what it's for.

Not handling n8n execution limits. n8n Cloud plans have execution limits. Each polling loop iteration counts as part of one execution (not separate executions), but very long-running workflows can hit timeout limits. Webhooks are better for production if you're processing lots of videos.

Performance tips

  • Parallel processing: n8n's Split in Batches node lets you process multiple videos concurrently. Each batch item submits its own API call. Start with batches of 5-10 and scale up.

  • Webhook vs polling: For production workflows, use the webhook approach described above. Replace the polling loop with a Webhook Trigger that receives completion events. Less execution overhead, more reliable.

  • Caching: If you process the same video multiple times (different sizes, formats), submit all commands at once and poll for all results. The FFmpeg API complete guide covers parallel command submission in detail.

  • Preset selection: -preset fast gives you decent speed. -preset slow gives smaller files but takes longer. For batch workflows where time isn't critical, slow saves bandwidth downstream.

Monitoring and logging

Once your video workflows run in production, you need visibility into what's happening. n8n gives you execution logs, but they won't tell you why an FFmpeg command failed or how long encoding took.

Log the command ID. After the submit node, route the command_id to a Google Sheet, Airtable, or database. When something fails three days later, you can look up the exact command and re-run it.

Track processing time. Add a Function node after the status check that calculates elapsed time:

const submitted = new Date($('Submit FFmpeg').item.json.created_at);
const completed = new Date($json.completed_at);
const seconds = (completed - submitted) / 1000;
return { processingTime: seconds, ...$json };

Log this alongside the command ID. If processing times spike, you know something changed: larger input files, heavier filter chains, or API-side issues.

Set up failure alerts. Route the FAILED status path to a Slack or email notification that includes the error message and input URL. Don't just log it and move on. Failed video jobs usually mean a user is waiting for output that never arrives.

Dashboard it. For high-volume workflows, push metrics (jobs submitted, completed, failed, average processing time) to a simple dashboard. A Google Sheet with a chart works. So does a Notion database. You don't need Grafana for 50 videos a day.

FAQ

Can n8n Cloud run FFmpeg?

No. n8n Cloud runs in a sandboxed environment with no shell access and no way to install binaries. You need an external API like RenderIO to handle FFmpeg commands. Self-hosted n8n technically can run FFmpeg via the Execute Command node, but you'd need a beefy server and careful resource management.

How long does video processing take?

It depends on the input file size, the complexity of your FFmpeg command, and the output format. A straightforward format conversion on a 2-minute clip typically finishes in 5-15 seconds. Heavy filter chains or long videos can take 1-3 minutes. The status polling loop handles the wait automatically.

Can I process multiple videos in parallel?

Yes. Use n8n's Split In Batches node to send multiple API requests concurrently. Each request gets its own command_id, so you can poll them independently. Start with small batches (5-10) and increase based on your plan's command limits.

What happens if the RenderIO API is down?

The HTTP Request node will return an error. Use "Continue on Fail" to catch it and route to a retry path or error notification. For production workflows, add a retry loop with exponential backoff: wait 10 seconds, then 30, then 60. If it's still down after 3 retries, alert your team and queue the job for later.

How do I handle large files?

RenderIO accepts input files via URL, so you don't upload through n8n. Point the input_files field at a URL where the video is hosted: S3, Google Drive (with a direct link), Cloudflare R2, anywhere with an HTTP-accessible URL. There's no file size limit on the API side, though very large files (over 2GB) will take longer to process.

Getting started with n8n video processing

The Starter plan (9/mo,500commands)coversdevelopmentandtesting.Forproductionworkflowsprocessingvideosregularly,theGrowthplan(9/mo, 500 commands) covers development and testing. For production workflows processing videos regularly, the Growth plan (29/mo, 1,000 commands) or Business plan ($99/mo, 20,000 commands) gives you room to scale.

Check the n8n convert video guide for format-specific examples, or jump to the full FFmpeg API reference for every available option.