Capturas de pantalla con javascript y HTML5

JavaScript Webcam Capture

JavaScript Webcam Capture

Este es un mini howto de como activar la cámara de tu computadora para tomar capturas de imágenes (screenshost).

Debo aclarar que para que el código funcione se debe de estar utilizando la IP 127.0.0.1 o su alias localhost y si en tu caso tienes dominios virtuales o estás listo para enviar a producción, será necesario que tengas un certificado de seguridad para tu sitio. Esto es debido a que el api de javascript restringe el uso de los dispositivos por razones de seguridad, entonces solamente se puede utilizar en localhost o a través de un dominio con un certificado de seguridad.

Entonces empecemos, lo primero será agregar al código html 2 etiquetas, que serán la primera para embeber el video y se utiliza para poner el buffer de la cámara a través de javascript y la segunda etiqueta es canvas, la cual usaremos para poner la imagen tomada a través del video.

<html>
 <head>
  <title>Javascript + Video + Canvas = Screenshot</title>
 </head>
 <body>
  <video id="video" width="640" height="480" autoplay></video>
  <hr>
  <button id="tomar">Capturar</button>
  <button id="detener">Detener</button>
  <hr>
  <canvas id="canvas" width="640" height="480"></canvas>
  <hr>
  <textarea id="contenido" style="width:100%" cols="10"></textarea>
 </body>
</html>

Lo siguiente es el código para hacer funcionar nuestra aplicación de captura de video, al iniciarse la aplicación saldrá una alerta en la parte superior del navegador (al menos Chrome) donde se nos pregunta si o no deseamos dar acceso para utilizar el dispositivo de video. Si lo aceptan deberían ver casi inmediatamente el video el tiempo real y en caso de no aceptarlo, simplemente no verán nada en el tag de video y para remover esa preferencia, deberán acceder a la configuración de sitios de su navegador.

window.addEventListener("DOMContentLoaded", function() {
	var video = document.getElementById('video');
	var localStream = null;
	var errBack = function(e) {
		console.log('Opps.. no se puede utilizar la cámara', e);
	};
 
	// Solicitar acceso a la cámara
	if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
		navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
			video.src = window.URL.createObjectURL(stream);
			video.play();
		});
	}
	else if(navigator.getUserMedia) { // Standard
		navigator.getUserMedia({ video: true }, function(stream) {
			video.src = stream;
			video.play();
			localStream = stream;
		}, errBack);
	} else if(navigator.webkitGetUserMedia) { // WebKit-prefixed
		navigator.webkitGetUserMedia({ video: true }, function(stream){
			video.src = window.URL.createObjectURL(stream);
			video.play();
			localStream = stream;
		}, errBack);
	} else if(navigator.mozGetUserMedia) { // Mozilla-prefixed
		navigator.mozGetUserMedia({ video: true }, function(stream){
			video.src = window.URL.createObjectURL(stream);
			video.play();
			localStream = stream;
		}, errBack);
	}
}, false);

Hasta este momento lo que se ha logrado es poner el buffer de video dentro de la etiqueta video (valga la redundancia redundante :D), y eso se logra a través del método navigator.mediaDevices.getUserMedia que es el método estándard.

Lo siguiente sería utilizar la etiqueta canvas para dejar un screenshot del video y eso sería igualmente sencillo con el siguiente código.

window.addEventListener("DOMContentLoaded", function() {
	var video = document.getElementById('video');
	var localStream = null;
	var canvas = document.getElementById('canvas');
	var context = canvas.getContext('2d');
	var errBack = function(e) {
		console.log('Opps.. no se puede utilizar la cámara', e);
	};
 
	// Solicitar acceso a la cámara
	if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
		navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
			video.src = window.URL.createObjectURL(stream);
			video.play();
		});
	}
	else if(navigator.getUserMedia) { // Standard
		navigator.getUserMedia({ video: true }, function(stream) {
			video.src = stream;
			video.play();
			localStream = stream;
		}, errBack);
	} else if(navigator.webkitGetUserMedia) { // WebKit-prefixed
		navigator.webkitGetUserMedia({ video: true }, function(stream){
			video.src = window.URL.createObjectURL(stream);
			video.play();
			localStream = stream;
		}, errBack);
	} else if(navigator.mozGetUserMedia) { // Mozilla-prefixed
		navigator.mozGetUserMedia({ video: true }, function(stream){
			video.src = window.URL.createObjectURL(stream);
			video.play();
			localStream = stream;
		}, errBack);
	}
 
	document.getElementById('tomar').addEventListener('click', function() {
		context.drawImage(video, 0, 0, 480, 360);
	});
}, false);

Adicionalmente se puede detener el video para evitar que se quede encendida la cámara y para ello solamente se requiere dejar vacío el origen del video, pausarlo y detener el stream.

// esto funcionará solamente si tienen una etiqueta button o similar con el id "detener".
document.getElementById('detener').addEventListener('click', function() {
	video.src = '';
	video.pause();
	localStream.getVideoTracks()[0].stop();
});

Y ahora que tienen la captura, lo ideal es tenerla en base64 para poderlo enviar al servidor y eso se logra mediante el uso del método toDataUrl() del objeto canvas, quizás el código que toma la captura de pantalla podría quedar de la siguiente manera.

document.getElementById('tomar').addEventListener('click', function() {
	context.drawImage(video, 0, 0, 480, 360);
	var c = document.getElementById('contenido');
	c.innerText = canvas.toDataURL();
});

El ejemplo completo lo pueden encontrar siguiendo esta url https://qbit.com.mx/labs/ y ya saben que pueden comentar que nada les cuesta y así aprendemos todos.

Happy Coding!! 😀

Co-fundador de Qbit Mexhico, usuario de linux, Developer en tecnologías web.. Nicaragüense, centro en basketball, primer centro en rugby y pintor los fines de semana. Ortögrafo y ambientalista psicológico (de escritorio).. ese soy yo!

Si te ha servido compártelo y difunde nuestro blog..

Facebook Twitter LinkedIn Google+ Flickr YouTube Skype 

Compartir en...Tweet about this on TwitterPin on Pinterest0Share on LinkedIn0Share on Google+0Share on Facebook1