Configuración de Servidor de Transcodificación FFmpeg
FFmpeg es la herramienta estándar en la industria para procesamiento de vídeo y audio, capaz de transcodificar prácticamente cualquier formato multimedia. Configurado correctamente en un servidor Linux, FFmpeg puede procesar múltiples streams en paralelo con aceleración hardware VAAPI (Intel/AMD) o NVENC (NVIDIA), construir pipelines de streaming en vivo y ejecutar tareas de procesamiento por lotes de forma eficiente. Esta guía cubre la configuración de FFmpeg como servidor de transcodificación en producción.
Requisitos Previos
- Ubuntu 20.04+, Debian 11+, CentOS 8+ o Rocky Linux 8+
- Mínimo 4 GB de RAM para transcodificación múltiple
- CPU multi-núcleo (8+ recomendados) o GPU NVIDIA/Intel con soporte NVENC/VAAPI
- Almacenamiento rápido (SSD o NVMe) para archivos temporales
- Para NVENC: NVIDIA con drivers 418.30+ y GPU con soporte NVENC
Instalación de FFmpeg
Ubuntu/Debian
# Instalar FFmpeg desde los repositorios oficiales (versión estable)
sudo apt update
sudo apt install -y ffmpeg
# Verificar la instalación y códecs disponibles
ffmpeg -version
ffmpeg -codecs | grep -E "h264|h265|hevc|vp9|av1"
# Verificar los encoders disponibles
ffmpeg -encoders | grep -E "264|265|nvenc|vaapi|qsv"
CentOS/Rocky Linux
# Instalar repositorios necesarios
sudo dnf install -y epel-release
sudo dnf install -y https://download1.rpmfusion.org/free/el/rpmfusion-free-release-$(rpm -E %rhel).noarch.rpm
sudo dnf install -y https://download1.rpmfusion.org/nonfree/el/rpmfusion-nonfree-release-$(rpm -E %rhel).noarch.rpm
# Instalar FFmpeg
sudo dnf install -y ffmpeg ffmpeg-devel
# Verificar
ffmpeg -version
Compilación desde Código Fuente
Para obtener soporte completo de códecs y aceleración hardware, compilar FFmpeg desde el código fuente:
# Instalar dependencias de compilación
sudo apt install -y \
build-essential git cmake pkg-config \
libx264-dev libx265-dev libvpx-dev libopus-dev \
libfdk-aac-dev libmp3lame-dev libvorbis-dev \
libva-dev libdrm-dev
# Clonar el código fuente de FFmpeg
git clone https://git.ffmpeg.org/ffmpeg.git /opt/ffmpeg-src
cd /opt/ffmpeg-src
# Configurar con todas las características necesarias
./configure \
--prefix=/usr/local \
--enable-gpl \
--enable-nonfree \
--enable-libx264 \
--enable-libx265 \
--enable-libvpx \
--enable-libopus \
--enable-libfdk-aac \
--enable-libmp3lame \
--enable-libvorbis \
--enable-vaapi \
--enable-libdrm
# Compilar usando todos los núcleos disponibles
make -j$(nproc)
# Instalar
sudo make install
sudo ldconfig
# Verificar la instalación compilada
ffmpeg -version
Selección de Códecs y Formatos
Codificación H.264 (AVC)
# Transcodificación básica H.264 con calidad constante (CRF)
# CRF: 18 (alta calidad) a 28 (baja calidad), 23 es el valor por defecto
ffmpeg -i entrada.mkv \
-c:v libx264 \
-crf 23 \
-preset medium \
-c:a aac -b:a 192k \
salida.mp4
# Para streaming (dos pasadas para bitrate constante)
# Primera pasada - análisis
ffmpeg -i entrada.mkv -c:v libx264 -b:v 3000k -pass 1 -an -f null /dev/null
# Segunda pasada - codificación final
ffmpeg -i entrada.mkv \
-c:v libx264 -b:v 3000k -pass 2 \
-c:a aac -b:a 192k \
salida-streaming.mp4
Codificación H.265 (HEVC)
# HEVC ofrece mejor compresión que H.264 al mismo nivel de calidad
ffmpeg -i entrada.mkv \
-c:v libx265 \
-crf 28 \
-preset medium \
-c:a aac -b:a 192k \
salida-hevc.mp4
# HEVC con metadata de nivel/perfil específico
ffmpeg -i entrada.mkv \
-c:v libx265 \
-crf 28 \
-x265-params "level-idc=41:profile=main" \
-c:a copy \
salida-hevc-compat.mp4
VP9 para Web
# VP9 con calidad variable (CRF) para web
ffmpeg -i entrada.mkv \
-c:v libvpx-vp9 \
-crf 30 -b:v 0 \
-deadline good -cpu-used 2 \
-c:a libopus -b:a 128k \
salida.webm
Aceleración Hardware VAAPI
VAAPI (Video Acceleration API) soporta Intel y AMD:
# Verificar el soporte VAAPI
vainfo
# Ver los dispositivos disponibles
ls /dev/dri/
# Transcodificación H.264 con VAAPI
ffmpeg -vaapi_device /dev/dri/renderD128 \
-i entrada.mkv \
-vf 'format=nv12,hwupload' \
-c:v h264_vaapi \
-qp 23 \
-c:a aac -b:a 192k \
salida-vaapi.mp4
# Transcodificación HEVC con VAAPI
ffmpeg -vaapi_device /dev/dri/renderD128 \
-i entrada.mkv \
-vf 'format=nv12,hwupload' \
-c:v hevc_vaapi \
-qp 28 \
-c:a aac -b:a 192k \
salida-hevc-vaapi.mp4
# Escalar resolución con VAAPI (1080p a 720p)
ffmpeg -vaapi_device /dev/dri/renderD128 \
-i entrada.mkv \
-vf 'format=nv12,hwupload,scale_vaapi=1280:720' \
-c:v h264_vaapi \
-b:v 2500k \
-c:a aac -b:a 128k \
salida-720p.mp4
Aceleración Hardware NVENC
NVENC usa el encoder de hardware de NVIDIA:
# Verificar soporte NVENC
nvidia-smi
ffmpeg -encoders | grep nvenc
# H.264 con NVENC
ffmpeg -i entrada.mkv \
-c:v h264_nvenc \
-preset p5 \
-rc vbr \
-b:v 4000k \
-maxrate 6000k \
-bufsize 8000k \
-c:a aac -b:a 192k \
salida-nvenc.mp4
# HEVC con NVENC (más eficiente en GPUs modernas)
ffmpeg -i entrada.mkv \
-c:v hevc_nvenc \
-preset p5 \
-rc vbr \
-b:v 3000k \
-tag:v hvc1 \
-c:a aac -b:a 192k \
salida-hevc-nvenc.mp4
# Decodificación hardware con NVIDIA (reduce carga de CPU)
ffmpeg \
-hwaccel cuda \
-hwaccel_output_format cuda \
-i entrada.mkv \
-c:v h264_nvenc \
-preset p4 \
-b:v 3000k \
-c:a copy \
salida-gpu.mp4
Procesamiento por Lotes
#!/bin/bash
# Script de transcodificación por lotes para convertir una carpeta entera
ENTRADA_DIR="/mnt/videos/originales"
SALIDA_DIR="/mnt/videos/transcodificados"
LOG_FILE="/var/log/ffmpeg-batch.log"
# Crear directorio de salida si no existe
mkdir -p "$SALIDA_DIR"
# Contar el total de archivos para mostrar progreso
TOTAL=$(find "$ENTRADA_DIR" -name "*.mkv" -o -name "*.avi" -o -name "*.mp4" | wc -l)
ACTUAL=0
# Procesar cada archivo de vídeo
find "$ENTRADA_DIR" -type f \( -name "*.mkv" -o -name "*.avi" -o -name "*.mp4" \) | while read -r archivo; do
ACTUAL=$((ACTUAL + 1))
NOMBRE=$(basename "$archivo" | sed 's/\.[^.]*$//')
SALIDA="${SALIDA_DIR}/${NOMBRE}.mp4"
echo "[$(date '+%Y-%m-%d %H:%M:%S')] Procesando ($ACTUAL/$TOTAL): $archivo" | tee -a "$LOG_FILE"
# Saltar si el archivo de salida ya existe
if [ -f "$SALIDA" ]; then
echo " -> Ya existe, omitiendo" | tee -a "$LOG_FILE"
continue
fi
# Transcodificar con VAAPI (o cambiar a libx264 si no hay GPU)
ffmpeg -vaapi_device /dev/dri/renderD128 \
-i "$archivo" \
-vf 'format=nv12,hwupload' \
-c:v h264_vaapi -qp 23 \
-c:a aac -b:a 192k \
-y "$SALIDA" \
>> "$LOG_FILE" 2>&1
if [ $? -eq 0 ]; then
echo " -> Completado: $SALIDA" | tee -a "$LOG_FILE"
else
echo " -> ERROR al procesar: $archivo" | tee -a "$LOG_FILE"
fi
done
echo "Procesamiento por lotes completado." | tee -a "$LOG_FILE"
# Ejecutar el script
chmod +x /opt/scripts/transcoding-batch.sh
/opt/scripts/transcoding-batch.sh
# O como tarea en segundo plano con nohup
nohup /opt/scripts/transcoding-batch.sh &
tail -f /var/log/ffmpeg-batch.log
Pipelines de Streaming
Streaming HLS (para reproductores web)
# Generar stream HLS desde un archivo (múltiples calidades)
ffmpeg -i entrada.mkv \
-filter_complex \
"[v:0]split=3[v1][v2][v3]; \
[v1]scale=1920:1080[1080p]; \
[v2]scale=1280:720[720p]; \
[v3]scale=854:480[480p]" \
-map "[1080p]" -c:v:0 libx264 -b:v:0 5000k \
-map "[720p]" -c:v:1 libx264 -b:v:1 2500k \
-map "[480p]" -c:v:2 libx264 -b:v:2 1000k \
-map 0:a -c:a aac -b:a 128k \
-f hls \
-hls_time 6 \
-hls_list_size 0 \
-hls_segment_filename "/var/www/hls/segment_%v_%03d.ts" \
-master_pl_name master.m3u8 \
/var/www/hls/stream_%v.m3u8
Restreaming RTMP
# Recibir stream RTMP y re-emitir a múltiples destinos
ffmpeg -i rtmp://localhost:1935/live/stream \
-c:v copy -c:a copy \
-f flv rtmp://destino1.ejemplo.com/live/clave1 \
-c:v copy -c:a copy \
-f flv rtmp://destino2.ejemplo.com/live/clave2
Optimización de Calidad
# Análisis de la calidad con VMAF (requiere compilación con libvmaf)
ffmpeg -i original.mkv -i transcodificado.mp4 \
-lavfi "[0:v][1:v]libvmaf" \
-f null -
# Verificar metadatos de un vídeo transcodificado
ffprobe -v quiet -print_format json -show_format -show_streams salida.mp4 | \
python3 -m json.tool | grep -E "codec_name|bit_rate|width|height"
# Ajustar el preset según la prioridad:
# ultrafast > superfast > veryfast > faster > fast > medium > slow > slower > veryslow
# Más rápido = menos CPU, menor compresión
# Más lento = más CPU, mejor compresión
ffmpeg -i entrada.mkv -c:v libx264 -crf 23 -preset veryfast salida-rapida.mp4
ffmpeg -i entrada.mkv -c:v libx264 -crf 23 -preset slow salida-calidad.mp4
Solución de Problemas
Error de VAAPI "No such file or directory" para /dev/dri/renderD128:
# Verificar disponibilidad del dispositivo
ls -la /dev/dri/
# Instalar los drivers de VA-API
sudo apt install -y vainfo libva-intel-driver intel-media-va-driver # Intel
# sudo apt install -y mesa-va-drivers # AMD
# Verificar acceso del usuario actual
groups $(whoami) | grep -E "video|render"
sudo usermod -aG render,video $(whoami)
Error "Cannot load nvcuda.dll" con NVENC:
# Verificar que los drivers NVIDIA están instalados
nvidia-smi
# Verificar la versión del driver (debe ser 418.30+)
nvidia-smi --query-gpu=driver_version --format=csv,noheader
Proceso de transcodificación muy lento:
# Monitorear el uso de CPU/GPU
htop
nvidia-smi dmon # Para NVIDIA
intel_gpu_top # Para Intel (requiere intel-gpu-tools)
# Verificar si se usa aceleración hardware real
ffmpeg -i entrada.mkv -c:v h264_nvenc -b:v 3000k -c:a copy salida.mp4 -v verbose 2>&1 | grep "nvenc"
Conclusión
FFmpeg configurado con aceleración hardware permite procesar vídeo de alta calidad con una fracción del coste computacional de la transcodificación por software. Dominar VAAPI y NVENC, junto con los parámetros de calidad como CRF y los presets, te permite construir pipelines de transcodificación eficientes que pueden escalar desde un único servidor hasta clusters de procesamiento distribuido.


