@xnkee/n8n-nodes-ffmpeg
v0.4.2
Published
n8n community node for the ffmpeg-api service — probe, yt-dlp fetch, cookies management, vertical/reel normalization, trim, concat, burned-in subtitles, raw ffmpeg render and media file management, with binary or URL input.
Downloads
91
Maintainers
Readme
@xnkee/n8n-nodes-ffmpeg
n8n community node para o serviço ffmpeg_api — a API HTTP fina na frente do ffmpeg
que faz o render que o n8n não consegue fazer sozinho (o Code node roda num runner
sandboxed e a imagem n8nio/n8n não traz ffmpeg).
O serviço em si (main.py) mora no repositório da API, buildado no host como
ffmpeg-api:1.0. Este repositório é só o node.
Instalação
npm install
npm run buildPara publicar: npm publish (após npm login).
Pré-requisito da API: POST /files
As operações que aceitam binário (File → Upload, Video → Burn Subtitles e qualquer
Input vindo de um campo binário) precisam de uma rota de upload no serviço. Ela não
existia até a v0.3.0 — o código pronto está em
api-snippets/files_upload.py, é só colar no main.py
e rebuildar a imagem.
Sem ela, essas operações falham com The upload did not return a file name. Todo o
resto do node continua funcionando normalmente.
Credencial — FFmpeg API
| Campo | Padrão | Para quê |
|---|---|---|
| Base URL | http://ffmpeg_api:8080 | Só resolve dentro da rede Docker do serviço (VagasNet) |
| Request Timeout (Ms) | 900000 | Precisa ser ≥ RENDER_TIMEOUT do serviço, senão o n8n desiste antes do ffmpeg terminar |
| Media Directory | /data/media | Precisa bater com o MEDIA_DIR do serviço. Só é usado para montar caminho absoluto em filtros que abrem arquivo por conta própria, como o subtitles=. |
O teste da credencial bate em GET /health. Não há autenticação — o serviço não é
exposto publicamente de propósito, já que /render executa argumentos ffmpeg arbitrários.
Resources e operations
Video
| Operation | Rota | Notas |
|---|---|---|
| Burn Subtitles | POST /render | Queima a legenda na imagem. Subtitle Source: Text (cola o SRT direto), Binary Field ou File Name. Estilo (fonte, tamanho, cor, contorno, posição) nas Options. |
| Probe | POST /probe | duration_s, width, height, has_audio e o raw do ffprobe. Útil num IF antes de decidir o preset. |
| Fetch | POST /fetch | Baixa de sites com extração (YouTube, Instagram, TikTok, X...) via yt-dlp. URL é a página, não o arquivo direto. Mode: Video (padrão, mescla melhor vídeo+áudio em mp4) ou Audio (extrai mp3). Option Format sobrescreve o seletor -f do yt-dlp. |
| To Reel | POST /preset/reel | Normaliza para vertical. Mode: blur (padrão), crop, pad. Options: Width 1080, Height 1920, FPS 30, CRF 23, Preset veryfast. |
| Trim | POST /preset/trim | Start + Cut Until (End Time / Duration / End of Video). Option Re-Encode (padrão ligado) dá corte exato; desligado é instantâneo mas corta no keyframe. |
| Concatenate | POST /preset/concat | Mínimo 2 inputs. Mode padrão pad. Options: Width, Height, FPS. |
| Custom Render | POST /render | Arguments entram entre os -i e o output: [0:v] é o primeiro input, [1:v] o segundo. Output Extension define o container. |
File
| Operation | Rota |
|---|---|
| Get Many | GET /files — tudo que está no volume ffmpeg_media |
| Upload | POST /files — manda um campo binário do item, ou texto puro, para o volume. Devolve { file, url, bytes }. |
| Download | GET /files/{name} — devolve binário no campo escolhido em Put Output File in Field |
| Delete | DELETE /files/{name} — apaga antes da retenção automática de 24h |
Service
| Operation | Rota | Notas |
|---|---|---|
| Health Check | GET /health | |
| Cookies Status | GET /cookies/status | Se há cookies ativos e de onde vieram (writable ou secret) — nunca o conteúdo. |
| Update Cookies | PUT /cookies | Cookies File Content é o cookies.txt (formato Netscape) completo, exportado de uma sessão logada. Usado pelo Video → Fetch em sites que exigem login (ex.: bot-check do YouTube). Sem redeploy: repete a operação quando os cookies expirarem. |
| Clear Cookies | DELETE /cookies | Remove o cookies.txt gravável. |
Encadeamento sem trafegar bytes
Input / Inputs aceitam URL http(s) (o serviço baixa) ou o file devolvido por
uma chamada anterior. É assim que se encadeia trim → reel → concat sem os bytes
passarem pelo n8n:
FFmpeg (Trim) → {{ $json.file }}
FFmpeg (To Reel) → {{ $json.file }}
FFmpeg (Concatenate)Toda operação de render devolve o mesmo formato:
{
"file": "out_a1b2c3.mp4",
"url": "http://ffmpeg_api:8080/files/out_a1b2c3.mp4",
"bytes": 4821004,
"elapsed_s": 12.4
}Para publicar o resultado, o node de destino pode receber a url direto (se estiver na
mesma rede) ou usar File → Download para trazer os bytes como binário.
Entrada binária
Quando o arquivo já está como binário dentro do n8n (veio de um HTTP Request, de um Convert to File, do Google Drive...), não há URL para dar ao serviço. Nesses casos o node sobe os bytes para o volume antes de renderizar e passa adiante só o nome.
- Probe, To Reel, Trim, Burn Subtitles — o campo Input Source alterna entre
URL or File NameeBinary Field. - Concatenate, Custom Render — as listas continuam sendo de strings, então uma
entrada que comece com
binary:é lida como campo binário do item:binary:data. Isso permite misturar as duas coisas na mesma lista.
Inputs:
{{ $json.url }} ← o serviço baixa
binary:data ← o node sobe antes de renderizarPrefira URL ou nome de arquivo sempre que possível: o upload faz os bytes atravessarem o n8n duas vezes, e é justamente isso que o encadeamento por nome evita.
Legenda queimada
Video → Burn Subtitles monta o filtergraph sozinho, sem precisar escrever
-vf subtitles=... na mão:
| Subtitle Source | Quando usar | |---|---| | Text | O SRT está em texto, numa variável ou expressão. Cole ou mapeie direto — o node grava o arquivo no volume. | | Binary Field | O SRT veio como arquivo binário (ex.: um Convert to File antes). | | File Name | A legenda já está no volume, de um File → Upload anterior. |
O subtitles= não é um -i: o filtro abre o arquivo por caminho, então passar o
SRT como input não funciona. É por isso que existe o campo Media Directory na
credencial — o node monta <Media Directory>/<arquivo> para o filtro.
Dois detalhes que costumam morder:
- Fonte.
Font Nameprecisa estar instalada no container do serviço. Se não estiver, o libass cai numa fonte padrão sem avisar. Uma imagem enxuta muitas vezes não tem fonte nenhuma além da do fontconfig. - Acento.
Character EncodingéUTF-8por padrão. Legenda gerada em Windows às vezes vem emlatin1, e o sintoma é acento virando caractere estranho no vídeo.
Cores são informadas em #RRGGBB normal — o node converte para o &HBBGGRR que o ASS
usa, que é a razão clássica de "pedi vermelho e saiu azul" quando se escreve o
force_style na mão.
Listas dinâmicas (Concatenate / Custom Render)
Inputs e Arguments têm dois modos:
- List — uma entrada por item, montada na UI.
- Array or Comma-Separated — um único campo que aceita um array vindo de expressão
(
{{ $json.clips }}), uma string de array JSON ou uma lista separada por vírgula.
Erros
Erro 422 do serviço traz o stderr do ffmpeg no detail — o node propaga isso na
description do erro, que é onde está a causa real quando um filtergraph está errado.
Retenção
Os arquivos são apagados após RETENTION_HOURS (24h por padrão). Não guarde nada
definitivo no volume — baixe ou publique dentro da janela.
