Removing crosshatch when creating a GIF in ffmpeg

January 12, 2020

If you’re a human that doesn’t want to download a whole new application just to do a bit of video manipulation or make a GIF, stop what you’re doing and check out ffmpeg. It’s a command-line tool you can use to do all sorts of things, but what I most often end up doing is converting a screen recording to a GIF. There are dozens of articles around the web on how to do this, but I wanted to note the command I use here for my own quick reference. I avoid creating a script with variables and instead prefer to keep it as copy and paste-able as possible.

Keep in mind this post covers less than 0.1% of what ffmpeg can do — it’s an incredible library that most of us will never fully appreciate.

MP4 to GIF, with defaults

ffmpeg -i my-video.mp4 my-gif.gif

This is how to create a GIF with zero manipulation. The problem is, if you turn up the brightness on your display and look closely at the GIF below, there’s a visible crosshatch pattern overlay that wasn’t in the original video:

bear-to-contentful-default-short

To remove this, you need to do some fancy manipulation.

MP4 to GIF, without dithering

The reason why the crosshatch exists is something called dither:

Dither is an intentionally applied form of noise used to randomize quantization error , preventing large-scale patterns such as color banding in images.

For our case, all we need to understand is that ffmpeg uses dithering algorithms to avoid visual errors and make the media we create more predictable.

To remove it, ffmpeg has these really neat features called palettegen and paletteuse, which allow you to create a color palette of 256 pixels from your video, define a dithering algorithm, and use it when creating your GIF. Here’s how we do that in one command:

ffmpeg -i my-video.mp4 -vf palettegen palette.png && ffmpeg -i my-video.mp4 -i palette.png -filter_complex “paletteuse=dither=none” my-gif.gif

bear-to-contentful-without-dither-short

If you look closely again, you can see the crosshatch is gone!

Note this command actually contains two commands that you can run separately:

  • ffmpeg -i my-video.mp4 -vf palettegen palette.png to create a color palette from your MP4, and
  • ffmpeg -i my-video.mp4 -i palette.png -filter_complex “paletteuse=dither=none” my-gif.gif to use your color palette and a few other filters to make a GIF.

MP4 to GIF, with many more filters

Finally, I want to reduce the file size, resize the GIF, and crop the resized GIF too. With the -filter_complex flag, we can add as many filters as we want with comma-separation:

ffmpeg -i my-video.mp4 -vf palettegen palette.png && ffmpeg -i my-video.mp4 -i palette.png -filter_complex “fps=15, scale=320:-1, crop=in_w:in_h-18:0:18, paletteuse=dither=none” my-gif.gif

The added filters include:

  • fps=15 to set the frames-per-second to 15, effectively reducing the file size
  • scale=320:-1 to set the width to 320 pixels and determine the height based on the original aspect ratio
  • crop=in_w:in_h-18:0:18 to crop 18 pixels from the top of the frame. This filter breaks down like this: crop=in_w:in_h:w:h, where:

    • in_w is the input file’s width,
    • in-h is the input file’s height,
    • w is the pixel to crop from on the x axis, and
    • h is the pixel to crop from on the y axis

And there we have it! Copy and paste away, future self.

Thanks for reading ❤️

If you're jazzed about this post, feel free to tweet this article 🐦

If I missed something, please do drop me a message and I'll fix it 🔨

Otherwise, read more articles! ✍️