In the last post, I explained my reasons for creating this HTML5 app as well as the key technologies that enabled me to do this little experiment. Now, I will go into more detail with the code behind the scenes.
One of the things that I had to decide was whether to use a third party JavaScript library to help with cross-browser issues. Since, many of the HTML technologies I was experimenting with did not require my app to be cross-browser friendly, I decided to skip my love of jQuery and go with native JavaScript. I had run out of practice with doing things in native JavaScript, so it was a nice refresher for me (not relying on jQuery).
With that out of the way, the next thing was deciding on the server-side platform. I decided to go with PHP since I was very familiar with it. In addition, PHP has a built-in command-line web server, for instances where I wanted to try something out quickly without having to upload everything to my webhost.
Here is the JavaScript code (record.html) that takes a snapshot of the video from the camera.

Once, you have the dataURI, you can send it up to the server. I won’t bore you with the details of sending the image data to the server via AJAX post. If you take a look at the code in the GitHub repository, you can see how I implemented that piece of the functionality.
The next step is how to control the taking of snapshots from a remote location. This is where the WebSockets server comes in. There are many ways to implement this, but I decided to use Node.js and the “ws” node module to handle this. Here is the full code for “server.js”. Pretty simple. Less than 35 lines of code.

You run the WebSocket server by typing this on the command-line:
$ node server.js
Continuing back on the client-side JavaScript (record.html), we now add this skeleton code to handle all the websocket messages that get sent from the server.

Any browser client that connects to the WebSocket server (ws://localhost:5000) is capable of broadcasting and receiving messages. We can leverage this power to communicate back and forth between the recording device and the viewing device.
Our websocket() function and “ws” object will handle 4 types of events: open, close, error, and message. The real work happens inside the onmessage event handler. I immediately do a JSON.parse on the message’s data because I expect all messages to be a JSON object. This JSON object that we pass around will be key to identifying the request, and what kind of response will be required by whomever is handling that request. I store this request object in a variable called “req”. Here is the code I add right after for listening to snapshot requests:
if (req.evt == ‘snapshot’) { snapshot(); }
Moving over to the snapshot() function, we need to send a websocket message signifying that the snapshot has been uploaded to the server. Note: You will need to implement your own method for uploading the image to your server.
ws.send(‘{“evt”:”snapshot_ready”,”message”:”Snapshot is ready.”}’);
At this point, the (record.html) code is all setup to receive and respond to snapshot requests from any remote viewer. Now let’s take care of what happens on the viewing device.
On the remote viewing device (view.html), we can make a snapshot request by doing something like this in our code:

Once the “Request snapshot” button is clicked, we send a websocket broadcast with {“evt”:“snapshot”}. As long as the recording device (record.html) is actively connected to the WebSocket server, it will receive that message and respond to that request by taking a snapshot, uploading the image to the server, and sending a websocket broadcast with {“evt”:”snapshot_ready”}. The viewing device (viewer.html) will receive the “snapshot_ready” websocket message, and will display the latest image from the server.
I have covered the basics of how to use the power of websockets/node.js and getUserMedia to control your webcam from a remote location. The full code that does a whole lot more, can be downloaded from my GitHub project page: https://github.com/thomasyung/ws-webcam
In the next post, I will discuss some challenges faced and how to deal with them.
Email me when Thomas Yung publishes or recommends stories