Create time lapse video from images: Difference between revisions

From WickyWiki
mNo edit summary
 
(15 intermediate revisions by the same user not shown)
Line 15: Line 15:


<syntaxhighlight lang=bash>
<syntaxhighlight lang=bash>
sourcedir=$HOME/Pictures/timelapse
find "$HOME/Pictures" -iname "*.jpg" -type f | sort | sed "s/\(.*\)/file '\1'/g"  > "$HOME/timelapse_files.txt"
 
find "${sourcedir}" -iname "*.jpg" -type f | sort | sed "s/\(.*\)/file '\1'/g"  > "${sourcedir}/../files.txt"
</syntaxhighlight>
</syntaxhighlight>


Line 23: Line 21:


<syntaxhighlight lang=bash>
<syntaxhighlight lang=bash>
ffmpeg -f concat -safe 0 -i "${sourcedir}/../files.txt" -r 25 -vcodec libx264 -crf 22 "${sourcedir}/../out.mp4"
ffmpeg -f concat -safe 0 -i "$HOME/timelapse_files.txt" -r 25 -vcodec libx264 -crf 22 ""$HOME/timelapse.mp4"
</syntaxhighlight>
</syntaxhighlight>


= Tuning =
= 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:


== Increase the playback speed ==
  Music length 2:30 minutes


Increase the playback speed (x2), the resulting file will be smaller:
Then use the following video filter to shorten the video by increasing the playback speed:


<syntaxhighlight lang=bash>
  setpts=(PTS-STARTPTS) * <music-length> / <video-length>
ffmpeg -f concat -safe 0 -i "${sourcedir}/../files.txt" -vf "setpts=(PTS-STARTPTS) / 2" -r 30 -vcodec libx264 -crf 22 "${sourcedir}/../out_fast.mp4"
 
</syntaxhighlight>
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


== Crop the picture  ==
= The complete example =


  crop=<width>:<height>:<left>:<top>
Settings:


<syntaxhighlight lang=bash>
<syntaxhighlight lang=bash>
ffmpeg -f concat -safe 0 -i "${sourcedir}/../files.txt" -filter:v "crop=1280:800:0:224" -r 25 -vcodec libx264 -crf 22 "${sourcedir}/../out.mp4"
projdir="$HOME/Downloads/"
picsdir="2019-03-24"
mp3file="my music.mp3"
</syntaxhighlight>
</syntaxhighlight>


== Add music, crop ==
Create the pictures index file:


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:
<syntaxhighlight lang=bash>
find "${projdir}/${picsdir}" -iname "*.jpg" -type f | sort | sed "s/\(.*\)/file '\1'/g"  > "${projdir}/files.txt"
</syntaxhighlight>


  2500 pictures -> 2500/25 = 100 seconds of video = 1:40 minutes
Count the number of pictures:


Lets say you have some music and want to speed-up the video to match the music length
<syntaxhighlight lang=bash>
numpics=$( wc -l "${projdir}/files.txt" | cut -d' ' -f1 )
</syntaxhighlight>


  Music length 1:30 minutes
Extract and calculate the length of the music in seconds:


Then use the following video filter to shorten the video
<syntaxhighlight lang=bash>
durationsec=$( 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' )
</syntaxhighlight>


  setpts=(PTS-STARTPTS) * <music-length> / <video-length>
Check the video length (and speed) calculation:


You can input this as a simple formula:
<syntaxhighlight lang=bash>
echo "Video length calculation : (PTS-STARTPTS) * ( ${durationsec} ) / ( ${numpics} / 25 )"
</syntaxhighlight>


  setpts=(PTS-STARTPTS)*(1*60+30)/(1*60+40)
Encode:
 
Complete example including crop:


<syntaxhighlight lang=bash>
<syntaxhighlight lang=bash>
ffmpeg -f concat -safe 0 -i "${sourcedir}/../files.txt" -i "${sourcedir}/../music.mp3" -filter:v "setpts=(PTS-STARTPTS)*(1*60+30)/(1*60+40), crop=1280:800:0:224" -r 35 -vcodec libx264 -crf 22 "${sourcedir}/../out.mp4"
ffmpeg -f concat -safe 0 -i "${projdir}/files.txt" -i "${projdir}/${mp3file}" -filter:v "setpts=(PTS-STARTPTS)*(${durationsec})/(${numpics}/25), crop=1280:800:0:224" -r 25 -vcodec libx264 -crf 22 "${projdir}/${picsdir} timelapse (${mp3file}).mp4"
</syntaxhighlight>
</syntaxhighlight>


= Options =
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


Input indexfile 'files.txt':
= Overview of the used options =
 
Input index-file 'files.txt':


   -f concat -safe 0 -i "files.txt"
   -f concat -safe 0 -i "files.txt"


These options allow for this indexfile format:
These options allow for this index-file format:


       file '/full/path/to/file1.jpg'
       file '/full/path/to/file1.jpg'
Line 80: Line 113:
       ...
       ...


Video filter. Speedup video by (1 / 0.4):
Add music from mp3 file:


   -vf "setpts=(PTS-STARTPTS)*0.4"
   -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:
Output framerate:


   -r 30
   -r 25
 
Output codec:
 
  -vcodec libx264


Output codec and quality setting 'Constant Rate Factor'. 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.
'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.


   -vcodec libx264 -crf 22
   -crf 22


Sources:
Sources:

Latest revision as of 15:45, 4 April 2019


Create timelapse

Install ffmpeg:

sudo apt install ffmpeg

Create timelapse indexfile:

find "$HOME/Pictures" -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:

durationsec=$( 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 video length (and speed) calculation:

echo "Video length calculation : (PTS-STARTPTS) * ( ${durationsec} ) / ( ${numpics} / 25 )"

Encode:

ffmpeg -f concat -safe 0 -i "${projdir}/files.txt" -i "${projdir}/${mp3file}" -filter:v "setpts=(PTS-STARTPTS)*(${durationsec})/(${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:

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: