Unir video y audio con ffmpeg y bash#

Recién mi novia me pidió el favor de ayudarle a descargar los videos de un curso antes de que se venciera el acceso a la cuenta, y tocaba descargar los videos de Vimeo. Pero el truco de descarga de estos videos, hace que luego toque unir el audio y el video, así que les contaré como hacerlo con FFMPEG y Bash.

Descargar video de Vimeo#

Bueno, este es el punto inicial de la aventura, y es cómo descargar un video de Vimeo a través de un sitio que posee autenticación. Resulta que si fuera directamente de Vimeo, bastaría con la extracción con uso de cookies que ofrece yt-dlp, pero como el video de Vimeo está embebido en otro sitio, esto no funciona (o no encontré cómo, pues salía un error de portal no reconocido para hacer el ingreso).

Al continuar la búsqueda, la única opción que encontré fue una extensión de Chrome que se llama Free Vimeo Downloader, que te habilita la opción de descarga desde el navegador de los videos de Vimeo embebidos en cualquier portal. Te ofrece la opción de descargar los videos en distintas calidades, aunque debes tener presente que el audio se descarga por separado, y para poderlo descargar debes primero iniciar la reproducción.

Atención

Recuerda reproducir el video para habilitar la descarga del audio.

Los archivos descargados tienen como patrón, el nombre del video seguido de la calidad de video, y en el caso del audio, seguido de -audio, ambos en formato MP4. Ahora, ¿cómo unimos el video y el audio?

Procesamiento con FFMPEG#

Ahora, la tarea asociada al procesamiento para unir los archivos de audio con los archivos de video, la vamos a delegar en FFMPEG, una potente utilidad de línea de comandos para el procesamiento de audio y video que es gratuita y de código abierto.

Si usas Debian/Ubuntu o algún derivado, como yo, puedes instalar de la forma que indico a continuación. Si no, puedes remitirte a la página oficial o también instalarla con el gestor de paquetes de conda (aplica a todos los sistemas operativos).

sudo apt install -y ffmpeg

Para probar el concepto, usaremos uno de los pares de archivos.

ffmpeg -i Modulo\ 2\ Clase\ 2\ Parte\ 5\ \(720p\ with\ 30fps\).mp4 -i Modulo\ 2\ Clase\ 2\ Parte\ 5-audio.mp4 -c copy output/Modulo\ 2\ Clase\ 2\ Parte\ 5.mp4

Como el audio y el video ya están en el mismo formato y codec, no es necesario FFMPEG para aplicar transformaciones, sino solo para mantener el canal de video del primer archivo y copiarle el canal de audio del segundo, para generar un nuevo archivo de multimedia.

Observamos el parámetro -i que usamos para indicar un archivo fuente, ya sea de audio, video o incluso imágenes y de texto. En este caso, lo usamos para indicar el archivo de video y el archivo de audio que queremos emparejar (cada archivo debe estar precedido de -i).

Si fuera necesario aplicar un codec a estos, se debería indicar la opción respectiva después de la ruta de cada archivo. En este caso, no nos interesa y esto nos ayuda a que ejecute más rápido. De tal forma que simplemente indicamos después del segundo archivo -c copy para indicar que se copia directamente, preservando calidad y formato original.

Por último, se indica la ruta del archivo de salida, es decir, el archivo resultado de nuestra unión de video y audio.

Consejo

FFMPEG y su documentación, no es muy cómoda para alguien que no sea familiar con la línea de comandos, por lo que si tienes dudas de donde empezar, te recomiendo visitar los recetarios de ffmprovisr.

Podemos abrir el video, y veremos que el video con el audio incluido. Y ahora, ¿qué sucede si son 56 videos con sus 56 audios?

Procesamiento en lote con Bash#

Como los archivos tienen un patrón en sus nombres, y pueden ser listados en orden, y el proceso que se ejecuta sobre cada par es el mismo, podemos crear una rutina para este procesamiento en lote, y evitar así posibles errores como omitir un par de archivos, mezclar un video con el audio de otro o errores de digitación.

Necesitaremos almacenar los listados por separado de los archivos de video y audio, de tal forma que iteremos de manera general sobre el total de videos y avancemos en los dos listados, que al estar ordenados y con el patrón de nombre iniciando por el nombre general del video, permitirá emparejarlos.

Luego, de manera cíclica obtenemos estas parejas, con las cuales formaremos los archivos para los parámetros -i de ffmpeg, y la asignación de la ruta de salida.

Esto lo haremos en bash (bueno, esto es para usuarios Linux, pero si usas Windows, te invito a replicarlo en PowerShell o tu lenguaje favorito).

Código bash para unir un conjunto de videos y audios con FFMPEG.#
 1#! /usr/bin/bash
 2
 3OUTPUT=output
 4mkdir -p $OUTPUT
 5AUDIO_LIST=(*audio.mp4)
 6VIDEO_LIST=(*fps*.mp4)
 7LEN=${#AUDIO_LIST[*]}
 8echo "$LEN videos"
 9for ((i = 0; i < LEN; i++)); do
10    echo "Procesando video: $((i + 1))"
11    VIDEO_NAME="${VIDEO_LIST[$i]}"
12    ffmpeg -i "$VIDEO_NAME" -i "${AUDIO_LIST[$i]}" -c copy "$OUTPUT/$VIDEO_NAME"
13done

Te explico el código.

Línea 1, es una línea shebang para indicar la ruta absoluta del interprete de shell, en este caso, bash.

En la línea 3, asignamos el nombre para el directorio de salida, que usaremos para crear dicho directorio en la línea 4 y para formar la ruta completa de salida en la línea 12.

En la línea 4 vemos la primera aparición de $ que usamos para expandir un resultado que puede ser de una variable como en este caso, o incluso de una ejecución. Aquí, sobre mkdir -p tenemos para decir que esto crea la carpeta, y su opción -p es para que no falle en caso de ya existir.

Para obtener el listado de archivos podríamos usar ls, pero para conertir a un arreglo tenemos que hacer ajustes en el IFS, y resulta más simple usar directamente la expansión global de nombre de archivo, como lo hacemos en las líneas 4 y 5.

La manera como nos referimos a un arreglo en Bash, es con ${ } rodeando lo requerido del arreglo, como la indicación a un elemento específico (${ARR[0]}) usado en la línea 11 y 12, la totalidad de elementos (${ARR[*]} o ${ARR[@]}) o una variante con el símbolo # antes del nombre del arreglo para hacer el conteo como se usa en la línea 7.

La sentencia echo la usamos para imprimir en la terminal, y vemos que el mensaje está en comillas dobles, lo que evita que el resultado se intente expandir (ejecutar), pues solo nos interesa hasta ese punto.

En las líneas 9 y 10 notamos la existencia de doble paréntesis, esto permite la expansión aritmética. Siempre que necesitemos operaciones aritméticas, usamos doble paréntesis. En particular, la línea 9 es el inicio del ciclo for en Bash, que usa expansión aritmética con la asignación del valor inicial de la variable para recorrer las listas, la condición del recorrido la cual es mientras sea menor que la longitud de las listas y finalmente el avance en uno para poder pasar al siguiente elemento. Luego sigue la indicación del do con el bloque que repetiremos, y que depende de nuestra variable del ciclo (i). Y para cerrar el ciclo, terminamos en done.

Bueno, con esto, estamos listos para ejecutar nuestro código que podemos disponer en un archivo unir_video.sh y ejecutar como:

bash unir_video.sh  # opción 1
. unir_video.sh  # opción 2
source unir_video.sh  # opción 3

Las últimas dos opciones son el motivo de usar el shebang de la línea 1, para distinguir la shell a usar.

Es hora de ejecutar, y deja que esto trabaje por ti con tu colección de videos.

Consejo

Los 3 recursos que te recomiendo para Bash: