Programacion en html y css3

Manejando audio (y vídeo) con HTML5

Por Juan Antonio Jiménez Torres -4 marzo, 2016215498 Twitter Linkedin Facebook ReddIt

Pequeños experimentos para probar cómo HTML5 permite manejar audio y vídeo en el navegador, añadir subtítulos en distintos idiomas y cómo, mediante JavaScript y las nuevas WebAPIs, se puede capturar el stream del micro y de la webcam.

Índice de contenidos

1. Introducción

En el cajón de las cosas que me quedan por aprender lleva mucho tiempo dando vueltas el tema del manejo de la webcam y micrófono desde el navegador, jugar con el text to speech y voice to text. La única forma de aprender es hacer pruebas y trastear en mi propio laboratorio virtual. Este post nace fruto de esa experimentación, y por eso surge este artículo, para compartir con el lector los resultados obtenidos.

Antes de HTML5 sólo se podía utilizar audio y vídeo en el navegador mediante algún tipo de plugin. Y flash era lo más utilizado para este fin. Pero eso tenía más contras que pros: el navegador requería tener instalado el software de Adobe, que no venía de serie en el browser y que no siempre ha demostrado ser seguro a lo largo de sus distintas versiones. Al final ese plugin ha caído en desgracia y cada vez su penetración en el sector es menor.

flash_en_gg_trends

Pero a la vez que Flash iba perdiendo protagonismo, han aparecido una serie de estándares que han venido al rescate, facilitando de forma natural la manipulación de audio y vídeo en los navegadores, a través de HTML5 y las nuevas WebAPIs.

Y en eso versa este artículo que se divide en dos grandes bloques:

  • el primero, trata de ver como mostrar audio y vídeo en la web, introduciendo subtítulos en distintos idiomas, y cómo capturar el stream de la webcam y el micrófono
  • el segundo trata de reconocimiento de voz, dictado, navegación mediante comandos de voz, y la operación inversa, que sería dado un texto, la correspondiente síntesis de voz.

2. Etiqueta <audio> y <video> de HTML

HTML5 introduce dos nuevas etiquetas <audio> y <video>. Me centraré en el primero, pues es el medio para conseguir el fin, siendo el objeto principal de estudio de este artículo el reconocimiento de voz y viceversa.

Como en tantas cosas, los distintos navegadores no se ponían de acuerdo en qué formatos de audio soportar. Hoy la mayoría soportan el formato ogg o mp3, siendo lo normal que soporten ambos, por lo que es conveniente proveerlos para que el browser utilice el primero que le resulte compatible.XHTML

12345<audio controls>  <source src=»ejemplo.mp3″ type=»audio/mpeg» />  <source src=»ejemplo.ogg» type=»audio/ogg» />  <p>Your user agent does not support the HTML5 Audio element.</p></audio>

Ver ejemplo 1: Sample Audio HTML Tag

Si tienes más interés, puedes consultar la lista de los formatos soportados por los distintos navegadores.

Algunos de los atributos que soporta la etiqueta <audio> son:

  • controls, que nos permite una representación gráfica de un reproductor, con sus correspondientes controles de pausa, play, volumen y una línea de tiempo.
  • autoplay, si se desea que empiece a reproducirse cuando se haya cargado el DOM.
  • preload que puede tomar alguno de los siguientes valores [«none», «metadata», «auto»], para precargarlo. Con metadata sólo se cargarían los metadatos (info, duración del fichero, etc…)
  • loop: para que se repita una y otra vez
  • mediagroup: para agrupar y hacer listas de reproducción.

Y hay numerosos eventos y propiedades vinculados a esta etiqueta que nos permiten jugar, siendo los siguientes los más comunes.JavaScript

123456789101112131415161718192021222324252627282930var audio = document.getElementById(&apos;audio&apos;);  function play(){   audio.play(); }  function pause(){   if (audio.paused){     audio.play();   }else{     audio.pause();   } }  function stop(){   audio.pause();   audio.currentTime = 0; }  function turnUpVolume(){   if (audio.volume<0.9){     audio.volume+=0.1;   } }  function turnDownVolume(){   if (audio.volume>0.1){     audio.volume-=0.1;   } }

Ver ejemplo 2: Sample Audio Events

3. ¿Y cómo ponemos subtítulos?

Para esto tenemos la etiqueta <track>, que se puede usar en combinación tanto con la etiqueta <audio> como con la etiqueta <video>.XHTML

1234567  <audio controls>    <source src=»ejemplo.mp3″ type=»audio/mpeg» />    <track kind=»subtitles» label=»Subtítulos en español» src=»subtitles_es.vtt» srclang=»es» default />    <track kind=»subtitles» label=»English subtitles» src=»subtitles_en.vtt» srclang=»en» />    <track kind=»subtitles» label=»Deutsche Untertitel» src=»subtitles_de.vtt» srclang=»de» />    <p>Your user agent does not support the HTML5 Audio element.</p>  </audio>

Esta etiqueta se puede usar para diversas finalidades que se pueden definir en el atributo kind:

  • captions
  • chapters
  • descriptions
  • metadata
  • subtitles

Esto nos puede dar mucho juego para poner subtítulos en nuestros vídeos o audios. Lo bueno es que se puede facilitar traducciones a distintos idiomas para un mismo audio (o vídeo).

Estos ficheros utilizan un estándar denominado WebVTT que tiene un formato de texto plano muy sencillo: comienza con la palabra WEBVTT y sigue con una lista de cues. Un CUE es el mínimo grupo de información que está formado por: un identificador (opcional), por un rango de tiempo y el texto a mostrar.

Por ejemplo:XHTML

12345678910111213WEBVTT 00:00:00.000 –> 00:00:05.170Bienvenidos a este curso de seguridad web 00:00:06.010 –> 00:00:08.870En Autentia nos encanta compartir lo que… 00:00:08.920 –> 00:00:11.580…aprendemos con la comunidad 00:00:12.680 –> 00:00:14.730¡¡¡Venga. Vamos al lío!!!

El formato de este fichero es ciertamente melindroso. En https://quuz.org/webvtt/ validan si el WebVTT que estamos generando es válido, si los tiempos son secuenciales y no se solapa nada. Muy útil.

Jugando con la posibilidad de poner subtítulos, y preparando un ejemplo para esto, me he tropezado con algún que otro inconveniente:

  • crossdomain: video/audio, vtt y html deben de compartir dominio y, si no, usar CORS para remediar este problema.
  • si se usa la etiqueta <audio>, Chrome no muestra los subtítulos, ya que no tiene “espacio” donde mostrarlos en el componente del reproductor de audio. Tendríamos que leer los CUEs mediante JavaScript, que se puede, y ponerlos en un <div> fuera del reproductor de audio. Sin embargo, si cambiamos la etiqueta por <video>, nos reproduce el audio y los subtítulos.
  • Si los subtítulos aparecen desde el segundo 0 se muestran en la imagen de previsualización del vídeo (antes de darle al “play”). Así que es mejor que aparezcan unos milisegundos después.

En el siguiente ejemplo, he subtitulado el famoso discurso de Martin Luther King Jr., “I have got a dream”, para consolidar lo aprendido sobre los ficheros WebVTT.

Ver ejemplo 3: Subtitulando “I have got a dream”, de Martin Luther King

4. Controlando la webcam y el micrófono

Ya sabemos reproducir audio y vídeo en nuestras páginas y aplicaciones web pero ¿y cómo capturamos fotos, un vídeo o nuestra voz? HTML nos da acceso al micrófono y a la webcam mediante un método del objeto navigator llamado getUserMedia().

Lo primero es independizar la sintaxis del motor del navegador, ya que aún hay alguno que no tiene el método getUserMedia e implementa su propia versión con prefijo:JavaScript

1234navigator.getUserMedia = navigator.getUserMedia ||                         navigator.mozGetUserMedia ||                         navigator.webkitGetUserMedia ||                         navigator.msGetUserMedia;

