When it comes to capturing time-lapse videos, there are numerous off-the-shelf solutions and libraries out there. For last year’s FedEx Day project, I decided to implement a minimalist solution on a Raspberry Pi using only the default image capture API that ships with Raspbian (raspistill), the built-in UNIX task-scheduler (cron), a video conversion utility (avconv), and a lightweight web server (lighttpd).
- Set up your Raspberry Pi with the latest version of Raspbian by burning the image to an SD card.
- Connect the camera and power on the Pi. Connect to your Wi-Fi or wired network, and open a terminal session, either via SSH or directly on the Pi.
- (Optional) Set up a static IP address. This will let you find your server in the same place every time. If you're feeling fancy, you can even set up a DNS server to resolve a URL (e.g. myraspitimelapse.local) to this IP address.
- Install libav, which contains avconv. This is the tool we will use to create a video from the captured stills:
sudo apt-get install libav-tools
- Install lighttpd. This will let you view your time-lapse video via a web browser:
sudo apt-get install lighttpd
- Create a basic web page containing the time-lapse video and save it in the directory where lighttp will know to serve it. The most straightforward way is to use the built-in text editor nano:
sudo nano /var/www/html/index.html
Then copy in the following HTML, which tells the browser to automatically play the video on loop (the muted attribute is required for some browsers to autoplay):
<video autoplay loop muted>
<source src="timelapse.mp4" type="video/mp4">
- To create the video, we'll use a simple shell script. Open a new file using nano as before:
sudo nano /home/pi/timelapse/timelapse.sh
and paste in the following script, which saves a new still photo and generates a video file from all the existing stills every time it runs. It takes an input argument that specifies the number of seconds for the video duration.
# check current time and only take pictures during daylight hours (5am to 7pm)
if (( `date +%H` > 5 && `date +%H` < 19 )); then
# find the total number of images $n
while [ -f /home/pi/timelapse/stills/img$n.jpg ]
# take a new picture
raspistill -w 640 -h 480 -o /home/pi/timelapse/stills/img$n.jpg
# input arg $1 specifies target duration of timelapse video
# combine all images in directory into a video
sudo avconv -r $framerate -i /home/pi/timelapse/stills/img%d.jpg /var/www/html/timelapse.mp4 -y
- Next, change the file permissions so that the script can be executed:
sudo chmod +x /home/pi/timelapse/timelapse.sh
You should now be able to run your script as:
and see the timelapse.mp4 file get created in the directory. Enter the Pi's IP address into your browser, and you should be able to play the 5-second long video. For now, it won't be too exciting, since it will just be a single frame.
- Finally, set up the cron job that will trigger shell script. Open the cron table file:
Add the following line to the end of the file:
0 * * * * /home/pi/timelapse/timelapse.sh 30 > /home/pi/timelapse/timelapse.log
This runs the shell script once per minute, and the input argument of 30 means that the video will be 30 seconds long. The > symbol redirects any errors to the specified log file. You can, of course, use other time intervals as well, and this handy website helps explain the syntax, which can be a little confusing.
- And that's it! You can change all the parameters as needed, and you can even try making some tweaks to the script. For example, maybe you want the time-lapse video to show each frame for a set amount of time rather than keeping a fixed duration for the whole video, in which case you can get rid of the input argument and simply set the framerate to a constant.
Learn more about DMC's embedded design expertise.