Create time lapse video from images
Create timelapse
Install ffmpeg:
sudo apt install ffmpeg
Create timelapse indexfile:
find "$HOME/Pictures/timelapse" -iname "*.jpg" -type f | sort | sed "s/\(.*\)/file '\1'/g" > "$HOME/timelapse_files.txt"
Create the video:
ffmpeg -f concat -safe 0 -i "$HOME/timelapse_files.txt" -r 25 -vcodec libx264 -crf 22 ""$HOME/timelapse.mp4"
Playback speed and Music
The original video-length is the length when we create the video without 'setpts=~'. The images will be read as a stream of 25 pictures per second (input framerate=25). For example:
2500 pictures -> 2500/25 = 100 seconds of video = 1:40 minutes
Lets say you have some music and want to speed-up the video to match the music length:
Music length 2:30 minutes
Then use the following video filter to shorten the video by increasing the playback speed:
setpts=(PTS-STARTPTS) * <music-length> / <video-length>
You can add this option as a simple formula:
setpts=(PTS-STARTPTS)*(2*60+30)/(2500/25)
Cropping
My source is a set of pictures of size 1280 x 1024, by cropping this to 1280:800 I will have a 16:10 aspect ratio (which is a better fit for my screen).
1280 * 10/160 = 800
I want to keep the bottom part of the picture so I need to move down by:
1024 - 800 = 224
This results in the video filter option:
crop=1280:800:0:224
The complete example
Settings:
projdir="$HOME/Downloads/" picsdir="2019-03-24" mp3file="my music.mp3"
Create the pictures index file:
find "${projdir}/${picsdir}" -iname "*.jpg" -type f | sort | sed "s/\(.*\)/file '\1'/g" > "${projdir}/files.txt"
Count the number of pictures:
numpics=$( wc -l "${projdir}/files.txt" | cut -d' ' -f1 )
Extract and calculate the length of the music in seconds:
mp3calcsec=$( ffmpeg -i "${projdir}/${mp3file}" 2>&1 | grep Duration | sed 's/.*\([0-9]\{2\}\):\([0-9]\{2\}\):\([0-9]\{2\}\).[0-9]\{2\},.*/\1*3600+\2*60+\3/g' )
Check the calculation:
echo "Video speed calculation : (PTS-STARTPTS) * ( ${mp3calcsec} ) / ( ${numpics} / 25 )"
Encode:
ffmpeg -f concat -safe 0 -i "${projdir}/files.txt" -i "${projdir}/${mp3file}" -filter:v "setpts=(PTS-STARTPTS)*(${mp3calcsec})/(${numpics}/25), crop=1280:800:0:224" -r 25 -vcodec libx264 -crf 22 "${projdir}/${picsdir} timelapse (${mp3file}).mp4"
Looking for some music to add? You might want to take a look here:
- https://www.jamendo.com/start
- https://cctrax.com/
- https://freemusicarchive.org/genre/Ambient/?sort=track_interest
Overview of the used options
Input index-file 'files.txt':
-f concat -safe 0 -i "files.txt"
These options allow for this index-file format:
file '/full/path/to/file1.jpg'
file '/full/path/to/file2.jpg'
...
Add music from mp3 file:
-i "music.mp3"
Video filter 'PTS' is the presentation timestamp, the time at which a frame ought to be presented. We can make a video twice as fast by dividing the frame-PTS by 2:
-filter:v "setpts=(PTS-STARTPTS) / 2"
Crop video filter. crop=<width>:<height>:<left>:<top>:
-filter:v "crop=1280:800:0:224"
Output framerate:
-r 25
Output codec:
-vcodec libx264
'Constant Rate Factor' quality setting. For x264, this means setting a value somewhere between 18 and 26 for this CRF. The default is 23, and higher values will give you worse quality.
-crf 22
Sources: