Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Gifski: Optimized GIF Encoder (github.com/imageoptim)
256 points by cl3misch on May 21, 2024 | hide | past | favorite | 64 comments


I've used this for years and it's the best out there. Definitely use it for converting videos for Google Slides and such.

But it's such a travesty that we're in 2024 and still using GIFs in place of videos. I guess it's not necessary on the web directly anymore, but so many other platforms, like Google, support GIFs but not videos. So we're all stuck encoding into an insanely space/cpu inefficient format just to get something animating.


I wish there was some kind of small, soundless video supporting transparency for emojis, stickers, small animations, diagrams in slide shows, etc, that is guaranteed to autoplay and loop without issues.

The problem with <video> of course is that there's no way to tell if it's going to play an annoying sound, take a long time to load, change the screen brightness due to HDR features, require a weird proprietary codec, need the browser to render video controls, and so on. So they end up getting blocked from autoplay by default.

I suppose APNG or WebP are ideal for this but it is poorly supported, in that very few tools let you export to APNG or WebP --- browsers actually have decent support for this [1] and Discord uses APNG for stickers.

[1] https://caniuse.com/apng


You can convert images/video to APNG at https://ezgif.com/apng-maker or to animated WebP at https://ezgif.com/webp-maker.


Many platforms already stopped using gifs, for precisely those reasons. Tumblr silently converts to animated webp when uploading a gif, imgur converts it to mp4, etc.


This is really annoying when trying to share gifs across platforms. I can't export a "gif" (.mp4) from telegram and upload it to Discord and display it like a gif instead of a click-to-play video, even though discord uses .mp4 under the hood as well...


Maybe all it takes for this is a new canonical file extension, i.e. something like .m4g?

The contract for these could be something like "no sound, default playback in a loop, 30 seconds or less; don't render if any of these requirements aren't met" to make sure people don't abuse it for auto-playing videos.


It's really more of a browser issue, a GIF you can just right click and download, but they don't make that option available for videos.


That option does actually exist for "plain" HTML5 <video> tags, as far as I know. It's just that most videos aren't hosted as simple as that, and are effectively stitched together out of multiple MPEG-DASH, HLS etc. fragments – or the site uses a custom video player.

In both cases, the result is a lack of a right-click-to-save option.


<img src="v.mp4"> is a thing, but unfortunately it’s not supported outside Safari. https://stackoverflow.com/questions/60114243/using-videos-in...


GIF = Graphics Interchange Format

_speechless at the irony


Creating GIFs for Google Slides is also exactly my main usecase for gifski. Today I played around with different formats for animated images (GIFs, apng, svg) and videos (webm, mp4, ...) in Google Slides. Only GIFs can be directly embedded. Other animated images are not supported, and videos have to be files in Google Drive.

Ironically, GIFs are way larger than e.g. a webm video but are the only format which can be directly embedded in a presentation.


One example is Stack Exchange (Stack Overflow) - supports GIFs up to 2 MB, but not videos.


GIFs up to 20MB on Reddit on most subs, but videos only on certain subs.


I really wish they could just make HTML support

    <img src="foo.mp4">
and have it behave exactly like all other images in how CSS handles it (with auto loop, no controls). This would solve all the reasons people use GIFs in place of videos.

Like for example

    <img src="foo.mp4" style="width:100%">
should make the image occupy 100% of the width of the parent element and auto-scale the height according to the mp4's aspect ratio. You can't do this with the <video> element without an extremely unintuitive wrapper div.



I think Google Slides supports video, the downside is that you need to upload them to Google Drive first


It does - or YouTube. But they will not auto play like a gif and take over the screen when playing.

feature requests for Google:

- inline video that auto plays and loops. This is like 1 line of html. Please do this!

- let me drag a video into the slide and just upload it for me and embed it

- or just convert videos to gifs for me when I drag in!!


Instead of GIF, use APNG or animated WebP, supported in almost all web browsers.


While on the subject of gifs, I'd like to recommend ScreenToGif. As the name suggests it supports screen recording, but the editor is nice for other gifs as well. It's easy to remove duplicate frames, change timing for all or some frames, etc. It can use ffmpeg and gifski for the gif encoding.

https://www.screentogif.com/

Also, I just learnt this, gifski has integrated gifsicle for lossy gif compression.


As others have mentioned below, a lot of sites and applications don't support embedded video, so GIF is the only way to go.