Luego indicamos si queremos capturar vídeo, audio o ambas cosas. En el ejemplo para ilustrar este ejercicio, en un primer momento capturaba sonido e imagen, y posteriormente los reproducía en una página web. Esto producía el lógico e indeseable acoplamiento del sonido, al escucharse por los altavoces lo mismo que se capturaba por el micrófono.JavaScript

1234567891011121314151617181920navigator.getUserMedia({video: true, audio: false}, onSuccess, onError); function onSuccess(streamVideo) {    var videoProvider;     if (window.URL) {        videoProvider = window.URL.createObjectURL(streamVideo);    } else {        videoProvider = streamVideo;    }     myVideo.src = videoProvider;    myVideo.play();     myButton.value = «stop»;} function onError(error) {    console.log(«getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gl/rStTGz for more details.», error);}

Ver ejemplo 4: Manage the webcam and micro

Si todo ha ido bien, el navegador nos habrá pedido permiso para poder capturar el vídeo a través de la webcam. Con window.URL.createObjectURL(streamVideo) se crea un objeto de tipo Blob o File que consume recursos, que no se liberarán hasta que se cierre la página. Puedes descargarlo cuando ya no se utilice llamando a revokeObjectURL.

Nota: ambos métodos forman parte de la nueva File API del W3C, que veremos en otro próximo artículo.

Con esto hemos capturado el stream de audio y de vídeo, y se lo enchufamos al source de nuestro componente pero, de esta forma, estamos confinados a nuestra aplicación web. Una pregunta lógica sería ¿se pueden hacer más cosas con esto? ¿se puede grabar? ¿se puede enviar al servidor o a otro dispositivo?

En principio, parece que hay una especificación del W3C, aún en borrador, que propone usar el propio elemento file con el atributo accept.

Por ejemplo, para tomar una foto de la cámara y enviarla sería:XHTML

1<input type=»file» accept=»image/*;capture=camera»>

Mientras que para grabar sonido o vídeo sería:XHTML

12<input type=»file» accept=»video/*;capture=camcorder»><input type=»file» accept=»audio/*;capture=microphone»>

La especificación que se está encargando de esto es: https://dev.w3.org/2009/dap/camera/. Os recomiendo echar un vistazo a los ejemplos, donde hay uno que explica cómo se haría con AJAX.

Ya sabemos capturar el sonido en bruto del micrófono pero ¿y si lo que queremos es grabar dicho sonido en un formato comprimido en tiempo real en el navegador? Hay un proyecto muy interesante sobre este tema que podéis encontrar en:

http://audior.ec/blog/recording-mp3-using-only-html5-and-javascript-recordmp3-js/

Por un lado hacen uso de la librería recorder.js para grabar el sonido y, por otro lado, han hecho una versión en JavaScript de la librería Lame MP3 encoder, libmp3lame.js, para comprimir a MP3 en tiempo real.

Si lo que deseamos es hacer videoconferencia sobre el navegador habría que recurrir a RTCPeerConnection y RTCDataChannel, pero eso lo dejamos para un posible POST más adelante sobre la WebRTC API.

En estos últimos puntos hemos pasado rápido, de puntillas, indicando una serie de enlaces donde averiguar más información, pero sin profundizar, y es que estos experimentos tienen enjundia suficiente como para tratarlos como una entidad propia y separada.

Y ahora retomamos nuestro objetivo inicial de poder dictarle al navegador (VTT: Voice TText), darle comandos de voz y la operación inversa: síntesis de voz desde el propio texto (TTS: Text TSpeech), pero eso lo haremos ya en el siguiente artículo.

[alert type=»warning» close=»false»]Ya puedes ver la continuación de este artículo: Reconocimiento y síntesis de voz en el navegador[/alert]

Deja un comentario

Información básica sobre protección de datos Ver más

  • Responsable: Ingenio Hosting.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento:  No se ceden o comunican datos a terceros para prestar este servicio.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.