Building a webcam with an old laptop, Canon camera and Linux

Recently I put together a webcam for the Aorangi Ski Club's lodge on Ruapehu. The system consists of a second-hand laptop, an old Canon camera and Ubuntu Linux. Images are automatically captured every hour, timestamped and posted to Flickr. The end result is a pretty impressive looking Flickr slideshow:

To put a similar setup together follow these steps.

Step 1: Get the gear

Find a Linux compatible laptop and a Canon camera compatible with the Capture software.

Step 2: Install Linux

I installed Ubuntu 8.04 on the laptop because from my experience it has the best 'out of the box' support for laptop hardware. It didn't prove me wrong when installing onto the four year old Toshiba, it even detected the winmodem.

Step 3: Internet connectivity

The problem of getting Internet connectivity will vary depending on where your webcam is located. In my case it was in a relatively isolated position half-way up one of New Zealand's largest mountains. That meant the only Internet connection available was via the phone line.

Unfortunately in this day and age winmodems are not supported that well by the popular Linux distributions. Your best bet is to get a hardware modem rather than relying on a cheaper 'winmodem' alternative. For me however budget was a driving factor so the winmodem had to stay. Fortunately the Conexant winmodem in the laptop did have a binary kernel driver available.

Setting up a modem in Linux will vary depending on your distribution, but if all else fails read the PPP howto and edit the configuration files directly.

Step 4: Install the software requirements

At this point it is a good idea to plug your laptop into your LAN and perform a full software update (i.e. apt-get update or yum update). Once that is complete install Imagemagick, Capture and the Perl library flickr_upload.

Imagemagick is very popular and should be just a case of running apt-get install imagemagick (or yum install imagemagick). Unfortunately it is highly unlikely you will find prebuilt .deb or .rpm packages for Capture or flickr_upload. In both cases it is best to download the source code and follow the compile/installation instructions. Both these packages have dependencies which you will need to track down and install, but trust me, both do compile and install on Ubuntu 8.04.

Step 5: Test your camera

At this point you should have all the prerequisits in place to start writing your webcam script.

Note: For simplicity these scripts will run as root. This gets around all the permissions issues when accessing modems and USB devices. Also the fact that this will be a standalone device doing non-mission critical work means it isn't a huge problem.

Create a directory somewhere (say /usr/local/webcam) and create a file called capture.sh.

nano capture.sh

Give it the following contents:

#!/bin/bash
# Get the new image from the camera
capture 'start'
capture 'flash off'
capture 'zoom 1'
capture 'metering spot'
capture 'focuspoint center'
capture 'capture raw.jpg'
capture 'detach'

Set the execute properties on this script.

chmod a+x

Plug the camera in to the laptop via a USB cable, turn it on and execute this script.

./capture.sh

All going well the camera should come alive, focus itself, take a photo and download it to the current directory (i.e. /usr/local/webcam) with a filename of raw.jpg.

If things do not work Google the error message, check the cable connections and try again. I tried the Capture application with a couple of supported Canon cameras and they all worked fine.

Step 6: Setup Flickr API access

Assuming your camera is happily taking photos when directed by your laptop you can go ahead and setup Flickr.

Sign up for a Flickr account (they are free). This will be where your webcam photos are sent to. Next sign up for a Flickr API key here: http://www.flickr.com/services/api/keys/apply/

Record the Flickr API key and secret that you are provided at the end of this process.

In the /usr/local/webcam directory create a file named flickr-auth.pl.

nano flickr-auth.pl

Give the file the following contents (replace YOUR_FLICKR_KEY/SECRET with your actual key and secret):

#!/usr/bin/perl

use Flickr::API;
use Flickr::Upload;

my $flickr_key = 'YOUR_FLICKR_KEY';
my $flickr_secret = 'YOUR_FLICKR_SECRET';

my $ua = Flickr::Upload->new(
{
'key' => $flickr_key,
'secret' => $flickr_secret
});
$ua->agent( "perl upload" );


my $frob = getFrob( $ua );
print "FROB:$frob;\n";

my $url = $ua->request_auth_url('write', $frob);
print "1. Enter the following URL into your browser\n\n",
"$url\n\n",
"2. Follow the instructions on the web page\n",
"3. Hit when finished.\n\n";

<>;

my $auth_token = getToken( $ua, $frob );
die "Failed to get authentication token!" unless defined $auth_token;

print "Token is $auth_token\n";

sub getFrob {
my $ua = shift;

my $res = $ua->execute_method("flickr.auth.getFrob");
return undef unless defined $res and $res->{success};

return $res->{tree}->{children}->[1]->{children}->[0]->{content};
}


sub getToken {
my $ua = shift;
my $frob = shift;

my $res = $ua->execute_method("flickr.auth.getToken",
{ 'frob' => $frob ,
'perms' => 'write'} );
return undef unless defined $res and $res->{success};

return $res->{tree}->{children}->[1]->{children}->[1]->{children}->[0]->{content};
}

Set the execute permissions for the file and run the script.

chmod a+x flickr-auth.pl
./flickr-auth.pl

Follow the onscreen instructions. You will be directed to open a browser window to the location specified, and accept the request. Once accepted press enter on the laptop and the script with return your Flickr auth token. Write this token down somewhere as it will be needed in a moment.

Step 7: Setup the Flickr upload script

Create a file named flickr-upload.pl and give it the following contents (again replace YOUR_FLICKR_KEY/SECRET/TOKEN with your actual key, secret and token):

#!/usr/bin/perl
use strict;

use Flickr::Upload;

my $flickr_key = "YOUR_FLICKR_KEY";
my $flickr_secret = "YOUR_FLICKR_SECRET";
my $auth_token = "YOUR_FLICKR_TOKEN";

my $photograph = "";
foreach my $arg (@ARGV) {
$photograph = $arg;
}

my $ua = Flickr::Upload->new(
{
'key' => $flickr_key,
'secret' => $flickr_secret
});

$ua.agent => ( "perl upload" );

$ua->upload(
'photo' => $photograph,
'auth_token' => $auth_token,
'tags' => 'webcam',
'is_public' => 1,
'is_friend' => 1,
'is_family' => 1
) or die "Failed to upload image";

You can also edit the last couple of lines to define the tags applied to the uploaded photo and its privacy settings.

Step 8: The webcam script

Create a file named process.sh and give it the following contents:

#!/bin/bash
TEMP="/usr/local/webcam"
DATESTRING=`date +%l:%M%P\ on\ %A,\ %d\ %B\ %Y`
RAWFILE="raw.jpg"
RESIZEDFILE="resized.jpg"
STAMPEDFILE="stamped.jpg"
UPLOADFILE="Webcam $DATESTRING.jpg"

logger "Webcam process initiated"

# Change to the temp directory
cd $TEMP

# Get the new image from the camera
echo "Taking photograph..."
./capture.sh

# Connect to the Internet
pon

# Convert and stamp the photograph
echo "...converting image for the web"
convert -resize 1024x768 $RAWFILE $RESIZEDFILE
convert -fill "#333333" -draw "rectangle 0,722 1024,768" $RESIZEDFILE $STAMPEDFILE
convert -fill "#eeeeee" -draw "rectangle 0,723 1024,768" $STAMPEDFILE $STAMPEDFILE
convert -font "Helvetica" -pointsize 28 -fill "#111111" -draw "text 25, 755 '$DATESTRING'" $STAMPEDFILE $STAMPEDFILE

# Wait for connection
echo "Connecting to the Internet..."
sleep 45

# Update the system time
ntpdate nz.pool.ntp.org

# Upload the photograph
echo "Uploading photograph"
# echo $UPLOADFILE
cp $STAMPEDFILE "$UPLOADFILE"
./flickr-upload.pl "$UPLOADFILE"

# Disconnect
echo "Disconnecting..."
sleep 5
poff
echo "...complete"

# Clean up - delete working files (if they exist)
rm *.jpg

logger "Webcam process complete"

This script ties everything together:

  1. it executes the capture.sh script and takes a photo
  2. connects the modem to the Internet
  3. syncs the system time with a nearby NTP server
  4. resizes and stamps the photograph with the current date and time
  5. uploads the resized image to your Flickr account
  6. disconnects from the Internet
  7. removes the temporary image files

Note: You will probably want to edit parts of this script. For example you could use different image names or temp directories or a time server pool for your country.

Set the execute permissions of the file, set the camera up and run the script.

chmod a+x process.sh
./process.sh

All going well your laptop and camera should run through the routine outlined above. If you experience any errors it is just a case of debugging and trying again.

Step 9: Setup the cron job

Once the script is working as expected setup a cron job to run on a regular basis. How often is semi-dependent on your daylight hours and available Flickr bandwidth. A free Flickr account has limited upload bandwidth per month so you want to be careful your webcam does not take too many photographs. In the case of the Aorangi webcam it takes a photo once per hour between 7:30am and 4:30pm.

Create a file in /etc/cron.d named webcam and give it the following contents:

30 7-15 * * * root /usr/local/webcam/process.sh

Restart cron and you should find everything runs like clockwork from that point forward.