Sorria para a webcam
Sorria para a webcam!

Em alguns tipos de sistemas, precisamos da foto da pessoa que esta sendo cadastrada e o sistema ser capaz de acessar a webcam para tirar a foto é uma mão na roda. Com o já não tão novo HTML5 podemos fazer isso diretamente no navegador e enviar a imagem para o backend codificada em base64 com bastante facilidade.

Vamos fazer um exemplo simples, onde exibimos um preview da webcam, fazemos isso através do elemento vídeo. Teremos também um botão para tirar a foto com um elemento de imagem para exibir a imagem tirada e um formulário onde o conteúdo da imagem codificada em base64 irá ser inserido para em um elemento textarea, que normalmente seria um campo input hidden.

Veja o HTML de exemplo abaixo.

<div class="content">
    <video autoplay="true" id="webcam"></video>

    <button type="button" onclick="foto()" class="btn">Tirar foto e salvar</button>
        
    <div class="image">
        <img src="person.svg" id="foto">
    </div>
    <form method="POST" action="imagem.php">
        <textarea name="image_base64" id="base64"></textarea>
            
        <button type="submit" class="btn">Enviar Imagem</button>
    </form>
</div>

Uma vez com com o HTML temos que carregar a webcam no elemento video, fazemos isso quando todo conteúdo da página for carregado.

Primeiro recuperamos o elemento de video que será o preview da webcam. Depois verificamos se o navegador possui suporte para a captura de mídia, se sim chamamos a função getUserMedia que solicita ao usuário permissão para usar uma entrada de mídia e que produz um MediaStream.

A função getUserMedia retorna um Promise que resolve o stream de mídia solicitado, ou a promise é rejeitada se o usuário não fornece acesso a webcam ou ela não é encontrada. A função recebe um objeto especificando as configurações da midia que queremos, neste caso não precisaremos do audio então configuramos audio: false e caso o usuário esteja utilizando um smartphone podemos definir para usar a câmera frontal com video: {facingMode: 'user'}.

Uma vez resolvido o stream atribuímos ele para o atributo srcObject do elemento de video. Isso já deve fazer o elemento video reproduzir o que a webcam esta captando. Veja o código de exemplo.

document.addEventListener( 'DOMContentLoaded', function(){
    let video = document.querySelector("#webcam");
		
	if (navigator.mediaDevices.getUserMedia) {
		navigator.mediaDevices.getUserMedia({audio: false, video: {facingMode: 'user'}})
		.then( function(stream) {
			video.srcObject = stream;
		})
		.catch(function(error) {
			alert("Não foi possível iniciar a webcam.");
		});
    }
});

Agora vamos a função que tira a foto, primeiro recuperamos o elemento video. Logo após criamos um elemento canvas, nele iremos copiar a imagem corrente da webcam, para isso configuramos as dimensões do do canvas para serem as mesma do video pegando estes valores do elemento video. Em seguida pegamos o contexto 2d do canvas para desenhar nele a imagem corrente que esta sendo captada, fazemos isso através da sua função drawImage que recebe como primeiro parâmetro a origem do desenho, que será o elemento video que esta reproduzindo a webcam.

Uma vez desenhada a imagem no canvas podemos pegar dela os dados codificados em base64 através do método toDataUrl do canvas, passando o mime-type desejado. Feito isso jogamos esta informação para o src da imagem para visualizarmos a foro “batida”. Também jogamos esta informação para o value do elemento de textarea para ser enviado pelo formulário.

function foto(){
	let video = document.querySelector("#webcam");
	
	let canvas = document.createElement('canvas');
	canvas.width = video.videoWidth;
	canvas.height = video.videoHeight;
	let ctx = canvas.getContext('2d');
	
	ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
	
	let dataURI = canvas.toDataURL('image/jpeg'); 
	document.querySelector("#foto").src = dataURI;
	document.querySelector("#base64").value = dataURI;
}

Para salvar a imagem enviada que esta codificada em base64 é bastante simples. para isso basta ler do campo do formulário com a função file_get_contents e depois utilizar a função file_put_contents para escrever seu conteúdo em algum arquivo.

$image = file_get_contents($_POST['image_base64']);
file_put_contents('imagem.jpg', $image);

Para ver este exemplo funcionando você pode acessar aqui.

Para fazer o download clique aqui.

Espero que tenha ajudado, é um exemplo simples mas pode ser expandido e seus dados enviados via requisição ajax ou mesmo enviar periodicamente através de um socket para algum tipo de monitoramento, as possibilidades são muitas.

Bom era isso T++.