HTML5: Como capturar imagem da webcam com Javascript?

Para acessar a webcam, precisamos utilizar a função navigator.mediaDevices.getUserMedia. Essa função retorna uma Promise, contendo ou MediaStream. Com essa função podemos acessar o áudio ou vídeo do computador do usuário.

Obviamente, quando chamamos getUserMedia, o browser irá exibir um dialogo pedido a sobre o acesso a um dispositivo de mídia.

Nota: É importante deixar claro que getUserMedia só pode ser usado em ambientes considerado seguros. Portanto, se quiser utilizar em seu site ou aplicação web, esteja ciente que o mesmo possua SSL configurado para o domínio. Para testes, podemos usar o famoso localhost normalmente.

Para acessarmos a webcam, precisamos passar um parâmetro em getUserMedia, para informar que queremos acessar a câmera.

Veja:

navigator.mediaDevices.getUserMedia({video: true})
.then(function (mediaStream) {
    // nosso código aqui
})
.catch(function (err) {
    console.log('Não há permissões para acessar a webcam')
})

Se tudo ocorrer corretamente acima, teremos acesso à variável mediaStream. É através dela que poderemos capturar fotos da webcam.


Pré-visualização da webcam

Precisamos agora que o usuário tenha uma pré-visualização da captura da webcam. Para isso, vamos utilizar uma tag <video>.

Código:

<video id="video"></video>
navigator.mediaDevices.getUserMedia({video: true})
.then(function (mediaStream) {
    const video = document.querySelector('#video');
    video.srcObject = mediaStream;
    video.play();
})
.catch(function (err) {
    console.log('Não há permissões para acessar a webcam')
})

Capturando a imagem da webcam com a tag Canvas

O próximo passo agora é passar a imagem que vemos na webcam e transformá-la em uma imagem. Para fazer isso, precisamos capturar um frame da tag <video> acima e enviarmos para a tag <canvas>.

No nosso código abaixo, além da tag canvas, vamos adicionar também um button. Quando clicarmos nesse botão, a imagem da webcam deverá ser enviada para o canvas.

Veja:

<video id='video'></video>
<canvas id='canvas'></canvas>
<button id='capture'>Capturar</button>

navigator.mediaDevices.getUserMedia({video: true}).then(function (mediaStream) {
    const video = document.querySelector('#video');
    video.srcObject = mediaStream;
    video.play();
});

document.querySelector('#capture').addEventListener('click', function (e) {
    var canvas = document.querySelector("#canvas");  
    canvas.height = video.videoHeight;
    canvas.width = video.videoWidth;
    var context = canvas.getContext('2d');
    context.drawImage(video, 0, 0)
})

Explicando o código

No código acima, primeiro definimos o tamanho do canvas para ficar exatamente do mesmo tamanho do vídeo. Em seguida, utilizamos context para desenhar a imagem capturada do vídeo. Toda vez que button#capture é clicado, o frame específico da da webcam será aplicado ao canvas


Convertendo o Canvas para Imagem

Para você ter acesso à imagem do canvas, basta utilizar os métodos Canvas.toBlob ou Canvas.toDataURL. A primeira converte o desenho do <canvas> em um Blob. Já a segunda, converte para um Data URI.

No nosso caso, vamos usar toBlob. Isso porque usaremos o mesmo para fazer o upoad da imagem.

Exemplo de upload

Se quisermos fazer o upload da imagem capturada pela webcam, podemos simplesmente usar a função toBlob e adicionar o Blob retornado em um FormData.

O código é bem simples.

<button id="upload">Upload</button>
document.querySelector('#upload').addEventListener('click', function (e) {
    var canvas = document.querySelector("#canvas");

    canvas.toBlob(function (blob) {

        var form = new FormData();
        form.append('image', blob, 'webcam.jpg');

        var xhr = new XMLHttpRequest();
        xhr.open('POST', '/upload', true);
        xhr.onload = function(e) {
            // upload concluído  
        };

        xhr.send(form);  

    }, 'image/jpeg');
})</code></pre>

NOTA: Observe que no nosso exemplo, utilizamos no segundo parâmetro de toBlob o valor image/jpeg. Isso porque preferencialmente preferi converter o resultado do canvas para JPEG. Caso queira usar outro formato, é possível informar o MIME desejado, como image/png e afins.