From-Scratch Build · Media Tooling
Give it a bloated GIF and a target size, and it shrinks the file to fit while keeping it looking as good as possible. It can also turn an MP4 clip into a tidy, optimised GIF. Runs as a browser app or straight from the command line. Built from scratch to learn how images are squeezed.
What it is
The tool solves one stubborn, everyday problem: a GIF is too big to attach, post or embed. You hand it a file and say "get this under one megabyte", and it works toward that budget automatically — trading away just enough detail to fit, and no more. It also accepts an MP4 and converts the clip into a GIF first, so a screen recording becomes a shareable loop.
I built this because "make it smaller" hides a surprising amount of engineering. There is no single knob — file size is the product of colours, dimensions, frame count and timing, and the art is deciding which to sacrifice and in what order.
The core idea I wanted to learn: compression to a target size is a search problem. You can't compute the perfect setting up front, so you try a strategy, measure the result, and adapt — reducing colours first, then scale, then frames — until the file lands inside the budget.
The stack
This rebuild leans on a few specialised media tools, each handling one part of the job. Here is what they do.
The Python imaging workhorse — reads and writes GIF frames, reduces colour palettes and rescales as a dependable fallback.
Turns the script into a browser app with upload, a settings sidebar, and a side-by-side before/after comparison.
Handles MP4-to-GIF conversion cleanly when present; the tool falls back to a pure-Python path when it isn't.
A dedicated GIF optimiser that squeezes harder than Pillow alone, used automatically whenever it's installed.
The same engine as a scriptable command, with batch mode to process a whole folder of GIFs at once.
A container image bundles the app and its media tools so it runs the same anywhere without a manual setup.
Architecture
Compression runs as a loop that keeps trying harder strategies until the file fits the target. Each step gives up a little more, so the result is the gentlest reduction that still meets the budget.
Take a GIF directly, or convert an incoming MP4 to a GIF first via FFmpeg or the Python fallback.
Optional cropping of dead borders, frame sampling and frame-duration tweaks before the real work begins.
The first, cheapest lever — fewer palette colours often hits the target with little visible loss.
If colour reduction isn't enough, shrink the dimensions toward a configurable floor.
As a last resort, sample out frames to cut size further while keeping the motion readable.
Run gifsicle for a final pass when available, then offer the result for download.
How it runs
The same engine is wrapped two ways, depending on whether you want clicks or scripts:
In my rebuild I cared most about the ordering of strategies — reaching the target with the least visible damage is the difference between a useful tool and a blunt one.
Reflection