Sonido Básico con JavaScript

¡Saludos visitante! si deseas comentar o hacer una pregunta sobre este post por favor dirígete a la nueva dirección en http://variabletecnica.com.ve. La página que estás leyendo dejará de estar disponible el 15/11/2015. Gracias, y disculpa las molestias 🙂 Estos últimos años los navegadores Web han hecho un notable esfuerzo por implementar el HTML siguiendo las…


¡Saludos visitante! si deseas comentar o hacer una pregunta sobre este post por favor dirígete a la nueva dirección en http://variabletecnica.com.ve. La página que estás leyendo dejará de estar disponible el 15/11/2015. Gracias, y disculpa las molestias 🙂

Estos últimos años los navegadores Web han hecho un notable esfuerzo por implementar el HTML siguiendo las recomendaciones de la W3C… Personalmente no creo que ellos tengan las mejores respuestas a todo (¿alguien dijo modelo de caja anti-intuitivo?) pero el hecho de que los desarrolladores de navegadores estén trabajando bajo un mismo estándar nos ha facilitado a los diseñadores y desarrolladores la tarea de crear páginas y aplicaciones Web coherentes y simples, sustituyendo los viejos hacks por las especificaciones de HTML5.

Pero ya entrando en materia, ¿la etiqueta <BGSOUND> te suena? ¿no?, pues a mí si, me recuerda aquellas viejas Webs que al abrirlas tocaba la música favorita del dueño de la página, como si a mi realmente me gustara… en fin, eso quedó atrás. Con la nueva API provista por HTML5 contamos con un mayor control sobre el sonido, hasta el punto en que podemos programar complejos juegos con sonido de fondo y efectos especiales usando solo JavaScript.

En este artículo vamos a ver un ejemplo muy simple de lo que se puede hacer con el nuevo elemento Audio de HTML5.

Woof?

Si estás programando una aplicación Javascript que requiera efectos de sonido (por favor: que realmente lo requiera) o algún juego con disparos o sonidos cortos, tu primera tarea será precargar los sonidos (como cuando hacemos precarga de imágenes) y «sonarlos» cuando corresponda.

Para la precarga, se debe crear un objeto Audio, asignarle la ruta a tu archivo de sonido y detectar el momento en que esté cargado y listo para sonar. Veamos el ejemplo:

//Disponible en: http://es.wikipedia.org/wiki/Archivo:Sound-of-dog.ogg
var rutaLadrido = 'http://upload.wikimedia.org/wikipedia/commons/c/ce/Sound-of-dog.ogg';

//Creamos el elemento Audio
var sonido = new Audio();
//Para el ejemplo usaremos una console, la veremos en un momento
var consola = document.getElementById('consola');

//Primer evento: el audio puede comenzar, pero tal vez se 
//detenga antes de terminar
sonido.addEventListener('canplay', function () {
    consola.innerHTML += '* &lt;strong&gt;canplay&lt;/strong&gt;: ' +
        'El audio puede iniciar, pero podría requerir buffering...&lt;br/&gt;';
}, false);

//Segundo evento: el audio puede comenzar sin interrumpirse
sonido.addEventListener('canplaythrough', function () {
    consola.innerHTML += '* &lt;strong&gt;canplaythrough&lt;/strong&gt;: ' +
        'El audio puede iniciar sin interrupciones...&lt;br/&gt;';
}, false);

//Tercer evento: El audio ya comenzó
sonido.addEventListener('play', function () {
    consola.innerHTML += '* &lt;strong&gt;play&lt;/strong&gt;: ' +
        '¡El audio acaba de iniciar!&lt;br/&gt;';
}, false);

//Cuarto evento: el audio acaba de terminar 
sonido.addEventListener('ended', function () {
    consola.innerHTML += '* &lt;strong&gt;ended&lt;/strong&gt;: ' +
        '¡El audio acaba de terminar!&lt;br/&gt;';
}, false);

//La ruta la asignamos después de los eventos para
//asegurarnos de que se disparen en el momento justo
sonido.src = rutaLadrido;

//Esperamos a que el usuario presione el botón
document.getElementById('iniciar').addEventListener('click', function () {
    sonido.play();
}, false);

Básicamente lo que hacemos es crear el elemento Audio, asignarle la ruta al archivo de sonido, y ejecutar el método play(); bastante simple, ¿no? Si quieres probar el código anterior agrégalo a la siguiente plantilla (o prueba directamente este jsFiddle):

&lt;!DOCTYPE HTML&gt;
&lt;html lang=&quot;es&quot;&gt;
    &lt;head&gt;
        &lt;meta charset=&quot;utf-8&quot;&gt;
        &lt;title&gt;Ejemplo básico de sonido&lt;/title&gt;
        
        &lt;script type=&quot;text/javascript&quot;&gt;
          window.addEventListener('DOMContentLoaded', 
            function(){
              //CODIGO AQUÍ
            }, false);
           
        &lt;/script&gt;
        
        &lt;style type=&quot;text/css&quot;&gt;
          #consola{
            border: 1px solid;
            width: 90%;
            height: 100px;
            overflow-y: scroll;
            margin: 5px;
            background-color: #FFD0A0;
          }
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;h1&gt;Ejemplo básico de sonido con javascript&lt;/h1&gt;
        &lt;br/&gt; 
        &lt;div id=&quot;consola&quot;&gt;&lt;/div&gt;
        &lt;input type=&quot;button&quot; id=&quot;iniciar&quot; value=&quot;Iniciar&quot; /&gt;
    &lt;/body&gt;
&lt;/html&gt;

Bien, ya sabemos como precargar un archivo de audio, y como ejecutar el sonido. Pero, ¿para qué sirven los eventos?

Eventos del elemento Audio

Al abrir la página con el código anterior (o el jsfiddle de ejemplo) verás que los primeros dos eventos se disparan al cargar la página, o para ser exactos, poco después de asignar la ruta el archivo de sonido a nuestro objeto sonido: el archivo de sonido se ha precargado.

El primero de estos dos eventos, canplay, indica el momento en que el audio puede iniciar; esto es, el momento a partir del cual puedes usar el método play() y el sonido comenzará inmediatamente.

Supongo que habrás visto algún videos HD en YouTube, si es así sabrás que ocasionalmente el video puede detenerse y te hará esperar hasta que llene el buffer antes de continuar. Esto mismo puede ocurrir con el audio, especialmente si la conexión a Internet es lenta o el archivo muy pesado. Por esta razón contamos con el evento canplaythrough, el cual nos indica el momento a partir del cual podemos usar el método play() con «poco riesgo» de que el sonido requiera buffering. Así es, dije «poco riesgo»: el navegador hará una estimación del tiempo que tomará descargar el archivo, considerando la velocidad de descarga actual (o promedio), y el peso y duración del archivo; y por supuesto, por ser una estimación, es posible que el evetno se dispare un poco antes o después del momento en que debería hacerlo. Este evento te servirá, por ejemplo, para determinar el momento en que todos los sonidos ya han sido precargados y están disponibles para que tu aplicación los utilice.

El evento play, que no debe confundirse con el método play(), te indicará el momento en que el sonido comenzó a emitirse. ¿Y para qué sirve eso?, bueno, tiene varios usos. Por ejemplo, cuando tu elemento audio es una etiqueta en el HTML y tiene establecido el atributo autoplay, tendrás que usar el evento play para determinar el momento en que empiece el sonido. Otra posibilidad es que uses el mismo elemento Audio en diferentes partes del código, y necesites un punto centralizado para saber cuando el audio comenzó a sonar.

El evento ended es un poco problemático, al menos al momento de escribir este artículo. Este evento, como su nombre lo indica, se dispara justo después de que el sonido termina. Sin embargo, en Chrome v28 para linux (probado en Ubuntu 12.4) hay un bug que impide que el evento ended se dispare al terminar el sonido (más informacioń en este hilo).

El elemento Audio tiene muchos otros eventos disponibles. Para mayor información, aquí tienes una lista completa de los eventos «oficiales»: http://www.w3.org/wiki/HTML/Elements/audio#Media_Events

