getUserMedia: HTML 5 también se integra con la webcam

Uno de los motivos por los cuales se suele desechar las aplicaciones web versus aplicaciones nativas es la falta de integración con el hardware como tal 🙁 Si lo que nos preocupa es el uso de ciertas partes del dispositivo, como la webcam, estamos de suerte 😀 ya que getUserMedia API nos puede proporcionar la funcionalidad que necesitamos.

¿Qué es lo que nos ofrece?

Gracias a esta especificación seremos capaces de capturar tanto el vídeo como el audio de nuestra webcam, previa autorización del usuario. Para verlo con un ejemplo podemos ejecutar la siguiente demo:

Si pulsamos sobre el botón Start, veremos que nuestro navegador nos pedirá autorización para acceder al vídeo y el micrófono de nuestro dispositivo. En el momento que demos autorización, podremos ver directamente el contenido que la webcam está interceptando. Del mismo modo, podemos parar la solicitud y tomar una foto que será mostrada a continuación.

¿Cómo lo hacemos?

window.onload = function() {
    //Compatibility
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia;
    var canvas = document.getElementById("canvas"),
        context = canvas.getContext("2d"),
        video = document.getElementById("video"),
        btnStart = document.getElementById("btnStart"),
        btnStop = document.getElementById("btnStop"),
        btnPhoto = document.getElementById("btnPhoto"),
        videoObj = {
            video: true,
            audio: true
        };
    btnStart.addEventListener("click", function() {
        var localMediaStream;
        if (navigator.getUserMedia) {
            navigator.getUserMedia(videoObj, function(stream) {              
                video.src = (navigator.webkitGetUserMedia) ? window.webkitURL.createObjectURL(stream) : stream;
                localMediaStream = stream;
                
            }, function(error) {
                console.error("Video capture error: ", error.code);
            });
            btnStop.addEventListener("click", function() {
                localMediaStream.stop();
            });
            btnPhoto.addEventListener("click", function() {
                context.drawImage(video, 0, 0, 320, 240);
            });
        }
    });
};​​

En este ejemplo se están utilizando además dos elementos propios de HTML 5: video y canvas. Gracias a ellos podremos reproducir la salida de vídeo que estamos recuperando de la cámara y canvas lo utilizaremos para plasmar el fotograma que hemos congelado al hacer click en Take a photo.

En primer lugar, para asegurarnos la compatibilidad con los navegadores, he asignado a navigator.getUserMedia el valor del mismo o de cualquiera de los prefijos disponibles. Recuperamos todas las variables necesarias y capturamos el evento click del botón btnStart. Dentro del mismo comprobamos si navigator.getUserMedia ha conseguido la interfaz necesaria para interactuar con la cámara (lo cual significa que el navegador soporta la API) y acto seguido llamamos a la función utilizando como parámetros videoObj, el cual contiene un object literal donde le indicamos que queremos recuperar tanto el vídeo como el audio, una función donde recuperamos con éxito el stream que asociaremos al elemento vídeo para visualizar el contenido que estamos recuperando de la cámara y, por último, una función para controlar los posibles mensajes de error.

En el ejemplo además se manejan los eventos click del botón btnStop para parar la integración con la webcam y de btnPhoto donde utilizamos el elemento canvas para pintar el fotograma capturado del vídeo que estábamos reproduciendo en el momento de hacer click en el botón.

¿Por qué no estamos recuperando el audio?

Según la especificación, el audio recogido de la webcam tiene como única salida PeerConnection, lo cual espero poder abordar más adelante.

A día de hoy está implementado por Chrome y Opera pero confío en que es cuestión de tiempo que esta funcionalidad sea totalmente aceptada por el resto de navegadores 🙂

Espero que haya sido de utilidad.

Demo completa: getUserMedia API.

¡Saludos!