Raspberry : Create a TimeLapse machine

Background

I'm about to have some workers at home constructing some fun stuff in the garden. It would be nice to "survey" the progress with some cool progress video. Why not a timelapse ? But How can I do this ?

What is a timelapse ?

Official definition : A timelapse is a video or sequence of photographs that has been captured over an extended period and played back at a faster speed than it was recorded. The purpose of a timelapse is to condense a long period of time into a shorter period, allowing viewers to see changes that occurred over that time span.

So, the plan is to take a single shot every x seconds and aggregate a large amount of pictures to create a video. Looks cool. But how ? Can I do that with a Raspberry ? Of course ;) I did some researches and I've found this implementation : https://darkspirit510.de/2021/10/raspberry-pi-construction-cam/.  This is a very good start, but I need something autonomous.

First, we need a webcam to take the picture. Easy. Then create a video from them. It's seems to be more software than hardware.

take_picture.sh
#!/bin/sh
current_index=$(find /home/pi/Pictures -maxdepth 1 -type f | rev | cut -d/ -f1 | rev | sort -n | tail -n 1 | cut -d. -f1)
echo $current_index
next_index=$(($current_index + 1))

#take picture
fswebcam --set brightness=30% --set contrast=20% --line-colour \#FF000000 --top-banner --skip 2 --font sans:20 -r 1920x1080 "/home/pi/Pictures/$next_index.jpg"

#move old picture to target directory (create if necessary)
target_dir=$((current_index/2880))
mkdir -p "/home/pi/Pictures/$target_dir"
mv "/home/pi/Pictures/$current_index.jpg" "/home/pi/Pictures/$target_dir"

makeVideo.sh
#!/bin/bash
clear
# Define some colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color
BOLD_WHITE='\033[1;37m'

# Website to find free lounge music : https://mixkit.co/free-stock-music/tag/lounge/

# Check if image directory folder is provided as argument
if [ -z "$1" ]
then
    echo "Error: no image directory folder provided"
    echo "Usage: $0 /path/to/image_directory"
    exit 1
fi

# Directory containing image files
image_dir="$1"

# Check if the path ends with '/'
if [[ "${image_dir}" != */ ]]; then
    # If it doesn't, add a '/'
    image_dir="${1}/"
fi

current_date=$(date +%Y-%m-%d)
output_file="${current_date}_output.mp4"

# Set video dimensions and frame rate
video_width=1440
video_height=1080
frame_rate=15

start_time=$(date +%s)

echo "___________.__                  .____
\__    ___/|__|  _____    ____  |    |    _____   ______   ______  ____
  |    |   |  | /     \ _/ __ \ |    |    \__  \  \____ \ /  ___/_/ __ \
  |    |   |  ||  Y Y  \\  ___/ |    |___  / __ \_|  |_> >\___ \ \  ___/
  |____|   |__||__|_|  / \___  >|_______ \(____  /|   __//____  > \___  >
                     \/      \/         \/     \/ |__|        \/      \/"
echo =========================================================================
echo -e "${BOLD_WHITE}TimeLapse Creator v0.9 (c) 2023 Frederic Lhoest${NC}"
echo =========================================================================
echo

echo -e "${GREEN}Searching for files ... ${NC}"
echo
find "${image_dir}" -maxdepth 1 -name '*.jpg' -printf '%f\n' | sort -n | tr '\n' '\0' | xargs -0 -I {} echo "file '{}'" > files.txt
sed "s/'\([0-9]\+\)\.jpg/'${image_dir//\//\\/}\1.jpg/" files.txt > new_files.txt
num_files=$(cat new_files.txt | wc -l)
echo -e "${BOLD_WHITE}$num_files${NC} images found in ${BOLD_WHITE}${image_dir}${NC} !"
echo
echo -e "${GREEN}Creating video using ${BOLD_WHITE}${frame_rate}${GREEN} fps rate ... ${NC}"
echo
ffmpeg -loglevel warning -hide_banner -f concat -safe 0 -i new_files.txt -framerate ${frame_rate} -s:v ${video_width}x${video_height} -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -preset slow -crf 22 -pix_fmt yuv420p -y ${output_file} 2> /dev/null

echo
echo -e "${GREEN}Adding audio track ... ${NC}"
echo
ffmpeg -loglevel warning -i ${output_file} -stream_loop -1 -i lounge_music.mp3 -c:a aac -map 0:v:0 -map 1:a:0 -c:v copy -shortest -y temp_output.mp4

mv temp_output.mp4 ${output_file}
echo

end_time=$(date +%s)

# Cleanup temp files
echo -e "${GREEN}Cleaning up ... ${NC}"

rm -rf files.txt new_files.txt

total_time=$((end_time - start_time))
minutes=$((total_time / 60))
seconds=$((total_time % 60))
echo
echo -e "${GREEN}Video create in ${minutes}m:${seconds}s${NC}"
echo

crontab
# m h  dom mon dow   command
* * * * * /home/pi/take_picture.sh
* * * * * ( sleep 30s ; /home/pi/take_picture.sh )

The result : 



As you can see, I need some exposure adjustments. This is still a bit tricky, but I'm getting there ;)

Next step would be to create a 3D printed enclosure that holds the raspberry and the webcam together. I'm pretty sure this is doable. I just need to time to design it and test it.

Comments

What's hot ?

Wallbox : Get The Most Of It (with API)

PCBWay : CNC Machining

Nutanix : CVM stuck into Phoenix