Audio y video en Java utilizando ffmpeg, Jffmpeg, y JMF

Introducción

Supongamos que queremos implementar un reproductor multimedia en Java. Si a priori no conocemos los codecs de audio o video que debemos soportar, o si simplemente no existe una implementación de ese codec en Java, podemos interactuar con ffmpeg para reproducir multimedia en un montón de formatos diferentes. Para ello podemos utilizar JMF, Jffmpeg del lado del “mundo Java” interactuando con ffmpeg del lado del “mundo nativo”.

ffmpeg es una solución muy completa, open source y multi plataforma para grabar, convertir y reproducir audio y video. El proyecto está licenciado bajo LGPL o GPL (dependiendo de la configuración).

JMF (Java Media Framework) es una API  que permite agregar audio y video a nuestras aplicaciones y applets implementadas sobre tecnología Java. Además de reproducir, JMF nos permite
capturar, transcodificar o hacer streaming en varios formatos.

Jffmpeg es el puente entre ffmpeg y JMF. Si bien JMF soporta algunos formatos, eventualmente nos cruzaremos con el mensaje de error “Unable to handle format:…”, especialmente al intentar reproducir los formatos más nuevos. Este plugin de JMF un wrapper Java que utiliza JNI para hacer las llamadas directas al código nativo de ffmpeg.

Instalación en Linux

Vamos a instalar y configurar las diferentes partes de la solución para poder reproducir video en Linux. Quizá el post tienda a compilar todo y configurar “a mano”, es debido a que documenta la necesidad de reproducción de pautas publicitarias en un NLPOS, un flavour de Linux de Novell bastante recortado y orientado a puntos de venta.

1. Instalación de ffmpeg

Como primer punto, compilaremos e instalaremos ffmpeg a partir del código fuente. Tenemos varias opciones: hacer un checkout de SVN, hacer un GIT clone,
o bajarnos el código de la última versión estable. Para cualquier opción, contamos con lo que necesitamos aquí.

Es una buena idea instalar codecs externos para luego poder integrarlos con ffmpeg. Entre estos codecs externos tenemos a LAME para MPEG Audio Layer III,  AMR para 3GPP y xvid para los estándares MPEG-4 Simple Profile and Advanced Simple Profile.

La primer parte de este link nos muestra cómo instalar los diferentes tanto los codecs externos como ffmpeg.

Para la instalación más básica, sin codecs externos, basta con hacer un

./configure

en el directorio en donde está ubicado el código de ffmpeg, luego un

make

y finalmente, con permisos de root un

make install

En distribuciones de Linux más “modernas”  seguramente tengamos la opción de instalar ffmpeg desde repositorios de paquetes, sin la necesidad de compilarlo a mano.

2. Instalación de JMF

JMF no tiene mucha ciencia para instalarlo, simplemente bajamos el instalador de aquí y lo corremos en el directorio que queramos instalarlo. Yo lo ejecuté desde /usr/lib para que JMF quede en /usr/lib/JMF-2.1.1e/ (llamaremos ${JMF_HOME} al directorio de instalación), pero no repercute en el funcionamiento. Debemos recordar que ${JMF_HOME}/lib/jmf.jar deberá estar en el classpath de nuestra aplicación.

3. Instalación de Jffmpeg

Jffmpeg tampoco da muchas dificultades para instalarlo. Podemos bajar el JAR y el .so (o .dll) de aquí, y descomprimirlos en el directorio que nos resulte más cómodo. Lo que debemos tener en cuenta después, es que el JAR deberá estar
en el classpath de nuestra aplicación, y el .so en LD_LIBRARY_PATH, o configurado en el path de las librerías de Linux.

Llamaremos ${JFFMPEG_HOME} al directorio en donde tenemos el JAR y el .so.

4. Classpath, LD_LIBRARY_PATH, etc.

Tanto las librerías nativas como los JARs de JMF y Jffmpeg deberán estar referenciadas por nuestra aplicación para ser tenidas en cuenta.

Para los JARs basta con agregarlos a una variable de entorno que luego se referenciará en el classpath de nuestra aplicación.

Para las librerías nativas podemos agregar un archivo de extensión conf en /etc/ld.so.conf.d/ que contenga una línea para cada directorio que deba ser considerado al buscar las librerías.

La otra opción es agregar los directorios a la variable de entorno LD_LIBRARY_PATH. Esta variable contiene una lista de directorio separados por coma, la cual es utilizada por el sistema operativo para buscar librerías antes de recurrir al conjunto predeterminado de directorios.

Si no queremos definir este conjunto de variables a mano, podemos editar el archivo ~/.bashrc agregando las siguientes líneas (quizá las rutas no sean las que correspondan):

# cat ~/.bashrc

export JMF_HOME=/usr/lib/JMF-2.1.1e
export JFFMPEG_HOME=/root/jffmpeg
export CLASSPATH=$ JMF_HOME /lib/jmf.jar:$JFFMPEG_HOME/jffmpeg-1.1.0.jar:.:$CLASSPATH
export LD_LIBRARY_PATH=$ JMF_HOME /lib:$JFFMPEG_HOME:${LD_LIBRARY_PATH}
export JAVA_HOME=/usr/java/jdk1.6.0_14

5. Registro de los codecs

Para agregar los codecs de Jffmpeg en JMF utilizaremos la herramienta JMFRegistry que viene con el Java Media Framework. Podemos ejecutarlo por consola tipeando “java JMFRegistry” o desde las preferencias del JMStudio, otra herramienta de JMF que hace de Media Player.

Para cada cambio que listamos a continuación, debemos hacer clickear el botón de commit.

En la pestaña de “Mime types” registramos las siguientes extensiones:

  1. video/vob -> vob
  2. audio/ogg -> ogg

Bajo la pestaña “
Plugins” registramos los siguientes “Demultiplexers”:

  1. net.sourceforge.jffmpeg.demux.vob.VobDemux
  2. net.sourceforge.jffmpeg.demux.ogg.OggDemux

Y bajo la pestaña “Codec” registramos los siguientes codecs:

  1. net.sourceforge.jffmpeg.VideoDecoder
  2. net.sourceforge.jffmpeg.AudioDecoder

6. Parámetros de la aplicación

Como último paso, debemos recordar agregar ya sea la variable $CLASSPATH al classpath de nuestra aplicación, o cada JAR por separado (${JMF_HOME}libjmf.jar,   ${JFFMPEG_HOME}jffmpeg-1.1.0.jar).

Conclusión

Si bien no es “soplar y hacer botellas”, en Java tenemos la posibilidad de agregar contenido multimedia a nuestras aplicaciones o applets utilizando la potencialidad que nos dan los codecs implementados como código nativo al sistema operativo.

En este post vimos un ejemplo en instalación y configuración en Linux; la configuración en Windows no es demasiado diferente.

Referencias

http://jffmpeg.sourceforge.net/download.html

http://downloads.xvid.org/downloads/xvidcore-1.2.2.tar.bz2

http://java.sun.com/javase/technologies/desktop/media/jmf/2.1.1/download.html

http://www.ffmpeg.org/

http://jffmpeg.sourceforge.net/

http://www.hiteshagrawal.com/ffmpeg/installing-ffmpeg-easily-on-linux

http://www.elctech.com/articles/installing-ffmpeg-with-faac-and-x264-encoders-from-source-on-ubuntu

http://www.luniks.net/luniksnet/html/java/jtvd/doc/jmf.html

http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html