Birds Timelapse

 

Intro

I setup a small bird feeder on my balcony and wanted to record the birds that visited throughout the day. Setting up my GoPro Session 5 was the obvious choice but revisiting my ffmpeg timelapse script I decided to make the process a bit more straigthforward.

GoPro Settings

For this application I used similar setting as I did for my previous timelapse applications:

Interval: 1 photo / 1 sec
Megapixels: 10MP Linear
Spot Meter: Off
Protune: On
  Color: Flat
  White Balance: Auto
  ISO Max: 800
  EV Comp: 0.0
  Sharpness: Medium

File Structure

GoPros nest file exports into different subfolders as follows:

- DCIM
    - 144GOPRO
        - G0014667.JPG
        - G0014668.JPG
        ...
        - G0014987.JPG
    - 145GOPRO
    - 146GOPRO
    ...
    - 165GOPRO

so we will have to go through them in generating our video.

Code

This time, instead of moving files around as I did last time, I wanted to do everything in place to make the processing easier and faster.

Getting a full filelist

The simplest way to build the timelapse video from files named sequentially placed in different folders is to compile a sorted list of their paths into a text file:

find . \
  -type f \( -name "*.jpg" -o -name "*.png" \) \  # Get all files with JPG or PNG extensions in subpaths
  | sort -V | \                                   # Sort naturally
  awk '{print "file \x27" $0 "\x27"}' \           # Prepends the word file and surround by quotation marks
  > list.txt                                      # Export to a txt file

Generating Video

To get the filelist compiled into a video we can use the following command:

ffmpeg \
  -f concat \         # Invokes the concatenator demuxer
  -safe 0 \           # Allows ffmpeg to read absolute and paths with special characters
  -r 50 \             # Sets the framerate to a specific value
  -i list.txt \       # Specifies the input file 
  -crf 28 \           # Sets the constant rate factor (higher means more compression but less quality)
  -preset slow \      # Sets the compression preset (slower means more compression but more processing time)
  -c:v libx265 \      # Sets the video encoder to libx265
  -pix_fmt yuv420p \  # Converts the video color format to yuv420p
  tlapse.mp4 

Metadata Overlay

One final thing that I wanted to add was an overlay with the date and timestamp so that I could track the times at which birds would more often visit. This was a bit trickier but after some searching I came across the following commands:

-vf "drawtext=fontfile='/Library/Fonts/Arial.ttf':text='%{metadata\:DateTime\:def_value}':fontcolor=white:fontsize=75:box=1:boxcolor=black@0.5:x=w-tw-100:y=h-th-100,scale=1920:-2"

Full Set of Instructions

With these parts in place, all we have to do is to navigate to our root folder from the terminal and run the following commands:

# Generate filelist
find . \
  -type f \( -name "*.JPG" -o -name "*.png" \) \
  | sort -V | awk '{print "file \x27" $0 "\x27"}'\
  > list.txt
  
# Create video
ffmpeg -f concat \
  -safe 0 \
  -r 50 \
  -i list.txt \
  -vf "drawtext=fontfile='/Library/Fonts/Arial.ttf':text='%{metadata\:DateTime\:def_value}':fontcolor=white:fontsize=75:box=1:boxcolor=black@0.5:x=w-tw-100:y=h-th-100,scale=1920:-2" \
  -crf 28 \
  -preset slow \
  -c:v libx265 \
  -pix_fmt yuv420p tlapse.mp4

Final Thoughts

These commands have saved quite a bit of processing time and the overlay helps quite a bit. Will put them together into a proper bash script in the future but for now this will have to do.