Guía de comandos de yt-dlp y ffmpeg

Guía de comandos de yt-dlp y ffmpeg

Recopilación de comandos útiles de ffmpeg y yt-dlp: convertir formatos, cortar, concatenar, comprimir, descargar streams y más con ejemplos prácticos.

FECHA:
ACTUALIZADO:
AUTOR:Jorge Beneyto Castelló
LECTURA:25 MINUTOS DE LECTURA

Si alguna vez has intentado convertir un vídeo a formato Telegram, cortar un fragmento de un stream, o descargar un vídeo de YouTube y te has encontrado con errores crípticos como Invalid data found when processing input o Unable to find a suitable output format, sabes de lo que hablo. La sintaxis de ffmpeg es brutal: cientos de flags, formatos de entrada y salida, códecs con nombres que parecen matemáticas pura. Y yt-dlp, aunque mucho más amigable, también tiene sus trampas cuando necesitas calidad específica o merge de formatos.

Este post no es un manual exhaustivo de las 3000 opciones de ffmpeg (para eso está la documentación oficial). Es una recopilación práctica de los comandos que realmente uso: descargar vídeos con calidad específica, convertir entre formatos, cortar sin perder calidad, comprimir para Telegram, y manejar streams en vivo. Cada sección explica qué necesitas resolver, por qué ese comando funciona y cómo adaptarlo a tu caso. Si necesitas instalar estas herramientas con Docker en WSL/Ubuntu, primero consulta el post Docker: ffmpeg y yt-dlp en Windows (WSL) y Ubuntu.

Referencias oficiales

yt-dlp: Quick Start

Descarga básica

# Descargar vídeo con mejor calidad disponible
yt-dlp "URL"

# Listar todos los formatos disponibles
yt-dlp -F "URL"

# Descargar con mejor vídeo + mejor audio (requiere ffmpeg para unir)
yt-dlp -f "bv+ba/b" "URL"

# Forzar merge a mp4
yt-dlp -f "bv+ba/b" --merge-output-format mp4 "URL"

# Simular sin descargar (mostraría qué haría)
yt-dlp --simulate "URL"

# Verificar versión
yt-dlp --version

# Actualizar yt-dlp
yt-dlp -U

Selección de formato y calidad

# Máxima calidad disponible
yt-dlp -f "bestvideo+bestaudio/best" "URL"

# Cap a 1080p máximo
yt-dlp -f "bestvideo[height<=1080]+bestaudio/best" "URL"

# Forzar 4K si está disponible
yt-dlp -f "bestvideo[height>=2160]+bestaudio/best" "URL"

# Preferir H.264/MP4 (máxima compatibilidad)
yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best" "URL"

# Preferir VP9 (mejor calidad en mismo bitrate)
yt-dlp -f "bestvideo[vcodec^=vp9]+bestaudio/best" "URL"

# Calidad específica (ejemplo: formato 22 = 720p mp4)
yt-dlp -f 22 "URL"

# Solo vídeo sin audio
yt-dlp -f "bestvideo" "URL"

# Solo audio sin vídeo
yt-dlp -f "bestaudio" "URL"

Extraer solo audio

# Extraer audio y convertir a mp3
yt-dlp -x --audio-format mp3 "URL"

# Extraer audio a calidad máxima (0 = mejor)
yt-dlp -x --audio-format mp3 --audio-quality 0 "URL"

# Extraer audio a 128k
yt-dlp -x --audio-format mp3 --audio-quality 128k "URL"

# Extraer audio como opus (menor tamaño, mejor calidad)
yt-dlp -x --audio-format opus "URL"

# Extraer audio como aac
yt-dlp -x --audio-format m4a "URL"

# Extraer audio sin re-codificar (si ya es mp3, solo extraer)
yt-dlp -x --audio-format mp3 --audio-quality -1 "URL"

# Extraer audio a flac (lossless)
yt-dlp -x --audio-format flac "URL"

Playlists

# Descargar playlist completa
yt-dlp "URL_PLAYLIST"

# Descargar solo los primeros 5 vídeos
yt-dlp --playlist-items 1-5 "URL_PLAYLIST"

# Descargar del vídeo 3 al 10
yt-dlp --playlist-items 3-10 "URL_PLAYLIST"

# Solo vídeos nuevos (guardar en archivo de archive)
yt-dlp --download-archive watched.txt "URL_PLAYLIST"

# Descargar solo vídeos de los últimos 30 días
yt-dlp --dateafter today-30days "URL_PLAYLIST"

# No descargar, solo listar títulos
yt-dlp --flat-playlist --print title "URL_PLAYLIST"

# Mantener orden de la playlist
yt-dlp --yes-playlist "URL_PLAYLIST"

# Invertir orden de descarga
yt-dlp --playlist-reverse "URL_PLAYLIST"

# Mezclar orden aleatorio
yt-dlp --playlist-random "URL_PLAYLIST"

Subtítulos

# Descargar subtítulos automáticos
yt-dlp --write-auto-subs "URL"

# Descargar subtítulos en español e inglés
yt-dlp --write-subs --sub-lang es,en "URL"

# Solo subtítulos (sin vídeo)
yt-dlp --write-subs --sub-lang es --skip-download "URL"

# Formato específico de subtítulos
yt-dlp --write-subs --sub-format srt "URL"

# Incrustar subtítulos en el vídeo (requiere ffmpeg)
yt-dlp --embed-subs --sub-lang es "URL"

# Subtítulos en todos los idiomas disponibles
yt-dlp --all-subs "URL"

Metadatos y thumbnails

# Incrustar thumbnail en el archivo
yt-dlp --embed-thumbnail "URL"

# Incrustar metadata (título, autor, etc.)
yt-dlp --embed-metadata "URL"

# Incrustar todo (thumbnail + metadata + subtítulos)
yt-dlp --embed-thumbnail --embed-metadata --embed-subs "URL"

# Guardar thumbnail como archivo separado
yt-dlp --write-thumbnail "URL"

# Guardar descripción del vídeo
yt-dlp --write-description "URL"

# Guardar información en formato JSON
yt-dlp -j "URL" > info.json

Cookies y autenticación

# Usar cookies del navegador (para vídeos privados o con restricción de edad)
yt-dlp --cookies-from-browser chrome "URL"

# Usar cookies de Firefox
yt-dlp --cookies-from-browser firefox "URL"

# Usar cookies de Edge
yt-dlp --cookies-from-browser edge "URL"

# Usar archivo de cookies (Netscape format)
yt-dlp --cookies cookies.txt "URL"

# Login con usuario y contraseña (no recomendado, usar cookies)
yt-dlp --username usuario --password contraseña "URL"

Rendimiento y red

# Fragmentos paralelos (más rápido en conexiones buenas)
yt-dlp -N 4 "URL"

# Limitar velocidad de descarga
yt-dlp --limit-rate 5M "URL"

# Limitar a 500KB/s
yt-dlp --limit-rate 500K "URL"

# Reintentos en fallos
yt-dlp --retries 10 --fragment-retries 10 "URL"

# Intervalo aleatorio entre descargas (evitar bans)
yt-dlp --sleep-interval 5 --max-sleep-interval 10 "URL"

# Usar proxy
yt-dlp --proxy "socks5://127.0.0.1:1080" "URL"

# Forzar IPv4
yt-dlp -4 "URL"

# Forzar IPv6
yt-dlp -6 "URL"

# Timeout de conexión
yt-dlp --socket-timeout 30 "URL"

Plantillas de salida

# Estructura por canal
yt-dlp -o "%(channel)s/%(title)s.%(ext)s" "URL"

# Con fecha
yt-dlp -o "%(channel)s/%(upload_date>%Y-%m-%d)s-%(title)s.%(ext)s" "URL"

# Con índice de playlist
yt-dlp -o "%(playlist_index)02d-%(title)s.%(ext)s" "URL_PLAYLIST"

# Variables disponibles:
# %(title)s       → Título del vídeo
# %(ext)s         → Extensión del archivo
# %(id)s          → ID del vídeo
# %(upload_date)s → Fecha (YYYYMMDD)
# %(channel)s     → Nombre del canal
# %(duration)s    → Duración en segundos
# %(view_count)s  → Número de vistas

Post-procesamiento

# Re-codificar a mp4 después de descargar
yt-dlp --recode-video mp4 "URL"

# Ejecutar comando post-descarga
yt-dlp --exec "echo Descargado: {}" "URL"

# Abrir con reproductor después de descargar
yt-dlp --exec "xdg-open" "URL"

# No re-codificar, solo cambiar contenedor
yt-dlp --merge-output-format mp4 "URL"

# Mover archivo a carpeta específica
yt-dlp --exec "mv {} ~/Videos/" "URL"

Grabación de livestream

# Grabar livestream desde el principio
yt-dlp --live-from-start "URL"

# Grabar fragmento específico de un directo
yt-dlp --live-from-start --live-fragments-start 100 "URL"

# Grabar solo el segmento actual (no desde el inicio)
yt-dlp "URL_LIVE"

Archivo de configuración

Crea ~/.config/yt-dlp/config:

--format bv*+ba
--merge-output-format mp4
--embed-thumbnail
--embed-metadata
--write-subs
--sub-lang es,en
--output ~/Videos/%(channel)s/%(title)s.%(ext)s

Se ejecuta automáticamente al usar yt-dlp. Puedes especificar otra ubicación:

yt-dlp --config-location ~/mi_config.txt "URL"

ffmpeg: Quick Start

Conversión de formatos

# Convertir a mp4
ffmpeg -i input.avi output.mp4

# Convertir a mkv
ffmpeg -i input.mp4 output.mkv

# Convertir a webm (VP9)
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 output.webm

# Convertir a mov (Apple)
ffmpeg -i input.mp4 output.mov

# Sin re-codificar (solo cambiar contenedor)
ffmpeg -i input.mkv -c copy output.mp4

# Cambiar extensión sin tocar codec
ffmpeg -i input.ts -c copy output.mp4

Extracción de audio

# Extraer audio sin re-codificar
ffmpeg -i video.mp4 -vn -c:a copy audio.aac

# Extraer y convertir a mp3
ffmpeg -i video.mp4 -vn -c:a libmp3lame -b:a 192k audio.mp3

# Extraer a wav (sin compresión)
ffmpeg -i video.mp4 -vn -c:a pcm_s16le audio.wav

# Extraer a flac (lossless)
ffmpeg -i video.mp4 -vn -c:a flac audio.flac

# Extraer solo un canal (mono)
ffmpeg -i video.mp4 -vn -ac 1 audio.mp3

# Extraer a 22050 Hz (para voz/podcasts)
ffmpeg -i video.mp4 -vn -ar 22050 audio.mp3

# Extraer solo un segmento de audio
ffmpeg -i video.mp4 -ss 00:01:00 -to 00:02:00 -vn -c:a libmp3lame audio.mp3

