2006-06-21

Automating iSight

Photobucket - Video and Image HostingSo you have this iSight camera built into your Mac and you want to make it take images on demand. My first thought was to get Automator to do it all, however Automator does not have access to the camera at this stage. As soon as Automator has a camera action then the task will become much more simple and you can toss out the mess of scripting below.

What follows is a number of experiments to take capture iSight images at set times. The methods use a neat piece of software from Axel Bauer at intergalactic. The software is run from the command line (universal binary) and allows you to take a picture as long as the camera is working and not in use.

Experimenting with AppleScript

I created a folder called /Applications/snapme where I placed all the script files, including Axel's isightcapture program. After looking around I noted an example script in AppleScript which I decided to improve upon. Thanks to some excellent tips from Michael Henley who pointed me at the shell script reference for AppleScript.
Applicactions : AppleScript : Script Editor
-- filename /Applications/snapme/snapme.once
do shell script "/Applications/snapme/isightcapture ${HOME}/Pictures/snap.`date '+%y%m%d.%H%M%S'`.jpg"

Shell script

Another option is to create a shell script with the following code. Save it as text if you are using text edit ("Format", "Make Plain Text").

I used the console program called pico to edit the script and saved it as /Applications/snapme/snapme
Terminal : pico /Applications/snapme/snapme
# filename /Applications/snapme/snapme
# returns image path+name or error
# use the isightcapture software from
# http://www.intergalactic.de/hacks.html
# to save an isight pic to the pictures folder
myimg=${HOME}/Pictures/snapme
# make the folder if it does not exist
if [ ! -d $myimg ]
then
mkdir "$myimg"
fi
# add date+jpg onto the path
myimg=${myimg}/`date "+%y%m%d.%H%M%S"`.jpg
# capture the image to the specified path/filname
/Applications/snapme/isightcapture $myimg
# test if parameter quiet in which case - echo nothing
if [ ! "$1" = "quiet" ]
then
# test if file created
if [ -f $myimg ]
then
# cp $myimg /var/www/webcam
echo $myimg
else
# file was not created
echo "error"
fi
fi
unset myimg
Remember to open a terminal session and chmod the saved shell script file so you can execute it. You may have to rename snapme.txt to snapme if you used TextEditor.
Terminal : command prompt
chmod 755 /Applications/snapme/snapme
I also placed a link in the path so I could run it from anywhere on the command line. You don't need to do this for Automator to work. But if you want to type "snapme" at the terminal prompt then this is one way to set up.
Terminal : command prompt
cd /bin
sudo ln -s /Applications/snapme/snapme
We can alter our AppleScript file to run this shell script, with the added benefit that the AppleScript now knows the name of the file produced and is able to further manipulate it should you wish to.
Applicactions : AppleScript : Script Editor
-- filename /Applications/snapme/snapme.once
-- The command below runs isightcapture prog directly with options
-- do shell script "/Applications/snapme/isightcapture ${HOME}/Pictures/snapme/`date '+%y%m%d.%H%M%S'`.jpg"
-- The command below runs the shell script "snapme"
set myImg to do shell script "/Applications/snapme/snapme"
We can also use Automator to create an app to run the shell script.
Applications : Automator
"Run Shell Script"
/Applications/snapme/snapme
Save as App called "snapme" {.app} in the /Applications/snapme folder. You should now be able to click on the snapme app and have a pic saved in your pictures folder with date-time in the name. You can alter the shell script above to change the destination path and/or the output filename.

Note that you can tell AppleScript to create an application under "File", "Save As". Change the "File Format:" to "application", untick "Startup Screen" and tick "Run Only".

cron

After a security update, cron was unable to run a shell script calling isightcapture properly - the captured image fails to be written. However, you can create a cron job to run an applescript app which issues the isightcapture shell command (such as snapme.once above). You could also try Lingon to run the script via launchd.

cron is a *nix command that can schedule repeated program calls for you. This is all very advanced so proceed with caution, chance to mess your system up is quite high. We want cron to run our shell script at specified times. First let us examine the cron command.
crontab -l
lists the cron jobs
crontab -r
removes all cron jobs
contab -e
edits cron jobs

cron file format
min hr day month dayOfWeek program
0-59 0-23 1-31 1-12 0-6(0=Sunday)
example:
20 1 * * * /Applications/snapme/snapme.once.app
run every morning at 1:20am
0 2 1 * * /Applications/snapme/snapme.once.app
run every morning at 2:00am on the 1st of day of every month
0,15,30,45 9-18 * * * /Applications/snapme/snapme.once.app
run every 15 minutes from 9am to 5:45pm
Note that if cron receives output from the script then it will email that output to you.

In OS X, "crontab -e" will invoke the text editor known as vi which is really not the editor of choice for most Mac users. vi is hard core.
Terminal : command prompt
crontab -e
Here's the few simple commands you want: tap "A" to get into insert mode, edit your text with only one of the crontab entries such as
0,15,30,45 * * * *  /Applications/snapme/snapme.once.app
then tap "ESC" to get out of insert mode.

WARNING: if you have that really cool speech recognition app going you are going to have to shut it down to stop it from absorbing the ESC char on you.

Type ":wq" and tap enter which will write and quit.

More
There is a lot of complicated scripting going on here. I am assuming a level of competence that you really shouldn't have to have.

Also check out Undercover, Prey and KeyCamX which does the whole thing for you and more. Check Timmargh for a slick way to script isight.

Hope someone finds some of this useful. Ah well, it was fun trying it out.

7 comments:

Mark Fowler said...

Just a thought, instead of using cron, you could use launchd to run it every 'n' seconds.

PeanuT said...

This is very interesting (if slightly overwhelming for a novice like myself!). I'm dreaming of a program or script which will take a photo of me with isight and automatically set it as my display picture for instant-messaging clients, so people can see me as I am at that moment but without the awkwardness of a webcam. Any ideas if this is possible? Let me know. Peanut.is.mint at gmail.com

neoporcupine said...

launchd has a different set of issues that could be seen as advantageous to use in this case, such as launchd won't take images when the computer is asleep.

However launchd can't specify fixed launch times like on the hour plus 15 minutes past plus 30 minutes past plus 45 minutes past. launchd will let you specify 900 seconds (15mins) starting from whenever launchd first sets its timer. So with cron, I know my image is will be taken at 10pm, but I have no idea with launchd unless I spied the last image being taken, noted the time and did the math. How would I know when to pick my nose?

---

Peanut's auto updating isight image into an instant messenger client is a very nifty idea. I had a go with Adium briefly but need to look at the idea again when I have some time.

Anonymous said...

I had isightcapture working via cron and now it won't save any pictures. I see that it runs, but no jpg gets saved. I'm thinking that a recent security patch broke it.. does it still work for you?

frank[at symbol]fperkins.com

erste said...

this is just what i was searching for!
thanks for this tip!

Gold Guide for World of Warcraft said...

good post :)

Big Guy said...

nice tutorial. Do you have any idea how to call this script from the web-server? I need it to be run on demand by apache, I want it to take a snapshot when I load a webpage. Can it be run as a cgi-bin application or from PHP script?