← All posts

FFmpeg em Serverless e Lambda: desafios e soluções

Por que rodar FFmpeg em AWS Lambda, Vercel e Cloudflare Workers dói — tamanho de binário, timeouts, memória, cold starts — e alternativas práticas.

FFHub·2026-05-02
FFmpeg em Serverless e Lambda: desafios e soluções

Plataformas serverless prometem escala infinita e zero ops. Então, quando você precisa processar vídeo — cortar um clipe, gerar uma thumbnail, transcodificar um upload — o pensamento óbvio é: vou rodar FFmpeg no Lambda. Quão difícil pode ser?

Muito difícil, na verdade. Este guia passa pelos desafios reais de rodar FFmpeg em plataformas serverless, os workarounds comuns, onde eles falham, e quando faz sentido usar uma API dedicada no lugar.

Por que FFmpeg em serverless é difícil

1. Tamanho do binário — 70MB+ antes de você começar

Um binário FFmpeg compilado estaticamente com codecs comuns (H.264, H.265, VP9, AAC, Opus) pesa 70-100 MB. Adicione bibliotecas como libass (legendas) ou libfdk-aac (AAC de alta qualidade) e você está olhando para 120 MB+.

Os limites das plataformas tornam isso doloroso:

PlataformaLimite de tamanho de deployInclui
AWS Lambda (zip)50 MB (250 MB descompactado)Código + dependências + binário
AWS Lambda (container)10 GBMais espaço, mas cold start mais lento
Vercel Serverless Functions50 MBComprimido
Cloudflare Workers10 MB (no plano pago)Sem suporte a binário nativo
Google Cloud Functions500 MB (fonte)Mais permissivo

No AWS Lambda com deploy via zip, só o binário do FFmpeg come a maior parte do seu orçamento de 50 MB. Seu código de aplicação compete pelo espaço que sobrou.

2. Timeout de execução — máximo 15 minutos

O tempo máximo de execução do AWS Lambda é 15 minutos. Outras plataformas são ainda mais rígidas:

PlataformaTimeout máximo
AWS Lambda15 min
Google Cloud Functions9 min (60 min na 2ª gen)
Vercel Serverless5 min (Pro), 60s (Hobby)
Cloudflare Workers30s (padrão), 15 min (Workflows)

Um timeout de 15 minutos parece generoso — até você perceber quanto o processamento FFmpeg realmente leva:

TarefaVídeo 1080p, 10 minTempo em 2 vCPU
Extração de thumbnail1 frame< 1 seg
Extração de áudioStream copy< 5 seg
Transcodificar para H.264CRF 23, medium8-12 min
Transcodificar para H.265CRF 28, medium15-25 min
Adicionar legendas hardcodedRe-encode10-15 min
Transcodificar para VP9CRF 3020-40 min

Tarefas simples como thumbnails e extração de áudio cabem fácil. Mas qualquer transcodificação séria de vídeos com mais que alguns minutos vai estourar o timeout do Lambda — ou chegar perigosamente perto. Para um olhar mais profundo nas configurações de encoding que afetam o tempo de processamento, veja nosso guia de boas práticas de compressão.

3. Limites de memória — sem espaço para arquivos grandes

Processamento de vídeo é memory-hungry. O FFmpeg faz buffer de dados de entrada e saída, e filtros complexos seguram múltiplos frames em memória ao mesmo tempo.

PlataformaMemória máxima
AWS Lambda10 GB
Google Cloud Functions32 GB (2ª gen)
Vercel Serverless3 GB
Cloudflare Workers128 MB

AWS Lambda com 10 GB parece bom — mas memória afeta diretamente o custo. O preço do Lambda é por GB-segundo. Uma função usando 4 GB por 10 minutos custa 40x mais que uma usando 256 MB por 15 segundos.

Uso real de memória em tarefas FFmpeg:

TarefaMemória típica
Extração de thumbnail100-200 MB
Extração de áudio50-150 MB
Transcodificação 1080p H.264500 MB - 1.5 GB
Transcodificação 4K H.2642-4 GB
Cadeias de filtro complexas1-4 GB

4. Sem aceleração GPU

Encoding com aceleração de hardware (NVENC, QSV, VAML) acelera dramaticamente o processamento de vídeo — 5-10x mais rápido para H.264/H.265. Mas plataformas serverless não oferecem acesso a GPU.

Isso significa que você fica preso com encoding por CPU, que é:

  • 5-10x mais lento que encoding por GPU
  • Mais caro por vídeo em escala
  • Mais propenso a estourar timeouts

5. Penalidade do cold start

Todo cold start significa carregar o binário do FFmpeg no ambiente de execução. Um binário de 70 MB+ adiciona 1-3 segundos de latência de cold start em cima da inicialização própria da plataforma.

Para Lambda baseado em container (necessário para binários maiores), cold starts podem chegar a 5-15 segundos.

6. Restrições de armazenamento efêmero

O Lambda fornece /tmp com 512 MB por padrão (configurável até 10 GB com custo extra). Arquivos de vídeo são grandes — um vídeo 1080p de 10 minutos tem 500 MB-1 GB. Você precisa de espaço para entrada e saída:

Input file:  500 MB
Output file: 300 MB
FFmpeg temp: 200 MB
─────────────────
Total:       1 GB  ← exceeds default /tmp

7. Sem processos persistentes

O FFmpeg geralmente se beneficia de processos persistentes — mantendo o binário aquecido, mantendo caches de decode, reusando conexões. Funções serverless são stateless e efêmeras. Toda invocação começa do zero.

Workarounds comuns

Apesar desses desafios, times rodam FFmpeg em serverless. As abordagens mais comuns:

Lambda Layers

AWS Lambda Layers permitem empacotar o FFmpeg separadamente do código da aplicação:

# Download a static FFmpeg build
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
tar xf ffmpeg-release-amd64-static.tar.xz

# Create Lambda layer structure
mkdir -p ffmpeg-layer/bin
cp ffmpeg-*-amd64-static/ffmpeg ffmpeg-layer/bin/
cd ffmpeg-layer && zip -r ../ffmpeg-layer.zip .

Aí na sua função Lambda:

const { execSync } = require('child_process');

exports.handler = async (event) => {
  // FFmpeg binary from layer is at /opt/bin/ffmpeg
  const result = execSync(
    '/opt/bin/ffmpeg -i /tmp/input.mp4 -vf "scale=-2:720" -crf 23 /tmp/output.mp4',
    { timeout: 300000 }
  );
  return { statusCode: 200 };
};

Limitações:

  • O tamanho do layer ainda conta para o limite de 250 MB descompactado
  • Você precisa enxugar o FFmpeg deixando só os codecs que precisa
  • Manter sua própria build de FFmpeg é um peso contínuo

Container images Docker

Lambda suporta container images até 10 GB, dando muito mais espaço:

FROM public.ecr.aws/lambda/nodejs:20

# Install FFmpeg
RUN yum install -y tar xz && \
    curl -L https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz | \
    tar xJ --strip-components=1 -C /usr/local/bin/ --wildcards '*/ffmpeg' '*/ffprobe'

COPY index.mjs ${LAMBDA_TASK_ROOT}/
CMD ["index.handler"]

Limitações:

  • Cold starts são significativamente mais longos (5-15 segundos)
  • Imagens maiores significam custos mais altos de armazenamento ECR
  • Você ainda enfrenta o timeout de 15 minutos e a falta de GPU

ffmpeg.wasm — FFmpeg no browser/edge

ffmpeg.wasm compila o FFmpeg para WebAssembly, fazendo ele rodar em browsers e edge runtimes:

import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile } from '@ffmpeg/util';

const ffmpeg = new FFmpeg();
await ffmpeg.load();
await ffmpeg.writeFile('input.mp4', await fetchFile(videoUrl));
await ffmpeg.exec(['-i', 'input.mp4', '-vf', 'scale=-2:720', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');

Limitações:

  • 3-10x mais lento que FFmpeg nativo
  • Suporte limitado a codecs (sem H.265, suporte limitado a filtros)
  • Restrição de memória em ambiente de browser
  • Não dá conta de arquivos maiores que algumas centenas de MB
  • Single-threaded na maioria dos ambientes

Processamento por chunks

Quebrar vídeos grandes em chunks, processar em paralelo, depois juntar:

# Split into 2-minute segments
ffmpeg -i input.mp4 -c copy -segment_time 120 -f segment -reset_timestamps 1 chunk_%03d.mp4
// Process chunks in parallel Lambda invocations
const chunks = ['chunk_000.mp4', 'chunk_001.mp4', 'chunk_002.mp4'];
const results = await Promise.all(
  chunks.map(chunk => lambda.invoke({
    FunctionName: 'process-chunk',
    Payload: JSON.stringify({ chunk })
  }).promise())
);

// Merge results
// (requires another Lambda invocation)

Limitações:

  • Orquestração complexa (Step Functions, SQS, etc.)
  • Nem toda operação suporta chunking (ex.: timing de legenda atravessa chunks)
  • O passo de merge adiciona latência e pode introduzir artefatos nas bordas dos chunks
  • Custo total geralmente sai mais alto do que um único processo de longa duração

Builds enxutas do FFmpeg

Compilar o FFmpeg só com os codecs que você precisa para reduzir o tamanho do binário:

./configure \
  --disable-everything \
  --enable-decoder=h264,aac,mp3 \
  --enable-encoder=libx264,aac \
  --enable-muxer=mp4,mp3 \
  --enable-demuxer=mov,mp4,mp3 \
  --enable-protocol=file,pipe \
  --enable-filter=scale,overlay \
  --enable-gpl --enable-libx264

Isso pode trazer o binário para 15-25 MB, mas significa perder funcionalidade. Precisa de suporte a VP9 mês que vem? Recompila.

Benchmark: Lambda vs servidor dedicado

Para ilustrar o gap, aqui vai um benchmark para um vídeo 1080p de 5 minutos:

TarefaLambda (3 GB, arm64)EC2 c6g.large (2 vCPU)EC2 g5.xlarge (GPU)
Thumbnail0.8s0.5s0.3s
Extração de áudio2s1.5s1.5s
H.264 CRF 234.5 min3.2 min25s
H.265 CRF 289 min7 min35s
VP9 CRF 3012 min9 minN/A

Comparação de custo para 1000 transcodificações H.264 (vídeo 1080p de 5 min cada):

AbordagemTempo por vídeoCusto por vídeoCusto total
Lambda (3 GB)4.5 min~$0.022~$22
EC2 c6g.large (reservado)3.2 min~$0.004~$4
EC2 g5.xlarge (GPU)25s~$0.008~$8

Lambda é aproximadamente 5x mais caro que uma instância EC2 reservada para cargas sustentadas, e perde a vantagem de custo assim que você processa mais que um punhado de vídeos por hora.

Quando serverless FFmpeg faz sentido

Apesar de todos os desafios, há casos legítimos:

  • Geração de thumbnails — Rápido, baixa memória, dentro dos limites
  • Extração de áudio com stream copy — Quase instantâneo, mínimo de recursos
  • Clipes curtos (< 30 segundos) — Transcodificação rápida que não dá timeout
  • Extração de metadados — ffprobe roda em milissegundos
  • Tráfego esporádico e imprevisível — Quando você pode passar horas sem uma única requisição
# These tasks work well on Lambda
ffmpeg -i input.mp4 -ss 00:00:05 -frames:v 1 thumbnail.jpg          # < 1s
ffmpeg -i input.mp4 -vn -c:a copy audio.aac                          # < 2s
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4  # < 1s

Quando usar uma API dedicada

Serverless não dá conta quando você precisa de:

  • Transcodificar vídeos com mais de 2-3 minutos — Risco de timeout
  • Encoding H.265 ou VP9 — Lento demais sem GPU
  • Cadeias de filtro complexas — Legendas, overlays, composições com múltiplas entradas
  • Processamento previsível em escala — Custo fica proibitivo
  • Suporte completo a codecs — Binários enxugados limitam suas opções
  • Aceleração GPU — Não disponível em serverless

Para esses casos, uma API dedicada de processamento de vídeo elimina as dores de cabeça de infra de uma vez. Se você está avaliando soluções gerenciadas, veja como FFHub se compara ao AWS MediaConvert.

FFHub: FFmpeg cloud sem a infra

FFHub oferece uma API cloud de FFmpeg desenhada especificamente para os problemas que serverless não resolve. Você manda os mesmos comandos FFmpeg que rodaria localmente, e o FFHub cuida da execução em infra otimizada.

# Instead of wrestling with Lambda layers and timeouts:
curl -X POST https://api.ffhub.io/v1/command \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "command": "-i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac output.mp4",
    "inputs": ["https://storage.example.com/input.mp4"],
    "webhook": "https://your-app.com/callback"
  }'

Vantagens-chave sobre FFmpeg em serverless:

  • Sem gestão de binário — FFmpeg completo com todos os codecs, sempre atualizado
  • Sem limite de timeout — Processe vídeos de qualquer duração
  • Infra otimizada — Hardware dedicado calibrado para processamento de vídeo
  • Mesma sintaxe FFmpeg — Sem nova API para aprender
  • Pague pelo uso — Sem custo de infra ociosa

Isso é particularmente valioso quando seu produto core não é processamento de vídeo — você não deveria estar mantendo builds do FFmpeg e Lambda layers quando poderia estar construindo features.

Framework de decisão

FatorUse ServerlessUse API dedicada
Duração do vídeo< 30 segundosQualquer duração
Tipo de tarefaThumbnails, metadados, copy de áudioTranscodificação, legendas, filtros
Volume< 50/diaQualquer volume
Necessidade de codecSó H.264Qualquer codec
Precisa GPUNãoSim (para velocidade)
Expertise do timeTime DevOps disponívelPrefere solução gerenciada

Resumo

Rodar FFmpeg em plataformas serverless é possível, mas dói. O tamanho do binário, os limites de timeout, o custo da memória, e a falta de GPU fazem disso uma péssima escolha para qualquer coisa além de tarefas simples como geração de thumbnail e extração de áudio.

Se sua carga envolve transcodificação de verdade, considere o custo total — não só a fatura do Lambda, mas o tempo de engenharia gasto construindo e mantendo deploys customizados de FFmpeg. Para a maioria dos times, uma API dedicada de processamento de vídeo é mais barata e mais confiável que tentar fazer serverless funcionar para um caso de uso para o qual ela não foi desenhada. Para entender o que o FFHub oferece como solução cloud de FFmpeg, ou explorar transcodificação em lote via API, confira esses guias.

Artigos relacionados

FFmpeg em Serverless e Lambda: desafios e soluções | FFHub