¿Porqué mi archivo musica.wav no se oye?

Este es un tema interesante y complicado: soporte de codecs. Para simplificar el tema, el formato WebM (que es un contenedor para los codecs de video VP8 y de audio Vorbis) tiene muy buen soporte, aunque en IE9 se debe instalar por separado; ogg (que es un contenedor para los codecs de video Theora y audio Vorbis) es soportado por Chrome, Gekko (Firefox, thunderbird…) y Android; el formato MP4 (con los codecs de video H.264 y de audio AAC o MP3) es soportado por IE, safary y Chrome, y pronto lo estará en Firefox. Más información sobre los formatos de audio en la MDN y Android Developers.

Como puedes ver, a la fecha no hay ningún formato «confiable», ya que diferentes navegadores soportan diferentes formatos y codecs. Una posible estrategia para utilizar el formato apropiado consiste en crear el audio en dos o tres formatos (la W3C propone ogg y mp4) y cargar el formato para el cual el navegador tenga soporte. Esto se hace mediante la función canPlayType (detalles aquí):

  var sonido = new Audio();
  var permiteOgg = sonido.canPlayType('audio/ogg');
  var permiteMp4 = sonido.canPlayType('audio/mp4');
  if ( permiteOgg===&quot;maybe&quot; || permiteOgg === &quot;probably&quot; ) {
    sonido.src = 'archivo.ogg';
  }else if (permiteMp4===&quot;maybe&quot; || permiteMp4 === &quot;probably&quot; ) {
    sonido.src = 'archivo.mp4';
  }else{
    //Otro intento (¿o desactivar el sonido?) :(
    sonido.src = 'archivo.mp3';
  }

Sería ideal si el valor devuelto por la función canPlayType fuera de tipo lógico; pero no, el valor devuelto es una cadena con los valores "probably" (el formato/codec indicado es casi seguro soportado), "maybe" (el formato/codec indicado podría ser soportado), y uno de los valores "no", "" o null (estos tres significan no soportado).

Este artículo fue apenas una visión general de lo que se puede hacer con sonido en Javascript. Si tienes un poco de tiempo libre podrías programar un reproductor de música completo, permitir que el usuario seleccione la música desde un listado o que suba propios archivos de música, implementar toda la botonera de un reproductor, son sus botones para pausa, volumen, velocidad, e incluso hacer mezclas y aplicar efectos. Bueno, sería mucho trabajo, tal vez en otro artículo 🙂

Derecho de uso

Los contenidos generados por el autor de este artículo (explicaciones, código fuente, y archivos adjuntos creados por el autor) están disponibles bajo licencia CC BY-SA 3.0, y pueden ser usados, derivados y compartidos bajo los términos indicados en la misma. Los contenidos no generados por el autor de este artículo son propiedad de sus respectivos dueños y están regidos por las licencias que estos hayan dispuesto.

Cita del día

Music can change the world because it can change people.
Bono (Paul David Hewson)

,

4 respuestas a “Sonido Básico con JavaScript”

  1. Gracias, muy buena información. Quisiera saber si me pudieras ayudar al recomendarme algún sitio donde pueda encontrar más documentación acerca del elemento Audio() de javascript, ya que quisiera saber sus métodos, como el volumen, pausa, etcétera, ya que solo encontré lo del «loop». Muchas gracias. Bueno otra duda y comentario… lo estuve probando en ie8 y no funciona sabes de algún otro elemento que sea compatible? Gracias.!

Soluciones claras y simples



Ing. Industrial, dedicado a la programación en ASP.NET+VB, SQL y Javascript+AJAX; y un poco de Android, Kotling, y Unity 🙂
Valencia, Venezuela



¿QUIERES APOYARME?

¿Te ha sido de ayuda alguno de mis artículos? Generar contenido técnico requiere de tiempo y esfuerzo. Con tu colaboración me puedes ayudar a mantener mi blog activo y actualizado. Si quieres y puedes apoyarme has clic aquí:

https://paypal.me/roimergarcia


ENTRADAS RECIENTES