Hace algún tiempo utilicé FFmpeg para la automatización de la grabación de algunos tutoriales y por eso quedé con la inquietud de crear un breve turtorial con algunas de sus principales funciones.
FFmpeg es un completo y muy avanzado conjunto de herramientas de software libre orientadas al procesamiento de video desde consola. Contempla aplicaciones para la grabación, reproducción, conversión, transcodificación y streaming de video. Además contiene un amplio conjunto de codecs y librerías de audio y video que lo convierten en una herramienta de desarrollo indispensable, así como tremendamente útil para la creación y manipulación de nuestros videos, la extracción o incorporación de audio, transferencia de video por red (streaming) e incluso la creación de ScreenCast para videotutoriales.
El proyecto FFmpeg viene con varios programas pero podríamos decir que los más importantes son ffmpeg, ffserver y ffplay.
El ffmpeg esta orientado fundamentalmente la grabación, transcodificación y conversión de videos. Permite entre otras cosas, convertir entre una amplia gama de formatos, pasando por la extracción de imágenes y sonido de nuestros videos o la conversión de imágenes indexadas a videos. Los principales parámetros de este programa son:
wsxga: 1600×1024
wuxga: 1920×1200
woxga: 2560×1600
wqsxga: 3200×2048
wquxga: 3840×2400
whsxga: 6400×4096
whuxga: 7680×4800
cga: 320×200
ega: 640×350
hd480: 852×480
hd720: 1280×720
hd1080: 1920×1080
16cif: 1408×1152
qqvga: 160×120
qvga: 320×240
vga: 640×480
svga: 800×600
xga: 1024×768
uxga: 1600×1200
qxga: 2048×1536
sxga: 1280×1024
qsxga: 2560×2048
hsxga: 5120×4096
wvga: 852×480
wxga: 1366×768
sqcif: 128×96
qcif: 176×144
cif: 352×288
4cif: 704×576
A continuación podemos ver algunos ejemplos del uso de estas herramientas:
ffmpeg -f video4linux2 -s 320x240 -i /dev/video0 -sameq ./out.mpg
ffmpeg -f oss -i /dev/dsp salida.mpg
ffmpeg -f alsa -i plughw:1,0 salida.mpg
ffmpeg -i my_audio.wav my_audio.ogg
ffmpeg -i my_video.flv my_video.mpeg
ffmpeg -i my_video.mpeg -s 500×500 my_video.flv
ffmpeg -i input_file_name.mp4 -vcodec flv -ar 22050 output_file_name.flv
Cuando convertimos videos a formatos comprimido es posible que se reduzca la calidad de la imagen, para evitar esto podemos usar el parámetro -qscale 0 donde el cero indica que se debe mantener la calidad en la medida de lo posible:
ffmpeg -i my_video.avi -qscale 0 my_video.mp4
ffmpeg -i test.mpg -r 25 image%d.jpg
ffmpeg -i test.mpg -r 25 -ss 00:00:10 -t 00:00:05 images%05d.png
ffmpeg -f image2 -i img%d.jpg /tmp/a.mpg
ffmpeg -f video4linux2 -s 320x240 -i /dev/video0 -f audio_device -ac 2 -i /dev/dsp1 -f mp4 Filename.mp4
ffmpeg -f oss -i /dev/dsp -f video4linux2 -s 320x240 -i /dev/video0 out.mpg
ffmpeg -ss 7.0 -t 5.5 -i video.mp4 -f gif image.gif
Entonces, con estos dos argumentos, FFmpeg buscará segundo 7.0
y leerá en los próximos 5.5
segundos para la creación del GIF. Otra forma de hacer esto para lograr un mejor resultado es combinar FFmpeg con Imagemagick en el siguiente pipeline:
ffmpeg -i video.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v pam -f image2pipe - | convert -delay 10 - -loop 0 -layers optimize output.gif
ffmpeg -i image.gif -f mp4 -pix_fmt yuv420p video.mp4
Entonces, con estos dos argumentos, FFmpeg buscará segundo 7.0
y leerá en los próximos 5.5
segundos para la creación del GIF.
ffmpeg -i audio.mp3 -i video.mpg -sameq video.mkv
ffmpeg -i audio.mp3 -i video.mpg -sameq video_result.mpg
ffmpeg -f concat -i file video1.mpg file video2.mpg -c copy video.mpg
ffmpeg -i "concat:video1.mpg|video2.mpg" -c copy video.mpg
ffmpeg -i "concat:$1|$2" -c copy $3
ffmpeg -f concat -safe 0 -i video.txt video.mp4
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 \
-filter_complex '[0:v:0] [0:a:0] [1:v:0] [1:a:0] [2:v:0] [2:a:0] concat=n=3:v=1:a=1 [v] [a]' \
-map '[v]' -map '[a]' output2.mkv
ffmpeg -i video.mp4 -vf scale=1280:766 video_1280x766.mp4 -hide_banner -qscale 0
ffmpeg -y -i video.mp4 -vf scale=1440:900,setsar=1:1 -c copy video2.mp4 -hide_banner
ffmpeg -i video.mpg -ss 00:00:02.000 -to 00:00:42.068 -c copy -copyts video_corto.mpg
# Conversión de formato por lotes
for FILE in *.{AVI,mpg} ; do \\
NAME=`echo "$FILE" | cut -d'.' -f1`; \\
ffmpeg -i $FILE -qscale 0 $NAME.mkv; \\
done
-vf "scale=640:-1"
-vf "scale=640x360,pad=640:480:0:60:black"
ffmpeg -i input.jpg -vf scale=w=320:h=240:force_original_aspect_ratio=decrease output_320.png
ffmpeg -y -i video.mp4 -aspect 16:9 scale=640x360,pad=640:480:0:60:black video_2.mp4
ffmpeg -i video.mp4 -vf scale=640:480,pad=1024:600:192:60:black -qscale 0 video_2.mp4
/opt/ffmpeg/ffmpeg -i CIMG1169_.mp4 -vf scale=800:600,pad=1024:600:112:0:black CIMG1169_2.mp4
ffmpeg -i original.avi -vf "transpose=1" resultado.avi
El valor del parámetro transpose indica el tipo de transformación, siendo 1 una rotación de 90 grados en el sentido de las agujas del reloj. El valor 2 giraría 90 grados en sentido contrario.
Para el parámetro de transposición puede pasar:
0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip
Úselo -vf "transpose=2,transpose=2"
para 180 grados. Otras dos transformaciones interesantes en esta misma línea que podemos aplicar mediante el argumento -vf son mirror y flip. Si queremos girar el vídeo 180 grados podemos aplicarlas ambas de modo conjunto (-vf mirror,flip).
Un ScreenCast es al vídeo lo que un SnapShot (pantallazo o captura de pantalla) a la fotografía. Hay algunos programas que realizan capturas de vídeo de lo que se muestra en nuestra pantalla, unos con mejores resultados que otros y también con mayor o menor dificultad de uso. Ejemplo de ello son Istanbul y RecordMyDesktop, dos soluciones que podrían funcionar muy bien. Sin embargo, no nos permiten grabar sonido de un micrófono mientras graba la pantalla, para por ejemplo dar un videotutorial, cosa que si podemos hacer con FFmpeg. A continuación muestro un ejemplo de como hacer esto, grabando un video de nuestra pantalla a 25 imágenes por segundo. El video se captura desde la esquina superior izquierda de la pantalla, y en este caso, hasta la coordenada 800x600:
ffmpeg -async 1 -f alsa -i plughw:1,0 -f x11grab -s 800x600 -r 25 -i :0.0 -b 128k ./out.mpg
ffmpeg -async 1 -f alsa -i plughw:1,0 -f x11grab -s 800x600 -r 25 -i :0.0 -sameq ./out.mpg
ffmpeg -async 1 -f alsa -i plughw:1,0 -f x11grab -s 800x600 -r 25 -i :0.0 -qscale 0 ./out.mpg
ffmpeg \
-async 1 \
-f oss \
-i /dev/dsp1 \
-f x11grab \
-s 1024x600 \
-framerate 20 \
-i :0.0 \
-sameq \
/root/video.mpg
Para la automatización de nuestros Screecast haremos uso de 2 herramientas (ffmpeg para realizar la captura de la pantalla y xwininfo para obtener las coordenadas y dimensiones de la ventana a grabar). Podemos realizar screencasts utilizando recursos mínimos y obteniendo óptimos resultados.
/bin/bash
\#!
Obtener las coordenadas y el tamaño de la ventana seleccionada
\# Esto excluye la decoración de la ventana.
\# unset x y w h
eval $(xwininfo -frame |
sed -n -e "s/^ +Absolute upper-left X: +([0-9]+).*/x=1/p"
-e "s/^ +Absolute upper-left Y: +([0-9]+).*/y=1/p"
-e "s/^ +Width: +([0-9]+).*/w=1/p"
-e "s/^ +Height: +([0-9]+).*/h=1/p" )
$w=$w + $w % 2 # que el ancho sea múltiplo de 2, sino ffmpeg se queja
WIN_XY=$x","$y # dar formato a las coordenadas XY
WIN_GEO=$w"x"$h # dar formato al tamaño de la ventana
notify-send mostrará un mensaje indicando el inicio del screencast.
\# correr ffmpeg con los parámetros que se ajusten a tu configuración.
\# notify-send "Iniciando screencast..." && ffmpeg -f alsa -i hw:0 -f x11grab -r 25 -s $WIN_GEO -i :0.0+$WIN_XY -acodec libmp3lame -async 1 -vcodec libx264 -preset ultrafast -crf 0 -threads 0 guardar.mp4
No hace falta entender completamente este scripts más allá de que genera una archivo de salida llamado guardar.mp4. Para obtener resultado, sin embargo, es necesario poder hacer ciertos cambios como:.
Si usás OSS, reemplazaremos -f alsa -i hw:0 por -f oss -i /dev/dsp
Si usamos solo ALSA, tenés que usar los parámetros que vienen en el script (-f alsa -i hw:0). Para determinar el número que va después de hw: podemos ejecutar aplay -l y elegir el número de la tarjeta de sonido adecuada.
Si usás Pulse Audio (Ubuntu y derivados usan esto), usá los parámetros -f alsa -ac 1 -i pulse.
Para varias las cantidad de frames por segundo (FPS): -r 25 indica los fps a los que deseemos grabar. 25 es una buena opción.
Con respecto al los Códec de audio, video y sincronización
Todas estas configuraciones fueron las que dieron mejores resultados: un archivo relativamente pequeño, una buena calidad de video, con audio sincronizado y sin lags. No obstante, te recomiendo sumergirte en la documentación de ffmpeg para descubrir otras.
#!/bin/bash
notify-send "Finalizando screencast..." && killall ffmpeg
Para que ambos scripts funcionen debemos tener instalado notify-send. La mayoría de las distribuciones deberían venir con esta herramienta instalada. En Arch y derivados: sudo pacman -S libnotify.
/opt/ffmpeg/ffmpeg \
-i image_fondo.jpg \
-i video.AVI \
-filter_complex \
"[1:v]chromakey=0x004682:0.15:0.0[keyed]; \
[0:v][keyed]overlay[out]" \
-map "[out]" \
-vcodec libx264 \
-crf 18 \
-preset slower \
video_result.avi
Por otra parte ffplay fue creado como un reproductor de video. El uso de ffplay es muy simple, aquí podemos ver unos ejemplos:
ffplay -f video4linux2 -i /dev/video0 >/dev/null &
ffplay out.mpg
El ffserver es una herramienta diseñada para servir el streaming de video, por ejemplo podemos usar la webcam en streaming para poder conectarnos desde cualquier lugar con el smartphone. FFmpeg maneja una gran cantidad de formatos en los que se puede emitir, además de ser relativamente fácil de configurar. La emisión del streaming se basa en el uso de dos programas: ffserver y ffmpeg. El primero se ejecuta en modo escucha y se encarga de hacer el streaming real mientras que el segundo recoge la imagen de alguna fuente y la envía a al primero.
Para empezar, es necesario crear un archivo de configuración: /etc/ffserver.conf, dejándolo como así:
Port 8090
BindAddress 0.0.0.0
MaxHTTPConnections 2000
MaxClients 1000
MaxBandwidth 1000
CustomLog -
<Feed webcam.ffm>
File /tmp/webcam.ffm
FileMaxSize 35M
</Feed>
<Stream webcam.swf>
Feed webcam.ffm
Format swf
VideoBitRate 320
VideoFrameRate 10
VideoSize 640x480
NoAudio
VideoQMin 1
VideoQMax 3
</Stream>
<Stream stat.html>
Format status
</Stream>
<Redirect index.html>
URL http://www.ffmpeg.org/
</Redirect>
Una vez configurado, es necesario iniciar el servicio con el comando:
ffserver -f ffserver.conf
Ahora sólo quedaría enviar la imagen al servidor con el comando ffmpeg y se puede utilizar cualquier entrada para redireccionarla al servidor. Por ejemplo, en el caso de una webcam, una capturadora de TV o cualquier entrada de vídeo, el comando sería:
ffmpeg -r 15 -s 320x240 -f video4linux -i /dev/video0 http://localhost:8090/webcam.ffm
En algunos casos podemos encontrarnos con este error:
[flv @ 0x97df6f0]rc buffer underflow VIDIOCMCAPTURE: Invalid argument
Para solucionar el problema, debemos escribir antes del comando ffmpeg, lo siguiente :
LD_PRELOAD=/usr/lib/libv4l/v4l1compat.so
Si todo va bien, podremos ver la imagen emitida con el navegador.
El sistema FFmpeg viene incluido en casi todos los repositorios oficiales de las principales distribuciones de GNU/Linux, sin embargo no siempre están compilados con todas las funciones que deseamos (con el dispositivo de grabación x11_grab por ejemplo) o, en ocaciones excepcionales, querremos preparar una nueva versión para nuestro sistema operativo. De cualquier modo es importante tener una breve receta de como compilar el FFmpeg desde las fuentes. Lo primero será descargar las fuentes, para esto lo mejor será ir a la zona de descargas de su sitio oficial: www.ffmpeg.org. Para el momento de escribir este artículo, la última versión es http://www.ffmpeg.org/releases/ffmpeg-2.1.tar.gz luego lo descomprimimos en algún directorio temporal, configuramos y compilamos así:
tar zxvf ffmpeg-2.1.tar.gz
cd ffmpeg-2.1.tar.gz
./configure --enable-gpl --enable-version3 --enable-nonfree --enable-postproc --enable-libfaac --enable-libmp3lame --enable-libtheora --enable-libx264 --enable-libxvid --enable-x11grab --enable-libvorbis --enable-libvpx --enable-shared --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libschroedinger --enable-libopenjpeg --enable-runtime-cpudetect
make
make install
Es importante verificar antes de compilar que el resultado de la configuración de las fuentes, reconoció como uno más de los dispositivos de grabación incorporados el x11_grab_device dentro de los “Enabled indevs”, debería verse algo así:
Enabled indevs:
alsa oss v4l2
dv1394 v4l x11_grab_device
En el caso de sistemas Debian o derivados, antes que nada deberemos actualizar nuestro archivo /etc/apt/sources.list agregando:
deb-src http://www.deb-multimedia.org sid main
deb http://www.deb-multimedia.org wheezy main non-free
Salvamos y actualizamos los indices de los paquetes disponibles:
apt-get update
apt-get install deb-multimedia-keyring
Después de esto recomiendan borrar la linea deb “http://www.deb-multimedia.org wheezy main non-free” del archivo /etc/apt/sources.list Luego podremos descargar el paquete ya preparado denominado ffmpeg-dmo y luego se procede a compilar como de costumbre:
apt-get install libxfixes-dev
apt-get source ffmpeg-dmo
cd ffmpeg-dmo-0.11
./configure
make && make install
Este post fue realizado sobre la vase de varios artículos publicados y algunas de mis experiencias previas (espero no olvidar ninguna de las fuentes): http://www.juanluperez.com/index.php/2010/09/screencast-con-ffmpeg-y-grabacion-de-microfono/ http://soledadpenades.com/2010/04/26/unknown-input-or-output-format-x11grab-ubuntu/ http://dmnet.bitacoras.com/archivos/software/streaming-de-una-webcam-con-ffmpeg.php http://www.freetux.com.ar/como-grabar-screencast-por-terminal-usando-ffmpeg/ http://sirlagz.net/2012/08/04/how-to-stream-a-webcam-from-the-raspberry-pi/ http://blog.giuseppeurso.net/raspberry-keychain-808-3-as-webcam/index.html http://www.raspberrypi-es.com/category/ffmpeg/ http://soledadpenades.com/2010/04/26/unknown-input-or-output-format-x11grab-ubuntu/ https://engineering.giphy.com/how-to-make-gifs-with-ffmpeg/ https://trac.ffmpeg.org/wiki/Concatenate https://ffmpeg.org/ffmpeg-filters.html#chromakey http://oioiiooixiii.blogspot.com/2016/02/ffmpeg-chromakey-filter-filthy-frank.html http://johnvansickle.com/ffmpeg/ https://blog.unlugarenelmundo.es/2012/12/26/chuletillas-y-xxxvi-rotar-videos-con-mencoder/
If you see mistakes or want to suggest changes, please create an issue on the source repository.
For attribution, please cite this work as
Sosa (2013, Nov. 10). Blog de José R Sosa: Edición de videos en línea de comandos con FFmpeg. Retrieved from https://josersosa.github.io/personalweb/posts/2021-05-03-edicin-de-videos-en-lnea-de-comandos-con-ffmpeg/
BibTeX citation
@misc{sosa2013edición, author = {Sosa, José R}, title = {Blog de José R Sosa: Edición de videos en línea de comandos con FFmpeg}, url = {https://josersosa.github.io/personalweb/posts/2021-05-03-edicin-de-videos-en-lnea-de-comandos-con-ffmpeg/}, year = {2013} }