Technology Solutions for Everyday Folks
Puppet bird with binoculars

Capturing Your Internet-Connected Webcam Images

Over the years, we've had a few public Internet-connected cameras pointing at various places around campus. We've used them for publicity and other purposes since the mid-1990's, and starting in around 2010 would sometimes be called upon to create a sort of time-lapse video of activity from one of said cameras.

After the first request, which I'd treated as a one-off, I decided to pull together a simple script (in PHP) to actually do the capture portion of the process. Once every X minutes, pull the current image from the camera, write it to file, and exit. The cron job for this particular script is a relatively simple one-liner, akin to:

*/5 * * * * /path/to/php /path/to/automation/script.php

The automation 'script' itself is pretty straighforward, too. Define a couple of variables:

$cameraUrl = 'http[s]://yourcamera.name/axis-cgi/jpg/image.cgi?'.rand(100,1000);
$filePath = '/path/to/your/local/files/name-' . date('m-d-y-H-i-s') . '.jpg';

I used cURL via PHP to actually make the HTTP[S] request:

$ch = curl_init($cameraUrl);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER,1);
$rawdata=curl_exec($ch);
curl_close($ch);

And then, write the file to disk:

if(file_exists($filePath)) {
	unlink($filePath);
}
$fp = fopen($filePath,'x');
fwrite($fp, $rawdata);
fclose($fp);

A Couple of Notes

The make of choice in our public cameras at the time of the automation was Axis. You would replace the HTTP[S] path in $cameraUrl to something befitting of your make. Whatever a client would actually source. I found the details via a combination of the manufacturer's information (manual) and some simple searches.

I also ended up adding an argument to the Axis image.cgi path (a random numeric value between 100 and 1000), which is effectively ignored by the camera's server but helps prevent client-side caching.

If your camera is password-protected or otherwise requires account credentials, cURL can handle that as well. In a future post, I intend to write about simple ways to work with automated cURL requests when authentication is required.

Simple, Effective, Automated

We've since reused the code above a number of times for various projects. While it doesn't stitch them together nicely, the end results can be easily handed off to someone with that knowledge and expertise (and often, software). In a future post, I might also illustrate a process by which we automated the image distribution process as well, which made the "IT" side of things pretty trivial.

I have made the generalized version of the source above available in GitHub.

As a final reminder, please use this source/example for Good, and not Evil or Nefarious purposes. We're all better than that!

Headline image via giphy