Skip to content

Instantly share code, notes, and snippets.

@aadm
Last active March 8, 2020 19:02
Show Gist options
  • Save aadm/661ff15f6b23f1d58c14c87c9a5ed9e0 to your computer and use it in GitHub Desktop.
Save aadm/661ff15f6b23f1d58c14c87c9a5ed9e0 to your computer and use it in GitHub Desktop.
Creating movies from an image sequence with ffmpeg
# execute with `sh script.sh`
DIR=/Users/alex/Pictures/sequence
for i in $DIR/*_BURST000.jpg
do
TMP=`basename ${i} .jpg`
IN=${TMP%???}
OU=`echo ${TMP} | cut -d'_' -f3`
echo "create video from sequence starting with ${IN}, output to ${TMP}.mp4"
ffmpeg -framerate 5 -i ${DIR}/${IN}%03d.jpg -vcodec h264 -pix_fmt yuv420p -s 1080x1920 -crf 20 ${OU}.mp4
done

How to create a movie from an image sequence

Start from a sequence of images, i.e. a high rate continuous shooting with a camera or a smartphone. You end up with a series of jpg named for example img000.jpg, img001.jpg, img002.jpg, etc.

Let's assume that you also know the speed at which the camera has fired off the shots, for example 5 fps.

This is how to merge them into a video:

ffmpeg -r 5 -i img%03d.jpg -vcodec h264 -pix_fmt yuv420p -crf 22 -s 1920x1080 MOVIE.mp4

The key parameter is the -r (or -framerate) followed by the fps (frame-per-second) value that will be equivalent to the one used to shoot the sequence (increasing the framerate gives accelerated video). This parameter has to be specified before the input frames!

The quality factor (crf) 22 is a good compromise, if you want to stick to Vimeo's guidelines either use -crf 18 or set the exact bitrate with -b:v xxM (Vimeo suggests between 10 and 20 Mbps for a full HD (1080p) video).

As a reference, keep in mind that raw video shot with common cameras are between 20 and 50 MBps:

DJI Spark Gopro 5 Nikon D600 Olympus OMD EM10
24 45 22 21

And the size of the output files (input file = 1.79 Gb) are:

  • crf 10 = 3.6 Gb
  • crf 18 = 1.4 Gb
  • crf 22 = 740 Mb
  • crf 25 = 455 Mb

To join together a few clips:

ffmpeg -f concat -safe 0 -i <(for f in *.mp4; do echo "file '$PWD/$f'"; done) -c copy OUT.mp4

To crop while creating the video (for example in this case I started from a sequence of vertical i.e. portrait oriented photos and wanted to cut only the middle part of the frame changing the orientation to horizontal):

ffmpeg -framerate 5 -i IMG%03d.jpg -filter:vf "crop=in_w:in_h-2844,scale=1920x1080" -OUT.mp4

The input dimensions to the crop filter have shortcuts like in_w and in_h which are equivalent to original width and height respectively. The frames are 2340x4160 px so the above crop means keeping the horizontal unchanged and the vertical cut so that I end up with 1316 pixel (=4160-2844) which gives back a 16:9 ratio. Then I rescale the output to Full HD size (1920x1080).

To batch process multiple sequences I can use a for loop like in the script below.

To make it smooth and create interpolated frames between each frame use butterflow:

butterflow -r 3x ${OU}.mp4 -o ${OU}_bf.mp4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment