Búsqueda de sitios web

Hackear FFmpeg con Python - Primera parte


FFmpeg es un excelente marco multimedia que te ayuda a manejar tus archivos de audio y vídeo. ¿Qué quiero decir con esto? Bueno, puedes convertir fácilmente de un formato a otro, extraer audio de un vídeo, comprimir un vídeo e incluso extraer imágenes de un vídeo. Hay muchas cosas interesantes que puedes hacer con esta herramienta. Está escrito principalmente en lenguaje de programación C y la mejor parte es que FFmpeg es de código abierto.

A través de este tutorial, aprenderá a utilizar el lenguaje de programación Python para interactuar con esta herramienta de código abierto y automatizar algunas tareas simples.

Configurando Python y ffmpeg en tu sistema Linux

La versión de Python que se utiliza en este artículo es Python 2.7.x, así que asegúrese de instalarla en su propia máquina Linux antes de continuar, ya que una versión diferente puede generar todo tipo de errores al ejecutar el código en el shell interactivo de Python.

Compilar el código fuente es un poco complicado, pero dado que es necesario cubrir esta instalación para casi cualquier tipo de distribución de Linux, no es posible pasar por todos los administradores de paquetes.

Abra la terminal y descargue el paquete de Python correcto usando la utilidad wget, como se muestra aquí:

wget --no-check-certificate https://www.python.org/ftp/python/2.7.11/
Python-2.7.11.tgz

Nota: wget es una utilidad de línea de comandos que se puede utilizar para descargar cosas a través del protocolo http.

Una vez que el paquete Python 2.7.x haya terminado de descargarse, la siguiente herramienta de línea de comando necesaria es tar:

tar -xzf Python-2.7.11.tgz

Cambie el directorio de trabajo usando el siguiente comando:

cd Python-2.7.11

Para compilar e instalar Python en su máquina, ejecute los siguientes comandos, uno por uno. Este es el último paso para garantizar que tiene instalada la versión correcta de Python. Sin él, no podrás aprovechar esta serie de hacking de FFmpeg:

./configure  
make  
sudo make install

Antes de compilar e instalar FFmpeg, siempre es una buena idea probar la nueva versión de Python que acaba de instalar.

El siguiente comando puede ayudar a ejecutar python2.7.x en su máquina Linux para verificarlo:

python2.7

Si aparece el shell de Python, significa que esta parte de la configuración se realizó correctamente.

Se debe hacer lo mismo para tener la utilidad FFmpeg en su nix box. El primer paso es descargar el código fuente del sitio oficial usando el comando que se muestra a continuación:

wget https://github.com/FFmpeg/FFmpeg/archive/master.zip

Como puede ver en el comando anterior, la herramienta wget se utiliza para descargar el código fuente, que necesitamos compilar.

El comando para descomprimir el archivo .zip es el siguiente:

unzip master.zip

Una vez que el directorio esté listo, ejecute el siguiente comando para asegurarse de que la configuración se realice correctamente:

./configurar

Si el comando anterior se completa sin errores, significa que puede compilar e instalar FFmpeg fácilmente en su máquina.

Utilice los siguientes comandos:

make
su -c 'make install'

Una vez finalizada la instalación de FFmpeg, le recomendamos encarecidamente que realice la misma prueba que hicimos con el shell de Python para asegurarse de que la herramienta funcione correctamente.

El siguiente comando se puede utilizar para ejecutar FFmpeg desde la línea de comando:

ffmpeg

Algunos ejemplos prácticos de FFMpeg

Antes de pasar directamente a piratear FFmpeg utilizando un lenguaje de programación como Python, se recomienda que se familiarice con algunas de las características que este marco multimedia líder de código abierto tiene para ofrecer.

En la instalación de la caja FFmpeg se incluye la utilidad ffprobe. Se puede utilizar para obtener información sobre un archivo de audio o vídeo, como las transmisiones, el formato o ambos, utilizando el siguiente código:

