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.
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.
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.
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.
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.
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.
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.
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
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:
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
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.
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.
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.
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.
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?
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.
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
- 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.
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.