Corte de vídeo

# Cortar por tiempo (rápido, sin re-codificar)
ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -c copy output.mp4

# Cortar con re-codificación (preciso)
ffmpeg -i input.mp4 -ss 00:01:00 -to 00:02:00 -c:v libx264 -c:a aac output.mp4

# Cortar los primeros 30 segundos
ffmpeg -i input.mp4 -t 00:00:30 -c copy output.mp4

# Cortar desde el segundo 60 hasta el final
ffmpeg -i input.mp4 -ss 00:01:00 -c copy output.mp4

# Cortar con precisión (para streaming)
ffmpeg -i input.mp4 -ss 00:05:00 -t 00:10:00 -c:v libx264 -c:a aac -avoid_negative_ts make_zero output.mp4

Concatenación de vídeos

# Método 1: filter_complex (mismos formatos)
ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[outv][outa]" -map "[outv]" -map "[outa]" output.mp4

# Método 2: archivo de lista (para muchos archivos)
# Crear archivo lista.txt:
# file 'video1.mp4'
# file 'video2.mp4'
# file 'video3.mp4'
ffmpeg -f concat -safe 0 -i lista.txt -c copy output.mp4

# Concatenar con transición de fade
ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex "[0:v]fade=t=out:st=4:d=1[v0];[1:v]fade=t=in:st=0:d=1[v1];[v0][v1]concat=n=2:v=1:a=0" output.mp4

Concatenación inteligente (con auto-detección)

Cuando los archivos tienen codecs, resoluciones o FPS distintos, el concat básico falla o produce corruptos. La solución es detectar compatibilidad y usar stream copy o re-encode automáticamente:

# Detectar si dos archivos son compatibles para concat
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate -of csv=p=0 video1.mp4
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name,width,height,r_frame_rate -of csv=p=0 video2.mp4

# Si la salida es idéntica → stream copy (rápido)
# Si difiere → re-encode con filter_complex concat

# Crossfade entre dos vídeos (transición suave)
ffmpeg -i v1.mp4 -i v2.mp4 \
  -filter_complex "[0:v][1:v]xfade=transition=fade:duration=1:offset=9[v]; \
                   [0:a][1:a]acrossfade=d=1[a]" \
  -map "[v]" -map "[a]" -c:v libx264 -preset fast -c:a aac output.mp4

Redimensionado y escalado

# Escalar a 1280x720
ffmpeg -i input.mp4 -vf scale=1280:720 output.mp4

# Manteniendo aspect ratio (con padding negro)
ffmpeg -i input.mp4 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" output.mp4

# Escalar al 50%
ffmpeg -i input.mp4 -vf scale=iw/2:ih/2 output.mp4

# Escalar por ancho (alto automático)
ffmpeg -i input.mp4 -vf "scale=1280:-2" output.mp4

# Cropping (recortar)
ffmpeg -i input.mp4 -vf "crop=640:480:100:50" output.mp4
# crop=ancho:alto:x:y

# Cropping centrado
ffmpeg -i input.mp4 -vf "crop=640:480:(iw-640)/2:(ih-480)/2" output.mp4

Video a GIF

# GIF básico
ffmpeg -i input.mp4 output.gif

# GIF con calidad (paleta optimizada)
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif

# GIF de un segmento específico
ffmpeg -i input.mp4 -ss 00:01:00 -t 5 -vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" output.gif

Marca de agua

# Imagen como marca de agua (esquina inferior derecha)
ffmpeg -i video.mp4 -i logo.png -filter_complex "overlay=W-w-10:H-h-10" output.mp4

# Imagen en esquina superior izquierda
ffmpeg -i video.mp4 -i logo.png -filter_complex "overlay=10:10" output.mp4

# Texto como marca de agua
ffmpeg -i video.mp4 -vf "drawtext=text='Mi Marca':fontsize=24:fontcolor=white:x=10:y=10" output.mp4

# Texto con sombra
ffmpeg -i video.mp4 -vf "drawtext=text='© 2026':fontsize=20:fontcolor=white:borderw=2:bordercolor=black:x=W-tw-10:y=H-th-10" output.mp4

# Marca de agua semi-transparente
ffmpeg -i video.mp4 -i logo.png -filter_complex "format=rgba,colorchannelmixer=aa=0.3[wm];[0:v][wm]overlay=W-w-10:H-h-10" output.mp4

Filtros de vídeo

# Ajustar brillo (0.0 a 2.0, 1.0 = normal)
ffmpeg -i input.mp4 -vf "eq=brightness=0.1" output.mp4

# Ajustar contraste (0.0 a 2.0, 1.0 = normal)
ffmpeg -i input.mp4 -vf "eq=contrast=1.2" output.mp4

# Ajustar saturación
ffmpeg -i input.mp4 -vf "eq=saturation=1.5" output.mp4

# Filtro de nitidez
ffmpeg -i input.mp4 -vf "unsharp=5:5:1.0" output.mp4

# Voltear horizontalmente
ffmpeg -i input.mp4 -vf "hflip" output.mp4

# Rotar 90 grados
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4

# Rotar 180 grados
ffmpeg -i input.mp4 -vf "transpose=2,transpose=2" output.mp4

Subtítulos

# Incrustar subtítulos SRT en el vídeo
ffmpeg -i video.mp4 -vf "subtitles=subtitles.srt" output.mp4

# Incrustar con estilo personalizado
ffmpeg -i video.mp4 -vf "subtitles=subtitles.srt:force_style='FontSize=24,PrimaryColour=&H00FFFFFF'" output.mp4

# Incrustar subtítulos ASS
ffmpeg -i video.mp4 -vf "ass=subtitles.ass" output.mp4

Normalización de audio

# Normalización simple (loudnorm)
ffmpeg -i input.mp4 -af "loudnorm" output.mp4

# Normalización dinámica
ffmpeg -i input.mp4 -af "dynaudnorm" output.mp4

# Ajustar volumen (2x más fuerte)
ffmpeg -i input.mp4 -af "volume=2.0" output.mp4

# Ajustar volumen (50% más bajo)
ffmpeg -i input.mp4 -af "volume=0.5" output.mp4

# Ecualización (ejemplo: realzar graves)
ffmpeg -i input.mp4 -af "equalizer=f=100:t=q:w=1:g=5" output.mp4

# Fade in de audio
ffmpeg -i input.mp4 -af "afade=t=in:st=0:d=2" output.mp4

# Fade out de audio
ffmpeg -i input.mp4 -af "afade=t=out:st=58:d=2" output.mp4

Dos pasadas (two-pass) para mejor calidad

# Pasada 1: análisis
ffmpeg -i input.mp4 -c:v libx264 -b:v 5M -pass 1 -f null /dev/null

# Pasada 2: codificación
ffmpeg -i input.mp4 -c:v libx264 -b:v 5M -pass 2 output.mp4

# Para H.265/HEVC
ffmpeg -i input.mp4 -c:v libx265 -b:v 3M -pass 1 -f null /dev/null
ffmpeg -i input.mp4 -c:v libx265 -b:v 3M -pass 2 output.mp4

Streaming HLS

# Preparar para streaming HLS
ffmpeg -i input.mp4 -c:v libx264 -c:a aac -f hls -hls_time 4 -hls_playlist_type vod output.m3u8

# Multi-bitrate (adaptativo)
ffmpeg -i input.mp4 \
  -map 0 -b:v:0 500k -s:v:0 640x360 -c:v libx264 \
  -b:v:1 1000k -s:v:1 1280:720 -c:v libx264 \
  -b:v:2 2000k -s:v:2 1920:1080 -c:v libx264 \
  -hls_time 4 -hls_playlist_type vod \
  -var_stream_map "v:0,a:0 v:1,a:0 v:2,a:0" \
  stream_%v.m3u8

Procesamiento por lotes

# Convertir todos los avi a mp4
for file in *.avi; do ffmpeg -i "$file" "${file%.avi}.mp4"; done

# Convertir todos los mkv a mp4 sin re-codificar
for file in *.mkv; do ffmpeg -i "$file" -c copy "${file%.mkv}.mp4"; done

# Redimensionar todos los vídeos a 720p
for file in *.mp4; do ffmpeg -i "$file" -vf scale=1280:720 "${file%.mp4}_720p.mp4"; done

# Extraer audio de todos los vídeos
for file in *.mp4; do ffmpeg -i "$file" -vn -c:a libmp3lame "${file%.mp4}.mp3"; done

Opciones útiles

# Sobreescribir sin preguntar
ffmpeg -y -i input.mp4 output.mp4

# No sobreescribir
ffmpeg -n -i input.mp4 output.mp4

# Ocultar banner de información
ffmpeg -hide_banner -i input.mp4

# Ver información del archivo
ffprobe -v error -show_format -show_streams input.mp4

# Ver duración
ffprobe -v error -show_entries format=duration -of csv=p=0 input.mp4

# Ver codec de vídeo
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 input.mp4

# Ver codec de audio
ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of csv=p=0 input.mp4

# Ver resolución
ffprobe -v error -select_streams v:0 -show_entries stream=width,height -of csv=p=0 input.mp4

# Ver FPS
ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of csv=p=0 input.mp4

Mejores prácticas de encoding

Para una guía completa de compresión de vídeo, consulta la FFmpeg Video Compression Best Practices Guide.

Tabla de CRF por codec y uso

CRF (Constant Rate Factor) controla la calidad. Menor valor = mejor calidad = archivo más grande.

Caso de usoH.264 CRFH.265 CRFNotas
Pérdida cercana a cero0–180–20Para archivado, backups
Alta calidad18–2222–26Entrega de calidad
Web / uso general23–2627–30Streaming, publicación
Streaming / móvil27–3230–35Bandwidth limitado
Screencasts / presentaciones28–3532–38Poco movimiento

Regla práctica: Cada +6 en CRF aproxima duplica el tamaño del archivo.

Presets: velocidad vs compresión

El parámetro -preset controla cuánto tiempo dedica el encoder a optimizar. Más lento = mejor compresión.

PresetVelocidad relativaTamaño archivoUso recomendado
ultrafast~15x más rápido~40-50% más grandeTesting, previews
veryfast~8x más rápido~25% más grandeTiempo real
fast~3x más rápido~10% más grandeLotes donde velocidad importa
medium1x (default)DefaultUso general
slow~0.5x~5% más pequeñoRenders finales, contenido importante
veryslow~0.1x~10-15% más pequeñoArchivado, raramente vale la pena

Recomendación: medium para uso general, fast para lotes grandes, slow para contenido que se servirá muchas veces.

Comparación de códecs

CódecTamaño relativoVelocidad encodingCompatibilidad (2026)
H.264 (libx264)100% (baseline)Rápido99%+ (universal)
H.265 (libx265)55-65%3-5x más lentoiOS, Android 5+, Smart TVs modernos
VP9 (libvpx-vp9)55-65%5-10x más lentoChrome, Firefox, Edge
AV1 (SVT-AV1)40-50%3-8x más lentoChrome 17+, Firefox, Safari 17+

