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.
Setting | Filesize | Quality |
---|---|---|
H.264, CRF 17 | 38MB | great |
H.265, CRF 17 | 27,5MB | great |
H.265, CRF 20 | 17,2MB | great |
H.264, CRF 23 | 13,7MB | good |
H.265, CRF 28 | 3,5MB | good (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 andffmpeg
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