martes, 22 de febrero de 2011

Reproducir un archivo MP3 en Java usando JLayer



Puede que queramos añadir música o algún tipo de efecto sonoro a alguna aplicación que estemos programando. Hoy explicaré como reproducir un archivo MP3 desde Java.

Para ello vamos a utilizar la librería JLayer, que es capaz de decodificar, convertir y reproducir archivos MP3 en tiempo real. Esta librería se puede encontrar en http://www.javazoom.net/javalayer/sources.html . Debemos descargar y descomprimir el archivo comprimido (zip o tar.gz) para obtener el archivo jl1.0.jar (podemos descargarnos alguna versión más moderna si existiese), que es el que nos interesa.

Hay que incluir ese archivo jar en nuestro proyecto: si utilizamos el IDE Eclipse lo haremos pinchando con el botón derecho sobre la carpeta del proyecto; pinchamos en Propiedades; opción "Java Build Path"; pestaña Librerías; finalmente pulsamos en "Add External JAR" y seleccionamos el archivo jl1.0.jar .

A nosotros nos interesa el paquete "player", que es el que se encarga de la reproducción (podemos encontrar la documentación de su API aquí). Concretamente utilizaremos la clase "Player" (documentación aquí).

El código


A continuación muestro una aplicación muy simple en el que se reproduce un archivo MP3 que se encuentra en mi disco duro (también se pueden reproducir archivos MP3 alojados en la web). Lo importante es la línea de código en la que se llama al constructor de la clase Player (con un objeto FileInputStream como argumento) y la línea en la que se llama al método "play" del objeto Player.


import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;

public class Principal {

    public static void main(String[] args) {

        try {
            FileInputStream fis;
            Player player;
            fis = new FileInputStream(
                    "D:\\Users\\Public\\Music\\Sample Music\\Sleep Away.mp3");
            BufferedInputStream bis = new BufferedInputStream(fis);

            player = new Player(bis); // Llamada a constructor de la clase Player
            player.play();          // Llamada al método play
        } catch (JavaLayerException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

    }

}



Cualquier duda o consulta que surja podeis ponerla en los comentarios.




55 Comentarios:

Anónimo dijo...

Muchas gracias bro, me funciono todo :D

Felipe Martínez D. dijo...

Me alegro de que funcione.

Saludos y gracias por comentar.

Diego dijo...

Hola Felipe, funciona todo perfecto, pero es una mierda que la clase Player sólo tenga el método play() , se puede implementar en swing con el paquete javazoom.jl.player.PlayerApplet ? , porque por lo que ví, esta sí tiene métodos como stop, getFileName etc..

Saludos desde Perú.
Diego

Anónimo dijo...

como puedo obtener los samples de un archivo mp3. como puedo navergar por su contenido para comparar con otro archivo mp3. Mi intencion es comparar dos archivos mp3

Felipe Martínez D. dijo...

Hola.

Diego, tienes razón, la clase Player es muy limitada funcionalmente pero cuando hice este artículo no buscaba nada más, simplemente reproducir un archivo MP3 desde mi aplicación Java. Si tu necesitas más funcionalidades como iniciar o parar la reproducción, la clase PlayerApplet te lo permite, puedes hacer uso de ella.

Para el último comentario: no entiendo bien lo que quieres conseguir. Explícame qué entiendes por comparar dos archivos MP3 e intentaré ayudarte.

Saludos a los dos.

Anónimo dijo...

esta muy bien el codigo pero tengo una pregunta como implementaria eso en un applet?? si me podrias ayudar te lo agradeceria

Felipe Martínez D. dijo...

Hola.

He encontrado un ejemplo que seguro que te vendrá muy bien. Está aquí:
http://www.mkyong.com/applet/how-to-play-mp3-file-in-applet-jmf/

La librería que utiliza para reproducir el archivo MP3 es javax.media .

Espero que te sirva. Cualquier duda que te surja, puedes planteármela.

Saludos.

infinito84 dijo...

Esta librería está uff!!! muchas gracias....
Para el amigo que quiere comparar 2 mp3 bueno eso ya es un trabajo arduo en el que debe utilizar inteligencia artificial o algoritmos complejos.. algunos programas traen eso incorporado pero pues para manejarlo desde java yo creería que toca hacer un autoimplementación... y pues para los que quieren hacer controles.. es solo de crear una clase con Threads y utilizar el método close y listo sale... hay tienen su control...

Felipe Martínez D. dijo...

Gracias infinito por tus aportaciones.

Saludos.

Patofet dijo...

En la parte que pones:
fis = new FileInputStream("D:\\Users\\Public\\Music\\Sample Music\\Sleep Away.mp3");
siento decirtelo pero es una guarrada muy grande XD, lo que busco es que me reproduzca un archivo que esta al lado del .class pero no consigo que me lo coja ¿sabes como?
He probado todo esto:
fis = new FileInputStream(".\\HAAX.mp3");
fis = new FileInputStream("\\HAAX.mp3");
fis = new FileInputStream("HAAX.mp3");
fis = new FileInputStream("/HAAX.mp3");
pero no me lo pilla, lo que quiero conseguir es que al pulsar un botón me reproduzca HAAX.mp3 pero claro que ese estee al lado de la .class para luego poder hacer un export a un .jar y que siga funcionando ¿tienes alguna idea?¿es demasiado complicado?

Felipe Martínez D. dijo...

Hola Patofet.

Lo que quieres hacer se puede conserguir mediante getClass().getResource(path). Ésto permite cargar recursos apartir del classpath, no desde la ruta del archivo. Mírate este ejemplo:

http://www.devx.com/tips/Tip/5697

Saludos.

azua564 dijo...

esta bien y todo pero me marca error en
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;
Player player;
player = new Player(bis);
} catch (JavaLayerException e)
no llevo mucho tiempo programando y realmente no se por que ayudame por fabor

Felipe Martínez D. dijo...

Hola azua564.

Probablemente no estés importando los paquetes necesarios. Sigue los pasos que se detallan en este post, en concreto la parte "Para ello vamos a utilizar la librería JLayer, que es capaz de decodificar ..."

Espero que te sirva.

Saludos.

azua564 dijo...

si ya me salio geracias

Felipe Martínez D. dijo...

De acuerdo, gracias a tí por comentar.

Saludos.

Andres Fernandez dijo...

Y si quieres importar varias canciones a alguna clase de "playlist"? y si quieres pausar? como se usaria u thead para la reproduccionn unicamente y todos estos controles?

Felipe Martínez D. dijo...

Hola Andres.

Buena pregunta, no me la había planteado.

He encontrado un ejemplo en el que se implementa una playlist. Lo hace mediante hilos y utiliza una lista que contiene los nombres de las canciones. Aquí está, espero que te sirva:

http://grepcode.com/file/repo1.maven.org/maven2/de.huxhorn.sulky/de.huxhorn.sulky.sounds-impl-jlayer/0.9.11/de/huxhorn/sulky/sounds/jlayer/JLayerSounds.java#JLayerSounds


Saludos.

Unknown dijo...

disculpen, alguien sabe como obtener el tiempo completo de reproducción de un audio, pero sin que se haya reproducido aun, es que deseo crear un JProgressBar pero para eso necesito el porcentaje de reproducción para que la barra se llene justo cuando acabe de reproducir

Unknown dijo...

a lo olvidaba pero usando la libreria de JLayer

Felipe Martínez D. dijo...

Hola Víctor.

