This is yet another take on how-to create a time-lapse video. In my case, a website updates a photo of the sky on a regular basis. I wanted to turn that into a time-lapse video and deploy to another, or possibly the same, website. I decided to use a Raspberry Pi 4 that was “sitting around.”
My project evolved as I tried different techniques and apps. I ended up creating a couple of bash scripts to do the job. I used the “ffmpeg” audio/video framework as it was bash command line friendly. I have tested my scripts on my Raspberry Pi 4 with Raspbian OS as well as on different Linux boxes running Ubuntu and Debian.
For how-to scripts with instructions, click on “more“
The first script I developed was to grab a remote image and store it locally in order to process images into video frames. I copy the remote image file using curl. If you have file access to the remote server, you might prefer to use ftp, sftp or scp. I rename the downloaded file (mv) to avoid processing a file that is not finished downloading. I occasionally saw an unfinished frame (top part of image only) when viewing video. Waiting for a completed download – and then renaming – fixed this issue. The stored files are named with the date and time and image type suffix – in my case “.jpg” Some other possibilities are .png, .jpeg, .tiff, etc. You should ensure correct conversion to video by using “ffmpeg” options for input file type, if needed.
#!/bin/bash
#
# grab_frames.sh
# copy remote image file to local directory
# - rename file to current date + time
# - sleep for set amount of seconds and loop
# - 120 seconds is a good choice for time-lapse video creation
# replace with your image URL
IMAGE_URL="https://server.com/subdir/webcam.jpg"
FRAMES_DIR="/home/pi/lapse_frames"
WAIT_SECS=120
while(true)
do
curl -s -o $FRAMES_DIR/temp_image.bin $IMAGE_URL
DATE=$(date +"%Y-%m-%d_%H%M")
mv $FRAMES_DIR/temp_image.bin $FRAMES_DIR/$DATE.jpg
sleep $WAIT_SECS
done
On my Raspberry Pi, as user Pi, I created a file in the home directory, “grab_files.sh” with the above shell script. After editing, change the permissions to make executable. My script saves the video frames to a directory, “/home/pi/lapse_frames” You need to create this dir before running the script 😉
pi@Pi4:~ $ vi grab_frames.sh #copy script into this file
pi@Pi4:~ $ chmod 755 grab_frames.sh
pi@Pi4:~ $ mkdir lapse_frames
To start the script in the background and keep it running even after logout, you use the “nohup” command in conjunction with (send to background) “&” You can also save any error messages to a log file:
pi@Pi4:~ $ nohup ./grab_frames.sh > grab_errors.log &
[1] 18053
nohup: ignoring input and redirecting stderr to stdout
The nohup command will return a process ID that you can use to kill the process – when you want it to stop. You’ll also (probably) see a message indicating that output (standard and errors) will be sent to “stdout” – which was set tp the file, “grab_errors.log” You can also find the process ID later or from a different terminal session using the “ps” command. See below for an example on how to find the PID and stop (kill) the process:
pi@Pi4:~ $ ps aux | grep -i grab_frames
pi 18053 0.0 0.0 7676 2476 pts/0 S 13:30 0:00 /bin/bash ./grab_frames.sh
pi@Pi4:~ $ kill 18053
OK, we now have a process running that will grab a remote image every 2 minutes and download to a local directory with date and time-stamp formatted name. We need to process the images (frames) into a video and clean-up the directory, as needed, so we don’t end up with a bunch of files that use up our disk space. I chose to make a cumulative video every 20 minutes for a single day. I also decided to create the video(s) only during daylight hours – as my need was for tracking clouds.
Create and edit “make_video.sh” in the Pi home directory. I use “vi” as my text editor but you may prefer another 😉
pi@Pi4:~ $ cd
pi@Pi4:~ $ vi make_video.sh #copy script into this file
pi@Pi4:~ $ chmod 755 make_video.sh
#!/bin/sh
# make_video.sh - Andy Felong - 15 Mar 2020
# grabs images from local dir: /home/pi/lapse_frames/
# filters images to today and selected (daylight) hours
# creates H.264, MP4 video file - set path below in $VIDEO_OUT
# set directory for input images (frames)
FRAMES_DIR="/home/pi/lapse_frames"
# set video output file
VIDEO_OUT="/home/pi/my_video_H264.mp4"
# set number of seconds between loops (1200 is 20 minutes)
LOOP_SECS=1200
# set debug flag to see more info
DEBUG=false
# Handle passed flags
# Handles "-" once-char and simple "--" one word flags
OPTS=`getopt -o hvd -l help,verbose,debug -- "$@"`
if [ $? != 0 ]
then
exit 1
fi
eval set -- "$OPTS"
while true ; do
case "$1" in
-h) echo "make_video.sh: usage: make_video.sh -[dhv]"; shift;;
-v) DEBUG=true; shift;;
-d) DEBUG=true; shift;;
--help) echo "make_video.sh: usage: make_video.sh -[dhv]"; shift;;
--verbose) DEBUG=true; shift;;
--debug) DEBUG=true; shift;;
--) shift; break;;
esac
done
#start of main loop
while(true) ; do
DATE=$(date +"%Y-%m-%d_")
YESTERDAY=$(date -d "yesterday 13:00" +"%Y-%m-%d")
if $DEBUG; then
echo 'date: '$DATE
echo 'yesterday: '$YESTERDAY
printf 'number of jpg files: '
ls $FRAMES_DIR/*.jpg | wc -w
fi
# creating video for today - delete old images from yesterday (if any)
rm $FRAMES_DIR/$YESTERDAY'_'*.jpg 2> /dev/null
# file names are in the format: YYYY-MM-DD_HHMM
# An example: 2020-03-17_1249.jpg
#
# I'm looking for daylight images - from 6am - only
# delete time entries with hours "00" to "05"
#
# NOTE: you may need to allow for time zone difference of your source!
# 6am Eastern is 3am Pacific - you may need to use "[012]" instead of "[012345]"
rm $FRAMES_DIR/$DATE'0'[012345]*.jpg 2> /dev/null
# assumes nighttime around 20:00 (8pm) - delete later images
# NOTE: you may need to allow for time zone difference of your source!
rm $FRAMES_DIR/$DATE'2'[0123]*.jpg 2> /dev/null
# clean-up for video creation - delete old video and index files
rm $VIDEO_OUT
rm /tmp/img*
# ffmpeg needs frames indexed (ordered and numbered)
# create index files in "/tmp" dir
x=1
for i in $FRAMES_DIR/*jpg
do
counter=$(printf %03d $x)
ln "$i" /tmp/img"$counter".jpg
x=$(($x+1))
done
# use ffmpeg to create video
# - ffmpeg has many options - check its manual page
# if DEBUG flag is set - show lots of info
# - if not set, keep silent
if $DEBUG; then
ffmpeg \
-f image2 \
-i /tmp/img%03d.jpg \
-vf format=yuv420p \
-framerate 24 \
-c:v libx264 \
-preset veryslow \
-qp 18 \
$VIDEO_OUT
else
ffmpeg \
-loglevel quiet \
-f image2 \
-i /tmp/img%03d.jpg \
-vf format=yuv420p \
-framerate 24 \
-c:v libx264 \
-preset veryslow \
-qp 18 \
$VIDEO_OUT
fi
# COPY video to a destination if desired using cp, scp, ftp, sftp, etc.
# ensure you have keys in place for no-login or add user + password to destination URL
# you do NOT want to enter authorization info every 20 minutes!
scp $VIDEO_OUT userame@remote_server.com:~
# wait/sleep for LOOP_SECS seconds (set above) and loop
sleep $LOOP_SECS
done
You can change the script to have complete 24 hour coverage if/as needed. You could also filter for specific hours as I have done. Remove or edit the “rm” statements in lines 65 & 69.
You can start/stop video creation using the same method as the frame-grabber script.
#start
pi@Pi4:~ $ nohup ./make_video.sh > make_video.log &
[2] 29007
nohup: ignoring input and redirecting stderr to stdout
#stop
pi@Pi4:~ $ ps aux | grep -i make_video
pi 29007 0.2 0.0 1940 1276 pts/0 S 17:42 0:00 /bin/sh ./make_video.sh
pi@Pi4:~ $ kill 29007
You can modify the scripts for your own needs. They could be turned into services that auto-start at system boot. I’ve run different pieces on different servers. My images already have the date and time in the lower right corner but, if desired, you could use “ImageMagick” tools to manipulate the images or add text with the “convert” command – such as a title or date and time.
LMK if you have questions or issues in the comments.
[…] are plenty of ways to create timelapse videos, but [Andy] has an efficient method for ensuring up-to-date ones exist for his infrared sky camera, and he has it running thanks to some well-documented shell scripts on a spare Raspberry Pi. The […]
[…] are many ways to create timelapse videos, but (Andy) has An efficient method to ensure there are up-to-date ones for your infrared sky camera, and you have it working thanks to some well documented shell scripts on a spare Raspberry Pi. The […]
[…] are plenty of ways to create timelapse videos, but [Andy] has an efficient method for ensuring up-to-date ones exist for his infrared sky camera, and he has it running thanks to some well-documented shell scripts on a spare Raspberry Pi. The […]
[…] are plenty of ways to create timelapse videos, but [Andy] has an efficient method for ensuring up-to-date ones exist for his infrared sky camera, and he has it running thanks to some well-documented shell scripts on a spare Raspberry Pi. The […]
Hi Andy,
What camera are you using and if you’re using it for night sky time lapses have you got any photos?
Will
Hi Will, My scripts grab an image from a remote site or server – so the camera doesn’t matter. I happen to be using a Raspberry Pi Zero SBC with “official” Pi NoIR Camera V2. It is oriented for IR but at night, all I get is a black image 😉 – Andy