FFmpeg en entornos serverless y Lambda: desafíos y soluciones prácticas
Por qué ejecutar FFmpeg en AWS Lambda, Vercel y Cloudflare Workers es complicado — tamaño del binario, timeouts, memoria, cold starts — y alternativas prácticas.

Las plataformas serverless prometen escala infinita y cero operaciones. Así que cuando necesitas procesar video —recortar un clip, generar una miniatura, transcodificar una carga— el pensamiento obvio es: simplemente ejecuta FFmpeg en Lambda. ¿Qué tan difícil puede ser?
Muy difícil, como resulta. Esta guía analiza los desafíos reales de ejecutar FFmpeg en plataformas serverless, las soluciones alternativas habituales, sus limitaciones, y cuándo tiene sentido usar una API dedicada.
Por qué FFmpeg en serverless es difícil
1. Tamaño del binario — 70 MB o más desde el principio
Un binario FFmpeg compilado estáticamente con los códecs comunes (H.264, H.265, VP9, AAC, Opus) pesa 70-100 MB. Agrega bibliotecas como libass (subtítulos) o libfdk-aac (AAC de alta calidad) y estarás viendo 120 MB o más.
Los límites de las plataformas hacen esto doloroso:
| Plataforma | Límite de tamaño de despliegue | Incluye |
|---|---|---|
| AWS Lambda (zip) | 50 MB (250 MB descomprimido) | Código + dependencias + binario |
| AWS Lambda (contenedor) | 10 GB | Más espacio, pero cold start más lento |
| Vercel Serverless Functions | 50 MB | Comprimido |
| Cloudflare Workers | 10 MB (con plan de pago) | Sin soporte de binario nativo |
| Google Cloud Functions | 500 MB (fuente) | Más permisivo |
En AWS Lambda con despliegue zip, el binario de FFmpeg por sí solo consume la mayor parte de tu presupuesto de 50 MB. El código real de tu aplicación compite por el espacio restante.
2. Tiempo de espera de ejecución — 15 minutos como máximo
El tiempo máximo de ejecución de AWS Lambda es de 15 minutos. Otras plataformas son aún más restrictivas:
| Plataforma | Tiempo de espera máximo |
|---|---|
| AWS Lambda | 15 min |
| Google Cloud Functions | 9 min (60 min 2ª gen) |
| Vercel Serverless | 5 min (Pro), 60s (Hobby) |
| Cloudflare Workers | 30s (estándar), 15 min (Workflows) |
Un tiempo de espera de 15 minutos parece generoso, hasta que te das cuenta de lo que realmente tarda el procesamiento con FFmpeg:
| Tarea | Video 1080p, 10 min | Tiempo en 2 vCPU |
|---|---|---|
| Extracción de miniaturas | 1 fotograma | < 1 seg |
| Extracción de audio | Stream copy | < 5 seg |
| Transcodificación a H.264 | CRF 23, medium | 8-12 min |
| Transcodificación a H.265 | CRF 28, medium | 15-25 min |
| Agregar subtítulos incrustados | Re-codificación | 10-15 min |
| Transcodificación a VP9 | CRF 30 | 20-40 min |
Las tareas simples como miniaturas y extracción de audio encajan fácilmente. Pero cualquier transcodificación real de videos de más de unos minutos alcanzará el tiempo de espera de Lambda, o se acercará peligrosamente. Para un análisis más profundo sobre los ajustes de codificación que afectan el tiempo de procesamiento, consulta nuestras mejores prácticas de compresión de video.
3. Límites de memoria — sin espacio para archivos grandes
El procesamiento de video consume mucha memoria. FFmpeg almacena en buffer los datos de entrada y salida, y los filtros complejos mantienen múltiples fotogramas en memoria simultáneamente.
| Plataforma | Memoria máxima |
|---|---|
| AWS Lambda | 10 GB |
| Google Cloud Functions | 32 GB (2ª gen) |
| Vercel Serverless | 3 GB |
| Cloudflare Workers | 128 MB |
AWS Lambda con 10 GB parece suficiente, pero la memoria afecta directamente el costo. El precio de Lambda es por GB-segundo. Una función que usa 4 GB durante 10 minutos cuesta 40 veces más que una que usa 256 MB durante 15 segundos.
Uso real de memoria para tareas con FFmpeg:
| Tarea | Memoria típica |
|---|---|
| Extracción de miniaturas | 100-200 MB |
| Extracción de audio | 50-150 MB |
| Transcodificación H.264 1080p | 500 MB - 1.5 GB |
| Transcodificación H.264 4K | 2-4 GB |
| Cadenas de filtros complejas | 1-4 GB |
4. Sin aceleración GPU
La codificación acelerada por hardware (NVENC, QSV, VAML) acelera drásticamente el procesamiento de video: 5-10 veces más rápido para H.264/H.265. Pero las plataformas serverless no ofrecen acceso a GPU.
Esto significa que estás limitado a codificación por CPU, que es:
- 5-10 veces más lenta que la codificación por GPU
- Más costosa por video a escala
- Más propensa a alcanzar los límites de tiempo de espera
5. Penalización por cold start
Cada cold start implica cargar el binario de FFmpeg en el entorno de ejecución. Un binario de 70 MB o más agrega 1-3 segundos de latencia de cold start además de la inicialización propia de la plataforma.
Para Lambda basado en contenedor (necesario para binarios más grandes), los cold starts pueden llegar a 5-15 segundos.
6. Restricciones de almacenamiento efímero
Lambda proporciona /tmp con 512 MB por defecto (configurable a 10 GB con costo adicional). Los archivos de video son grandes: un video 1080p de 10 minutos ocupa 500 MB-1 GB. Necesitas espacio tanto para la entrada como para la salida:
Archivo de entrada: 500 MB
Archivo de salida: 300 MB
Temp de FFmpeg: 200 MB
─────────────────────────────
Total: 1 GB ← supera el /tmp predeterminado
7. Sin procesos persistentes
FFmpeg se beneficia de procesos persistentes: mantener el binario caliente, conservar cachés de decodificación, reutilizar conexiones. Las funciones serverless son stateless y efímeras. Cada invocación comienza desde cero.
Soluciones alternativas habituales
A pesar de estos desafíos, los equipos sí ejecutan FFmpeg en serverless. Estas son las aproximaciones más comunes.
Lambda Layers
Los Lambda Layers de AWS te permiten empaquetar FFmpeg por separado del código de tu aplicación:
# Descargar una compilación estática de FFmpeg
wget https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz
tar xf ffmpeg-release-amd64-static.tar.xz
# Crear la estructura del layer de Lambda
mkdir -p ffmpeg-layer/bin
cp ffmpeg-*-amd64-static/ffmpeg ffmpeg-layer/bin/
cd ffmpeg-layer && zip -r ../ffmpeg-layer.zip .
Luego en tu función Lambda:
const { execSync } = require('child_process');
exports.handler = async (event) => {
// El binario FFmpeg del layer está en /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 };
};
Limitaciones:
- El tamaño del layer sigue contando hacia el límite de 250 MB descomprimido
- Necesitas reducir FFmpeg solo a los códecs que usas
- Mantener tu propia compilación de FFmpeg es una carga continua
Imágenes de contenedor Docker
Lambda soporta imágenes de contenedor de hasta 10 GB, lo que da mucho más espacio:
FROM public.ecr.aws/lambda/nodejs:20
# Instalar 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"]
Limitaciones:
- Los cold starts son significativamente más lentos (5-15 segundos)
- Las imágenes más grandes implican mayores costos de almacenamiento en ECR
- Aún enfrentas el tiempo de espera de 15 minutos y la falta de GPU
ffmpeg.wasm — FFmpeg para navegador/edge
ffmpeg.wasm compila FFmpeg a WebAssembly, haciéndolo ejecutable en navegadores y runtimes de edge:
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');
Limitaciones:
- 3-10 veces más lento que FFmpeg nativo
- Soporte limitado de códecs (sin H.265, soporte de filtros limitado)
- Restringido por la memoria en entornos de navegador
- No puede manejar archivos de más de algunos cientos de MB
- Single-threaded en la mayoría de entornos
Procesamiento por fragmentos
Divide los videos grandes en fragmentos, procésalos en paralelo y luego combínalos:
# Dividir en segmentos de 2 minutos
ffmpeg -i input.mp4 -c copy -segment_time 120 -f segment -reset_timestamps 1 chunk_%03d.mp4
// Procesar fragmentos en invocaciones Lambda paralelas
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())
);
// Combinar resultados
// (requiere otra invocación de Lambda)
Limitaciones:
- Orquestación compleja (Step Functions, SQS, etc.)
- No todas las operaciones soportan fragmentación (p. ej., los tiempos de subtítulos abarcan fragmentos)
- El paso de combinación agrega latencia y puede introducir artefactos en los bordes de los fragmentos
- El costo total suele ser mayor que el de un único proceso de larga duración
Compilaciones de FFmpeg reducidas
Compila FFmpeg solo con los códecs que necesitas para reducir el tamaño del binario:
./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
Esto puede reducir el binario a 15-25 MB, pero implica perder funcionalidades. ¿Necesitas soporte para VP9 el mes que viene? A recompilar.
Benchmark: Lambda vs servidor dedicado
Para ilustrar la diferencia, estos son los benchmarks para un video 1080p de 5 minutos:
| Tarea | Lambda (3 GB, arm64) | EC2 c6g.large (2 vCPU) | EC2 g5.xlarge (GPU) |
|---|---|---|---|
| Miniatura | 0.8s | 0.5s | 0.3s |
| Extracción de audio | 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 |
Comparativa de costos para 1.000 transcodificaciones H.264 (video 1080p de 5 min cada una):
| Aproximación | Tiempo por video | Costo por video | Costo 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 es aproximadamente 5 veces más caro que una instancia EC2 reservada para cargas de trabajo sostenidas, y pierde la ventaja de costo en cuanto procesas más de un puñado de videos por hora.
Cuándo tiene sentido FFmpeg en serverless
A pesar de todos los desafíos, hay casos de uso legítimos:
- Generación de miniaturas — Rápido, poca memoria, bien dentro de los límites
- Extracción de audio con stream copy — Casi instantáneo, recursos mínimos
- Clips de video cortos (< 30 segundos) — Transcodificación rápida que no alcanzará el tiempo de espera
- Extracción de metadatos — ffprobe se ejecuta en milisegundos
- Tráfico esporádico e impredecible — Cuando puedes estar horas sin una sola solicitud
# Estas tareas funcionan bien en 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
Cuándo usar una API dedicada
El enfoque serverless se queda corto cuando necesitas:
- Transcodificación de videos de más de 2-3 minutos — Riesgo de tiempo de espera
- Codificación H.265 o VP9 — Demasiado lento sin GPU
- Cadenas de filtros complejas — Subtítulos, overlays, composiciones con múltiples entradas
- Procesamiento predecible a escala — El costo se vuelve prohibitivo
- Soporte completo de códecs — Los binarios reducidos limitan tus opciones
- Aceleración GPU — No disponible en serverless
Para estos casos, una API dedicada de procesamiento de video elimina completamente los dolores de cabeza de infraestructura. Si estás evaluando soluciones gestionadas, consulta cómo FFHub se compara con AWS MediaConvert.
FFHub: FFmpeg en la nube sin la infraestructura
FFHub proporciona una API cloud de FFmpeg diseñada específicamente para los problemas que serverless no puede resolver. Envías los mismos comandos FFmpeg que ejecutarías localmente, y FFHub maneja la ejecución en infraestructura optimizada.
# En lugar de lidiar con Lambda layers y 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"
}'
Ventajas clave frente a FFmpeg en serverless:
- Sin gestión de binarios — FFmpeg completo con todos los códecs, siempre actualizado
- Sin límites de tiempo de espera — Procesa videos de cualquier duración
- Infraestructura optimizada — Hardware dedicado ajustado para el procesamiento de video
- Misma sintaxis FFmpeg — Sin nueva API que aprender
- Pago por uso — Sin costos de infraestructura inactiva
Esto es especialmente valioso cuando tu producto principal no es el procesamiento de video: no deberías estar manteniendo compilaciones de FFmpeg y Lambda layers cuando podrías estar construyendo funcionalidades.
Marco de decisión
| Factor | Usa serverless | Usa API dedicada |
|---|---|---|
| Duración del video | < 30 segundos | Cualquier duración |
| Tipo de tarea | Miniaturas, metadatos, copia de audio | Transcodificación, subtítulos, filtros |
| Volumen | < 50/día | Cualquier volumen |
| Necesidades de códec | Solo H.264 | Cualquier códec |
| GPU necesaria | No | Sí (para velocidad) |
| Experiencia del equipo | Equipo DevOps disponible | Prefiere solución gestionada |
Resumen
Ejecutar FFmpeg en plataformas serverless es posible, pero doloroso. El tamaño del binario, los límites de tiempo de espera, los costos de memoria y la falta de GPU lo hacen un mal candidato para cualquier tarea más allá de simples operaciones como generación de miniaturas y extracción de audio.
Si tu carga de trabajo implica transcodificación real, considera el costo total: no solo la factura de Lambda, sino el tiempo de ingeniería invertido en construir y mantener despliegues personalizados de FFmpeg. Para la mayoría de los equipos, una API dedicada de procesamiento de video es tanto más económica como más confiable que intentar que serverless funcione para un caso de uso para el que no fue diseñado. Para entender lo que FFHub ofrece como solución cloud de FFmpeg, o para explorar la transcodificación en lotes vía API, consulta esas guías.
Artículos relacionados
- ¿Qué es FFHub? - Descubre cómo FFHub proporciona FFmpeg en la nube sin la sobrecarga de infraestructura
- API de transcodificación de video en lotes - Procesa miles de videos mediante programación con una simple REST API
- FFHub vs AWS MediaConvert - Una comparativa honesta de FFHub y el servicio de transcodificación de video gestionado de AWS