Puedes utilizar la librería MP3SPI ( http://www.javazoom.net/mp3spi/mp3spi.html ) que está basada en JLayer y programada por los creadores de JLayer. Con el siguiente código podrás obtener la duración del archivo:

--------------------------------------------------------
File file = new File("filename.mp3");
AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(file);
Map properties = baseFileFormat.properties();
Long duration = (Long) properties.get("duration");
--------------------------------------------------------

Fuente:
http://stackoverflow.com/questions/3140992/read-out-time-length-duration-of-an-mp3-song-in-java


Saludos.

Anónimo dijo...

La verdad me sorprendí xq me funciono de una!
Y pues declarando las excepciones en el main el código es muy poco!
Ahora bien, es verdad que no tiene stop(),
me interesaría o bien saber como hacer para usar jl.player.PlayerApplet o si me puedes hechar una mano para adaptarla a una app en swing, tal ves con JMF pero no se si solo instalando queda pronta...
Como sea Gracias!!!
jorge

Felipe Martínez D. dijo...

Hola Jorge.

Puedes probar el ejemplo que cité anteriormente: http://www.mkyong.com/applet/how-to-play-mp3-file-in-applet-jmf/. Es un applet, por tanto hay que incrustarlo en una página web, pero es muy sencillo: en el apartado "Create a HTML" de ese mismo tutorial explica cómo hacerlo. Si estás trabajando con Eclipse se puede ver el resultado sin necesidad de crear un archivo html, puedes mirar este tutorial en el que se explica cómo hacerlo: http://www.roseindia.net/eclipse/applet-eclipse.shtml .

Si te surgen dudas, coméntamelas.

Un saludo.

Anónimo dijo...

Gracias x la respuesta Felipe, te cuento que al final logré encontrar la librería que nesecitaba, y es BasicPlayer 3.0 también de javazoom.
SDi no0 la conoces t6e cuento que es re completa, basada en jLayer y tritonus, implementa Listeners
que permiten obtener datos como duración, formato, etc.
Además se puede añadir un controlador para:
pause();
start();
stop();
seek();
setGain(); //volumen
setPan();// balance

En fin, la cosa es que logré hacer un reproductor mp3 digno de ser llamado así, con una GUI en swing, e implementando una clase que me encontré x allí que muestra un analizador gráfico de espectro de audio en tiempo real (tipo winamp).

También he logrado crear listas de reproducción y almacenarlas entre otras funciones que le he puesto.

Bien, ahora mi duda surge de lo siguiente, me gustaría poder agregarle la opción de equalización, se que usando MP3SPI:
(http://www.javazoom.net/mp3spi/sources.html)

se puede, pero no se como hacer ya que yo los mp3 los reproduzco en en el basicplayer como files, no como FileStream...

Me gustaría que me dieras una mano, solo nesecito saber como puedo mezclar eso de MP3SPI (?) a mi reproductor (no quiero volver a hacerlo desde 0!).

Gracias de nuevo, tu blog ha sido un buen punto de partida para mi proyecto, si quisieras verlo te puedo enviar un .jar de prueba.


Jorge


jorge_dan03@hotmail.com

Felipe Martínez D. dijo...

Hola de nuevo Jorge.

No conocía BasicPlayer y por lo que me cuentas, tiene muy buena pinta y en general todo tu proyecto. Acerca de lo de añadir la ecualización, no he trabajado con la librería MP3SPI y mis conocimientos en este tema son muy limitados. Si tienes alguna duda referente a la programación de tu proyecto y de Java en concreto, estaré encantado de poder ayudarte.

Me encantaría ver tu proyecto cuando esté terminado.

Saludos.

Anónimo dijo...

Hola de nuevo! Al final pude encontrar como equalizar el sonido, era mas fácil de lo q pensaba!
Aún no está terminado pero lefalta poco, le he agregado entre otras tantas cosas un editor de etiquetas ID3 (el cual aún no funciona 100% bien), y 10 vias de ecualización, déjame aprolijarla un poco mas y te mando el instalador para que la pruebes (tuve que crearle un instalador x el tema de la persistencia de datos en archivos txt, listas, opciones de configuración Etc.).
Pero en breve ya lo saco a la luz que hace ya un rato que lo vengo haciendo y no he parado de agregarle chucherias, ja!
Vuelvo a agradecrte x haberme animado con el proyecto, en breve tendrás noticias.

Felipe Martínez D. dijo...

Hola.

Al final te va a quedar un reproductor muy completo! Como te dije, cuando lo tengas terminado me encantaría verlo, porque por lo que me cuentas, puede ser un proyecto muy interesante.

Un saludo y hasta pronto.

AdriAnna dijo...

hola!!! ice todo lo k me dijiste pero yo tengo k hacer correr esto en Ready to program y la clase JLayer no ce donde uvicarla en el programa asi k no corre por no tener la clase porfa me puedes ayudar T.T
pork me sale error en
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player; y por ende en Player
muchas gracias

Felipe Martínez D. dijo...

Hola AdriAnna.

Debes de importar las librerías en tu proyecto. Al principio de este post indico cómo descargarlas e incluirlas en el proyecto.

Saludos.

Unknown dijo...

hola ya descarge las librerias pero me sigue marcado k la libreria java.zoom no exites me podrian decir el por que?

gracias.

Felipe Martínez D. dijo...

Hola Hans.

Una vez que descargas las librerías debes de importarlas al proyecto, tal y como explico en la parte "Hay que incluir ese archivo jar en nuestro proyecto: ...".

Si sigues teniendo errores, coméntamelo e intentaré ayudarte.

Saludos.

Unknown dijo...

Muchisimas Gracias Me Sirvio Mucho Para Mi Proyecto
MilGracias

Felipe Martínez D. dijo...

Me alegro de que te sirviera. Saludos.

Anónimo dijo...

estoy trabajando en netbeans como agregar el archivo .jar

Felipe Martínez D. dijo...

Hola.

No trabajo con Netbeans, pero en este enlace se explica como hacerlo: http://jsumon.wordpress.com/2009/11/24/adding-external-jar-or-library-to-netbeans-java-project/

Si tienes dudas, pregúntame.

Saludos.

Unknown dijo...

oye pero como creas el constructor play??

Felipe Martínez D. dijo...

Hola rammstein haifisch.

¿A qué constructor te refieres?.

Saludos.

Anónimo dijo...

Esta muy bueno, ya me sirve, pero cuando reproduce el archivo mp3, el Frame que tenia con fondo me lo deja en blanco, solo reproduce

Felipe Martínez D. dijo...

Me alegro de que te sirviera. Si quieres que te ayude con lo del frame, muéstrame algo de tu código.

Saludos.

Unknown dijo...

Muchas Gracias, ya pude solucionarlo, pero te agradezco, me sirvio muchisimo

Felipe Martínez D. dijo...

Me alegro!. Un saludo.

Anónimo dijo...

¿EL codigo funciona tambien en un Applet?

Felipe Martínez D. dijo...

Hola.

Yo creo que sí. Si encuentras alguna dificultad a la hora de implementarlo en un applet, dímelo y te intentaré ayudar.

Saludos cordiales.

Unknown dijo...

Hola, al parecer a todos les funciona muy bn, yo tengo error en la linea donde pongo...

fis = new FileInputStream("D:\Borre's Account\Mis documentos\Mi música\MUSIk\Zedd - Find You - [Lyric Video] ft. Matthew Koma & Miriam Bryant.mp3");
BufferedInputStream bis = new BufferedInputStream(fis);

Felipe Martínez D. dijo...

Hola Josue de Jesús.

Creo que tu problema está en la parte donde se indica el nombre del archivo de audio: "D:\Borre's Account\Mis documentos\Mi música\MUSIk\Zedd - Find You - [Lyric Video] ft. Matthew Koma & Miriam Bryant.mp3"

Sustituye "\" por "\\", igual que hago yo en el ejemplo. También intenta no utilizar caracteres "raros" como &, [, ] o ' .

Si sigue apareciéndote el error, puedes indicarme exactamente el mensaje de dicho error e intentaré ayudarte.

Saludos cordiales.

Unknown dijo...

Buenas Tardes, ejecute el código inicial y funciono perfectamente, lo que necesito es que pueda pausar la reproducción y continuar...

Felipe Martínez D. dijo...

Hola Roosevel.

La clase Player es muy limitada funcionalmente pero cuando hice este artículo no buscaba nada más, simplemente reproducir un archivo MP3 desde mi aplicación Java. Si tu necesitas más funcionalidades como iniciar o parar la reproducción, la clase PlayerApplet te lo permite, puedes hacer uso de ella.

Saludos.

LuisRivera dijo...

llenas de orgullo a tu nación, funciona perfectamente, gracias por el aporte

Felipe Martínez D. dijo...

Hola José Luis.

Gracias a tí por comentar.

Un saludo.

Unknown dijo...

Hola, me sirvió y todo, pero tengo un problema, veras introduci el código a un botón para que el archivo ser reprodujera, pero al momento de presionar el botón, ninguno de los otros botones me funcionan y tengo otra opción que cerrarlo y abrirlo de nuevo, como soluciono esto?

Felipe Martínez D. dijo...

Hola.

Necesito ver tu código para poder ayudarte. ¿Qué botones tienes en tu aplicación y para qué se utilizan?.

Saludos.

Anónimo dijo...

muchas gracias, todo funciona perfecto

Felipe Martínez D. dijo...

Gracias a tí por comentar. Un saludo.

Anónimo dijo...

hola como podria mandar a llamar a al archivo.mp3 desde el paquete y reproducirlo. me esta dando fallos ya que el archivo tipo File es para la musica desde el paquete y el jlayer me solicita el FileInputStream ayuda, acabo de empezar en esto del manejo de archivos

Felipe Martínez D. dijo...

Hola.

Muestra tu código y el error completo que te aparece.

Saludos.

Unknown dijo...

Como podria hacer para reprducir una cancion automaticamente despues de que termine la anterior? javazoom

Publicar un comentario

Felinfo: Java, Linux, Virtualización. Open Source.  ©Template Blogger Green by Dicas Blogger .

TOPO