¿Qué códec usar?

  • Máxima compatibilidad: H.264
  • Archivos más pequeños (Apple/móvil): H.265
  • Web, royalty-free: VP9
  • Futuro, mejor compresión: AV1

Comandos de ejemplo por códec

# H.264 — máxima compatibilidad
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset medium -c:a aac -b:a 128k output.mp4

# H.265 — 40% más pequeño
ffmpeg -i input.mp4 -c:v libx265 -crf 28 -preset medium -c:a aac -b:a 128k output.mp4

# VP9 — royalty-free, bueno para web
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 30 -b:v 0 -row-mt 1 -c:a libopus -b:a 128k output.webm

# AV1 (SVT-AV1) — mejor compresión
ffmpeg -i input.mp4 -c:v libsvtav1 -crf 30 -preset 6 -c:a libopus -b:a 128k output.mp4

Resolución y bitrate recomendado

ResoluciónBitrate típico H.264Bitrate típico H.265
4K (3840x2160)15-30 Mbps8-15 Mbps
1440p (2560x1440)8-15 Mbps4-8 Mbps
1080p (1920x1080)4-8 Mbps2-4 Mbps
720p (1280x720)2-4 Mbps1-2 Mbps
480p (854x480)1-2 Mbps0.5-1 Mbps
360p (640x360)0.5-1 Mbps0.3-0.5 Mbps

¿Cuándo usar CRF vs Two-pass?

  • CRF: Cuando priorizas calidad constante (web, archivado). Más simple, una sola pasada.
  • Two-pass: Cuando necesitas un tamaño de archivo específico (ej: Discord 25MB, límite de email). Dos pasadas, más lento pero preciso.

¿Cuándo usar -c copy?

Cuando el vídeo ya está en el códec correcto (H.264+AAC) y solo necesitas cambiar el contenedor. Esto es 100x más rápido que re-codificar:

# Cambiar mkv a mp4 sin re-codificar
ffmpeg -i input.mkv -c copy output.mp4

Para detectar si puedes usar -c copy:

ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of csv=p=0 input.mp4
ffprobe -v error -select_streams a:0 -show_entries stream=codec_name -of csv=p=0 input.mp4

Si el vídeo es h264 y el audio es aac, puedes usar -c copy.

Combinados: yt-dlp + ffmpeg

Descargar y reconvertir

# Descargar y convertir a mp4 con ffmpeg
yt-dlp -f "bv+ba/b" "URL" --exec "ffmpeg -i {} -c:v libx264 -c:a aac {}.mp4"

# Descargar y redimensionar a 720p
yt-dlp -f "bv+ba/b" "URL" --exec "ffmpeg -i {} -vf scale=1280:720 -c:v libx264 -c:a aac {}_720p.mp4"

# Descargar y comprimir a tamaño específico
yt-dlp -f "bv+ba/b" "URL" --exec "ffmpeg -i {} -c:v libx264 -b:v 1M -c:a aac {}_compressed.mp4"

Descargar solo audio y convertir

# Descargar audio directamente con yt-dlp
yt-dlp -x --audio-format mp3 "URL"

# Descargar audio y convertir con ffmpeg (más control)
yt-dlp -x --audio-format wav "URL" --exec "ffmpeg -i {} -c:a libmp3lame -b:a 320k {}.mp3"

# Descargar playlist como mp3
yt-dlp -x --audio-format mp3 --yes-playlist "URL_PLAYLIST"

# Descargar y normalizar audio
yt-dlp -x --audio-format mp3 "URL" --exec "ffmpeg -i {} -af loudnorm {}_normalized.mp3"

Pipeline completo: descargar → comprimir → organizar

#!/bin/bash
# Script para descargar y comprimir vídeos

URL="$1"
CARPETA="$HOME/Videos/$(date +%Y-%m-%d)"
mkdir -p "$CARPETA"

# Descargar
yt-dlp -f "bv+ba/b" --merge-output-format mp4 -o "$CARPETA/%(title)s.%(ext)s" "URL"

