
High quality GIF with FFmpeg - ux
http://blog.pkh.me/p/21-high-quality-gif-with-ffmpeg.html
======
dangerlibrary
ffmpeg is downright magical - just don't get caught using the one in the
Ubuntu/Debian repositories. Compile your own ffmpeg if you have any need to do
serious work; the Libav fork just isn't as capable. The reasons are obvious if
you look into the development philosophies of the two projects.

[https://github.com/mpv-player/mpv/wiki/FFmpeg-versus-
Libav](https://github.com/mpv-player/mpv/wiki/FFmpeg-versus-Libav)

~~~
amelius
> ffmpeg is downright magical

Actually, in my experience, ffmpeg is the linux-program that by far outshines
any other program in... failing or crashing :/

I'm sorry to say this. And, unfortunately, there isn't any other open source
program doing a better job in terms of file format support.

~~~
dangerlibrary
I would agree that ffmpeg has warts. It is pretty poorly documented. Also,
filter pipelines are finicky and not commutative, which can be super
confusing, but most of the time you don't need them. Aspect ratio syntax is a
disaster, but aspect ratio specifications are a little bit of a disaster, so I
don't know how much to blame ffmpeg. But simply failing or crashing? I can't
say I've ever had a crash that wasn't the result of a misconfiguration on my
part.

What's nice is that on linux VLC is basically a QT4 GUI wrapper around ffmpeg,
so you can do pretty much whatever you need to do from within VLC.

~~~
chanux
I think ffmpeg deserves my support on this as well. I maintain a video system
at work and using ffmpeg for conversions. ffmpeg has never given me troubles
(we compile our own ffmpeg).

------
quotedmycode
So it's using a simple Median Cut quantization... which is okay, but you can
get great results using an octree quantizer, and without dithering. Dithering
kills your compression savings in GIF so you'd want to avoid it if possible.
In any case, you can see the difference a better quantizer makes here:

[http://www.leptonica.com/color-
quantization.html](http://www.leptonica.com/color-quantization.html)

~~~
derf_
Any method that makes axis-aligned subdivisions (which includes both standard
median cut and octree), even in a space like HSV, is going to be pretty
suboptimal. There's probably been more sophisticated things done since I
looked at this in the 1990's, but Xiaolin Wu's 1992 approach [1] works quite a
bit better than both (including the 1991 Wu v2 implementation of an octree
method linked elsewhere in this thread). It's based on recursive PCA, dynamic
programming to assign colors along the principal axis, and K-means refinement
in CIE L* u* v* coordinates. Not the fastest algorithm, but the topic is "high
quality".

And you can still dither the image without completely destroying compression.
You just have to use an ordered dither [2].

[1] Xiaolin Wu, "Color Quantization by Dynamic Programming and Principal
Analysis", ACM Transactions on Graphics 11(4): 348-372, 1992.
[https://dl.acm.org/citation.cfm?id=146475](https://dl.acm.org/citation.cfm?id=146475)

[2]
[https://xiphmont.livejournal.com/35634.html](https://xiphmont.livejournal.com/35634.html)

~~~
pornel
Aligned subdivisions are not that much of a problem actually.

I've tested median cut that can cut at various angles and variants that cut
out spheres, and it didn't make much difference.

Choice of the box to cut and the location where you cut is more important.
Wu's method is nice in this case because it exactly measures variance of sets
after a split, while median cut just estimates.

However, Wu's method needs lookup tables for the whole color (hyper)cube,
which requires either large (or for RGBA still ridiculous) amount of RAM or
reduced precision, and losing bits of input is way worse than having
suboptimal division.

The biggest wins I've found (and implemented in libimagequant) were:

• Voronoi iteration after generating palette (like a final step in LBG
quantization). This shifts axis-aligned subdivisions to local optimum (I've
tried applying that after every subdivision, but it didn't matter — once in
postprocessing is enough!)

• Adjust weights/counts in histogram from quality feedback measured from
remapped image. If you're aiming to minimize MSE, then that's not too
expensive and it's similar to gradient descent.

~~~
derf_
_> However, Wu's method needs lookup tables for the whole color (hyper)cube,_

You're talking about the 1991 method. The 1992 paper I cited explicitly claims
as one of its advantages that it does not require lookup tables (and thus
avoids the usual step of pre-quantizing down to 5 bit color to get a
reasonably-sized table).

Your two big wins sound an awful lot like "K-means". I'd believe they are
responsible for the bulk of the improvement (they're also the bulk of the
computation), but they mean you don't have axis-aligned partitioning anymore,
which was my point.

The problem is that K-means is notoriously sensitive to the initial
clustering. For unsupervised learning, I'd want to do as good a job there as
possible, and applying PCA means you are picking the split direction that
exactly minimizes variance in the orthogonal directions. Random restarts are
also a nice way to escape local minima, but are even more expensive
computationally.

~~~
pornel
It is similar to K-means, but with exactly the crucial difference that
clusters are not random, but picked by a guided subdivision algorithm.

------
1ris
>As you probably know, GIF is limited to a palette of 256 colors.

No, it's not. OK, the current, wrong, implementations do limit it to 256
colors, but that's not a limitation of gif. Mulitple frames without a delay
allow multiple pallets and multiple times 265 colors.

But this limitation is just another reason not to use it.

Can I use Webm?

[http://caniuse.com/#feat=webm](http://caniuse.com/#feat=webm)

Yes, you can, and you should. Or h.264:

[http://caniuse.com/#feat=mpeg4](http://caniuse.com/#feat=mpeg4)

~~~
wukerplank
While GIF is surely inferior to short looped videos, it's still ahead in terms
of usability/portability: Drag & drop the file to the desktop and re-upload
elsewhere (or embed in your own website). AFAIK this experience is unmatched
by web video.

~~~
1ris
Global support for h.264 video in the browser: over 90%. And on the desktop
it's close to 100%. That's IMO just good enough.

~~~
wukerplank
That's not what I was referring to. Yes, technically videos are superior, no
doubt. The nice thing about GIFs is though that they are treated like images
by the browser and the OS. That makes them easier to handle by non-technical
users (think imgur, Tumblr, etc.).

~~~
1ris
I just realised that imgur does not support webm. I thought it does. Thats
kind of stupid. For other websites it'd be as simple as adding a mime type to
the list of accepted uploads. Unfortunalty you are right, right now webm is
still exotic.

~~~
Springtime
I've seen WebMs on Imgur. When saved and opened to check the encoding some are
VPx, while others are h.264 encoded in a WebM container.

I can probably find some links later. As I see no option to upload video
directly I'm wondering if it requires an account, or whether it was their
new(ish) GIF conversion process (IIRC some look like original videos though).

~~~
1ris
You can't upload webms tough.

------
artursapek
I use this shell script for generating gifs out of .mov files:
[https://gist.github.com/artursapek/5b3d15ecac5ff75593c4](https://gist.github.com/artursapek/5b3d15ecac5ff75593c4)

I can probably improve it further by using some of what's in this article, but
it's already faster and better than any online tool I've found.

~~~
ux
> (convert -delay 5 -loop 0 $tmp_dir/ffout*.png $2) >& /dev/null

So using ImageMagick for this... How is this memory wise BTW? (all frames are
in memory at once or not?)

~~~
bigboat
Yes, all frames will be in memory prior to making the GIF. Probably fine for
most GIFs, but if you want to go FFmpeg | ImageMagick | FFmpeg for processing
a video, or maybe for a longer GIF, you can use this script to keep only a
frame at a time in memory:
[http://www.imagemagick.org/Usage/scripts/process_ppm_pipelin...](http://www.imagemagick.org/Usage/scripts/process_ppm_pipeline)

------
FranOntanaya
ffmpeg doesn't get nearly enough credit. As long as you can grok the various
settings, it makes you feel like McGyver with a paperclip. We work often with
media from unusual sources, and after the first "can we do this with ffmpeg"
filter there's very little left to handle.

------
Pephers
This is pretty cool. I use GIFs for marketing for my SaaS startup[1] because
it has the best support for autoplaying across devices, but the file sizes are
a bit high (690 KB and 270KB for screencasts of a few minutes each). I use
licecap[2] for recording and Gifsicle for optimizing, but perhaps I should
give ffmpeg a go and compare the results.

[1] [https://zapla.co](https://zapla.co)

[2] [http://www.cockos.com/licecap/](http://www.cockos.com/licecap/)

------
theophrastus
This is an interesting discussion, thank you. It would be great to see it
compared with the parallel ImageMagick methods:
[http://www.imagemagick.org/Usage/anim_opt/](http://www.imagemagick.org/Usage/anim_opt/)

~~~
ux
ImageMagick is very popular, but apparently the algorithms in pngquant gives
excellent results. Don't forget to include it if you do comparisons with the
different solutions.

Also keep in mind that the compression efficiency and quality depends a lot on
the content and how you play with the encoding options (how surprising...). I
tried to cover most of the cases in my post, but make sure you are "fluent"
with the other tools as well to make an objective comparison.

Overall, I think FFmpeg trump-card is that it includes the whole stack;
timing, decoding, filtering, encoding, everything is in.

------
syoc
There is no reason to create new content in .gif and not webm as of now.
FFmpeg is really nice though.

~~~
mikehearn
I'm not going to tell you anything new here, but there are reasons to use GIF
instead of video. WebM isn't supported on Safari & IE. H.264 isn't officially
supported on Firefox (though I believe OS X and Window may now provide their
own decoders that Firefox uses). To get a similar experience to GIF, you need
two formats and it needs to be embedded in an HTML file using a <video> tag.
Compare that to the GIF experience, where you link to the image and it works
the same way everywhere.

There simply is not a video-based standard that implies "short, silent,
autoplayed, looped video" in the way that animated GIFs do. There are ways to
approximate the behavior in HTML, but none of them are perfect in the way GIFs
are.

~~~
kuschku
Actually, Firefox supports h264 nowadays. Cisco bought a license to the
patent, and gave it to Mozilla for free, so they can freely distribute an h264
decoder.

------
mplewis
I wanted to use FFmpeg in an iOS app, but I ran into licensing issues—the
FFmpeg wrapper [1] and FFmpeg itself [2] are both LGPL 2.1, which I didn't
think you could use in an iOS app.

Since this project does exactly that, I took a second look and found a
discussion on that specific use case [3]. It didn't quite clarify things, but
it looks like it _might_ be legal to use FFmpeg in an app.

[1]
[https://github.com/OpenWatch/FFmpegWrapper](https://github.com/OpenWatch/FFmpegWrapper)
[2] [https://www.ffmpeg.org/legal.html](https://www.ffmpeg.org/legal.html) [3]
[https://trac.ffmpeg.org/ticket/1229](https://trac.ffmpeg.org/ticket/1229)

~~~
chrisballinger
Oh hey, I wrote that! There are plenty of apps that are distributing LGPL code
on the App Store, for example, VLC for iOS [1] includes FFmpeg. The static
linking requirement on iOS 7 and earlier prompted some proprietary app
developers (like Sparrow [2]) to distribute their object files to allow re-
linking.

Now that iOS 8 offers dynamic frameworks, I'm not sure if this situation has
changed. Even though they are dynamically linked, it is impossible for the end
user to replace a library due to the code signing requirements.

1\. [http://www.videolan.org/vlc/download-
ios.html](http://www.videolan.org/vlc/download-ios.html) 2\.
[https://web.archive.org/web/20131013023029/http://sprw.me/lg...](https://web.archive.org/web/20131013023029/http://sprw.me/lgpl.php)

------
neeee
Gifsicle is very good at making highly optimized GIFs, but slightly more
cumbersome as you have to convert each frame to a separate image first.

[http://www.lcdf.org/gifsicle/](http://www.lcdf.org/gifsicle/)

------
oakwhiz
What would be really cool is if ffmpeg/avconv gained the ability to create
lossy LZW GIFs, like in this tool:

[https://github.com/pornel/giflossy](https://github.com/pornel/giflossy)

------
sorenjan
Nice article and good job implementing it. I would have preferred a small
explanation of the filter graph option (-lavfi), but I guess that's outside
the scope of the post.

~~~
ux
Yeah, but the article is already quite long so I omit the "details" on that...

Basically, it's just to specify a complex filtergraph: in the case of -vf
you're just passing one video stream which gets filtered by successive
filters. In the case of -lavfi (or -filter_complex if you prefer) you can feed
multiple inputs (and get multiple outputs). In this case, the second input is
the palette image.

You can find more information on [http://ffmpeg.org/ffmpeg-
filters.html#Filtering-Introduction](http://ffmpeg.org/ffmpeg-
filters.html#Filtering-Introduction)

------
lnanek2
The improved screenshots do look quite improved, with less screen door effect.
Nice.

------
simas
Very nice of you to share this with the community! Examples are just awesome.

------
pkhamre
I like your domain.

------
imaginenore
And to complete the circle, run the gif through Gfycat and check out the
mindblowing bandwidth savings:

[http://gfycat.com/IllustriousHairyGermanpinscher](http://gfycat.com/IllustriousHairyGermanpinscher)

GIF: 1 MB

Video: 73k

~~~
dublinben
Yes please. Let's leave GIF in the 20th Century, where it belongs.

~~~
IgorPartola
If only iOS (and Android?) allowed you to play inline videos the way you can
on the desktop, and the way they play animated GIF's inline. Besides allowing
us to adopt video throughout and save on bandwidth and have better video
quality, this will be a _huge_ productivity boost to developers: we can
finally stop having the GIF vis JIF pronunciation debate.

~~~
acqq
Unless somebody's producing ads, why would he insist on having the video
"inline like on the desktop" on the small screen of the mobile phone?

~~~
IgorPartola
To replace GIFs. I don't have a problem with users being able to opt out, etc.
But GIF's are still useful, yet a huge drain on resources. If for nothing, I
want my cat videos still available inline without having to click them.

~~~
cardiffspaceman
Hardware video decoders mostly only handle one video at a time and if you
could multiplex the one decoder the chip has, to keep up with multiple videos
playing at once it just might take a milliwatt or two.

