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.

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:
| Plataforma | Limite de tamanho de deploy | Inclui |
|---|---|---|
| AWS Lambda (zip) | 50 MB (250 MB descompactado) | Código + dependências + binário |
| AWS Lambda (container) | 10 GB | Mais espaço, mas cold start mais lento |
| Vercel Serverless Functions | 50 MB | Comprimido |
| Cloudflare Workers | 10 MB (no plano pago) | Sem suporte a binário nativo |
| Google Cloud Functions | 500 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:
| Plataforma | Timeout máximo |
|---|---|
| AWS Lambda | 15 min |
| Google Cloud Functions | 9 min (60 min na 2ª gen) |
| Vercel Serverless | 5 min (Pro), 60s (Hobby) |
| Cloudflare Workers | 30s (padrão), 15 min (Workflows) |
Um timeout de 15 minutos parece generoso — até você perceber quanto o processamento FFmpeg realmente leva:
| Tarefa | Vídeo 1080p, 10 min | Tempo em 2 vCPU |
|---|---|---|
| Extração de thumbnail | 1 frame | < 1 seg |
| Extração de áudio | Stream copy | < 5 seg |
| Transcodificar para H.264 | CRF 23, medium | 8-12 min |
| Transcodificar para H.265 | CRF 28, medium | 15-25 min |
| Adicionar legendas hardcoded | Re-encode | 10-15 min |
| Transcodificar para VP9 | CRF 30 | 20-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.
| Plataforma | Memória máxima |
|---|---|
| AWS Lambda | 10 GB |
| Google Cloud Functions | 32 GB (2ª gen) |
| Vercel Serverless | 3 GB |
| Cloudflare Workers | 128 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:
| Tarefa | Memória típica |
|---|---|
| Extração de thumbnail | 100-200 MB |
| Extração de áudio | 50-150 MB |
| Transcodificação 1080p H.264 | 500 MB - 1.5 GB |
| Transcodificação 4K H.264 | 2-4 GB |
| Cadeias de filtro complexas | 1-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:
| Tarefa | Lambda (3 GB, arm64) | EC2 c6g.large (2 vCPU) | EC2 g5.xlarge (GPU) |
|---|---|---|---|
| Thumbnail | 0.8s | 0.5s | 0.3s |
| Extração de áudio | 2s | 1.5s | 1.5s |
| H.264 CRF 23 | 4.5 min | 3.2 min | 25s |
| H.265 CRF 28 | 9 min | 7 min | 35s |
| VP9 CRF 30 | 12 min | 9 min | N/A |
Comparação de custo para 1000 transcodificações H.264 (vídeo 1080p de 5 min cada):
| Abordagem | Tempo por vídeo | Custo por vídeo | Custo 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
| Fator | Use Serverless | Use API dedicada |
|---|---|---|
| Duração do vídeo | < 30 segundos | Qualquer duração |
| Tipo de tarefa | Thumbnails, metadados, copy de áudio | Transcodificação, legendas, filtros |
| Volume | < 50/dia | Qualquer volume |
| Necessidade de codec | Só H.264 | Qualquer codec |
| Precisa GPU | Não | Sim (para velocidade) |
| Expertise do time | Time DevOps disponível | Prefere 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
- O que é FFHub? - Saiba como o FFHub oferece FFmpeg cloud sem o overhead de infra
- API de transcodificação em lote - Processe milhares de vídeos programaticamente com uma REST API simples
- FFHub vs AWS MediaConvert - Uma comparação honesta entre FFHub e o serviço gerenciado de transcodificação da AWS