I love using ScreenToGif to embed little videos into my email responses when I'm doing technical support. It's so much easier to show someone the process than describe everything in click by click detail.

I've been doing this for years, and people are always amazed at the videos.


After clicking your link I had instant nostalgia. I used this tool years ago and completely forgot about it. I went to download it, but it appears to be windows only which explains why I stopped using it as I haven't used windows in about a decade.

That said, I'd highly recommend Giphy Capture for recording gifs on mac. It has a very sleek/light UI.


I use it for Documentation (when interactive), for Teams with integrated short clips, for Powerpoint Presentations when I'm doing a live demo (having a second slide with the gif as a backup, when the live demo doesn't work).

The editor is minimal and has a non existent learning curve.

AFAIK screentogif even has the gifsky encoder plus a few others.


Def has my vouch too, been using it for years.


Love this thing! It enabled me to add a “Convert to GIF” for videos in my Clop app (https://lowtechguys.com/clop) in just a few lines of code. The GIF gets encoded at its optimal size by default so I didn’t have to do a second optimization step.

I also like that the author spent time to add an easy way to build a static binary, which I need in order to ship gifski inside the app.

Compressing all these static binaries so I can ship them in Clop with a <100MB download was not so easy though. I’ve been using the included xz in macOS but I’m switching to lrzip [1] for better compression size and especially speed

[1] https://github.com/ckolivas/lrzip


If you don't want to use something more composed like this, the main trick gifski is doing is using a two-pass approach to generate a palette for the gif. You can do this pretty easily with just ffmpeg / ffprobe. Here's my personal script I use for generation:

    #!/bin/sh

    SCALE=500
    FPS=15
    SCALEPROVIDED=false
    
    for arg in "$@"
    do
        case $arg in
            -s=*|--size=*)
            SCALE="${arg#*=}"
            SCALEPROVIDED=true
            shift 
            ;;
            -f=*|--fps=*)
            FPS="${arg#*=}"
            shift 
            ;;
        esac
    done
    
    palette="/tmp/palette.png"

    # Look at the width/height of the video
    width=`ffprobe -v error -select_streams v:0 -show_entries stream=width -of csv=s=x:p=0 $1`
    height=`ffprobe -v error -select_streams v:0 -show_entries stream=height -of csv=s=x:p=0 $1`
    
    # Get the max
    max=$(( width > height ? width : height))
    
    # If we havent provided a scale, and the max size is lower than the default, set it to the lower value
    if [ "$SCALEPROVIDED" == true ]
    then
        minScale=$SCALE
    else
        minScale=$(( SCALE < max ? SCALE : max))
    fi
    
    # Set our flags
    filters="fps=$FPS,scale=$minScale:-1:flags=lanczos"
    
    # If there's no name provided, output the same name as the input with gif as the extension
    output=$2
    if [ -z "$output" ]
    then
        output=${1%.*}.gif
    fi
    
    # Output our gif
    ffmpeg -v error -i $1 -vf "$filters,palettegen=max_colors=256" -y $palette
    ffmpeg -v error -i $1 -i $palette -lavfi "$filters [x]; [x][1:v] paletteuse" -y $output
    
    echo created $output at ${minScale}px

Example usage is something like:

    gif input.mov
But you can also optionally specify framerate, size, and output name:

    gif -s=800 -f=22 input.mov my-800px-22fps-gif.gif


gifski works in a single pass, and streams its output.

    ffmpeg -i input.mov -f yuv4mpegpipe | gifski --width=500 -o out.gif -


aside: find it funny (genuinely), you describe this as "pretty easy" xD. ffmpeg is so impressive but so daunting from a cli perspective to me. how do you even know whats possible! I would never have imagined it could generate palettes


Highly recommend using an LLM for this actually! GPT is surprisingly good at generating ffmpeg commands. Agree it is super complex though.


"It produces animated GIFs that use thousands of colors per frame." - caught my interest.

I googled, and saw that one technique for this is layering multiple frames with different palettes and a delay of 0.


I've tried an absurd amount of video-to-gif tools and Gifski somehow is orders of magnitude better quality than all of them


Gifski does two things that most video-to-gif tools generally don't do:

1. It uses a unique color palette for each frame rather than using one global color palette for all frames.

2. It takes advantage of the fact that pixels from previous frames can be retained and used as part of the next frame even if the colors from those pixels are no longer part of the color palette. This is the main trick gifski uses to get more than 256 colors in a frame.

