viernes, 9 de julio de 2010

ffmpeg - batch encoding

Actualización: aunque no voy a borrar esta entrada he encontrado una mejor manera. Usar el comando find que nos permite también ejecutar un comando por cada archivo encontrado.

¿Qué pasa si un colaborador nos ha dado un DVD completo de archivos de medios sin comprimir o con una compresión inadecuada para nuestro sistema, o para el proyecto en que estamos trabajando? Por ejemplo, varios archivos de audio en wav en lugar de estar en ogg. En este caso tenemos los archivos pesando 16 MB o más por 5 minutos de duración cuando podrían pesar 5 MB o menos y sonar igual (para fines prácticos). Al menos que queramos editar los archivos no necesitamos los wav sino que querremos ya el producto final.

Bueno, si estamos en Windows podemos usar Super! que es una gui para ffmpeg, mencoder y demás, y que permite listar varias operaciones.

Pero Super! no funciona en Linux. Esto es paradójico. Super! usa mencoder y ffmpeg pero no corre en Linux. Claro debe haber aplicaciones similares. Si las buscamos en synaptic seguro aparecen, y si no aparecen en synaptic seguro realizando una búsqueda en internet damos con ellas. Hacer las nuestras propias tampoco es tan difícil, por ejemplo, podríamos hacer un script o compilar un sencillo programa en Lazarus que implemente OnDropFiles, que tenga un par de campos para controlar parámetros como el bitrate y que pase todo eso a ffmpeg usando TProcess.

Pero, y lo digo por experiencia, ponerse a hacer toda una aplicación en el mismo momento en que surgió la necesidad no es buena idea. Estas cosas hay que hacerlas con tiempo y previa planeación. Nada de "¡oh! Necesitaría una gui para ffmpeg, me pongo a programar una ya".

Pero por fortuna, para hacer una operación en batch no es necesaria una gui. Aún si estamos usando un programa de consola que sólo acepta un único archivo como entrada y un único como salida. Siempre tenemos la opción de escribir un bat (si estamos en Windows) o un script si estamos en Linux.

El siguiente ejemplo es para salir del paso. Un script muy sencillo para recodificar todos los archivos de un directorio usando los mismos parámetros para todos. El bitrate es 320 Kb/s, el muestreo 44100 Hz, el formato de salida mp3. Crea un subdirectorio llamado encoded. Sin interactividad alguna:

#!/bin/bash

mkdir -v "encoded"

for i in *.wav
do
ffmpeg -i "$i" -acodec libmp3lame -ab 320k -ar 44100 "encoded/$i.mp3"
done

Ese script lo guardé como convert-to-mp3-320kbs-44100hz.sh en el directorio que quería procesar. En este caso era un directorio lleno de archivos wav. Luego de guardar el script en el mismo directorio que los wav, inicio la terminal, hago cd hasta el directorio con los wav, y escribo: ./convert-to-mp3*.sh y luego enter y empieza.

Esto de ir a la terminal lo digo para poder ver la salida de ffmpeg. Si cometemos el error de dar doble clic sobre el script en vez de ejecutarlo desde la terminal pasará que no obtendremos ningún indicador de progreso de ffmpeg, lo cual puede causarnos molestias si intentamos acceder a un archivo que todavía se está procesando.

Noten que el formato de salida es mp3, yo tuve mis motivos para optar por este formato. Algo no muy recomendable, ya que optamos por un sistema libre vamos a tratar de contribuir con la proliferación de los formatos libres y no al revés. Para adaptar el script para que la salida sean archivos ogg, simplemente alteramos la penúltima linea, reemplazando libmp3lame por ogg.

ffmpeg -i "$i" -acodec vorbis -ab 320k -ar 44100 "encoded/$i.ogg"

La idea de esta entrada es mostrar (a quien no esté al tanto aún) que hacer un batch encoding es posible en Ubuntu sin instalar nada adicional y sin pasar demasiado trabajo.

Improvisarse uno de estos scripts es sencillo, o simplemente copiar y pegar los que yo coloco aquí como ejemplos.

Yo lo uso copiándolo a la carpeta que contiene los wav pera no tener que escribir la ruta completa al script cada vez que quiero invocarlo.

Ahora, si queremos hacer que el script acepte parámetros de entrada, por ejemplo si queremos que deje especificar un filtro para los archivos de entrada y alguna regla para los archivos de salida, podríamos hacer el script un poco más complejo, hacer que cheque los parámetros pasados desde la terminal, para que se pueda escribir algo como esto: encodedir.sh --input wav --output ogg -b 128K -r 44100, pero eso significaría tener que probar varias veces el script para ver que todo quede en orden, que era precisamente lo que yo quería evitar hacer esta vez. De todas formas les doy la idea por si quieren intentarlo.

Antes de recurrir a la solución del script intenté desde la terminal con pipes o lo que fuera, pero no encontré una forma convincente y productiva de hacerlo. Escribir el script fue la manera que probó ser la más conveniente.

Después de haber escrito esta entrada, leí un poco más sobre la terminal y scripts del shell. Y llegué a la conclusión de que hay incluso una mejor y más práctica manera de usar los scripts.

Hice una serie de scripts que contienen los parámetros que más uso con ffmpeg. Por ejemplo, usualmente uso un bitrate de 128K para audio, así que no hay necesidad de estarlo escribiendo cada vez. Por lo que coloqué el script para llamar a ffmpeg con esos parámetros y de paso que procese el directorio completo y lo puse en un directorio llamado enctools junto con otros scripts que automatizan tareas de encodeo. Luego creé un enlace simbólico en mi directorio home. Entonces, para llamar a cualquiera de los scripts ya no necesito copiarlo y pegarlo en el mismo directorio donde están los archivos que quiero codificar, ahora simplemente escribo en la terminal:

$HOME/enctools/encode-to-ogg-128k-44100hz.sh

O, cuando me da pereza teclear tanto:

$HOME/enctools/encode-to-ogg*.sh

Nota: los archivos que serán procesados son los que se encuentran en el directorio actual, el que se muestra a la izquierda en la terminal. Por lo tanto solo tengo que hacer cd hasta el directorio que contiene los archivos a codificar y luego llamar al script.

0 comentarios:

Publicar un comentario