Webcam on Android, the Unix way

This is another take on the "android phone as a webcam" theme.

My requirements are simple: take photos at regular intervals and upload them to a server, reliably.

There's quite a few answers to that in the play store, but after some testing I found that they all didn't really work reliably -- they stopped working after some time, the ones that promised to cache the pictures during a loss of connectivity and upload them later didn't, there were problems with picture quality, etc.

So there were two choices: Either write an android app, or go the Unix way.

A bit of googling showed that handling of the camera seems to be one of those parts of the Android API that sucks, and after that, there would still be issues with handling the upload (no WebDAV support, no rsync support, no scp support in the API) and scheduling.

That left me, again, with the Unix way: use existing programs that do all the heavy lifting and glue them together with a bit of shell script to make them do what you want.

Components

  • "IP Webcam" by Pavel Khlebovich, which seems to reliably drive the camera

  • "rsync backup for Android" by Michał Kowalczuk which provides the reliable transport mechanism

  • wget to get a photo from IP Webcam

  • cron to drive the whole thing

wget and cron are already installed on Cyanogenmod, otherwise you need busybox. Oh, and a rooted phone, but you wouldn't be here if you didn't swing that way, would you?

The glue

 #!/bin/sh

 cachedir="/sdcard/cam"
 photo_url="http://localhost:8080/photo.jpg"
 rsync_dest="rsync://user@host.name/dir/"
 export RSYNC_PASSWORD="secret"
 bwlimit=20

 fname="$cachedir/`date +%FT%H.%M.%S`.jpg"

 logfile="`date +%F`.log"
 exec >> "$cachedir/$logfile" 2>&1

 ## get the photo
 wget -O $fname $photo_url

 ## now that we got the picture, we can upload it
 rsync -rv --remove-source-files --bwlimit=20 --chmod=u=rw,go=r \
     --exclude $logfile "$cachedir/" $rsync_dest
 ## this uploads/appends today's logfile without deleting it
 rsync -rv --bwlimit=20 --chmod=u=rw,go=r \
     "$cachedir/$logfile" $rsync_dest

This goes (in my case) in /sdcard/scripts/cam.sh. Cron needs to be started at boot, it isn't by default; on CM7, you can create a /data/local/userinit.sh to have it started on boot:

echo "/system/xbin/crond -c /data/cron" >> /data/local/userinit.sh

Then, the crontab in /data/cron/root (hmm... this probably doesn't need to run as root...):

echo "*/15 * * * * sh /sdcard/scripts/cam.sh" > /data/cron/root

Set IP Webcam to start at boot, configure the picture properties, setup your rsnyc server, see that the phone has power and drop it somewhere interesting. That's it.