On top of that gifski uses pngquant for color quantization (converting to 256 colors) which is extremely good at its job in its own right.


gifski is also maintaining consistent Floyd-Steinberg dithering across frames (basically dithering in 3 dimensions).

This allows more reuse of the background colors, and keeps file sizes lower by avoiding adding unnecessary temporal noise. Other converters that remap and dither each frame independently will needlessly create unique noise patterns in each frame.


I just ran a test on a ~4 second hires screen recording in Gifski and GIF Brewery 3 (which is what I've been using for years).

Gifski took 11 seconds, and GIF Brewery took 59. Both apps set to maximum quality, 50fps, no resizing. The Gifski version is a little bigger at 5.5mb vs 4.2mb but also looks a bit better.

I embed short screen recording GIFs into GitLab/GitHub several times a week as it's just a better user experience vs real video files on those platforms. I'm definitely switching tools! I wish I had known about this sooner.


ImageOptim is a really good desktop tool. Whatever scripts I write to optimise images on the server, nothing gets to the level of optimisation that ImageOptim does, even though it uses the same tools under the hood.


I've used the GUI version before (Mac App) and it's my favorite, favorite little tool for quickly whipping up GIF's. I'm a big fan


Same. It annoys me that I can’t easily place a video in a Google Doc so converting to GIF is my usual go-to. Gifski has been great for that.


While Gifski is fantastic, I'd really like to know what kind of tech https://gifs.com uses. Their GIFs are really high quality and small in size.

I thought they were using Gifski but I'm not sure about it.


Are they actually GIFs? Some websites use looping videos and call them GIFs, even though they’re H.264 in MP4 or something like that.


> Some websites use looping videos and call them GIFs

That’s exactly what they’re doing. Just used the web inspector on one of their GIFs. Imgur does the same thing.


Not from here. Here's one I got from their front page. https://j.gifs.com/qjOKXp.gif

The content-type response header is image/gif.


Interestingly you can change the `.gif` to `.mp4` and you get a video _with_ audio.


webm seems to be the modern replacement for GIFs in browsers. I would suspect gifs.com supports them. Somehow their site is buggy for me atm so I could not test it.


I wish WebM could be the standard. GIFs shouldn't even be used in 2024. It's a format of the past, with no upsides.

I usually only need GIFs for GitHub readmes. GitHub doesn't support WebM autoplay videos.

In texting, Telegram has introduced WebM stickers so there's at least a choice there.


Note that Github does support the slightly better animated WebP... as long as you change the file extension to .gif :)


The extension trick works in all sorts of place. And in reverse too. You can often upload an animated GIF to sites that don't support it by just changing the extension to .jpg or .png.


Whoa! Really!? I gotta try that!


WebM is just a container format, though it's usually used with VP9 and opus, and is functionally equivalent to using any other kind of actual video.

Animated GIFs remain quite useful for non-video animations where you don't want lossy compression, and want to use other GIF features like transparency. Animated PNGs are a potential replacement, and support all of the features of GIFs along with 24-bit color, but software support remains lackluster.


Where are WebM files used? Safari browsers/Apple don't even support it.


They do now. At least on desktop. But it is a more recent feature (within the last few years, I can’t remember when exactly).

MP4 with H.264 is still king for compatibility, but WebM with VP9 isn’t as bespoke as it once was.


According to https://caniuse.com/webm, desktop Safari is green since 2022, while iOS Safari is green since two months ago.


Aka "gifs with sound" - I always asked myself who came up with this absurd term ;)


They do have an option to download GIFs


Playing with the quality options with Gifski can yield a significant drop in size sometimes without much drop in quality (sometimes no noticeable drop in quality unless you really look). Perhaps gifs.com are using the same (or similar) algorithm with more size-optimised defaults?


I'd like to see if we can extract the details from their GIFs and reproduce it with Gifski.


Wish these services could be run locally. I'd even pay for it. For people at companies uploading a clip of something internal for a slide deck to a 3rd party is a non-starter.


Like Ethernet, as long as the two commandments of "Does it work?" and "Is it secure?" pass, people will keep the default.

P.S. The example gif on their site is gorgeous.


Pretty sure the gif is from the short movie Cosmo Laundromat by Blender Studios, would definitely recommend giving it a watch:

https://gooseberry.blender.org


gifcap.dev compiles it into WebAssembly to get you an in-browser GIF screen recorder.

