A video-to-GIF transcoder. Using ffmpeg for video decoding and gif encoding, and OpenGL for frame processing.
Work in progress...
So, why yet another gif encoder, don't we have enough of them already? Well, there are many on the market, but none of them are good enough for my liking.
-
The use of a perceptually uniform color space is crucial, but rarely implemented. This often results in poor color choices both while generating the palette and while matching colors against it.
-
Additionally, common dithering methods also have their shortcomings:
-
Error diffusion: This is the typical choice when aiming for quality. However, it tends to be too volatile for gif purposes. A single pixel change can trigger a complete dithering recalculation, resulting in distracting motion artifacts and ridiculous file sizes.
-
Ordered dithering: While it offers reasonable visual quality and file sizes, most implementations are stuck with the ordinary Bayer threshold matrix instead of the lovely blue noise. This results in gifs having that retrowave 8-bit kind of aesthetic, which is rarely desirable.
-
So, the idea is to use a good perceptually uniform color space (Oklab my beloved) for high-quality palette generation and color matching, and blue noise for dithering. In theory, this approach should result in gifs that would look pleasant to the human eye, while offering a nice balance between quality and file sizes.
# acquire precompiled ffmpeg
curl -fLO https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl-shared.zip
unzip -d deps ffmpeg-*.zip && rm ffmpeg-*.zip
mv deps/ffmpeg-* deps/ffmpeg
# and blue noise textures
git clone https://github.com/Calinou/free-blue-noise-textures deps/assets/blue-noise
# debug mode build and run
zig build run -- input.mp4
# explicit release build
zig build -Doptimize=ReleaseFast -Dtarget=x86_64-windows-gnu -Dcpu=baseline
# upgrade Glad
url=$(curl -Lo /dev/null -w %{url_effective} https://gen.glad.sh/generate \
-d 'generator=c&api=gl%3D4.6&profile=gl%3Dcore&options=HEADER_ONLY')
curl -o deps/include/glad/gl.h ${url}include/glad/gl.h
# upgrade GLFW
url=$(curl -Lo /dev/null -w %{url_effective} https://github.com/glfw/glfw/releases/latest)
curl -LO ${url/tag/download}/glfw-${url##*/}.bin.WIN64.zip
unzip -q glfw-*.zip
cp -r glfw-*/include/GLFW/ deps/include/
cp glfw-*/lib-mingw-w64/libglfw3.a deps/lib/glfw.lib
rm -rf glfw-*