AS3: Webcam Upload Tutorial

Posted on April 29, 2011 by Jimmy K. in Tutorials.

In an article on my previous blog, I covered how to take an image with your webcam and upload it to your web server using ActionScript and PHP. This article was always very popular, so I have decided to bring it back to life with updated programming and include it in this new blog.

My final delivery for this project was an Adobe AIR application that used a MySQL database to distinguish between and manage the webcams, with a PHP backend for storing and displaying the images. This article will instead be a stripped down, bare bones approach to getting an image from your webcam, to your server, and onto your website.

Connecting to your webcam.

I have created one .fla file: webcam.fla and one class: Webcam.as for this tutorial. It is generally considered bad practice to place code directly on the timeline, so this tutorial may seem difficult if you’re unfamiliar with ActionScript classes. This class can easily be converted to run in the timeline if your project requires it.

Note: This tutorial utilizes the JPEGEncoder class in the as3corelib library by Mike Chambers. This package is freely available from github.

package com.endseven {

	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.geom.Rectangle;
	import flash.media.Camera;
	import flash.media.Video;
	import flash.net.URLRequest;
	import flash.net.URLRequestMethod;
	import flash.net.URLLoader;
	import flash.net.URLVariables;
	import flash.utils.ByteArray;
	import flash.utils.setTimeout;

	import com.adobe.images.JPGEncoder;

	public class Webcam extends MovieClip {

		private var sUploadURL:String = "http://[WEBSITE_URL_GOES_HERE]/upload.php"; // the url to the upload file..
		private var iUploadInterval:uint = 2000; // the interval to upload snapshots..
		private var rDimensions:Rectangle = new Rectangle(0, 0, 640, 480); // the camera dimensions..

		private var aBitmapByteArray:ByteArray;
		private var iUploadTimeout:uint;
		private var oCamera:Camera;
		private var oJPGEncoder:JPGEncoder;
		private var oVideo:Video;

		/* the constructor */
		public function Webcam() {

			trace("Webcam object has been created."); // debug trace..

			try {

				this.oCamera = Camera.getCamera();
				this.oCamera.setMode(rDimensions.width, rDimensions.height, 15);
				this.oCamera.setQuality(0, 100);

				this.oVideo = new Video(rDimensions.width, rDimensions.height);
				this.oVideo.attachCamera(this.oCamera);
				this.addChild(this.oVideo);

				this.oJPGEncoder = new JPGEncoder(50);
				this.iUploadTimeout = setTimeout(jUploadSnapshot, iUploadInterval);
				trace("Camera has been initialized.");

			} catch (oException:*) {
				trace("Unable to initialize camera."); // debug trace..
			}

		}

		/* uploads a snapshot to the web server. */
		protected function jUploadSnapshot():void {

			// create a bitmap data object to hold our snapshot..
			var oBitmapData:BitmapData = new BitmapData(rDimensions.width, rDimensions.height, false, 0x000000);
			oBitmapData.draw(this.oVideo);

			// encode the bitmap data, free the memory..
			this.aBitmapByteArray = oJPGEncoder.encode(oBitmapData);
			oBitmapData.dispose(); oBitmapData = null;

			// create a url request to send the bitmap data..
			var oURLRequest:URLRequest = new URLRequest(sUploadURL);
			oURLRequest.method = URLRequestMethod.POST;
			oURLRequest.data = aBitmapByteArray;

			// create a url loader to perform the request..
			var oURLLoader:URLLoader = new URLLoader();
			oURLLoader.addEventListener(Event.COMPLETE, eUploadComplete, false, 0, true);
			oURLLoader.addEventListener(IOErrorEvent.IO_ERROR, eUploadFailed, false, 0, true);
			oURLLoader.load(oURLRequest);

		}

		/* triggered when the upload completes. */
		private function eUploadComplete(oEvent1:Event):void {

			this.iUploadTimeout = setTimeout(jUploadSnapshot, iUploadInterval);
			trace("Snapshot has been uploaded."); // debug trace..

		}

		/* triggered when the upload fails. */
		private function eUploadFailed(oEvent1:IOErrorEvent):void {

			this.iUploadTimeout = setTimeout(jUploadSnapshot, iUploadInterval);
			trace("Error: Unable to upload snapshot."); // debug trace..

		}

	}

}

This class initializes the default Camera on your computer, attaches it to a Video object, then adds that Video object to the stage. At set intervals (I set mine to every two seconds), it draws the Video object’s bitmap data, converts the bitmap data to a byte array using the JPGEncoder class and uploads it as raw POST data to the “upload.php” file (which by now should reside happily on your web server).

Saving the image on your server.

When the raw POST data is received by “upload.php”, we’re going to need to save the data as an image. This was actually the most overly-complicated part of the whole process when I was looking for help online. I’m amazed at how simple it actually was:

<?php

	$aFullsizeDimensions = array("Width" => 640, "Height" => 480);
	$aThumbDimensions = array("Width" => 120, "Height" => 90);

	// save the fullsize image..
	$oHandle = fopen("./fullsize.jpg", "w+");
	fwrite($oHandle, file_get_contents("php://input"));
	fclose($oHandle);

	// create the thumbnail image..
	$oSource = imagecreatefromjpeg("./fullsize.jpg");
	$oThumbnail = imagecreatetruecolor($aThumbDimensions['Width'], $aThumbDimensions['Height']);
	imagecopyresampled($oThumbnail, $oSource, 0, 0, 0, 0, $aThumbDimensions['Width'], $aThumbDimensions['Height'], $aFullsizeDimensions['Width'], $aFullsizeDimensions['Height']);
	imagejpeg($oThumbnail, "./thumb.jpg");

	// free the memory..
	imagedestroy($oThumbnail);
	imagedestroy($oSource);

	?>

This code simply takes the raw POST input and saves it to a file using the fopen(), file_get_contents(), fwrite() and fclose() functions. Raw POST data is available to PHP using the php://input wrapper. This wrapper allows you to read raw data from the request body and is preferable to $HTTP_RAW_POST_DATA as it does not depend on special php.ini directives.

After we save the fullsize image, we’re going to scale it down and save a thumbnail. This will help conserve server resources and reduce bandwidth consumption.

This tutorial should be enough to get you started. It’s not a packaged solution, but I leave that to your imagination and willingness to create something on your own. I hope this tutorial helps point you in the right direction and also, if you do use the concepts included in this tutorial, please let me know. I would be very interested in seeing another person’s take on it.

Click here to download the source files.

Tags: , , , ,

 

Jimmy K. is a Chicago-based web developer who actively posts tutorials, articles and insights on his web development blog to help other programmers and developers.

You can find Jimmy on Google+ and Twitter.

 
 
 
 
 

If you like this, please leave a comment.

Name (required)
Email Address (required)
Website
Comments: