Tengo un problema que me llevaba persiguiendo mucho tiempo: acumulo vídeos en montones de formatos diferentes (AVI, MKV, WebM, FLV) que necesito convertir, cortar, comprimir o editar. Cada vez que quiero hacer algo tengo que buscar en Google “cómo convertir vídeo a telegram”, “cómo cortar vídeo sin perder calidad”, “cómo ponerle efecto fade”… y termino copiando comandos de ffmpeg que no entiendo del todo.
Un día me dije: esto tiene que ser más fácil. Quiero una sola herramienta donde pueda decirle “cortame esto de aquí a aquí y pásalo a formato Telegram” y que haga todo solo. Sin copiar comandos, sin buscar tutoriales, sin equivocarme.
Así nació midu.sh: un script que ahora tiene 33 modos de operación. Empezó siendo un scriptito para cortar vídeos y fue creciendo hasta convertirse en una navaja suiza del vídeo.
El problema real
Cada vez que necesito hacer algo con un vídeo, tengo que:
- Buscar el comando correcto de ffmpeg (que es potente pero complicadísimo)
- Aprenderme los parámetros (¿cuál es el bitrate correcto para Instagram? ¿cuánto puedo subir a Telegram?)
- Ejecutarlo sin equivocarme (un parámetro mal y el vídeo sale corrupto o pesadísimo)
Y si quiero descargar algo de YouTube, necesito otra herramienta. Si quiero cortar, otra. Si quiero ponerle efectos, otra. Son 4-5 herramientas distintas para cosas que deberían hacerse desde un solo sitio.
Lo que hice
Creé midu.sh: un script que junta todo lo que necesitas para trabajar con vídeos en un solo comando. Lo puse en Docker para que funcione en cualquier máquina sin instalar nada, y le añadí un “preview watcher” que abre automáticamente los vídeos en VLC cuando estoy en WSL.
Los 33 modos
Descarga y extracción
| Modo | Descripción | Ejemplo |
|---|---|---|
download | Descargar de YouTube, Twitch, Kick, TikTok, +1000 sitios | -d "URL" |
audio-only | Extraer solo audio (mp3, m4a, flac, wav, opus) | -ao "URL" |
Nuevos flags de descarga:
# Seleccionar calidad
./midu.sh -d "URL" -dq 1080 # 1080p máximo
./midu.sh -d "URL" -dq 720 # 720p máximo
./midu.sh -d "URL" -dq audio-only # Solo audio
# Seleccionar formato de salida
./midu.sh -d "URL" -df mkv # Salida en MKV
./midu.sh -d "URL" -df webm # Salida en WebM
# Descargar playlist completa
./midu.sh -d "URL" --playlist
# Solo subtítulos
./midu.sh -d "URL" --dl-subs-only
# No re-descargar (archive)
./midu.sh -d "URL" --download-archive ~/descargas.txt
# Filtrar por fecha
./midu.sh -d "URL" --dateafter 20260101 --datebefore 20260801
# Seleccionar items de playlist
./midu.sh -d "URL" --playlist-items 1-5
# Listar playlist sin descargar
./midu.sh -d "URL" --flat-playlist
Corte y edición
| Modo | Descripción | Ejemplo |
|---|---|---|
cut | Cortar lossless (sin re-encoding) | --cut -ss 00:01:30 -e 00:03:45 |
cut --remove | Eliminar secciones del vídeo | --cut --remove --clips 00:01:00-00:02:30 |
cut --extract | Extraer clips y unirlos | --cut --extract --clips 00:01:00-00:02:30 |
concat | Unir varios vídeos | --concat v1.mkv v2.mkv v3.mkv |
concat-smart | Unir con auto-detección de compatibilidad | --concat-smart v1.mkv v2.mkv |
crossfade | Unir con transición suave entre clips | --concat-smart --crossfade 1 v1.mp4 v2.mp4 |
El corte lossless funciona porque ffmpeg puede leer y escribir contenedores como MKV y MP4 sin re-codificar el stream de vídeo. Solo cambia los timestamps de inicio y fin.
Conversión y compresión
| Modo | Descripción | Ejemplo |
|---|---|---|
convert | Convertir/comprimir con presets | --convert -s telegram |
fps | Cambiar frames por segundo | --fps 60 |
speed | Acelerar o ralentizar | --speed 2.0 |
Efectos de imagen
| Modo | Descripción | Ejemplo |
|---|---|---|
rotate | Girar 90°, 180° o 270° | --rotate 90 |
crop | Recortar a tamaño específico | --crop 640:480 |
fade | Fade in/out automático | --fade 2 |
stabilize | Quitar temblor (vidstab) | --stabilize 5 |
adjust | Brillo, contraste, saturación, gamma | --adjust brightness=0.5 |
denoise | Reducir ruido | --denoise 50 |
sharpen | Enfocar vídeo borroso | --sharpen 5 |
reverse | Invertir vídeo (al revés) | --reverse |
deinterlace | Quitar rayas de TV vieja | --deinterlace |
Multimedia
| Modo | Descripción | Ejemplo |
|---|---|---|
gif | Crear GIF animado | --gif --gif-fps 15 --gif-scale 320:-1 |
thumbnail | Extraer frame como PNG | --thumbnail --thumbnail-time 00:01:30 |
watermark | Poner imagen encima | --watermark logo.png |
Análisis y metadatos
| Modo | Descripción | Ejemplo |
|---|---|---|
info | Mostrar duración, codecs, resolución | --info |
scenes | Detectar escenas y cortar auto | --scenes 0.3 |
keyframes | Extraer imágenes I-frame | --keyframes |
aspect | Cambiar ratio de aspecto | --aspect 16:9 |
metadata | Editar título, autor, comentario | --metadata title="Mi vídeo" |
Avanzados
| Modo | Descripción | Ejemplo |
|---|---|---|
subtitles | Embeber (soft) o quemar (hard) subtítulos | -sh subs.srt |
censor | Pixelar regiones (caras, matrículas) | --censor 100:50:200:150 |
remux | Cambiar contenedor sin re-encoding | --remux --container mkv |
tracks | Reordenar pistas de vídeo/audio/subtítulos | --tracks "v:0,a:1,s:0" |
Pipeline encadenado
# Cortar + convertir + fade en un solo comando
./midu.sh --chain "cut=00:01:00:00:05:00" "convert=720" "fade=2"
# Rotar + denoise + enfocar
./midu.sh --chain "rotate=90" "denoise=30" "sharpen=3"
# Pipeline completo: descargar + cortar + convertir
./midu.sh --chain "cut=00:00:10:00:02:00" "convert=telegram"
Operaciones disponibles: cut, convert, rotate, fade, reverse, denoise, sharpen, normalize.
Compose (selección de pistas)
Selecciona qué pistas de vídeo, audio y subtítulos quieres en el archivo final, con codec y bitrate independientes por cada pista de audio:
./midu.sh --compose
Flujo:
- Seleccionar pista de vídeo (copy sin re-encode o elegir otra)
- Elegir varias pistas de audio (rango: 1-3 o selección múltiple 1,2,4)
- Asignar codec individual por cada pista de audio (aac, copy, opus, ac3, eac3, flac)
- Elegir subtítulos (opcional)
- Seleccionar contenedor de salida (mkv, mp4, ts)
# Ejemplo: mkv con 3 pistas de audio (español + inglés + director) cada una con codec diferente
./midu.sh --compose
# → Selecciona pista 1 de vídeo (copy)
# → Selecciona pistas 1,2,3 de audio
# → Asigna: español→aac 192k, inglés→copy, director→opus 128k
# → Añade subtítulos español
# → Salida en mkv
El modo compose es ideal para crear archivos multimedia con múltiples pistas de audio (películas multilingües, comentarios de director, etc.) sin necesidad de escribir comandos ffmpeg complejos con -map.
HLS (streaming)
Prepara vídeos para streaming con múltiples calidades y playlist maestro adaptativo:
./midu.sh --hls
Genera:
- Múltiples calidades (360p a 4K)
- Segmentos configurables (default 4s)
- Playlist maestro adaptativo (master.m3u8)
# Ejemplo de salida:
# video_hls/
# ├── master.m3u8 # Playlist maestro
# ├── 720p/
# │ ├── playlist.m3u8 # Playlist 720p
# │ └── segment_000.ts # Segmentos
# └── 1080p/
# ├── playlist.m3u8 # Playlist 1080p
# └── segment_000.ts # Segmentos
GPU Encoding automático
midu.sh detecta automáticamente la GPU disponible y usa el encoder óptimo:
| GPU | Encoder usado | Speedup |
|---|---|---|
| NVIDIA | h264_nvenc / hevc_nvenc | 2-5x |
| Intel/AMD | h264_vaapi / hevc_vaapi | 1.5-3x |
| CPU | libx264 / libx265 | 1x |
La aceleración por hardware se aplica ahora en todos los modos de edición (stabilize, adjust, censor, denoise, sharpen, reverse, aspect, concat), no solo en la conversión.
Smart Concat
concat-smart auto-detecta si los archivos son compatibles (mismo codec, resolución, FPS):
- Compatibles → stream copy (rápido, sin re-encoding)
- Incompatibles → re-encode automático con filter_complex
- Crossfade → transición suave entre clips con
--crossfade DURACIÓN
# Unir 3 archivos (auto-detecta compatibilidad)
./midu.sh --concat-smart video1.mp4 video2.mp4 video3.mp4
# Unir con crossfade de 1.5 segundos
./midu.sh --concat-smart --crossfade 1.5 video1.mp4 video2.mp4
Presets de red social
Cada preset define resolución, tamaño máximo, códec y preset de codificación optimizado para la plataforma:
./midu.sh --convert -s whatsapp # 720p, 1GB, h264, preset web
./midu.sh --convert -s telegram # 1080p, 2GB, hevc, preset default
./midu.sh --convert -s instagram # 1080p, 0.5GB, h264
./midu.sh --convert -s tiktok # 1080p, 0.5GB, h264
./midu.sh --convert -s youtube # original, sin límite, h264, archive
./midu.sh --convert -s twitter # 720p, 0.5GB, h264, web
./midu.sh --convert -s facebook # 1080p, 1GB, h264
Reintentos de tamaño
Si el vídeo supera el límite de la plataforma, el script re-codifica con menor bitrate automáticamente (hasta 2 intentos):
- Intento 1: bitrate calculado para el tamaño objetivo
- Si supera → Intento 2: bitrate reducido un 20%
- Si sigue superando → Advertencia pero continúa
Presets de calidad
| Preset | CRF | Velocidad | Uso |
|---|---|---|---|
ultrafast | 28 | ultrafast | Muy rápido, poco peso |
web | 28 | fast | Rápido, buen balance |
default | 23 | medium | Equilibrado |
archive | 18 | slow | Alta calidad |
quality | 15 | veryslow | Máxima calidad |
CRF (Constant Rate Factor): valor de 0-51 donde menor = mejor calidad. 18 es prácticamente indistinguible del original.
Códecs soportados
| Códec | Encoder | Notas |
|---|---|---|
h264 | libx264 | Máxima compatibilidad |
hevc | libx265 | Mejor calidad/menor tamaño (50% menos bitrate) |
av1 | libsvtav1 | Máxima eficiencia (muy lento de codificar) |
vp9 | libvpx-vp9 | Buen equilibrio para web |
Aceleración por hardware
El script detecta automáticamente el hardware disponible:
- NVENC (NVIDIA): Si
nvidia-smiestá disponible → usah264_nvenc/hevc_nvenc - VAAPI (Intel/AMD): Si
vainfoestá disponible → usah264_vaapi - CPU: Fallback con libx264/libx265
./midu.sh --convert -s telegram --hw-accel # Usar GPU si está disponible
Flags generales
| Flag | Descripción |
|---|---|
-n, --non-interactive | Sin prompts, usa valores por defecto |
-v, --verbose | Progreso detallado |
--two-pass | Two-pass encoding (mejor calidad con —max-gb) |
--hw-accel | Aceleración por hardware |
--dry-run | Preview sin ejecutar (muestra comandos) |
--collision skip|rename|overwrite | Colisión de archivos |
--notify | Notificación al terminar (notify-send) |
--write-subs | Descargar subtítulos con yt-dlp |
--sub-langs LANGS | Idiomas de subtítulos (default: es,en) |
--audio-lang LANG | Idioma de audio a seleccionar (default: español) |
--checkpoint FILE | Guardar progreso para resume |
--resume [FILE] | Continuar desde checkpoint |
--retry | Reintentar archivos fallidos al terminar |
--compose | Modo compose: selección de pistas personalizada |
Preview Watcher (WSL)
Script que se ejecuta en el host (WSL) y abre automáticamente los vídeos en VLC cuando midu.sh los solicita desde el contenedor Docker.
bash preview_watcher.sh --daemon # segundo plano
bash preview_watcher.sh --stop # detener
bash preview_watcher.sh --status # verificar
bash preview_watcher.sh --once # procesar una petición y salir
bash preview_watcher.sh # debug en primer plano
Cómo funciona el watcher
midu.shescribe la ruta del vídeo entest_video/.midu_preview_req- El watcher detecta el archivo (poling cada 2 segundos)
- Convierte la ruta Linux a Windows (
/mnt/c/...→C:\...) - Abre el vídeo en VLC (o reproductor por defecto)
- Elimina el archivo de petición
Variables del watcher
| Variable | Default | Descripción |
|---|---|---|
IDLE_TIMEOUT | 600 | Segundos sin actividad antes de apagarse |
MIDU_CONTAINER_NAME | yt_ffmpeg_downloader | Nombre del contenedor Docker |
MIDU_CONTAINER_MATCH | ^(yt_ffmpeg_downloader|ffmpeg-yt-dlp-downloader) | Regex para detectar el contenedor |
Scripts de automatización
Backup de canales de YouTube
scripts/backup_youtube.sh descarga canal completo con archive automático (no re-descarga):
# Backup de canales específicos
bash scripts/backup_youtube.sh https://www.youtube.com/@Canal1 https://www.youtube.com/@Canal2
# Con calidad y formato personalizados
bash scripts/backup_youtube.sh -q 720 -f mkv https://www.youtube.com/@Canal1
# Directorio personalizado
BACKUP_DIR=/mnt/backup bash scripts/backup_youtube.sh https://www.youtube.com/@Canal1
Monitor de carpeta (compresión automática)
scripts/monitor_folder.sh vigila una carpeta y comprime vídeos nuevos:
# Monitor con configuración por defecto
bash scripts/monitor_folder.sh ~/Downloads/videos
# Personalizar CRF, preset y destino
bash scripts/monitor_folder.sh -o /mnt/comp -c 23 -p medium ~/Videos/nuevos
# Con intervalo de polling personalizado
bash scripts/monitor_folder.sh --interval 60 ~/Videos/para_comprimir
# Solo procesar grabaciones terminadas, escalando a 720p (uso en pipeline)
bash scripts/monitor_folder.sh --completed-only -r 720 /ruta/a/vigilar
Flags clave del monitor
| Flag | Descripción | Default |
|---|---|---|
-o, --output DIR | Directorio de salida | Videos/comprimidos |
-c, --crf VALUE | Calidad CRF (menor = mejor) | 28 |
-p, --preset NAME | Preset de velocidad | fast |
--codec NAME | Códec de vídeo | libx264 |
-r, --resolution N | Escalar altura a N px (ej: 720) | sin reescalar |
--completed-only | Procesar solo *_completed.* | off |
--interval SEGS | Segundos entre comprobaciones | 30 |
Pregunta de borrado del original (convert)
En el modo conversión interactivo (midu.sh --convert), al terminar cada archivo el script pregunta “¿Eliminar archivo ORIGINAL? [s/N]” (solo en terminal interactiva). El modo automatizado (monitor) conserva siempre el original.
Monitor como servicio del pipeline
El proyecto define el servicio Docker monitor (ffmpeg_monitor-sendo), pensado para el pipeline de compresión automática. Este monitor es la pieza central del pipeline “Grabar → Comprimir → Subir a Telegram”: vigila la carpeta de grabaciones, comprime los vídeos nuevos a 720p y los deja listos para que el uploader los suba a Telegram.
cd /home/jorge/dev/devjobs/ffmpeg-yt-dlp
docker compose build
docker compose up -d monitor # arranca el monitor en background
docker compose logs -f monitor # logs del monitor
docker compose stop monitor # parar solo el monitor
Vigila data/pipeline/grabaciones/test/ (donde TwitchRecorder deja los *_completed.mp4), comprime a 720p y guarda en data/pipeline/comprimidos/.
Parámetros del monitor:
| Parámetro | Default | Descripción |
|---|---|---|
-t, --threads N | 4 | Hilos de ffmpeg (parallel encoding) |
--completed-only | off | Solo procesar archivos *_completed.* |
--directo-completo | off | Procesar directos completos (no dividir) |
--codec NAME | libx264 | Códec de vídeo |
-c, --crf VALUE | 28 | Calidad CRF |
-p, --preset NAME | fast | Preset de velocidad |
-r, --resolution N | sin reescalar | Escalar altura a N px |
Flujo del pipeline completo:
TwitchRecorder graba → grabaciones/test/*_completed.mp4
↓
ffmpeg_monitor-sendo comprime → comprimidos/*_compressed.mp4
↓
telegram-uploader-sendo sube → Telegram (por topic/serie)
Uso típico
# 1. Construir la imagen
docker compose build
# 2. Ejecutar (interactivo o CLI)
docker compose up
# 3. En WSL, arrancar el watcher (opcional)
bash preview_watcher.sh --daemon
# 4. Usar midu.sh dentro del contenedor
# Los vídeos se abren automáticamente en VLC en Windows
Flujo recomendado
# 1. Descargar
./midu.sh -d "https://youtube.com/watch?v=..."
# 2. Cortar (lossless, sin re-encoding)
./midu.sh --cut -ss 00:05:00 -e 00:10:00
# 3. Convertir para Telegram
./midu.sh --convert -s telegram
Peculiaridades
- Compose mode: Selección visual de pistas de vídeo/audio/subtítulos con codec independiente por cada pista de audio
- HLS streaming: Genera múltiples calidades con playlist maestro adaptativo
- Auto-detección de español: Selecciona automáticamente la pista de audio en español (spa/es/español/castellano), configurable con
--audio-lang - Scripts de automatización: Backup de canales de YouTube y monitoreo de carpeta con compresión automática
- Remux automático: Si el vídeo ya es h264+aac sin corte, se remuxa sin re-encoding (copia directa de streams)
- Reintentos de tamaño: Si supera el límite, re-codifica con menor bitrate (hasta 2 intentos)
- Panel de progreso: Muestra progreso por archivo con hilos paralelos (max 4)
- Checkpoint/resume: Guarda estado para reanudar si se interrumpe
- Colisión: Opciones skip/rename/overwrite para archivos existentes
- Notificaciones: notify-send (Linux) y ntfy.sh (push a móvil)
- Detección de GPU: Auto-detecta NVENC/VAAPI y usa aceleración por hardware
- Filtros combinados: Resolución + velocidad + subtítulos en una sola cadena
-vf - atempo encadenado: Para velocidades extremas (0.25x, 4x) usa múltiples filtros atempo (ffmpeg limita cada filtro a 0.5x-100x)
- Auto-setup: El Dockerfile instala todas las dependencias automáticamente
Instalación
¿Cómo instalar y configurar midu.sh, el monitor y el preview watcher? Consulta la guía de instalación completa — con Docker, sin Docker, monitor de compresión y configuración de notificaciones.
Estructura
ffmpeg-yt-dlp/
├── docker-compose.yml # servicios Docker: downloader + monitor
├── preview_watcher.sh # abre vídeos en WSL/Windows (host)
├── scripts/
│ ├── backup_youtube.sh # backup automático de canales de YouTube
│ └── monitor_folder.sh # monitoreo y compresión automática (+ pipeline)
└── test_video/
├── midu.sh # script principal (~6000 líneas, 33 modos, v5.0.0)
├── optimizados/ # vídeos convertidos (por defecto)
└── test/ # vídeos de entrada (por defecto)
Detalle completo del monitor y su papel en el pipeline:
README_MONITOR.md.
