Una de mis herramientas preferidas para conversión multimedia es ffmpeg. Se trata de una herramienta de línea de comandos que permite realizar multitud de tareas relacionadas con video, audio o incluso imágenes.
Aunque su uso no es excesivamente complejo, la gran cantidad de parámetros, combinaciones y el inmenso abanico de formatos y sus características, hacen que el uso de ffmpeg sea poco intuitivo cuando empezamos a utilizarlo (o incluso más tarde, si no lo tenemos bien claro).
En este artículo vamos a explicar como utilizar esta herramienta de forma sencilla, dando un repaso a las tareas de edición de video más comunes y prácticas, viendo ejemplos prácticos para aplicar.
Instalación de ffmpeg
La herramienta ffmpeg es multiplataforma, por lo que puede instalarse en cualquier sistema, ya sea GNU/Linux, Windows o Mac. En nuestro caso, que es GNU/Linux (o Windows bajo WSL), puedes utilizar el siguiente comando:
$ sudo apt-get install ffmpeg
Si quieres comprobar si todo ha ido bien y ya tienes disponible el comando, puedes escribir which ffmpeg
, el cuál debería devolverte algo similar a /usr/bin/ffmpeg
. Eso significa que ya está instalado.
Antes de continuar, observa que al ejecutar el comando ffmpeg
siempre nos aparece un montón de información, que normalmente no queremos estar revisándola:
$ ffmpeg
ffmpeg version 7.0.2-static https://johnvansickle.com/ffmpeg/
Copyright (c) 2000-2024 the FFmpeg developers built with gcc 8 (Debian 8.3.0-6)
configuration: --enable-gpl --enable-version3 --enable-static --disable-debug
--disable-ffplay --disable-indev=sndio --disable-outdev=sndio --cc=gcc --enable-fontconfig
--enable-frei0r --enable-gnutls --enable-gmp --enable-libgme --enable-gray --enable-libaom
--enable-libfribidi --enable-libass --enable-libvmaf --enable-libfreetype
--enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb
--enable-libopenjpeg --enable-librubberband --enable-libsoxr --enable-libspeex
--enable-libsrt --enable-libvorbis --enable-libopus --enable-libtheora --enable-libvidstab
--enable-libvo-amrwbenc --enable-libvpx --enable-libwebp --enable-libx264 --enable-libx265
--enable-libxml2 --enable-libdav1d --enable-libxvid --enable-libzvbi --enable-libzimg
libavutil 59. 8.100 / 59. 8.100
libavcodec 61. 3.100 / 61. 3.100
libavformat 61. 1.100 / 61. 1.100
libavdevice 61. 1.100 / 61. 1.100
libavfilter 10. 1.100 / 10. 1.100
libswscale 8. 1.100 / 8. 1.100
libswresample 5. 1.100 / 5. 1.100
libpostproc 58. 1.100 / 58. 1.100
...
Para evitar que nos aparezca toda esta información, podemos utilizar el parámetro -hide_banner
. Esto hará que la omita y nos centremos sólo en el resto de información.
Uso básico de ffmpeg
Veamos la sintaxis básica de ffmpeg
para utilizarlo tanto para obtener información de un archivo multimedia, como para convertirlo a otro formato.
La sintaxis mínima de ffmpeg
es escribir el parámetro -i
para indicar que queremos establecer un archivo de entrada y a continuación, el nombre de dicho archivo:
$ ffmpeg -hide_banner -i video.mp4
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf55.43.100
Duration: 02:42:45.01, start: 0.000000, bitrate: 6180 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p(tv, bt709), 1920x1080 [SAR 1:1 DAR 16:9], 6003 kb/s, 60 fps, 60 tbr, 90k tbn, 120 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 160 kb/s (default)
Metadata:
handler_name : SoundHandler
At least one output file must be specified
La parte clave es la que resalto a continuación:
- 1️⃣ El comando indicado: En este caso,
ffmpeg
con el parámetro-i
(indicar un video de entrada). - 2️⃣ Duration y bitrate: Características del archivo (duración y calidad en tasa de bits).
- 3️⃣ Stream #0:0: Info del canal de video: codec, resolución, proporción, calidad de video, fps, etc...
- 4️⃣ Stream #0:1: Info del canal de audio: codec, frecuencia de muestreo, calidad de audio, etc...
Con esto puedes obtener información sobre un archivo de video y sus características. En la siguiente tabla puedes ver algunos parámetros interesantes, que explicaremos poco a poco más adelante:
Parámetro | Descripción |
---|---|
-i fichero.ext | Muestra información de ese archivo (audio o video). |
-i origen.ext destino.ext | Convierte un archivo de un formato a otro. |
-formats | Muestra todos los formatos soportados por ffmpeg. |
-codecs | Muestra todos los codecs soportados por ffmpeg. |
-decoders | Muestra todos los codecs de entrada soportados. |
-encoders | Muestra todos los codecs de salida soportados. |
Conversión entre formatos
Uno de los puntos fuertes de ffmpeg es que permite realizar practicamente cualquier tipo de conversión entre los diferentes formatos de video y audio (que no son pocos). Es requisito recomendable tener una idea general de los diferentes formatos y codecs de video y formatos y codecs de audio que existen antes de comenzar a utilizar ffmpeg.
Podemos realizar conversiones aprovechándonos de las extensiones comunes de ciertos formatos de video, ya que ffmpeg los detecta automaticamente. Por ejemplo:
$ ffmpeg -i video_original.avi video_destino.mp4
En este ejemplo, le indicamos a ffmpeg que el formato de entrada es video_original.avi (mediante el parámetro -i) y que lo convierta a un archivo de destino al cuál le hemos indicado la extensión .mp4. De esta forma, ffmpeg busca los codecs de video y de audio apropiados para este formato (automáticamente selecciona h264 para video y aac para audio).
Si realizaramos otra conversión desde un fichero .mp4
a otro .mkv
, podremos fijarnos en estas líneas, las cuales nos indican que tipo de conversión se está realizando:
[...]
Stream mapping:
Stream #0:0 -> #0:0 (mpeg4 (native) -> h264 (libx264))
Stream #0:1 -> #0:1 (aac (native) -> vorbis (libvorbis))
[...]
No obstante, podemos ser más específicos y personalizar los formatos que queremos utilizar. Por ejemplo, especificando el codec de video y el codec de audio que queremos en el archivo de destino:
$ ffmpeg -i video_original.mp4 -vcodec libx264 video_264.mkv
$ ffmpeg -i video_original.mp4 -vcodec libx265 video_265.mkv
En ambos ejemplos anteriores estamos creando un archivo de video Matroska (MKV), con canal de audio vorbis en ambos casos. Sin embargo, en el primer ejemplo, estamos utilizando el codec de video h264 (mediante la librería libx264), mientras que en el segundo ejemplo utilizamos el codec de video h265 (mediante la librería libx265), aún en desarrollo y futuro sucesor de H264.
Los resultados son bastante interesantes, puesto que el primer archivo resultante ocupa 120MB, mientras que el segundo 69MB. Ambos a 1080p (HD) y con la misma aparente calidad (eso sí, el segundo tarda más en comprimir y crearse).
También podemos hacer lo mismo con los canales de audio:
$ ffmpeg -i video.mp4 -vcodec copy -acodec mp3 h264_mp3.mkv
$ ffmpeg -i video.mp4 -vcodec copy -acodec aac h264_aac.mkv
$ ffmpeg -i video.mp4 -vcodec copy -acodec libvorbis h264_vorbis.mkv
Observa que en estos casos, hemos especificado copy en el codec de video, lo que obliga a ffmpeg a no hacer conversión de formatos de video, sino utilizar el que ya tiene (ahorrando mucho tiempo porque no hay que recomprimir el video), mientras que le especificamos el codec de audio mediante acodec.
Tanto con -vcodec
como con -acodec
tenemos que especificar la librería de codec a utilizar. En el caso de especificar solo la extensión en el archivo (por ejemplo, .mp3
), el ffmpeg se encarga de seleccionar la librería más apropiada (libmp3lame, en este caso).
Podemos ver las librerías de codecs y formatos que soporta ffmpeg escribiendo en una terminal las lineas de comandos ffmpeg -formats
o ffmpeg -codecs
.
Parámetro | Descripción |
---|---|
-vcodec | Fuerza a usar un codec de video de salida. |
-acodec | Fuerza a usar un codec de audio de salida. |
Reducir calidad (bitrate)
Por defecto, ffmpeg
se encarga de detectar la calidad (bitrate) del video y audio del archivo original y le asigna uno equivalente al archivo de destino. Sin embargo, esto depende mucho del archivo en cuestión y puede que ffmpeg reduzca demasiado la calidad (y se vea con mala calidad el archivo resultante) o mantenga una calidad demasiado alta (y ocupe demasiado el archivo final).
Generalmente, ffmpeg hace un gran trabajo en este aspecto. Pero si queremos personalizar la calidad, utilizaremos el parámetro -b:v
para el bitrate de video y -b:a
para el bitrate de audio. Por ejemplo:
$ ffmpeg -i video.avi -b:v 2500k -b:a 192k video_final.mp4
Esto conseguiría que el archivo MP4 final tenga un video con un bitrate de 2500kb/s y un audio con un bitrate de 192kb/s.
Parámetro | Descripción |
---|---|
-b:v | Establece el bitrate de video de salida (no olvides la k!). |
-b:a | Establece el bitrate de audio de salida. |
Trabajando con canales de audio
Es muy posible que queramos trabajar con los canales de audio de un video.
Otra operación muy común es querer extraer el audio de un video, para pasarlo a un archivo MP3, por ejemplo. Esto es muy sencillo de hacer con ffmpeg:
$ ffmpeg -i video.mp4 -vn audio.mp3
En algunos casos, como el caso anterior, ffmpeg detectará que el archivo de destino es un archivo de audio y hará la conversión automáticamente sin necesidad de indicar parámetros como -vn. Sin embargo, será necesario si queremos hacerlo en un formato final mkv sin canal de video.
Parámetro | Descripción |
---|---|
-vn | Elimina el canal de video. |
-an | Elimina el canal de audio. |
La mayoría de formatos de video de la actualidad funcionan como contenedores que son capaces de incluir varios canales de audio (e incluso de otros tipos). Es muy común, por ejemplo, para añadir audio en diferentes idiomas. Con ffmpeg
podemos gestionar esas pistas múltiples presentes en un archivo de video.
Un ejemplo de uso podrían ser los siguientes comandos:
$ ffmpeg -i video.mp4 -i audio_es.mp3 -map 0:v -map 0:a -map 1:a -vcodec copy video_final.mp4
$ ffmpeg -i video.mp4 -map 0:0 -map 0:2 solo_canal1_audio.mp4
En el primer ejemplo, obtenemos dos archivos de entrada: video.mp4
(un video en inglés) y audio_es.mp3
(el audio en español). Nuestra intención es añadir este audio en el video, de modo que se pueda seleccionar el idioma. Con -map 0:v
y -map 0:a
indicamos que utilizaremos el video y audio del primer archivo de entrada (video.mp4) y con -map 1:a
indicamos que utilizaremos el audio del segundo archivo de entrada (audio_es.mp3) para incorporarlo al video final.
En el segundo ejemplo, partimos de un archivo video.mp4 que tiene varios canales de audio, y con los parámetros -map 0:0
y -map 0:2
indicamos que queremos generar un archivo con el video (canal 0) y la segunda pista de audio (canal 2), eliminando por tanto la primera pista (canal 1).
Parámetro | Descripción |
---|---|
-map #:@ | Mapea un canal de audio o video. En # va el número del canal y en @ va una a o una v . |
-filter_complex | Utiliza un filtro complejo. |
Pero en algunas ocasiones no interesa añadir otra pista de audio al video, sino mezclarla con la pista existente. Para ello, podemos utilizar el filtro de audio amerge, como vemos en el siguiente ejemplo:
$ ffmpeg -i audio1.mp3 -i audio2.mp3 -filter_complex amerge audio_mezclado.mp3
Volumen de audio
Por otro lado, a veces necesitaremos modificar el volumen de nuestras pistas de audio.
De la misma forma análoga al ejemplo anterior (donde eliminabamos el canal de video en un archivo de video), podemos eliminar el canal de audio de un archivo de video:
$ ffmpeg -i video.mp4 -an video_mute.mp4
Muchas veces tenemos un video que tiene un audio muy bajo. Podemos subirle el volumen del canal de audio con el parámetro -vol
, indicándole un valor numérico donde 256
es el volumen original, pudiendo subirlo o bajarlo:
$ ffmpeg -i video.mp4 -vol 512 video_final.mp4
$ ffmpeg -i video.mp4 -af volume=2
En el segundo ejemplo vemos una forma alternativa utilizando filtros de audio, en el que subimos el volumen al doble de su volumen original.
Parámetro | Descripción |
---|---|
-vol | Cambia el volumen de audio (256 normal, 512 doble, 128 mitad) |
-af [filtro] | Establece un filtro avanzado de audio. |
-vf [filtro] | Establece un filtro avanzado de video. |
Transformaciones
En ciertos casos, es muy probable que queramos realizar transformaciones a nuestro video. Cosas como rotarlo, redimensionarlo a otro tamaño o recortar y quedarte sólo con una parte del video.
Una operación bastante frecuente es la de redimensionar el tamaño de un video. También es una operación muy sencilla de realizar con ffmpeg, aunque hay que tener en cuenta la proporción de aspecto, de modo que al redimensionar no se deforme el mismo. Veamos algunos ejemplos:
$ ffmpeg -i video.mp4 -vf scale=320:240 video_320x240.mp4
$ ffmpeg -i video.mp4 -vf scale=320:-1 video_320x180.mp4
$ ffmpeg -i video.mp4 -vf scale=iw/2:ih/2 video_x.mp4
En el primero de los casos, obligamos a ffmpeg a redimensionar el video a la resolución 320x240
, independientemente del tamaño del video original. En la segunda opción, sin embargo, al indicar -1
le decimos a ffmpeg que utilice el alto apropiado para que el video no se deforme, reemplazándolo por su alto equivalente:
En el tercer ejemplo, utilizamos las palabras clave iw
(input width) y ih
(input height). Al dividirlas entre dos, lo que indicamos es que el video resultante tenga la mitad de tamaño tanto de ancho como de alto.
Nota: Hay que tener cuidado con algunos codecs, puesto que no permiten redimensiones a tamaños que no sean múltiplos de 4 o restricciones similares.
También es muy común tener la necesidad de rotar un video, ya sea porque nos interesa tenerlo así o porque alguien tuvo la osadía de hacer un maldito vídeo vertical. Para solucionarlo, podemos rotar el video haciendo lo siguiente:
$ ffmpeg -i video.mp4 -vf transpose=clock video_rotado_90.mp4
$ ffmpeg -i video.mp4 -vf transpose=clock,transpose=clock video_rotado_180.mp4
$ ffmpeg -i video.mp4 -vf hflip video_invertido_horizontalmente.mp4
$ ffmpeg -i video.mp4 -vf vflip video_invertido_verticalmente.mp4
En el primer ejemplo, utilizamos el filtro de video transpose para girar 90 grados en el sentido de las agujas del reloj. En el caso de indicar el valor cclock en lugar de clock, se gira en el sentido contrario de las agujas del reloj. En el segundo ejemplo, aplicamos el filtro dos veces, por lo que conseguimos como resultado un giro de 180 grados. Los dos últimos ejemplos son para invertir un video horizontal o verticalmente.
Existe un parámetro rotate en ffmpeg que es mucho más flexible, pero cuidado, los valores deben expresarse en radianes.
Imagina por un momento que tienes un video, pero sólo te interesa quedarte con una región concreta del mismo. Esto es lo que se llama crop
(recortar), y también se puede realizar con ffmpeg, con una línea de comandos como la que vemos a continuación:
$ ffmpeg -i screencast.mp4 -ss 00:30 -to 03:50 -vf crop=640:480:500:250 video_final.mp4
En ella, escogemos un fragmento de video, en el que sólo nos quedamos con una región de tamaño 640x480 desde la posición (500,250) de la pantalla. Esto puede ser muy útil para recortar grabaciones que hemos hecho y queremos extraer sólo una región de la pantalla.
Recortar fragmentos
Otra operación interesante que nos puede surgir es la de recortar un fragmento de tiempo de un video más largo. Por ejemplo, obtener el fragmento de video desde los 35seg
hasta los 65seg
(30seg de duración).
Existe un parámetro con el que podemos realizar estas operaciones:
$ ffmpeg -i video.mp4 -ss 35 -t 30 fragmento.mp4
$ ffmpeg -i video.mp4 -ss 00:35 -to 01:05 fragmento.mp4
En el primer ejemplo, estamos seleccionando el fragmento de video desde los 35seg
(como marca de inicio), y a partir de ahí, 30seg
hacia adelante. En el segundo ejemplo, estamos seleccionando el fragmento de video desde la marca de tiempo de 35seg
hasta 1min 5seg
, ambos del video original.
Parámetro | Descripción |
---|---|
-ss | Establece el momento de inicio de un fragmento de video/audio. |
-to | Establece el momento de final de un fragmento de video/audio. |
-t | Establece la duración del fragmento de video/audio. |
Extraer fotogramas de un video
Con ffmpeg también podemos realizar tareas con formatos de imágenes. Es posible extraer los fotogramas de un video (o un fragmento de video) y pasarlos a imágenes individuales. Para hacerlo, simplemente escribimos la siguiente línea de comandos:
$ ffmpeg -i video.mp4 image%d.jpg
Teniendo en cuenta que los videos, por lo general, tienen entre 25-30fps (fotogramas por segundo), esto quiere decir que, salvo que se trate de un video muy corto, cada video generará gran cantidad de imágenes.
Para evitarlo, se puede reducir los fotogramas por segundo a uno, por ejemplo, utilizando el siguiente filtro:
$ ffmpeg -i video.mp4 -vf fps=1 image%d.png
De esta forma, sólo generará una imagen por segundo. También podemos realizar la operación contraria, de modo que teniendo una serie de imágenes, las unamos y convirtamos en un video, algo ideal para técnicas de stop-motion, realizadas con una cámara digital:
$ ffmpeg -f image2 -i image%d.jpg video.mp4
Efectos
Un efecto muy elegante y utilizado es el viñeteado, muy utilizado por los fans de Instagram. Con ffmpeg podemos también aplicar un viñeteado a nuestro video, en todos sus fotogramas, dándole un aspecto más elegante y profesional.
Para aplicarlo, basta con utilizar el filtro de video vignette, junto a un valor que representa el ángulo del mismo en radianes:
$ ffmpeg -i video.mp4 -vf vignette=PI/4 video_vignette.mp4
$ ffmpeg -i video.mp4 -vf vignette='PI/4+random(1)*PI/50':eval=frame
El valor aplicado por defecto al viñeteado es pi/5
, sin embargo se pueden hacer cosas un poco más complejas, como el segundo ejemplo, donde se crea un viñeteado que vibra aleatoriamente, simulando un efecto retro de reproducción antigua.
Otro efecto elegante utilizado a menudo en videos es el de los «fundidos a negro» (fade-out) o su proceso inverso (fade-in). Estos fundidos son muy comunes al inicio o al final de un video, ya que es una forma elegante de terminarlo.
Con ffmpeg se pueden crear de la siguiente forma:
$ ffmpeg -i video.mp4 -vf fade=t=in:st=0:d=5 video-fadein.mp4
$ ffmpeg -i video.mp4 -vf fade=t=in:st=0:d=5,fade=t=out:st=25:d=5 video-fadeout.mp4
Teniendo en cuenta que nuestro video.mp4 tiene una duración de 30 segundos, en el primer ejemplo, creamos un fundido desde negro (fade-in). Los parámetros indicados fade=t=in:st=0:d=5
son para realizar un tipo de fundido de entrada (fade-in), que comience en la marca de tiempo de 0seg
y dure 5seg
desde que pasa de negro a desvanecerse por completo.
En el segundo ejemplo, añadimos además un fundido a negro (fade-out), que comienza a los 25seg
y dura 5seg
. También podríamos añadir un párametro c=white
para realizar los fundidos al color blanco, en lugar de negro.
Sin embargo, ya que tenemos el fundido a negro visualmente hecho, también podemos utilizar el filtro de audio afade
para hacer lo mismo con el sonido:
$ ffmpeg -i true.mp4 -vf fade=t=in:st=0:d=5,fade=t=out:st=25:d=5 -af afade=t=in:ss=0:d=5,afade=t=out:st=25:d=5 truefade.mp4
Utilizando el siguiente comando, podemos crear una especie de morphing (fading) de una imagen a otra. Sólo tenemos que asegurarnos que la primera imagen tiene el mismo tamaño que la segunda, y ejecutar el siguiente comando:
# Morphing entre dos imágenes (image1.jpg e image2.jpg)
$ ffmpeg -loop 1 -i image1.jpg -loop 1 -i image2.jpg \
-filter_complex "[1:v][0:v]blend=all_expr='A*(if(gte(T,3),1,T/3))+B*(1-(if(gte(T,3),1,T/3)))'" \
-t 4 final.mp4
Añadir marca de agua
Quizás, uno de los ejemplos más prácticos puede ser el siguiente. En él, lo que hacemos es insertar una imagen en una posición concreta de la imagen. Esto es ideal para insertar logotipos o marcas de agua en un video. Ten en cuenta, que si utilizas imágenes PNG puedes aprovechar el canal alfa de transparencia del mismo y colocar marcas de aguas que no sean totalmente opacas. El primer ejemplo que se ve a continuación inserta la imagen logo.png en la posición (10,10), comenzando desde la esquina superior izquierda:
$ ffmpeg -i video.mp4 -i logo.png -filter_complex overlay=10:10 final.mp4
$ ffmpeg -i video.mp4 -i logo.png -filter_complex overlay=x=(main_w-overlay_w):y=(main_h-overlay_h) final.mp4
Por otro lado, el segundo ejemplo realiza la misma tarea, pero utilizando variables predefinidas, que equivalen a colocar ese logotipo en la esquina inferior derecha, algo quizás más habitual.
Otros comandos
Añado algunos otros comandos interesantes que he utilizado en alguna ocasión:
# Incrementar velocidad de video
$ ffmpeg -i original.mp4 -vf setpts=0.02*PTS destino.mp4
# Zoom IN
$ ffmpeg -loop 1 -i imagen.png -i audio.mp3 \
-vf "zoompan=z='min(zoom+0.0010,1.5)':d=700:x='iw/2-(iw/zoom/2)':y='ih/2-(ih/zoom/2)':s=1080x1920" video.mp4
# Eliminar escenas con frames duplicados de un video
$ ffmpeg -i input.mp4 -vf mpdecimate,setpts=N/FRAME_RATE/TB output.mp4
# Trim del audio (eliminar silencio antes y después)
$ ffmpeg -i original.mp3 -af silenceremove=1:0:-50dB:1:0:-75dB destino.mp3
# Rotar 270 grados
$ ffmpeg -i video.mp4 -vf transpose=clock,transpose=clock,transpose=clock video_rotado_270.mp4
Esto sólo es una selección práctica con algunos pequeños ejemplos de lo que se puede hacer con ffmpeg. Si te ha resultado útil o conoces algún parámetro interesante que no esté en la lista, por favor, compártelo con nosotros en los comentarios.