Creating Animated Gifs from MP4 and WebM files using ffmpeg
Efficient video encoding has meant that sharing video files in formats like mp4 or webm has become increasingly-popular. However, there are a number of tools which don't yet support video embedding, Google Slides being a prominent example. In these cases, we need to wind back the clock and reach for the old reliable animated gif format.
Converting mp4 to an animated gif
Ffmpeg is a wonderful command line tool which can convert pretty much any media file format into a different media file format. Converting from a mp4 to a gif is as simple as running
ffmpeg -i input.mp4 output.gif
The same command works for converting a webm to an animated gif:
ffmpeg -i input.webm output.gif
We can control the number of frames per second our gif will have by specifying this in the conversion. A higher number means more frames per second, and a smoother animation, though at the cost of a larger filesize:
ffmpeg -i input.mp4 -vf "fps=10" output.gif
The -vf
option in FFMPEG stands for "video filter". It allows us to apply various video filters and effects to the input video. In this case, the fps=10
parameter sets the frame rate of the output video to 10 frames per second.
This will break the mp4 file apart into a series of frames, and combine them again into a gif. I tried this recently with a screen recording for an upcoming presentation, and while it worked, there were a few issues with it. The visual noise on the image is noticeable, resulting in a poor quality image. We need to remove these artefacts from the image.
Gif:

Removing the artefacts
The artefacts visible in the original transformation often occur when the colour palette ffmpeg is using to create the gif doesn't quite match with the source file.
To reduce this artefacting, we need to follow an intermediary step, which will help ffmpeg to be aware of the full colour paletter in use.
ffmpeg -i input.mp4 -vf palettegen palette.png
This command will create a palette.png
file containing the different colours used in the video. This is generally a fairly small file (16x16-type size), which contains each of the identified colours in the palette.

We can then take this colour palette and feed it back in to ffmpeg for the final conversion:
ffmpeg -i input.mp4 -i palette.png -filter_complex paletteuse -r 10 output.gif
In this command, -filter_complex paletteuse
is telling ffmpeg that we want to use the palette file from our inputs (-i
). We're also using -r 10
to set the framerate to 10 frames per second. This is functionally the same as the vf
filter we used earlier, but runs at a subtly different time. Earlier, the -vf
option will change the frame rate the video is extracted at, while the -r
version manipulates the frame rates outputted at the end of the conversion. The end result is generally going to be the same, but as we're already specifying filters, ffmpeg gives out if we try to add a -vf
param to this command:
Filtergraph 'fps=10' was specified for a stream fed from a complex filtergraph. Simple and complex filtering cannot be used together for the same stream.
Once we run the command successfully, the output is noticeably smoother:

And, as a happy benefit, depending on the complexity of the colour space in your original video, the use of the palette file not only improves the animation, but can also give us a much smaller resulting file size. It does this by reducing the number of colours needed to generate the gif.
Thanks to the magic of ffmpeg, these commands tend to work equally well on webm or mp4 files. So if you need to create a high quality gif in a hurry, don't forget to use the palette step!
CyberWiseCon 2025
In May 2025, I'll be presenting Digital Cat-and-Mouse: Strategies to Outsmart Scrapers, Phishers, and Thieves at CyberWiseCon in Vilnius, Lithuania. From selling 10 Downing St, to moving the Eiffel Tower to Dublin, this talk covers real-world examples of unconventional ways to stop scrapers, phishers, and content thieves. You'll gain practical insights to protect assets, outsmart bad actors, and avoid the mistakes we made along the way!
Get your ticket now and I'll see you there!