https://gifcap.dev/


GIF Optimizer at https://ezgif.com/optimize could further optimize a demo GIF image https://gif.ski/jazz-chromecast-ultra.gif by 23% using Lossy GIF Compression and by 27% using Optimize Transparency. So there is still much to improve in Gifski.


ezgif uses a lossy GIF compressor written by me — author of gif.ski.

I can run:

     gifski -Q50 jazz-chromecast-ultra.gif -o even-smaller.gif
and it reduces the same file by 65%. With -Q20 it can be 78% smaller: https://gif.ski/jazz-ultra-small.gif

By that measure, gif.ski is 78% better than itself!

With lossy compression it's always possible to make files smaller, and smaller, and smaller. Comparisons of lossy encoders without controlling for quality lead to such absurd results. See https://kornel.ski/en/faircomparison


This is an awesome cli to convert video to gifs. If you need GUI, you can use Gifski app on macOS or my app Quick Drop

I wrote about the integration here https://quickdrop.antran.app/blogs/video_to_gif_conversion


My image optimization trio as of now:

- GIF: gifski (squeeze out the best possible out of the ancient format)

- PNG: pngquant (lossy but respectful of what many PNGs are: lots of flat surfaces + limited color palette, transparency)

- JPG: jpegli (writing this post mostly to share the news about this one, it's new from libjxl learnings, approximately as good qualitatively as Guetzli, but 1000x faster -actual number, not an exaggeration-. It's amazing! https://github.com/libjxl/libjxl/tree/main/lib/jpegli )

Below's my lil' `image-opt` helper making for a nice workflow to optimize any gif/jpg/png file(s) :)

  #!/usr/bin/env bash
  set -euo pipefail
  
  dbg() { if [ "${DEBUG:=false}" = 'true' ]; then echo "$@"; fi }
  die() { echo "Error: $*" 1>&2; zenity --error --text="$*"; exit 1; }
  
  if ! command -v pngquant > /dev/null; then die 'You must install pngquant'; fi
  if ! command -v cjpegli > /dev/null; then die 'You must install cjpegli'; fi
  if ! command -v gifsicle > /dev/null; then die 'You must install gifsicle'; fi
  
  for filename in "${@:1}"; do
    if [ -d "$filename" ]; then
      echo && echo "ℹ File '$filename' is a directory. Skipping."
      continue
    fi
    if [ ! -f "$filename" ]; then
      echo && echo "ℹ File '$filename' does not exist. Skipping."
      continue
    fi
  
    extension_raw="${filename##*.}"
    extension="${extension_raw,,}"  # Convert to lowercase
    if [[ "$extension" != 'jpg' && "$extension" != 'png' && "$extension" != 'gif' ]]; then
      echo && echo "ℹ Skipping file $filename due to unsupported extension: .$extension"
      continue
    fi
  
    filename_noext="${filename%.*}"
    filename_original="${filename_noext}_beforeOpt.${extension_raw}"
    filename_final="${filename_noext}.${extension}"
    dbg "filename($filename), filename_noext($filename_noext), extension($extension), filename_original($filename_original)"
  
    echo && echo " Compressing $filename ..."
    mv "$filename" "$filename_original"
    if [ "$extension" == 'jpg' ]; then
      cjpegli "$filename_original" "${filename_noext}_q50.${extension}" -q 50
      cjpegli "$filename_original" "${filename_noext}_q60.${extension}" -q 60
      cjpegli "$filename_original" "${filename_noext}_q70.${extension}" -q 70
      cjpegli "$filename_original" "${filename_noext}_q80.${extension}" -q 80
      cjpegli "$filename_original" "${filename_noext}_q90.${extension}" -q 90
    elif [ "$extension" == 'png' ]; then
      pngquant --strip --force --verbose --output "$filename_final" "$filename_original"
    elif [ "$extension" == 'gif' ]; then
      # https://kornel.ski/lossygif , set --lossy to 20 for light compression, 200 for heavy
      gifsicle -O3 --lossy=50 --verbose --output "$filename_final" "$filename_original"
    fi
    gio trash "$filename_original"
  done
  
  sync


I feel dense for advocating for jpegli to everyone and then totally forgetting to replace it in my export chain myself. The tools you quote should be the only ones used in 2024. Everything else should be scorched.


I kind of dislike the Gif-ification of the internet. I rather watch video or look at static pictures.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: