FFmpeg para Producción de Video
FFmpeg es la herramienta esencial para el procesamiento de video/audio. Este skill cubre operaciones comunes para proyectos de video con Remotion.
Referencia Rápida
GIF a MP4 (compatible con Remotion)
ffmpeg -i input.gif -movflags faststart -pix_fmt yuv420p \
-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" output.mp4
Por qué estas banderas:
-movflags faststart- Mueve los metadatos al inicio para transmisión web-pix_fmt yuv420p- Garantiza compatibilidad con la mayoría de reproductoresscale=trunc(...)- Fuerza dimensiones pares (requerido por la mayoría de códecs)
Redimensionar Video
# A 1920x1080 (mantener relación de aspecto, agregar barras negras)
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2" output.mp4
# A 1920x1080 (recortar para llenar)
ffmpeg -i input.mp4 -vf "scale=1920:1080:force_original_aspect_ratio=increase,crop=1920:1080" output.mp4
# Escalar al ancho, altura automática
ffmpeg -i input.mp4 -vf "scale=1280:-2" output.mp4
Comprimir Video
# Buena calidad, archivo más pequeño (CRF 23 es el valor predeterminado, menor = mejor calidad)
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4
# Compresión agresiva para vista previa web
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 96k output.mp4
# Tamaño de archivo objetivo (ej., ~10MB para video de 60s = ~1.3Mbps)
ffmpeg -i input.mp4 -c:v libx264 -b:v 1300k -c:a aac -b:a 128k output.mp4
Extraer Audio
# Extraer a MP3
ffmpeg -i input.mp4 -vn -acodec libmp3lame -q:a 2 output.mp3
# Extraer a AAC
ffmpeg -i input.mp4 -vn -acodec aac -b:a 192k output.m4a
# Extraer a WAV (sin comprimir)
ffmpeg -i input.mp4 -vn output.wav
Convertir Formatos de Audio
# M4A a MP3 (para muestras de voz de ElevenLabs)
ffmpeg -i input.m4a -codec:a libmp3lame -qscale:a 2 output.mp3
# WAV a MP3
ffmpeg -i input.wav -codec:a libmp3lame -b:a 192k output.mp3
# Ajustar volumen
ffmpeg -i input.mp3 -filter:a "volume=1.5" output.mp3
Recortar/Cortar Video
# Cortar desde una marca de tiempo con duración (recomendado - confiable)
ffmpeg -i input.mp4 -ss 00:00:30 -t 00:00:15 -c:v libx264 -c:a aac output.mp4
# Cortar desde una marca de tiempo hasta otra
ffmpeg -i input.mp4 -ss 00:00:30 -to 00:00:45 -c:v libx264 -c:a aac output.mp4
# Copia de flujo (más rápido pero puede perder fotogramas en los puntos de corte)
# Usar solo cuando la fuente tenga fotogramas clave frecuentes
ffmpeg -i input.mp4 -ss 00:00:30 -t 00:00:15 -c copy output.mp4
Nota: Se recomienda la recodificación para recortar. La copia de flujo (-c copy) puede eliminar video silenciosamente si el punto de búsqueda no se alinea con un fotograma clave.
Acelerar / Ralentizar
# Velocidad 2x (video y audio)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mp4
# Velocidad 0.5x (cámara lenta)
ffmpeg -i input.mp4 -filter_complex "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]" -map "[v]" -map "[a]" output.mp4
# Solo video (sin audio)
ffmpeg -i input.mp4 -filter:v "setpts=0.5*PTS" -an output.mp4
Concatenar Videos
# Crear lista de archivos
echo "file 'clip1.mp4'" > list.txt
echo "file 'clip2.mp4'" >> list.txt
echo "file 'clip3.mp4'" >> list.txt
# Concatenar (mismo códec/resolución)
ffmpeg -f concat -safe 0 -i list.txt -c copy output.mp4
# Concatenar con recodificación (fuentes diferentes)
ffmpeg -f concat -safe 0 -i list.txt -c:v libx264 -c:a aac output.mp4
Agregar Fundido de Entrada/Salida
# Fundido de entrada en el primer 1 segundo, fundido de salida en el último 1 segundo (video a 30fps)
ffmpeg -i input.mp4 -vf "fade=t=in:st=0:d=1,fade=t=out:st=9:d=1" -c:a copy output.mp4
# Fundido de audio
ffmpeg -i input.mp4 -af "afade=t=in:st=0:d=1,afade=t=out:st=9:d=1" -c:v copy output.mp4
Obtener Información del Video
# Duración, resolución, información del códec
ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 input.mp4
# Información completa
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4
Patrones Específicos de Remotion
Ajuste de Velocidad de Video para Remotion
Cuándo usar FFmpeg vs playbackRate de Remotion:
| Escenario | Usar FFmpeg | Usar Remotion |
|---|---|---|
| Velocidad constante (1.5x, 2x) | Cualquiera funciona | ✅ Más simple |
| Velocidades extremas (>4x o <0.25x) | ✅ Más confiable | Puede tener problemas |
| Velocidad variable (acelerar con el tiempo) | ✅ Preprocesar | Solución compleja necesaria |
| Necesita sincronización de audio perfecta | ✅ Garantizado | Generalmente bien |
| Demo necesita ajustarse al tiempo de locución | ✅ Precalcular | Ajuste en tiempo de ejecución |
Limitación de Remotion: playbackRate debe ser constante. La interpolación dinámica como playbackRate={interpolate(frame, [0, 100], [1, 5])} no funcionará correctamente porque Remotion evalúa los fotogramas de forma independiente.
# Acelerar demo para ajustarse a una escena (ej., demo de 60s en 20s = velocidad 3x)
ffmpeg -i demo-raw.mp4 \
-filter_complex "[0:v]setpts=0.333*PTS[v];[0:a]atempo=3.0[a]" \
-map "[v]" -map "[a]" \
public/demos/demo-fast.mp4
# Cámara lenta para énfasis (velocidad 0.5x)
ffmpeg -i action.mp4 \
-filter_complex "[0:v]setpts=2.0*PTS[v];[0:a]atempo=0.5[a]" \
-map "[v]" -map "[a]" \
public/demos/action-slow.mp4
# Acelerar sin audio (común para grabaciones de pantalla)
ffmpeg -i demo.mp4 -filter:v "setpts=0.5*PTS" -an public/demos/demo-2x.mp4
# Efecto timelapse (velocidad 10x, eliminar audio)
ffmpeg -i long-demo.mp4 -filter:v "setpts=0.1*PTS" -an public/demos/timelapse.mp4
Calcular factor de velocidad:
- Para ajustar X segundos de video en Y segundos de escena:
velocidad = X / Y - Multiplicador setpts = 1 / velocidad` (ej., velocidad 3x = setpts=0.333*PTS)
- Valor atempo = velocidad` (ej., velocidad 3x = atempo=3.0)
Velocidad extrema (>2x audio): Encadenar filtros atempo (cada uno limitado al rango 0.5-2.0):
# Audio a velocidad 4x
-filter_complex "[0:a]atempo=2.0,atempo=2.0[a]"
# Audio a velocidad 8x
-filter_complex "[0:a]atempo=2.0,atempo=2.0,atempo=2.0[a]"
Preparar Grabación de Demo para Remotion
# Estándar 1080p, 30fps, listo para Remotion
ffmpeg -i raw-recording.mp4 \
-vf "scale=1920:1080:force_original_aspect_ratio=decrease,pad=1920:1080:(ow-iw)/2:(oh-ih)/2,fps=30" \
-c:v libx264 -crf 18 -preset slow \
-c:a aac -b:a 192k \
-movflags faststart \
public/demos/demo.mp4
Grabación de Pantalla a Activo de Remotion
# Desde grabación de iPhone/iPad (generalmente 60fps, resolución variable)
ffmpeg -i iphone-recording.mov \
-vf "scale=1920:-2,fps=30" \
-c:v libx264 -crf 20 \
-an \
public/demos/mobile-demo.mp4
Convertir GIF por Lote
for f in assets/*.gif; do
ffmpeg -i "$f" -movflags faststart -pix_fmt yuv420p \
-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" \
"public/demos/$(basename "$f" .gif).mp4"
done
Problemas Comunes
"Height not divisible by 2"
Agregar filtro de escala: -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2"
El video no se reproduce en el navegador
Usar: -movflags faststart -pix_fmt yuv420p -c:v libx264
Audio desincronizado después del cambio de velocidad
Usar filter_complex con atempo: -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]"
Archivo demasiado grande
Aumentar CRF (23→28) o reducir resolución
Pautas de Calidad
| Caso de Uso | CRF | Preajuste | Notas |
|---|---|---|---|
| Archivo/Maestro | 18 | slow | Mejor calidad, archivos grandes |
| Producción | 20-22 | medium | Buen equilibrio |
| Web/Vista previa | 23-25 | fast | Archivos más pequeños |
| Borrador/Rápido | 28+ | veryfast | Codificación rápida |
Optimización de Salida Específica por Plataforma
Después de que Remotion renderice tu video (típicamente a out/video.mp4), usa FFmpeg para optimizarlo para cada plataforma de distribución.
Integración de Flujo de Trabajo
Renderizado de Remotion (maestro) Optimización FFmpeg Carga a plataforma
↓ ↓ ↓
out/video.mp4 ────────→ out/video-youtube.mp4 ───→ YouTube
────────→ out/video-twitter.mp4 ───→ Twitter/X
────────→ out/video-linkedin.mp4 ───→ LinkedIn
────────→ out/video-web.mp4 ───→ Inserción en sitio web
YouTube (Configuración Recomendada)
YouTube recodifica todo, así que sube con alta calidad:
# Optimizado para YouTube (1080p)
ffmpeg -i out/video.mp4 \
-c:v libx264 -preset slow -crf 18 \
-profile:v high -level 4.0 \
-bf 2 -g 30 \
-c:a aac -b:a 192k -ar 48000 \
-movflags +faststart \
out/video-youtube.mp4
# YouTube Shorts (vertical 1080x1920)
ffmpeg -i out/video.mp4 \
-vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" \
-c:v libx264 -crf 18 -c:a aac -b:a 192k \
out/video-shorts.mp4
Twitter/X
Twitter tiene límites estrictos: máximo 140s, 512MB, 1920x1200:
# Optimizado para Twitter (objetivo de menos de 15MB para carga rápida)
ffmpeg -i out/video.mp4 \
-c:v libx264 -preset medium -crf 24 \
-profile:v main -level 3.1 \
-vf "scale='min(1280,iw)':'min(720,ih)':force_original_aspect_ratio=decrease" \
-c:a aac -b:a 128k -ar 44100 \
-movflags +faststart \
-fs 15M \
out/video-twitter.mp4
# Verificar tamaño de archivo y duración
ffprobe -v error -show_entries format=duration,size -of csv=p=0 out/video-twitter.mp4
LinkedIn prefiere MP4 con audio AAC, máximo 10 minutos:
# Optimizado para LinkedIn
ffmpeg -i out/video.mp4 \
-c:v libx264 -preset medium -crf 22 \
-profile:v main \
-vf "scale='min(1920,iw)':'min(1080,ih)':force_original_aspect_ratio=decrease" \
-c:a aac -b:a 192k -ar 48000 \
-movflags +faststart \
out/video-linkedin.mp4
Sitio Web/Inserción (Optimizado para Carga Rápida)
# MP4 optimizado para web (archivo pequeño, carga progresiva)
ffmpeg -i out/video.mp4 \
-c:v libx264 -preset medium -crf 26 \
-profile:v baseline -level 3.0 \
-vf "scale=1280:720" \
-c:a aac -b:a 128k \
-movflags +faststart \
out/video-web.mp4
# Alternativa WebM (mejor compresión, soporte más amplio de navegadores)
ffmpeg -i out/video.mp4 \
-c:v libvpx-vp9 -crf 30 -b:v 0 \
-vf "scale=1280:720" \
-c:a libopus -b:a 128k \
-deadline good \
out/video-web.webm
GIF (para Vistas Previas/Miniaturas)
# GIF de alta calidad (primeros 5 segundos)
ffmpeg -i out/video.mp4 -t 5 \
-vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
out/preview.gif
# GIF de archivo más pequeño
ffmpeg -i out/video.mp4 -t 3 \
-vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
out/preview-small.gif
Referencia Rápida de Requisitos de Plataforma
| Plataforma | Resolución Máx. | Tamaño Máx. | Duración Máx. | Audio |
|---|---|---|---|---|
| YouTube | 8K | 256GB | 12 horas | AAC 48kHz |
| Twitter/X | 1920x1200 | 512MB | 140s | AAC 44.1kHz |
| 4096x2304 | 5GB | 10 min | AAC 48kHz | |
| Instagram Feed | 1080x1350 | 4GB | 60s | AAC 48kHz |
| Instagram Reels | 1080x1920 | 4GB | 90s | AAC 48kHz |
| TikTok | 1080x1920 | 287MB | 10 min | AAC |
Exportación por Lote para Todas las Plataformas
#!/bin/bash
# guardar como: export-all-platforms.sh
INPUT="out/video.mp4"
# YouTube (alta calidad)
ffmpeg -i "$INPUT" -c:v libx264 -preset slow -crf 18 \
-c:a aac -b:a 192k -movflags +faststart \
out/video-youtube.mp4
# Twitter (comprimido)
ffmpeg -i "$INPUT" -c:v libx264 -crf 24 \
-vf "scale='min(1280,iw)':'-2'" \
-c:a aac -b:a 128k -movflags +faststart \
out/video-twitter.mp4
# LinkedIn
ffmpeg -i "$INPUT" -c:v libx264 -crf 22 \
-c:a aac -b:a 192k -movflags +faststart \
out/video-linkedin.mp4
# Inserción web (pequeño)
ffmpeg -i "$INPUT" -c:v libx264 -crf 26 \
-vf "scale=1280:720" \
-c:a aac -b:a 128k -movflags +faststart \
out/video-web.mp4
echo "Exportado:"
ls -lh out/video-*.mp4
Manejo de Errores
Errores comunes y soluciones al procesar video:
# Verificar si FFmpeg tuvo éxito
ffmpeg -i input.mp4 -c:v libx264 output.mp4 && echo "Éxito" || echo "Falló: verificar archivo de entrada"
# Validar que el archivo de salida se pueda reproducir
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 output.mp4
# Obtener información detallada del error
ffmpeg -v error -i input.mp4 -f null - 2>&1 | head -20
Manejo de Fallos Comunes
| Error | Causa | Solución |
|---|---|---|
| "No such file" | Ruta de entrada incorrecta | Verificar ruta, usar comillas para espacios |
| "Invalid data" | Entrada corrupta | Volver a descargar o regrabar la fuente |
| "height not divisible by 2" | Dimensiones impares | Agregar filtro de escala con trunc |
| "encoder not found" | Códec faltante | Instalar FFmpeg con códecs completos |
| Salida de 0 bytes | Fallo silencioso | Revisar la salida completa de ffmpeg para errores |
Comentarios y Contribuciones
Si este skill carece de información o se puede mejorar:
- ¿Falta un comando? Describe lo que necesitabas
- ¿Encontraste un error? Házmelo saber qué está mal
- ¿Quieres contribuir? Puedo ayudarte a:
- Actualizar este skill con mejoras
- Crear un PR en github.com/digitalsamba/claude-code-video-toolkit
Solo di "mejora este skill" y te guiaré en la actualización de .claude/skills/ffmpeg/SKILL.md.