Apuntes mientras aprendo sobre software y computadoras.

programación

Cortar y editar videos de forma automática con FFmpeg

En este apunte rápido voy a buscar la forma de hacer la edición de un grupo de videos utilizando FFmpeg.

Voy a trabajar específicamente con el sistema operativo Linux. Pero la mayoría del texto aplica bien para otros sistemas, aunque los resultados pueden variar.

Y sin dar más rodeos, vamos a la…

Lista de materiales

Digamos que en un directorio tengo un conjunto de videos.

Teniendo en cuenta el bienestar de este ejemplo voy a utilizar solamente cuatro videos. Pueden ser más o menos, es simplemente un ensayo para que el sistema funcione.

Entonces yo tengo estos archivos, y quiero extraer un solo fragmento de cada uno.

Es lo que puede ser un simple montaje de video, quiero extraer una parte de cada plano para crear una nueva secuencia.

Mi primer trabajo va a ser conocer el timecode de cada uno de estos planos que voy a cortar. Dicho de otro modo, tengo que saber cuándo empieza y cuándo termina cada corte en cada archivo.

Estos ya mencionados audiovisuales ahora se llaman:

video_001.mp4
video_002.mp4
video_003.mp4
video_004.mp4

Lo primero que tengo que hacer es crear un documento de texto que voy a llamar: “timecode.txt”.

En este archivo voy a escribir el nombre del video que estoy cortando, el momento donde empieza corte, el momento donde se termina el corte y el nombre del nuevo archivo resultante. Por ejemplo:

video_001.mp4, 00:00:10.0, 00:00:20.0, corte01.mp4

Esto quiere decir que el “video_001.mp4” va a ser cortado entre el segundo “00:00:10.0” y el segundo “ 00:00:20.0” de su duración.

Al final, el nuevo archivo de diez segundos que va a resultar al ejecutar el código va a llamarse “corte01.mp4”.

Y el archivo de texto completo me queda de este modo:

video_001.mp4, 00:00:10.0, 00:00:20.0, corte01.mp4
video_002.mp4, 00:00:08.0, 00:00:11.0, corte02.mp4
video_003.mp4, 00:00:02.0, 00:00:05.0, corte03.mp4
video_004.mp4, 00:01:03.0, 00:01:25.0, corte04.mp4

Esta forma de hacer el montaje no es completamente automática, necesito conocer los videos y saber donde va a ir cada corte para empezar.

Las cosas están por ponerse más interesantes, ya que todo va a empezar a completarse con mayor facilidad.

Leer el archivo y cortar el video

Para cortar el video voy a necesitar un comando de ffmpeg. Ese comando es el siguiente:

ffmpeg -ss INICIO -to FINAL -i ENTRADA -c copy SALIDA

Lo que hace este comando es cortar un video entre el timecode de “inicio” y el timecode “final”. Esto lo hace sobre un archivo de “entrada” y me devuelve un archivo de “salida”.

Por ejemplo, si quisiera cortar solo uno de los videos de mi ejemplo el comando queda de esta forma:

ffmpeg -ss 00:00:10.0 -to 00:00:20.0 -i video001.mp4 -c copy corte01.mp4

El archivo que va a exportarse no va a resultar modificado en ninguna de sus características. Retiene su formato, su extensión y ese tipo de cosas.

Eso es material para otro apunte, por lo que en este caso esta forma de hacer el trabajo va a funcionar mejor si todos los archivos comparten el mismo tipo. Pero eso no es difícil, si por ejemplo todos los videos son de la misma cámara o tienen el mismo origen.

Entonces tengo el comando para cortar un video. Pero en mi lista tengo cuatro archivos, y podría tener una lista con ciertos de cortes.

¿Cómo hago para leer el archivo de texto e ingresar eso dentro del comando?

Bueno, para eso voy a usar otro comando. Este se llama “gawk” y su manual me dice:

NAME
gawk – pattern scanning and processing language

manual de gawk

Bueno, gawk es la implementación GNU de “Awk”, una herramienta que sirve para escanear patrones y procesamiento de lenguaje.

Esta herramienta parece bastante compleja y es un lenguaje de programación en si mismo… por suerte a mi solamente me interesa una cosa: poder leer el archivo de texto, separando cada linea en fragmentos y agregando todo luego como partes de otro comando.

Por ejemplo en esta primera linea de “timecode.txt” tengo:

archivo01.mp4, 00:00:10.0, 00:00:20.0, nuevoarchivo01.mp4

Esto es, cuatro elementos separados por una “coma” (,) cada uno.

Si ahora combino Gawk con el comando ffmpeg tengo:

gawk -F, '{cmd="ffmpeg -ss " $2 " -to " $3 " -i " $1 " -c copy " $4 ""; system(cmd)}' timecode.txt

¿Cómo funciona esto?

Bueno, según puedo entenderlo Gawk entiende cada uno de los fragmentos de una linea como variables, y las separa de esta forma:

$1                $2           $3               $4
archivo01.mp4, 00:00:10.0, 00:00:20.0, nuevoarchivo01.mp4

Luego estas variables se incluyen dentro del comando. Y se repiten cada vez, una por cada linea dentro de timecode.txt para ayudarme a editar cada video.

Con esto no solo consigo leer un archivo de texto para usarlo como variables para un comando, ahora tengo cuatro videos recién cortados listos para ser integrados en un nuevo audiovisual.

Editando un conjunto de videos con ffmpeg

Ahora tengo cuatro nuevos videos en mi directorio. Estos videos van desde “corte01.mp4” hasta “ corte01.mp4”… pasando por los dos intermedios, lo que es fácil imaginar.

Sin embargo para poder continuar voy a necesitar un nuevo archivo de texto. Ese archivo tiene que contener el nombre de cada video, ocupando cada nombre una linea distinta.

Por suerte puedo crear esta nueva lista de forma rápida con el comando “ls”, ejecutandolo en la carpeta de esta forma:

ls -1 *.mp4 | sed 's/^/file /' > montaje.txt

El resultado tiene que ser un archivo de texto con el nombre “montaje.txt”, donde en cada linea aparece el nombre de cada uno de los videos. Y frente a cada nombre el comando “sed” va a agregar el prefijo “file” a cada nombre, de modo que ffmpeg pueda entender que esos son los archivos para unir.

Realmente lo que hace el comando es utilizar una wildcard para listar todos los archivos .mp4 en mi carpeta, pero como en mi caso son solamente cuatro esos son los que aparecen en el mismo.

Ahora que lo pienso, tal vez lo mejor es primero mover los videos que necesito editar a un nuevo directorio, para no terminar listando sin querer también los originales. En este punto necesito trabajar solamente con los nuevos cortos.

El resultado es un documento de texto que se lee del siguiente modo:

file corte01.mp4
file corte02.mp4
file corte03.mp4
file corte04.mp4

Lo último que me queda es editar esos cuatro videos en uno solo, y eso lo puedo conseguir con el siguiente comando:

ffmpeg -f concat -safe 0 -i montaje.txt -c copy terminado.mp4

Lo que hace ffmpeg en ese caso es concatenar todos los archivos del texto “montaje.txt” y me da por resultado un nuevo video llamado “terminado.mp4”.

Hay que tener en cuenta que, como mencioné antes, los resultados pueden variar.

Puede ocurrir que el video tenga algunos errores o “glitchs” si es que había diferencias entre los detalles de los videos, como resoluciones distintas.

Y otra cosa es que los cortes tal vez no son completamente precisos. Puede pasar, por lo que creo es una cuestión de cantidad de cuadros en el archivo. Dos archivos pueden tener distinta cantidad de cuadros, o el corte puede caer en un cuadro que genera algún error.

De todas formas FFmpeg tiene opciones para mejorar eso, aunque revisar las misma es algo que escapa a la brevedad de este apunte. Y la verdad es que siempre puedo preguntarle a una inteligencia artificial para que me ayude, todo error es provisorio.

Conclusión:

Esta es al menos una forma de hacer la edición de un grupo de videos utilizando ffmpeg en Linux.

Seguramente existen otras formas de automatizar el montaje de grandes cantidad de video utilizando otros programas. Pero de este modo lo conseguimos hacer usando solamente la terminal de comandos y algunas herramientas.

Y lo mejor es que el resultado llega muy rápido, ffmpeg corta a toda velocidad.

Además siempre es posible unir todo en un mismo script de Bash, y conseguir hacerlo luego todavía más práctico.

Cualquier idea o crítica que tengas, me gustaría leer tus comentarios o correos electrónicos.

La seguimos en el próximo apunte.

Recursos:

Leave a Reply