Making a GIF fit a size limit without asking anyone to pick a frame rate
Every GIF maker asks the same questions: width, frame rate, colours, dithering. None of them is what the person wants. They want the GIF to go into a chat, a pull request or a document that refuses files over some size, and they want it to look as good as that size allows. So this page asks for the size, and works the settings out. For an animation there are really only two settings that matter. A GIF has at most 256 colours per frame whatever quality is asked for, so its size comes almost entirely from how many pixels each frame has and how many frames there are per second. The page caps those at 640 pixels on the long side and 15 frames a second, which is where most chat apps shrink a GIF anyway, and reduces them from there.
Working out the settings starts from a size model fitted to real clips. Eight seconds each of a screen recording, a drawn animation and a lecture were encoded natively at three sizes and two frame rates in both formats, and the sizes followed a simple rule closely: bytes grow with pixel area to the power 0.9 for GIF and 0.55 for WebP, and with frame rate to the power 0.5 and 0.7. What the rule cannot predict is the content. The animation came out four times bigger per pixel than the screen recording, and for WebP the spread was about nine times. So the first encode is a guess, and it deliberately assumes the easiest content, which means that when it misses it misses by being too big rather than too small. That encode then tells the page how this particular clip compares with the model, and the next guess uses the real figure with an 8 percent margin. Up to three encodes are made, and the largest one that fits is kept.
The page does not use the shared target-size engine that the image and video compressors use, and the reason was found by measurement rather than decided in advance. That engine corrects its second attempt by how far the first file was from the budget. That works when the first guess followed the budget, but the best settings are a ceiling, and when the model says the best settings fit and they do not, the distance from the budget understates how wrong the model was. On the drawn animation a 2 MB target produced a 2.7 MB GIF after both of the engine’s attempts. With the correction based on the clip’s real size instead, forty runs across four real clips, both formats and five budgets from 300 KB to 5 MB all fitted, the ones that had to shrink landed at 71 to 98 percent of the budget, and none needed more than three encodes.
The GIF itself is built the careful way. The palette is generated from the clip rather than taken from a fixed set of 256 colours, weighted towards what changes between frames. Only the rectangle of each frame that differs from the one before is stored, which is why a screen recording, where most of the screen sits still, makes a GIF a fraction of the size of camera footage. Dithering uses a fixed ordered pattern rather than error diffusion, because diffusion scatters noise differently in every frame and that noise would defeat the rectangle trick. Animated WebP skips all of that, since it is a real compressed format, and it is often a tenth of the size of the same GIF. It does not play in every app that accepts GIFs, which is why GIF stays the default. Either way the result says exactly what size and frame rate it settled on, and if even the smallest settings cannot get under the limit, it says that too instead of handing over a file that will be rejected.