Back to my Raspberry Pi page

Raspberry Pi Webcam

Recently I purchased a camera module for the Pi.

With the camera module I built a webcam, documenting the growth of our tomatoes on the balcony like a flip-book. ;-).

A demo of the webcam page can be seen here.

Since the webcam software I found online didn't fit my needs and it's fun to do it by oneself, I created my own.
It only consists of two small bash scripts combined with a bit of HTML and Javascript code,
served by an HTTP server on the Pi (lighttpd in my case).

The webserver lighttpd only needs a simple configuration change to work for this task:
It should serve user-created data (in the user directory ~/public_html) additionally to the root data.

sudo apt-get install lighttpd
cd /etc/lighttpd/conf-enabled
sudo ln -s ../conf-available/10-userdir.conf
sudo /etc/init.d/lighttpd restart

The user website is available at address http://servername/~username/ then,
in my case it's http://pi1/~pi/

Then create the needed directories:

mkdir -p ~/public_html/images
mkdir -p ~/public_html/templates
mkdir -p ~/bin

The following two scripts should be stored in a directory being in the PATH, e.g. your ~/bin.

First the script klick which takes the picture(s) and stores them in a directory accessible by the webserver:


filename=p_$(date +"%Y-%m-%d_%H-%M").jpg

raspistill -w 800 -h 600 -t 10 -o ${targetdir}/${filename} -l ${targetdir}/${lastfilename}

So there are a few (or many) picture files with timestamp in their names and the most recent picture named p-last.jpg additionally.

The following script makenavi creates a navigation document in HTML (~/public_html/navigation.html) from the collected pictures,
using a template file ~/public_html/templates/navigation.template shown further down.


cd ~/public_html

if [ ! -f templates/navigation.template ] ; then
  echo ""
  echo "Error: No navigation.template file found in ~/public_html/templates/"
  exit 1

sed -e '/@IMAGES@/,$d' templates/navigation.template

echo "<ul>"

ls -1t images/p_* | awk '{printf "  <li onmouseover=\"showpic('\''%s'\'')\"> %s &nbsp;%s:%s </li>\n", substr($0,8,22), substr($0,10,10), substr($0,21,2), substr($0,24,2)}'

echo "</ul>"

sed -e '1,/@IMAGES@/d' templates/navigation.template

) > navigation.html

The above created HTML file ~/public_html/navigation.html gets embedded in the main html file ~/public_html/index.html:

<!doctype html>
<html id="htmlindex">
<meta type="text/html" charset="utf-8">
<meta http-equiv="refresh" content="300">
<title>pi1's webcam page</title>
  <b>Scripting needs to be allowed for a proper function!</b>

<body id="indexbody">

<h1>My garden-webcam</h1>

  A new picture will be taken every hour.
  If this window is active it should be refreshed every 5 minutes with the most current picture automatically - if the browser supports this ... <br>
  To browse through the pictures simply hover over the filenames.

<div id="navdiv" style="width: 20em ; float: left;">
  <nav id="nav">
  <iframe id="obj" src="navigation.html" style="width: 18em; height:600px; border:0;">
  Here the navigation should appear...

<div id="picture" style="width:850px; height: 650px; float: right;">
  <img src="images/p-last.jpg"> <br>
  most current picture


Here the above mentioned template file ~/public_html/templates/navigation.template:

<!doctype html>
<meta type="text/html" charset="utf-8">
<base target="picture">

function showpic(p) {
  parent.document.getElementById('picture').innerHTML =
    '<img src="images/' + p +'" title="' + p + '"> <br>' + p;

function dofilter() {
  var ft1 = document.getElementById("filtertext").value;

  for (var i = 0; i < document.getElementsByTagName("li").length; i++)
    var ob1 = document.getElementsByTagName("li")[i];
    var at1 = ob1.attributes[0];
    var va1 = ob1.firstChild.nodeValue;
     * // simple string search
     * if ( va1.indexOf(ft1) == -1 ) {

    // regular expression search
    // see for details
    if ( == -1 ) {
      ob1.hidden= "hidden";
    } else {
      ob1.hidden= "";

  ul { list-style-type: none;
       font-size: 0.5em;
       line-height: 110%;
  ul li { cursor: pointer; }


<p>The pictures, sorted by date/time:

<!-- The ENTER key needs to be handled separately here too. -->
<input type="text" name="filtertext" id="filtertext" value="" size="16em"
       title="normal text or a regular expression to filter by"
       onkeypress="if (event.keyCode == 13) {dofilter(); return false;} else {return true;}">
<input type="button" name="filter" value="filter" onclick="dofilter()">
<input type="button" name="clearfilter" value="all"
       onclick="document.getElementById('filtertext').value = '';dofilter()">



The webcam is operated by a crontab entry every hour between 05:00 and 22:00 o'clock:

# m h  dom mon dow   command
00 5-22 * * * /home/pi/bin/klick && /home/pi/bin/makenavi

That crontab entry/entries can be created/edited with:

crontab -e