# Comprimir todos los vídeos nuevos
for file in "$CARPETA"/*.mp4; do
    ffmpeg -i "$file" -c:v libx264 -crf 28 -preset fast -c:a aac -b:a 128k "${file%.mp4}_compressed.mp4"
    rm "$file"
done

Workflow de lotes: descargar playlist + comprimir

#!/bin/bash
# Descargar playlist y comprimir cada vídeo

PLAYLIST_URL="$1"
OUTPUT_DIR="$HOME/Videos/comprimidos"
mkdir -p "$OUTPUT_DIR"

# Descargar playlist
yt-dlp -f "bv+ba/b" --merge-output-format mp4 \
  -o "$OUTPUT_DIR/%(playlist_index)02d-%(title)s.%(ext)s" \
  --yes-playlist "$PLAYLIST_URL"

# Comprimir cada vídeo
for file in "$OUTPUT_DIR"/*.mp4; do
    echo "Comprimiendo: $file"
    ffmpeg -i "$file" \
      -c:v libx264 -crf 28 -preset fast \
      -c:a aac -b:a 128k \
      -movflags +faststart \
      "${file%.mp4}_small.mp4"
    rm "$file"
done

echo "¡Listo! Vídeos comprimidos en $OUTPUT_DIR"

Descargar segmento específico y comprimir

# Descargar solo un trozo de un vídeo
yt-dlp --external-downloader ffmpeg \
  --external-downloader-args "ffmpeg_i:-ss 00:10:00 -to 00:20:00" \
  -f "bv+ba/b" "URL"

# Descargar y comprimir ese segmento
yt-dlp --external-downloader ffmpeg \
  --external-downloader-args "ffmpeg_i:-ss 00:10:00 -to 00:20:00" \
  -f "bv+ba/b" "URL" \
  --exec "ffmpeg -i {} -c:v libx264 -crf 28 -c:a aac {}.mp4"

Descargar canal completo y organizar por carpeta

# Descargar canal organizado por carpetas
yt-dlp -o "%(channel)s/%(playlist_title)s/%(title)s.%(ext)s" "URL_CANAL"

# Descargar canal con límite de calidad
yt-dlp -f "bestvideo[height<=1080]+bestaudio/best" \
  -o "%(channel)s/%(title)s.%(ext)s" "URL_CANAL"

# Descargar canal y comprimir
yt-dlp -f "bv+ba/b" --yes-playlist \
  -o "%(channel)s/%(title)s.%(ext)s" "URL_CANAL" \
  --exec "ffmpeg -i {} -c:v libx264 -crf 28 -c:a aac {}_compressed.mp4"

Tabla resumen de opciones rápidas

yt-dlp

OpciónDescripción
-f "best"Mejor calidad disponible
-FListar formatos
-x --audio-format mp3Extraer solo audio
-o "patron"Plantilla de salida
--embed-thumbnailIncrustar thumbnail
--embed-metadataIncrustar metadata
--write-subsDescargar subtítulos
-N 4Fragmentos paralelos
--limit-rate 5MLimitar velocidad
--cookies-from-browserUsar cookies del navegador
--yes-playlistDescargar playlist
--download-archiveGuardar historial
--dateafterFiltrar por fecha
-UActualizar yt-dlp

ffmpeg

OpciónDescripción
-i inputArchivo de entrada
-c copySin re-codificar
-c:v libx264Códec de vídeo H.264
-c:a aacCódec de audio AAC
-b:v 5MBitrate de vídeo
-b:a 128kBitrate de audio
-vf scale=W:HRedimensionar
-ss / -to / -tCorte por tiempo
-vnSin vídeo (extraer audio)
-ySobreescribir
-movflags +faststartOptimizar para web
-crf 28Calidad (menor = mejor)
-preset fastVelocidad de codificación
-filter_complexFiltros complejos
-mapSeleccionar pistas

Casos de uso específicos

WhatsApp (límite 16MB)

# Comprimir para WhatsApp (máximo 16MB)
ffmpeg -i input.mp4 -c:v libx264 -b:v 800k -c:a aac -b:a 64k \
  -fs 16M -movflags +faststart whatsapp.mp4

# Script para detectar duración y ajustar bitrate
#!/bin/bash
INPUT="$1"
DURATION=$(ffprobe -v error -show_entries format=duration -of csv=p=0 "$INPUT" | cut -d. -f1)
# 16MB = 131072 kbits, restamos audio (64k * duración)
VIDEO_BITRATE=$(( (131072 - (64 * DURATION)) / DURATION ))
ffmpeg -i "$INPUT" -c:v libx264 -b:v "${VIDEO_BITRATE}k" -c:a aac -b:a 64k \
  -movflags +faststart "whatsapp_${INPUT}"

Telegram (límite 2GB)

# Comprimir para Telegram (máximo 2GB)
ffmpeg -i input.mp4 -c:v libx264 -crf 28 -preset fast \
  -c:a aac -b:a 128k -movflags +faststart telegram.mp4

# Para máxima compresión (calidad aceptable)
ffmpeg -i input.mp4 -c:v libx264 -crf 32 -preset fast \
  -c:a aac -b:a 96k -movflags +faststart telegram_small.mp4

Instagram

# Instagram Feed (máximo 60 segundos, 1080x1080)
ffmpeg -i input.mp4 -ss 0 -t 60 -vf "scale=1080:1080:force_original_aspect_ratio=decrease,pad=1080:1080:(ow-iw)/2:(oh-ih)/2" \
  -c:v libx264 -b:v 3500k -c:a aac -b:a 128k instagram_feed.mp4

# Instagram Reels (9:16, máximo 90 segundos)
ffmpeg -i input.mp4 -ss 0 -t 90 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" \
  -c:v libx264 -b:v 3500k -c:a aac -b:a 128k instagram_reel.mp4

# Instagram Stories (9:16, máximo 15 segundos)
ffmpeg -i input.mp4 -ss 0 -t 15 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" \
  -c:v libx264 -b:v 3500k -c:a aac -b:a 128k instagram_story.mp4

TikTok

# TikTok (9:16, máximo 3 minutos)
ffmpeg -i input.mp4 -ss 0 -t 180 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2" \
  -c:v libx264 -b:v 3000k -c:a aac -b:a 128k tiktok.mp4

# TikTok con texto superpuesto
ffmpeg -i input.mp4 -vf "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,drawtext=text='Mi TikTok':fontsize=36:fontcolor=white:x=(w-tw)/2:y=50" \
  -c:v libx264 -b:v 3000k -c:a aac -b:a 128k tiktok_texto.mp4

YouTube

# YouTube (recomendado 1080p o 4K)
ffmpeg -i input.mp4 -c:v libx264 -crf 18 -preset slow \
  -c:a aac -b:a 192k -movflags +faststart youtube_1080p.mp4

# YouTube 4K
ffmpeg -i input.mp4 -c:v libx264 -crf 18 -preset slow \
  -vf scale=3840:2160 -c:a aac -b:a 256k -movflags +faststart youtube_4k.mp4

# YouTube Shorts (9:16, máximo 60 segundos)
ffmpeg -i input.mp4 -ss 0 -t 60 -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 128k youtube_short.mp4

Twitter/X

# Twitter (máximo 140 segundos, 1280x720 máximo)
ffmpeg -i input.mp4 -ss 0 -t 140 -vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:(ow-iw)/2:(oh-ih)/2" \
  -c:v libx264 -b:v 5000k -c:a aac -b:a 128k twitter.mp4

Backup de canales de YouTube

#!/bin/bash
# Script para backup de canal de YouTube

CANAL_URL="$1"
BACKUP_DIR="$HOME/Backups/YouTube/$(date +%Y-%m-%d)"
mkdir -p "$BACKUP_DIR"

# Descargar canal completo con metadata
yt-dlp \
  -f "bestvideo[height<=1080]+bestaudio/best" \
  --merge-output-format mp4 \
  --embed-thumbnail \
  --embed-metadata \
  --write-description \
  --write-info-json \
  -o "$BACKUP_DIR/%(upload_date>%Y-%m-%d)s-%(title)s.%(ext)s" \
  --yes-playlist \
  "$CANAL_URL/videos"

echo "Backup completado en: $BACKUP_DIR"

Organizar biblioteca de vídeos

#!/bin/bash
# Script para organizar vídeos descargados

CARPETA="$1"
OUTPUT="$HOME/Videos/Organizados"
mkdir -p "$OUTPUT"

for file in "$CARPETA"/*.mp4; do
    # Extraer metadata
    TITLE=$(ffprobe -v error -show_entries format_tags=title -of csv=p=0 "$file" 2>/dev/null)
    DATE=$(ffprobe -v error -show_entries format_tags=date -of csv=p=0 "$file" 2>/dev/null)
    
    if [ -z "$TITLE" ]; then
        TITLE=$(basename "$file" .mp4)
    fi
    
    if [ -z "$DATE" ]; then
        DATE="SinFecha"
    fi
    
    # Crear carpeta por año-mes
    CARPETA_DEST="$OUTPUT/$DATE"
    mkdir -p "$CARPETA_DEST"
    
    # Mover archivo
    mv "$file" "$CARPETA_DEST/$TITLE.mp4"
    echo "Movido: $TITLE → $CARPETA_DEST"
done

Scripts completos de automatización

Script de monitoreo de descargas

#!/bin/bash
# Monitorear carpeta y descargar automáticamente

CARPETA="$HOME/Downloads/pendientes"
LOG="$HOME/Downloads/log_descargas.txt"

echo "Monitoreando: $CARPETA" | tee -a "$LOG"

while true; do
    for file in "$CARPETA"/*.url; do
        if [ -f "$file" ]; then
            URL=$(cat "$file")
            echo "$(date): Descargando: $URL" | tee -a "$LOG"
            
            yt-dlp \
              -f "bv+ba/b" \
              --merge-output-format mp4 \
              -o "$HOME/Videos/%(channel)s/%(title)s.%(ext)s" \
              --embed-thumbnail \
              --embed-metadata \
              "$URL"
            
            if [ $? -eq 0 ]; then
                echo "$(date): Completado: $URL" | tee -a "$LOG"
                rm "$file"
            else
                echo "$(date): ERROR: $URL" | tee -a "$LOG"
            fi
        fi
    done
    sleep 60
done

Script de compresión automática

#!/bin/bash
# Comprimir vídeos nuevos automáticamente

CARPETA="$HOME/Videos/para_comprimir"
OUTPUT="$HOME/Videos/comprimidos"
mkdir -p "$OUTPUT"

inotifywait -m -r -e create "$CARPETA" |
while read path action file; do
    if [[ "$file" == *.mp4 ]]; then
        echo "Comprimiendo: $file"
        
        # Esperar a que el archivo esté listo
        sleep 5
        
        ffmpeg -i "$path$file" \
          -c:v libx264 -crf 28 -preset fast \
          -c:a aac -b:a 128k \
          -movflags +faststart \
          "$OUTPUT/$file"
        
        if [ $? -eq 0 ]; then
            echo "Completado: $file"
            rm "$path$file"
        else
            echo "ERROR: $file"
        fi
    fi
done

Script de backup automático

#!/bin/bash
# Backup automático de canales de YouTube

CANALES=(
    "https://www.youtube.com/@canal1"
    "https://www.youtube.com/@canal2"
    "https://www.youtube.com/@canal3"
)

BACKUP_DIR="$HOME/Backups/YouTube"
LOG="$BACKUP_DIR/log.txt"

mkdir -p "$BACKUP_DIR"

for canal in "${CANALES[@]}"; do
    NOMBRE=$(echo "$canal" | sed 's/.*@//')
    CARPETA="$BACKUP_DIR/$NOMBRE"
    mkdir -p "$CARPETA"
    
    echo "$(date): Descargando: $NOMBRE" | tee -a "$LOG"
    
    yt-dlp \
      -f "bestvideo[height<=1080]+bestaudio/best" \
      --merge-output-format mp4 \
      --download-archive "$CARPETA/.archive" \
      -o "$CARPETA/%(upload_date>%Y-%m-%d)s-%(title)s.%(ext)s" \
      --yes-playlist \
      "$canal/videos"
    
    echo "$(date): Completado: $NOMBRE" | tee -a "$LOG"
done

echo "$(date): Backup general completado" | tee -a "$LOG"

Cron para ejecución automática

# Editar crontab
crontab -e

# Añadir estas líneas:

# Backup diario a las 3 AM
0 3 * * * /home/usuario/scripts/backup_youtube.sh

# Comprimir vídeos nuevos cada hora
0 * * * * /home/usuario/scripts/comprimir_nuevos.sh

# Limpiar caché de yt-dlp semanalmente (domingos a las 4 AM)
0 4 * * 0 rm -rf ~/.cache/yt-dlp/*

Systemd service para monitoreo

# /etc/systemd/system/video-monitor.service

[Unit]
Description=Monitor de vídeos para comprimir
After=network.target

[Service]
Type=simple
User=usuario
ExecStart=/home/usuario/scripts/comprimir_nuevos.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Activar:

sudo systemctl enable video-monitor
sudo systemctl start video-monitor

Aceleración por hardware (GPU)

ffmpeg puede usar la GPU para acelerar la codificación de vídeo. Los encoders principales:

GPUEncoderComando
NVIDIANVENC-c:v h264_nvenc -preset fast
Intel/AMDVAAPI-vaapi_device /dev/dri/renderD128 -c:v h264_vaapi
CPUlibx264-c:v libx264 -preset fast
# NVIDIA: detectar si hay GPU disponible
nvidia-smi

# Codificar con NVENC (2-5x más rápido)
ffmpeg -i input.mp4 -c:v h264_nvenc -preset fast -c:a copy output.mp4

# Codificar con NVENC HEVC (mejor compresión)
ffmpeg -i input.mp4 -c:v hevc_nvenc -preset fast -c:a copy output.mp4

# Intel/AMD: codificar con VAAPI
ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 \
  -vf 'format=nv12,hwupload' -c:v h264_vaapi -c:a copy output.mp4

# Detectar GPU automáticamente (script)
if command -v nvidia-smi &>/dev/null && nvidia-smi &>/dev/null 2>&1; then
    ENCODER="h264_nvenc"
elif [[ -e /dev/dri/renderD128 ]] && command -v vainfo &>/dev/null; then
    ENCODER="h264_vaapi"
else
    ENCODER="libx264"
fi
ffmpeg -i input.mp4 -c:v "$ENCODER" -preset fast -c:a copy output.mp4

Speedup típico:

OperaciónCPU (libx264)GPU (NVENC)Speedup
Convertir 1080p30 fps120 fps4x
Estabilizar15 fps60 fps4x
Denoise10 fps40 fps4x

Pipeline encadenado con ffmpeg

Ejecutar múltiples operaciones en un solo comando, evitando archivos intermedios:

# Cortar + convertir + fade en un solo pass
ffmpeg -i input.mp4 \
  -ss 00:01:00 -t 00:04:00 \
  -vf "scale=1280:720,fade=t=in:st=0:d=2,fade=t=out:st=178:d=2" \
  -c:v libx264 -preset fast -c:a aac -b:a 128k \
  -movflags +faststart output.mp4

# Rotar + denoise + enfocar
ffmpeg -i input.mp4 \
  -vf "transpose=1,nlmeans=s=3:p=3:r=9,unsharp=5:5:3:5:5:0" \
  -c:v libx264 -preset fast -c:a copy output.mp4

# Pipeline completo: descargar + cortar + convertir (yt-dlp + ffmpeg)
yt-dlp -f "bestvideo[ext=mp4]+bestaudio[ext=m4a]" -o "temp.mp4" "URL" && \
ffmpeg -i temp.mp4 -ss 00:01:00 -t 00:05:00 \
  -vf "scale=1280:720" -c:v libx264 -preset fast -c:a aac \
  -movflags +faststart output.mp4 && \
rm temp.mp4

Solución de problemas

Errores comunes de yt-dlp

ErrorCausaSolución
ERROR: Unable to extractYouTube cambió su estructurayt-dlp -U (actualizar)
HTTP Error 403Bloqueo de rate limiting--sleep-interval 5
ERROR: Sign in to confirmNecesita cookies--cookies-from-browser chrome
ERROR: PoTokenToken de prueba falla--cookies-from-browser chrome
ERROR: File already existsArchivo existente--no-overwrites
ERROR: Network unreachableProblema de red--proxy o -4
ERROR: Fragment download failedFragmento corrupto--fragment-retries 10
ERROR: Requested format not availableFormato no existeyt-dlp -F "URL" (listar formatos)

Errores comunes de ffmpeg

ErrorCausaSolución
Invalid argumentParámetro mal formadoRevisar comillas y escapes
No such fileArchivo no existeVerificar ruta
Error opening inputFormato no soportadoActualizar ffmpeg
Encoder not foundCódec no disponibleCompilar con libx264/libx265
Cannot writePermisos o disco llenoVerificar permisos/espacio

Solución a PoToken (YouTube 2026)

YouTube requiere un Proof-of-Origin Token en 2026. Soluciones:

# Opción 1: Usar cookies de navegador (recomendado)
yt-dlp --cookies-from-browser chrome "URL"

# Opción 2: Forzar extractor específico
yt-dlp --extractor-args "youtube:player_client=web" "URL"

# Opción 3: Usar bgutil-ytdlp-pot-provider
# Instalar: pip install bgutil-ytdlp-pot-provider
# Luego usar normalmente
yt-dlp "URL"
COMPARTIR:
COMENTARIOS:

📋 Contenido