ffprobe -show_format -show_streams test.mp4

El comando anterior analiza el video 'test.mp4' en busca de etiquetas de formato y transmisiones. El resultado que este comando muestra en la consola es muy largo, como se muestra a continuación.

[STREAM]
index=1
codec_name=aac
codec_long_name=AAC (Advanced Audio Coding)
profile=LC
codec_type=audio
codec_time_base=1/44100
codec_tag_string=mp4a
codec_tag=0x6134706d
sample_fmt=fltp
sample_rate=44100
channels=2
channel_layout=stereo
bits_per_sample=0
id=N/A
r_frame_rate=0/0
avg_frame_rate=0/0
time_base=1/44100
start_pts=0
start_time=0.000000
duration_ts=9262080
duration=210.024490
bit_rate=95999
max_bit_rate=103664
bits_per_raw_sample=N/A
nb_frames=9045
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=1
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
TAG:creation_time=2015-04-23T08:06:29.000000Z
TAG:language=eng
TAG:handler_name=IsoMedia File Produced by Google, 5-11-2011
[/STREAM]
[FORMAT]
filename=test.mp4
nb_streams=2
nb_programs=0
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=210.023333
size=8691199
bit_rate=331056
probe_score=100
TAG:major_brand=mp42
TAG:minor_version=0
TAG:compatible_brands=isommp42
TAG:creation_time=2015-04-23T08:06:28.000000Z
[/FORMAT]

El resultado producido por este comando nos brinda mucha información sobre las secuencias del archivo. Cada secuencia tiene su propio índice. La primera secuencia tiene un índice de 0, pero a los efectos de este artículo no se muestran aquí todas las secuencias investigadas por ffprobe.

Supongamos que uno quiere extraer sólo la secuencia de audio de un vídeo musical. Según mi experiencia, el comando perfecto es el que copia la transmisión de audio sin volver a codificarla:

ffmpeg -i video.mp4 -vn -acodec copy audio.aac

El comando anterior es realmente útil cuando se trata de extraer la transmisión de audio. Sin embargo, hay un gran problema con esto. Para copiar la transmisión de audio se necesita la extensión correcta, que en el caso anterior es .acc. ¡Aquí es donde ffprobe se vuelve realmente útil!

Encontrar la extensión correcta para guardar el archivo de audio que se está copiando es tan fácil como echar un vistazo al valor codec_name dentro de la información de la secuencia de audio que proviene de sondear el archivo con la siguiente utilidad de línea de comando ffprobe:

[STREAM]
index=1
codec_name=aac

........
........
.......
[/STREAM]

Para obtener más información sobre cómo utilizar la utilidad de línea de comandos ffmpeg, lea nuestro artículo sobre comandos prácticos que se pueden utilizar en situaciones reales.

Comience a usar Python para interactuar con ffmpeg

Python es un lenguaje de programación informática de alto nivel perfecto para crear secuencias de comandos que a uno le gusta automatizar. No es necesario ser un experto en Python para seguir este tutorial o utilizar otros códigos de Python. Incluso un principiante en codificación puede seguir, comprender y ejecutar los códigos que se comparten en este artículo.

Inicie un shell de Python usando el siguiente comando en su terminal:

python2.7

Hay muchos módulos disponibles en la biblioteca estándar que ofrece Python. La que realmente se adapta a nuestras necesidades es la biblioteca de subprocesos.

Para hacer uso de un módulo de Python, primero debes importarlo usando el siguiente comando:

import subprocess

Pero ¿cuál es el propósito del módulo que acabamos de importar? Según la documentación oficial de Python, el módulo de subproceso le permite generar un proceso. En otras palabras, puedes ejecutar un programa a través de Python. No sólo esto, sino que también puedes conectarte a sus tuberías de entrada/salida e incluso obtener códigos de retorno.

El siguiente ejemplo es realmente bueno para darle una mejor idea de cómo se puede utilizar el módulo de subproceso para generar un proceso.

