Webcambilder auslesen

Am Fedex Day habe ich mich mit dem Thema auseinander gesetzt, wie mit den aktuellen Webtechnologien (HTML5/JavaScrit, kein Flash) die Webcam angesteuert werden kann.

Technologie

Moderne Browser stellen ein „getUserMedia“-Objekt zur Verfügung, welches für die Kommunikation mit der Webcam oder einem Mikrofon verwendet werden kann. Die API dazu findet Ihr hier: http://dev.w3.org/2011/webrtc/editor/getusermedia.html

Kompatibilität

Das Objekt wird momentan von folgenden Browsern unterstützt: http://caniuse.com/#search=getUserMedia

HTML Ausgabe

Damit die Daten der Webcam angezeigt und gespeichert werden, brauchen wir folgende Tags:
– viedo: Für die Anzeige der Webcamstreams
– canvas: Für die Bildgenerierung
– img: Für die Anzeige des generierten Bildes
– Formular, um das Bild herunterzuladen. (und die Client-Server-Komunikation zu verdeutlichen)

<video id="videostream" autoplay></video>
<img id="capturedImage" src="">
<canvas style="display:none;" width="640"  height="480"
></canvas>
<form action="save.php" method="post">
<input type="hidden" value="" name="imgData" id="imgData" />
<input type="button" value="upload" id="upload" />
</form>

Initalisierung
Mit der folgenden Initialierung wird sichergestellt, dass je nach Browser das richtige getUserMedia-Objekt (bzw. window.URL-Objekt – Dieses Objekt wird für das Auslesen der Bilddaten gebraucht) verwendet wird.

<script type="text/javascript">
   navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
    window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
</script>

Bevor die Webcam aktiviert werden kann, sollten noch die Konfigurationen der Webcam festgelegt werden: (Weitere Infos zu den Konfigurationen finden Sie hier.)

    /*
     * Configuration of the webcam Output 
     */
    var customConstraints = {
		  video: {
		    mandatory: {
		      minWidth: 640,
		      minHeight: 480,
		    },

		  }
		};

Um die Webcam zu aktivieren, wird nun das präparierte getUserMedia-Objekt mit folgenden Parametern verwendet:

1. die Konfiguration

2. Callback Methode, welche beim Erfolg aufgerufen wird.

3. Callback Methode, welche beim Fehlschlag aufgerufen wird (z.B. Der User lehnt die Aktivierung der Webcam ab)

In der „SuccessCallback“ Methode wird nun der Webcamstream an das Videotag gebunden, und ermöglicht dadurch die Anzeige der Bilddaten der Webcam.

if(navigator.getUserMedia)
    {
    	navigator.getUserMedia(customConstraints, successCallback, function(){alert("Webcam initialization failed");});
    }
    else
    {
    	alert("Your Browser dosen't support getUserMedia");
    }
function successCallback(stream) {
        /*
         * For Mozilla Browser
         */
        if (video.mozSrcObject !== undefined) {
            video.mozSrcObject = stream;
        } else {
            video.src = (window.URL && window.URL.createObjectURL(stream)) || stream;
        };
        video.play();

        localMediaStream = stream;

       }

Nun sollte der Webcamstream im Video-Tag ausgegeben werden.

Bilddaten speichern

Damit ein Bild von der Website gespeichert werden kann, wird der Videostream in ein Canvas-Element gerendert und aus diesem Canvas Element ein base64 Bild generiert:

jQuery(document).ready(function(){
		jQuery("#videostream").click(function()
		{
		 if (localMediaStream) {
			/*
			 * Draw the image in the Canvas element
			 */
	   		ctx.drawImage(video, 0, 0);

	      	document.querySelector('img').src = canvas.toDataURL('image/png');
   		};
	});    
});

Bildaten auf den Sever laden

Damit die Bilder serverseitig verwendet werden können, wird das base64 kodierte Bild an den Server gesendet.

	jQuery("#upload").click(function()
	{
		jQuery("#imgData").val(document.querySelector('img').src);
		jQuery("form").submit();

	});

Das Bild dekodieren (Datei save.php)

Zuerst werden die Headinformationen des Bildes entfernt. (In unserem Beispiel: data:image/png;base64) Aus dem Header kann bei bedarf der Dateityp ermittelt werden oder wie das Bild kodiert wurde.
Wenn die Headerinformationen entfernt wurden, muss das Bild nur noch dekodiert werden und wir erhalten die rohen Bilddaten, welche z.B. mit  der Funktion file_put_contents in eine Datei geschrieben werden können.

<?php

if(isset($_POST['imgData']))
{
	/*
	 * Remove the Headerdata
	 */
	$data = substr($_POST['imgData'], strpos($_POST['imgData'], ",")+1);

	header('Content-Description: File Transfer');
	header('Content-Type: application/octet-stream');
	header('Content-Disposition: attachment; filename="testimage.png"'); 
	header('Content-Transfer-Encoding: binary');
	header('Connection: Keep-Alive');
	header('Expires: 0');
	echo base64_decode($data);
}
exit;
?>

Working Example
Testinstallation Kamerabilder