FFmpeg: high quality animated GIF?

I've written a tool specifically for maximum quality:

https://gif.ski

ffmpeg -i video.mp4 frame%04d.png
gifski -o clip.gif frame*.png

It generates good per-frame palettes, but also combines palettes across frames, achieving even thousands of colors per frame.

If you want to reduce the video dimensions, add a scaling filter:

ffmpeg -i video.mp4 -vf scale=400:240 frame%04d.png

If you want to reduce the frame rate, add the fps filter:

ffmpeg -i video.mp4 -vf fps=12 frame%04d.png

You can combine the filters with -vf scale=400:240,fps=12


The key issue is that any gif picture or frame has an extremely limited palette of only 256 of the possible millions of colors in your video.

This is well explained here.

So, fairly recently (2015, version 2.6) ffmpeg got the palettegen and paletteuse filters that can generate better pallettes for each frame.

Therefore, make sure you are using a fairly recent version of ffmpeg.

So, there's your secret and key search term to get you to make high quality gifs in no time - study up on palettegen filters. Reddit beware.

Some references:

ffmpeg 2.6 release notes

ffmpeg docs

superuser

blog.phk.me


shell_exec("/usr/bin/ffmpeg -i video.mkv -r 20 -f image2pipe -vcodec ppm - | convert -delay 5 - output.gif");

I suppose you have no imageMagick installed on your environment, because "convert" is one of IM's tools.

As for the video artifacts, it is caused by the default dithering method in FFmpeg. For best results, I'd recommend floyd_steinberg or sierra2_4a, and maybe bayer with scale set to 3. (Also, there's no such things like "huge" pixels, they are the atomic elements of raster images.)

On the other side, you can achieve better results with ffmpeg only. First, I'd generate a palette of the input video:

ffmpeg -i <your_input.mkv> -filter_complex "fps=10;scale=500:-1:flags=lanczos,palettegen=stats_mode=full" -t 10 palette.png

Then, use this color template to generate the actual gif file:

ffmpeg -i <your_input.mkv> -i palette.png -filter_complex "[0]fps=10;scale=500:-1:flags=lanczos[scaled]; [scaled][1:v] paletteuse=dither=sierra2_4a" -t 10 <output.gif>

You might need to fiddle with the params and the dithering methods to achieve best result. You may also try to generate new palette for each frame, so you can skip the first pass, and use the new option in the paletteuse filter.