p = subprocess.Popen('ls', stderr=subprocess.PIPE, stdin=subprocess.PIPE, 
stdout=subprocess.PIPE)

El código Python anterior ejecuta el comando ls que enumera los archivos dentro de un directorio. ¡Inténtalo tú mismo!

Luego, obtenga el resultado del proceso abierto anteriormente comunicándose con él como se muestra a continuación.

output, _ = p.communicate()

Para imprimir el resultado, se puede utilizar esta declaración de impresión de Python:

print(_)

La declaración anterior mostrará el resultado devuelto por la comunicación con el proceso. Si todo funcionó correctamente, debería obtener una lista de los archivos y subdirectorios dentro del directorio de trabajo actual.

Python también puede ayudar a generar un proceso para la utilidad ffmpeg como se muestra en el siguiente código:

cmds = ['/usr/local/bin/ffmpeg']
ffmpeg_p = subprocess.Popen(cmds, stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE, 
                            stderr=subprocess.PIPE)

Comuníquese con el proceso para obtener el resultado:

output, _ = ffmpeg_p.communicate()

Imprima el resultado devuelto por ffmpeg en la consola usando esta declaración de impresión de Python:

print(_)

La declaración impresa anterior imprimirá lo siguiente:

ffmpeg version 3.2 Copyright (c) 2000-2016 the FFmpeg developers
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.2 --enable-shared 
--enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables 
--enable-avresample --cc=clang --host-cflags= --host-ldflags= 
--enable-libmp3lame --enable-libx264 --enable-libxvid --enable-opencl 
--disable-lzma --enable-vda
  libavutil      55. 34.100 / 55. 34.100
  libavcodec     57. 64.100 / 57. 64.100
  libavformat    57. 56.100 / 57. 56.100
  libavdevice    57.  1.100 / 57.  1.100
  libavfilter     6. 65.100 /  6. 65.100
  libavresample   3.  1.  0 /  3.  1.  0
  libswscale      4.  2.100 /  4.  2.100
  libswresample   2.  3.100 /  2.  3.100
  libpostproc    54.  1.100 / 54.  1.100
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options]
 outfile}...

Use -h to get full help or, even better, run 'man ffmpeg'

Es lo mismo que ejecutar el comando ffmpeg en la consola, pero esta vez usamos Python para hacer el trabajo por nosotros.

Obtener las transmisiones y el formato del archivo de video con Python es tan fácil como definir los comandos necesarios para generar el proceso con el módulo de subproceso.

En nuestro caso los comandos son los siguientes:

cmds = ['/usr/local/bin/ffprobe', '-show_format', '-show_streams', 
'test.mp4']

Como puede ver, almacenamos los comandos en un objeto de Python que se conoce como lista. La sintaxis para definir una lista es la siguiente:

[]

Luego abra un nuevo proceso y pase el cmds como argumento, como se muestra a continuación:

ffprobe_p = subprocess.Popen(cmds, stdin=subprocess.PIPE, 
stdout=subprocess.PIPE, stderr=subprocess.PIPE)

Para obtener las transmisiones y el formato del archivo de video, debe utilizar el método de comunicación como lo hicimos en los ejemplos anteriores. Utilice este código:

output, _ = ffprobe_p.communicate()

Luego use la declaración de impresión para imprimir las secuencias y la información de formato devuelta por la operación de sondeo.

Conclusión

¡FFmpeg no es solo una herramienta geek utilizada por geeks como nosotros! La industria multimedia también lo utiliza. Hay muchos rumores en torno a que Youtube lo utiliza para codificar sus videos. No vale la pena memorizar la lista completa de comandos que esta herramienta tiene para ofrecer, pero este es un caso perfecto para cuando un lenguaje de script como Python se vuelve realmente útil.

La diversión apenas comienza, ¡disfrutémosla!

Artículos relacionados: