Chapter 2
Time-Lapse Imaging Viewed via the
Web

The official title of this project is “A Surveillance Pi with Time-Lapse Image Capture Accessed Remotely via the Web,” but we’ll stick with the SpyPi name. In the first chapter we got the Raspberry Pi to produce a single image; now we’re going to have it do some bona fide surveillance. You’ll set up your SpyPi to automatically take a picture every minute and also make a web page so that you can remotely access the most current image at any time. And we’ll talk about how you can combine the images to make a single time-lapse animated GIF of the activity!
You’ll create all of this via the terminal, as in the previous chapter. In this case, you’ll write scripts using the nano editor, save them, and then run them with the Python language interpreter. Meanwhile, you’ll set up the web server in the background. Finally, you’ll use a stand-alone tool to make the animated GIF.
A typical use case would be to set up your Pi in a forest or over an area where you need to maintain security, or even to capture traffic at a busy street intersection. Really, the legal uses are up to you. Everything we make is configurable, so you can make your system take one picture of road traffic every second, or one picture of the sunset every minute, or one picture of your house every hour. Best of all, you don’t need to be near your Pi to view these images; just point your web browser to the Raspberry Pi’s web page and watch the images from the luxury of your own home.

Figure 2-1: Time series of a SpyPi surveillance of our basement floor, showing a stuffed animal crossing. (Image brightness is due to camera.)
Capturing Time Sequences Automatically
First, you’ll write a short script file using the Python language to automatically run your camera with a regular time sequence. To do this, you’ll use the nano editor to enter the program. Type the following commands into the terminal:
nano timelapse.py
And enter the following code exactly as you see it. Python is
very touchy about indentations—be sure to indent the code
exactly as shown here. We’ll use 60 seconds
(1 minute)
as a delay time, but you can change that value in the code to
whatever you need. Lines preceded by #
are comments
that explain the code.
# Spy-Pi code version 1
# this code takes an image every minute (60 seconds),
# and overwrites the current image with the new one
import os
import time
# choose a delay time in seconds by modifying the next line
delay = 60
# below are the default location to put the files, and the name to use
directory = "/home/pi/"
filename = "spycam"
stem = ".jpg"
webfile = directory + filename + stem
# and this is the command to run.
mycommand = "fswebcam -d /dev/video0 -r 640x480 --no-banner"
# this is the actual 'do stuff' part. It runs forever
while True:
runme = mycommand + " " + webfile
os.system(runme)
time.sleep(delay)

Figure 2-2: What you’ll see in nano when you make this first Python script
This is a general structure we’ll use often in this book—using
Python as a wrapper around our external programs like
fswebcam
. We’ll later add in a package called openCV
for facial recognition. Python is easy to learn and modify, and it
will let us set time-lapse loops and other tricks.
Once you’ve typed in this program, save it by pressing Ctrl-X
and name it timelapse.py
. At the
terminal prompt run it with python timelapse.py
. Your gadget is now
taking a new picture every 10 seconds, overwriting the old one. You
can see the image on the desktop or look at it within the window by
typing feh spycam.jpg
.

Figure 2-3: Our first image: a stuffed animal on a piano!
This code will run forever, as long as the Raspberry Pi has
power. You can stop it at any time, fortunately, by pressing
Ctrl-C. There’s also a fancy way to run it in the background so
that you can type other things in the terminal—when you call it up,
add an &
, as in
python timelapse.py &
Don’t do this yet. In the next chapter, we’ll talk about using a
routine called crontab
to automatically run your code
in the background. If you do want to play around with using
&
to run the program in the background, know that
if you type fg
it will bring the
program up again, at which point you can then press Ctrl-C and kill
it. Playing around with running scripts in the background or
bringing them to the foreground so you can nix them is a very
common Pi/Linux way to work on and run scripts.
Make the Pi into a Web Server
To make your Pi into a web server so that you can point a
browser to it, you…well, actually, you already did this. Back in
Chapter 1 when you typed sudo apt-get
install apache2 -y
you told the Raspberry Pi to install a
complete web server package. We’re just going to make it easier to modify
things. (You can also read more at
www.raspberrypi.org/documentation/remote-access/web-server/apache.md.)
Here’s your default homepage, if you didn’t change your Pi’s name:
If you did change it as we recommended, it’s
and, if you are on your Pi, it can also see the page as

Figure 2-4: The default web page auto-installed on your Pi (that you’ll soon delete)
To make life easier, we’ll show you how to make a link to where the Pi stores web pages so it will be easy for you to drop stuff into your home directory. Type these two lines
ln -s /var/www/html /home/pi/web
sudo chown pi . *
to make a new directory in your home directory
called web
, which is the location where any web page
is stored. The chown
line makes it so you can write
and edit stuff in that (otherwise, it’ll tell you permission
denied
). Anything you put into the web
directory will be visible to the outside world via a browser, if
the individual knows the address of your Raspberry Pi. There’s
already a default page called index.html
there. Let’s
change it!
Go to the web directory:
cd web
Move the original index.html
file to
index-orig.html
:
mv index.html index-orig.html
And create a new index.html
file:
nano index.html
And now that you’ve invoked the nano editor, type the following into the file:
Hi
and then save the file and look at it in a browser.

Figure 2-5: The world’s simplest web page
Okay,
it’s a very boring web page, but as you can see, anything you put
into index.html
appears to your web visitors.
Now you’ll make a new index page that works with the camera.
You’ll also make a new Python script that automatically triggers
the camera. Together, the two work like this: Every 1 minute, the
Python script tells the Pi “Take a new picture and stick it in the
web
directory.” Meanwhile, people visiting your new Pi
web page will see the most recent picture—and their browser will
automatically refresh itself every minute so it can catch when the
picture changes.
Also, that 1 minute is an arbitrary time setting that you can change. If you think what the Pi can see will change faster or slower, make it a different time (every 5 minutes, every 30 seconds, every 5 seconds). Similarly, you can change the web page to update more rapidly—but beware, it takes time to load an image over the network via the web, so any web page that refreshes faster than 1 minute might mean your browser hasn’t even finished loading a picture before the next refresh happens. Put another way, you should not take pictures faster than you can serve them.
First, modify our previous timelapse.py
script by
changing the one line that reads
directory = '/home/pi/'
to instead read
directory = '/home/pi/web/'
This will make the camera program write the image file into the web-visible area.
We now need to put an HTML web file in that web area that points to the picture. At the terminal prompt, type these two lines:
cd web
nano index.html
and then, when nano comes up, type this in the editor:
<html>
<head><title>SpyPi</title>
<meta http-equiv="refresh" content="60" />
</head>
<body>
<img src='spycam.jpg' alt='pi image'>
Image refreshes every minute!
</body>
</html>
Now save this code (in nano, press Ctrl-X and name the file
index.html
). Feel free to change
SpyPi
in the title and the Image refreshes every
minute!
text. That’s just text for this demo and it can be
changed to read anything you want. The key part is the meta keyword
in the head
tag, which sets the auto-refresh to every
60 seconds. This triggers any visiting web browser to reload the
page every minute. You can set any time interval; one minute is
useful for tracking slow state changes such as the camera being
moved. Set it longer if you find it takes a long time to load an
image in your browser.
Let’s give it a try. Start the infinitely looping Python script:
python timelapse.py
and look at what’s in the web directory by pointing your smartphone or tablet to the web page http://spypi.local/.
You should see what the Pi sees in your web browser. It’s the same test image as before, but now you can access it via your web browser from a remote machine. Success!

Figure 2-6: Sample image from our SpyPi, framed in your web browser
The Pi as a Remote WiFi Hotspot
Right now, the Pi is running the web server and technically, the web pages are visible to any other machine on its network. You can find it from other machines via a web browser at http://spypi.local/.
This is great for a SpyPi that is able to log into your local WiFi network. You can use the SpyPi at home or work, and you’ll be able to check it from any machine on that network. You can place the Pi so that it creates its own hotspot that enables people to log into it, even if the Pi can’t connect to an external network. This is great if you want to, say, place it in a forest to monitor wildlife and still want to be able to log into it remotely.
In this section, we’re going to set up the Raspberry Pi so it doesn’t have to be connected to an existing network. Instead, the Pi itself will create a WiFi hotspot that you can log into. This means anyone close enough to be in WiFi range of the Pi can connect to it.
To access your Pi, even without an Internet connection, follow any of these three tutorials:
www.raspberrypi.org/documentation/configuration/wireless/access-point.md
www.instructables.com/id/Make-Your-Pi-a-Local-Cloud-Server/
https://thepi.io/how-to-use-your-raspberry-pi-as-a-wireless-access-point/
The software installed is two packages called
HostAPD
(that makes your Pi a stand-alone Internet
device) and DHCP
(a network standard for automatically
assigning addresses and names to devices that connect to your Pi).
We’ll also toss in a firewall called iptables
. You’ll
install them with the usual:
sudo apt-get install hostapd isc-dhcp-server iptables-persistent
and then follow any of the tutorial links. Once done, you can log into your Pi as if it were its own Internet.
Cleaning and Archiving
At this point you are always serving up the current image.
However, archiving past images moves the SpyPi past “toy” into
“genuine surveillance.” Let’s modify our Python script to save the
previous N
days’ worth of images, where N
is however many days you want to keep.
Type
nano timelapse2.py
in the terminal,
and enter the following code as is. Remember to maintain the proper
indentations.
# Spy-Pi code version 2
# takes an image every minute, and saves 1 week (7 days) of data
# it also makes the most current image available
import os
import time
import shutil
# choose a delay time in seconds by modifying the next line
delay = 60
# this says to save 7 days (1 week) at a time, feel free to change to a different duration
savedays = 7
# do not change this math code, it converts our savedays to how often to retake a pic in secs
# note that 1 day at 1 picture/minute is 10,080 files per week
waitcount = savedays * 24 * 60 * 60 / delay
# below are the default location to put the files, and the name to use
directory = '/home/pi/web/'
filename = "spycam"
stem = ".jpg"
# also, this is the file the webserver expects
webfile = directory + filename + stem
# and this is the command to run.
mycommand = "fswebcam -d /dev/video0 -r 640x480 --no-banner"
# this is the actual 'do stuff' part. It runs forever
icount = 0
while True:
icount += 1
myfile = directory + filename + "_" + str(icount) + stem
runme = mycommand + " " + myfile
os.system(runme)
# copy new file to the webfile location so it is web-visible
shutil.copy(myfile, webfile)
# new purge routine removes older images after expiration time
inix = icount - waitcount
if inix > 0:
deleteme = directory + str(inix) + filename + stem
os.remove(deleteme)
time.sleep(delay)
Again, running python timelapse2.py
will do three things:
- Take a picture at the given interval (here, 1 minute).
- Save all the pictures it takes, up to the given period (here, 1 week), deleting older ones.
- As written, it restarts the image count at
0
whenever you power up, so you lose old data and start afresh each time.
You may want to clean up when you stop or restart the time-lapse routine. These two commands, typed into the terminal, will get rid of all old files:
cd web
rm spycam*.jpg
Now you can rerun python timelapse.py
without the
clutter from previous runs.
Animating a Time-Lapse GIF
To view the archive of images, log into your Pi and either download the set or view the images on the Pi. Or you can choose to make them into an animated time-lapse GIF! Type in your terminal the following sequence to build a GIF at any time.
First, if you didn’t install
imagemagick
in Chapter 1, type this:
sudo apt-get install imagemagick
Now, using your terminal, type these commands to go into the
directory with the files and turn all the images into a time-lapse
animated GIF file. Note the unit: delay
is in
hundredths of a second, so 10
= 0.1 second between
frames, and loop 0
= loop infinitely:
cd web
convert -delay 10 -loop 0 spycam*.jpg timelapse.gif
Let’s look at it via the web. As before, you need to make a web
page that calls it. So in the web
directory, make the
file timelapse.html
:
cd web
nano timelapse.html
In that file, put these lines:
<html><body>
<img src="timelapse.gif" alt="timelapse">
</body></html>
Now, with your web browser, point to
http://spypi.local/timelapse.html
And you can see your amazing animated time-lapse image! The following is a tiled version of eight time-lapse images.

Figure 2-7: Tiled version of eight consecutive SpyPi time-lapse images