Skip to content

Instantly share code, notes, and snippets.

@TaylorBurnham
Created February 1, 2021 14:08
Show Gist options
  • Save TaylorBurnham/ad83f7e549561903a6408e6dcec49215 to your computer and use it in GitHub Desktop.
Save TaylorBurnham/ad83f7e549561903a6408e6dcec49215 to your computer and use it in GitHub Desktop.
Timelapse using ffmpeg and glob patterns

This is a quick and dirty script to create a timelapse using ffmpeg. I have a systemd timer that takes a snapshots of all my cameras every 5 minutes and dumps them into a folder, which allows me to make some interesting time lapses.

The gist of the script is:

  • Uses find to locate the first file in the directory, and then ffprobe to get the resolution of the image.
  • Uses glob patterns to build a list of all files and runs it through ffmpeg.
  • filter_complex is used to hold the last frame for 2 seconds, which can be adjusted with the $FFMPEG_HOLD variable.

Syntax is below:

make-timelapse.sh <input path as glob> <output file>

Example

make-timelapse.sh "Front-Yard/*/*.jpg" "2021-02-01 Front Yard.mp4"

This was written and tested on ffmpeg version 3.2.14-1~deb9u1, and this does not work on ffmpeg version 4.2.3 built with gcc for Windows because glob patterns aren't supported. You can get around this by using sequence wildcards, e.g. -i image%03d.jpg, but that's up to you. This ran fine on Debian under WSL.

#!/bin/bash
# Input and Output
INPUT_PATH="$1"
OUTPUT_FILE="$2"
# Get the resolution of a single file
SAMPLE_FILE=$(find $INPUT_PATH | head -n1)
FFMPEG_RESOLUTION=$(ffprobe -v error -show_entries stream=width,height -of csv=p=0:s=x "${SAMPLE_FILE}")
# Modify as needed, but 30fps for snapshots taken every 5 minutes
# produces a very smooth time lapse.
FFMPEG_FRAMERATE=30
FFMPEG_CODEC="libx264"
FFMPEG_CRF=17
# Duration to hold the last frame for.
FFMPEG_HOLD=2
FFMPEG_HOLD_FILTER="[0]trim=0:${FFMPEG_HOLD}[hold];[0][hold]concat[extended];[extended][0]overlay"
# Create the timelapse file
ffmpeg -framerate "${FFMPEG_FRAMERATE}" -pattern_type glob -i "${INPUT_PATH}" \
-s:v "${FFMPEG_RESOLUTION}" -c:v "${FFMPEG_CODEC}" \
-crf "${FFMPEG_CRF}" -pix_fmt yuv420p \
-filter_complex "${FFMPEG_HOLD_FILTER}" \
"${OUTPUT_FILE}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment