· 563 words · 3 minute read

Creating movies and GIFs from a series of photos

I sometimes use ‘burst mode’ on my camera if I’m making photographs of my daughter (or cat), so I can select the best photo and discard the rest. After a while I found out that these burst-photos are also cool to show as a video. These short ‘movies’ look they are shot with an old-fashioned videocamera.

Here’s my process 🤓

Images to MP4 #

The command to create a movie from a series of jpg-images (without resizing):

ffmpeg -r 10 -pattern_type glob -i "*.JPG" -vcodec libx265 -tag:v hvc1 -preset veryslow -crf 20 -an -pix_fmt yuv420p result.mp4
  • -vcodec libx265: the best quality encoder
  • -tag:v hvc1: necessary for playback on OSX
  • -crf 20: great quality / filesize (28 is default, 16 is visually lossless)
  • -an: no audio
  • -pix_fmt yuv420p: also necessary for playback in Quicktime
  • -preset veryslow: slow encode, best quality
  • -r 20: 20 ms between frames
  • optionally -vf "scale=-1:420, format=gray": rescale (to 420p) and gray-scale

CRF is a factor to indicate quality/filesize. I find it extremly hard to judge the result from this. One source suggests using CRF 16, but to my eye there is no difference between 17 or 20. You can check for yourself with two samples I generated: image 1, image 2. I’ve included the previous encoder of choice in the table below as well to show how impressive H.265 is. According to the documentation, CRF 23 is default in H.264 and CRF 28 is default in H.265.

H.264, CRF 1738MBgreat
H.265, CRF 1727,5MBgreat
H.265, CRF 2017,2MBgreat
H.264, CRF 2313,7MBgood
H.265, CRF 283,5MBgood (impressive for this filesize)

for 24 JPG images all at 4,7MB (totaling 112,8MB)

Images to GIF #

H.265 is nice, but sometimes you need a more archaic format if you want to share your movie. The following incantation converts a series of images to a GIF. You will need ffmpeg and ImageMagick installed (which is easy, if you have brew on your Mac).

ffmpeg -pattern_type glob -i "*.jpg" -vf scale=800:-1 -r 10 -f image2pipe -vcodec ppm - | convert -delay 10 -layers Optimize -loop 0 - result.gif

The above seems to create the best looking gif for the smallest filesize (2,5MB for the same 24 images).

Other methods I’ve tried:

  • using only ffmpeg: some weird pattern gets added to the GIF
  • using imagemagick first and ffmpeg last: same weird pattern added to the GIF
  • using only imagemagick: the file ends up twice as big, no visible improvement
  • using graphicsmagic: similar results to imagemagick
  • using palettes, different scaling, different dithering in ffmpeg… Nothing got close to the combo-option described above:

Different dithering (looks good, bigger filesize)

ffmpeg -r 10 -pattern_type glob -i "*.JPG" -vf scale=800:-1:sws_dither=ed -an -pix_fmt rgb8 ffmpeg_dither.gif

Using palette creation and different rescaling (not a great result, also big file)

ffmpeg -r 10 -pattern_type glob -i "*.JPG" -vf scale=800:-1:flags=lanczos,palettegen -an -pix_fmt rgb8 -y tmp_palette.png
ffmpeg -r 10 -pattern_type glob -i "*.JPG" -i tmp_palette.png -lavfi scale=800:-1:flags=lanczos,paletteuse=dither=floyd_steinberg -an -pix_fmt rgb8 -y ffmpeg_lanczos_palette_dither.gif

Here’s more info on these settings

note: ImageMagick uses ‘delay’ and FFMPeg uses FPS. The delay in ImageMagick is described in ticks (1/100 of a second). So 20 FPS is a delay of 5 (delay=100/FPS)

Optimization #

Apparently ImageMagick already does a great job of optimizing. Using gifsicle --optimize does not result in a smaller filesize (sometimes even enlarging the file).

Tools used: ffmpeg 3.4.1, imagemagick 7.0.7-18