Sound Manager 2 : La mejor opción para reproductores de audio

Si hablamos de librerías bien hechas, ésta es una de ellas. Cuenta con una API completísima y una funcionalidad a prueba de balas.

Sound Manager 2 es una librería escrita en JavaScript que permite la interacción con sonidos en la web. Es el mejor amigo cuando necesitamos reproducir archivos de audio en un sitio.

Lo mejor de SM2 es que es multiplataforma y funciona tanto en web como en dispositivos móviles. Utiliza la API de audio de HTML5 en exploradores modernos y flash cuando el explorador no soporta <audio>

Otra característica importante es su peso. En la web sabemos que lo bajo en peso funciona mejor en términos de desempeño, y SM2 solo pesa 12KB. Cuenta con una API bien documentada y tiene un control total sobre los audios.

It starts out easy, but you can go down the rabbit hole if you want.

En resumen, es una librería a todo terreno y que si queremos experimentar o llevarla a proyectos reales, no nos traerá ningún problema.

Ahora, si no tienen tanta experiencia en JavaScript o si quieren utilizarla y no quieren leer toda la documentación, pueden leer el siguiente tutorial llamado…

Cómo hacer un reproductor de audio usando Sound Manager 2

Para comenzar el tutorial tenemos que ordenar nuestras ideas y espectativas con respecto a lo que queremos desarrollar. Es por eso que lo primero que hay que hacer es definir las funcionalidades que tendrá nuestro player y luego dibujar la interfaz.

Ahora, como muchos saben, para mi los tutoriales son como recetas en donde importan tanto los ingredientes como la preparación. El plato se sirve a punto y se debe probar antes de servir. Así que, partamos con esta receta:

Ingredientes

  • 1 lista de funcionalidades
  • mockups de interfaz
  • 1 plugin Sound Manager 2
  • 1 plugin jQuery
  • Una pizca de desarrollo en Javascript
  • FontAwesome para sazonar

Preparación

Lo primero que debemos hacer es definir la lista de funcionalidades que puede tener un player y elegir las que vamos a desarrollar. En nuestro ejemplo tenemos las siguientes:

  • Reproducir un mp3 ✔️
  • Botón play/pausa ✔️
  • Control de volumen ✔️
  • Botón de stop ✔️
  • Tiempo total y tiempo de progreso de la canción ✔️
  • Lista de canciones
  • Botón siguiente/anterior
  • Barra de progreso
  • Foto de la canción
  • Continuación automática

De estas funcionalidades solo elegí las primeras 5, donde prefiero hacer un player que haga sonar 1 solo mp3 en lugar de una lista, ya que es más simple y es mejor para entender el funcionamiento de SM2.

De acuerdo a esta lista se realizan los mockups, los cuales muestran la interacción del player:

tutorial_sm2_mockups

La interfaz no es muy compleja, la verdad. Con HTML y CSS se puede lograr lo siguiente:

En este ejemplo usé el tag <input type="range"> para el control de volumen, mientras que para los botones usé Font Awesome. Gracias a la magia de JSFiddle, usé SASS como preprocesador de CSS.

Con todo esto preparado comenzaremos con el desarrollo del player, para esto usaremos el script de Sound Manager directamente desde cdnjs.com: https://cdnjs.cloudflare.com/ajax/libs/soundmanager2/2.97a.20150601/script/soundmanager2-jsmin.js
Así como cargaremos jQuery, directamente desde este link: https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.min.js

La canción que usaremos será el 755 // Mixtape Vol 04 que subí hace poco a Mixcloud.

Entonces, con eso definido comenzaremos comenzaremos definiendo en head los plugins correspondientes:

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/soundmanager2/2.97a.20150601/script/soundmanager2-jsmin.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.0.0-beta1/jquery.min.js"></script>
</head>

Con esto definido, y entendiendo que la interfaz cuenta con un contenedor de id #player, iniciaremos el player y luego daremos play a nuestro mp3.

Iniciando el player

Según documentación lo primero que debemos hacer es configurar el soundManager; la idea es decirle dónde están los archivos SWF en caso de que el explorador no sea capaz de reproducir el MP3 por sí solo.

Para nuestro ejemplo no usaremos la configuración de los SWF ya que asumiremos que el explorador soporta sonido nativo. En caso de que se necesite, se debe escribir el siguiente código:

<script>
soundManager.setup({
  url: '/directorio/a/los/archivos-swf'
  onready: function(){
    console.log('sound manager cargado!');
  }
});
</script>

En estas líneas nos damos cuenta que al cargar el plugin se nos habilita la variable soundManager que contiene las funciones del plugin.

Play, Pausa, Stop

El siguiente paso es hacer la función de Play, Pausa y Stop. Para esto necesitaremos una variable is_paused, para identificar si el mp3 está en pausa. Cargaremos nuestro MP3 en el evento onready, para asegurar que nuestra configuración funcionó.

<script>
var player, is_paused;

soundManager.setup({
  onready: function(){  
    is_paused = false;
    player = soundManager.createSound({
      url: 'http://alvaroveliz.cl/uploads/2016/03/Mixtape_Vol_04.mp3'
    });
  }
});
</script>

Al botón de clase buttons-play le asignaremos la función para hacer sonar la música o detenerla, y al botón de clase buttons-stop le daremos la función para detener la música. Todo esto, usando jQuery.

<script>
var player, is_paused;

soundManager.setup({
  onready: function(){
    is_paused = true;
    player = soundManager.createSound({
      url: 'http://alvaroveliz.cl/uploads/2016/03/Mixtape_Vol_04.mp3'
    });
  }
});

$(document).ready(function(){

  // funcion play / pausa
    $('.buttons-play').on('click', function(){
    if (is_paused) {
      $('.title').html('755 // Mixtape Vol 04');
        player.play();
      is_paused = false;
      $('.buttons-play span').removeClass('fa-play');
      $('.buttons-play span').addClass('fa-pause');
    } else {
      $('.title').html('755 // Mixtape Vol 04 (pausado)');
        player.pause();
      is_paused = true;
      $('.buttons-play span').removeClass('fa-pause');
      $('.buttons-play span').addClass('fa-play');
    }
  });

  // funcion stop
  $('.buttons-stop').on('click', function(){
        player.stop();
    is_paused = true;
    $('.title').html('Ejemplo de player');
    $('.buttons-play span').removeClass('fa-pause');
    $('.buttons-play span').addClass('fa-play');
  });
});
</script>

En la función anterior, nos percatamos que si la variable is_paused utilice la función .play() y en caso contrario, la función .pause(). Además, debemos redefinir esta variable para que pueda resumirse la canción. Lo que también se cambia es la clase fa-play por fa-pause, para cambiar el botón.

Para la función detener usamos la función .stop() y nuevamente cambiamos la variable y el botón.

Adicionalmente hice que el titulo cambiara cuando la canción comenzara a sonar, usando la clase .title.

El funcionamiento del player hasta este minuto se ve de esta forma:

Progreso de canción

Para poder calcular el progreso de la canción debemos tener dos funciones: 1) que convierta los milisegundos al formato 00:00 2) una función que agregue un 0 cuando son menos de 10 segundos.

Estas funciones se deben usar en el método whileplaying de la definición del player:

<script>
var player, is_paused;

soundManager.setup({
  onready: function(){
    is_paused = true;
    player = soundManager.createSound({
      url: 'http://alvaroveliz.cl/uploads/2016/03/Mixtape_Vol_04.mp3',
      whileplaying: function(){
        pos = durationFormat(this.position);
        dur = durationFormat(this.duration);
        $('.time').html(pos.m+':'+pos.s+' / '+dur.m+':'+dur.s);
      }
    });
  }
});

function durationFormat(msecs)
{
  var secs = msecs / 1000;
  var hours = Math.floor(secs / (60 * 60));

  var divisor_for_minutes = secs % (60 * 60);
  var minutes = Math.floor(divisor_for_minutes / 60);

  var divisor_for_seconds = divisor_for_minutes % 60;
  var seconds = Math.ceil(divisor_for_seconds);

  var obj = 
  { 
    "h": intToString(hours), 
    "m": intToString(minutes), 
    "s": intToString(seconds) 
  };

  return obj;
}   

function intToString(time) 
{                
  return (parseInt(time) < 10 ? ('0' + time) : time);       
}
</script>

Acá podemos ver las dos funciones durationFormat que hace la conversión y intTostring. Ambas funciones se utilizan en el método whileplaying que detecta dos variables this.duration que corresponde al total de milisegundos del mp3 y this.position que corresponde al tiempo transcurrido.

Control de volumen

Para finalizar, implementaremos el Listener del input range usando jQuery y el método .setVolume de Sound Manager.

<script>
...

  // volumen
  $('.volume input[type=range]').on('change', function(){
    player.setVolume($(this).val());
  });
</script>

Resultado

Con todo lo anterior, más algunos arreglos de interfaz, el resultado es el siguiente:

Un player listo para ser utilizado en cualquier sitio web.

Si tienen dudas, por favor háganlas todas acá abajo y si les gustó, compártanlo.

¡Espero que les sirva!

Blog, Tutorial, Tutorial Javascript
5 minutos