Monday, August 4, 2014

Convert video to animated gif with ffmpeg

Thanks to the help in this SuperUser question, I'm posting some commands for future reference that make it easy to convert video or movie files to animated GIF.

This requires ffmpeg (and image-magick, if you want better quality). If you have a Mac and need those programs, you can do brew install ffmpeg imagemagick to install them.

NOTE: To convert videos to a more HTML5-compatible format like WebM, install ffmpeg with the --with-libvpx --with-libvorbis --with-fdk-aacc options.

Basic conversion:

ffmpeg -i input.mp4 -r 20 output.gif

-r 20 means 20 frames per second, which is pretty common; 20 FPS looks smooth to the human eye.

Better quality:

ffmpeg -i input.mp4 -r 20 -f image2pipe -vcodec ppm - | convert -delay 5 - output.gif

-f image2pipe tells ffmpeg to output the images through the stdout pipe. -vcodec ppm indicates that the codec used should be for the PPM format (a kind of plain-text representation of images using RGB color values). The -delay 5 means that convert should insert a new frame every 5 ticks. There are 100 ticks in a second, so this equates to 20 FPS. By disproportioning the -r and -delay values, you can make your gif faster or slower.

Better quality at smaller file size:

ffmpeg -i input.mp4 -r 20 -f image2pipe -vcodec ppm - | convert -delay 5 - gif:- | convert -layers Optimize - output.gif

Here we run it through convert twice to optimize the different layers. This should reduce the file size a little bit.

But after all this, I discovered that just encoding the original videos using Handbrake with "Web Optimized" checked and moving up the RF slider to a higher value (like 22) was significantly better. A nice-looking gif was about 10 MB but a nice-looking, re-encoded video from Handbrake was only about 200 KB. Go figure.

Bonus tips: resizing images

Image Magick can also resize images on-the-fly and en masse.

One image:

convert input.png -resize 400x400 resized.png

Many images:

mogrify -resize 400x400 *.png

Note that, by default, convert and mogrify will resize the image to fit into those dimensions, keeping the aspect ratio. They will not distort the image. In other words, the -resize value is the maximum dimensions for either side (WxH).

Also, mogrify will overwrite original files. However, the latest versions generate backup files with a tilde (~) at the end of the file name. If you want to prevent this, specify a sub-directory to put the results into:

mogrify -path resized_images -resize 400x400 *.png

(I noticed a more pixellated quality on my Retina MBP when using the -path option. I don't know why. Also, the path must exist beforehand.)

Yay for not doing this all manually!

Extra bonus: convert MP4 to WebM

Thanks to this guide, it's pretty easy to convert MP4 to WebM:

ffmpeg -i input.mp4 -c:v libvpx -crf 40 -b:v 1M -c:a libvorbis output.webm

The CRF value can be anywhere from 4-63 where a lower value is higher quality. They recommend to start at 10, but if your goal is small file size, try a value around 40 and go from there. I found 40 to produce a small video that was still good enough for the web.