Video tools

Video to GIF

Convert a video clip to an animated GIF. In the browser only, like video-extract-frames (src/tools/video-extract-frames.ts), because decoding frames needs WebCodecs, which Node has no equivalent of. WebCodecs has no GIF codec at all, so this decodes frames with mediabunny/WebCodecs and then builds the GIF89a bytes itself (src/gif.ts): one shared 256-colour palette (median-cut, sampled across every frame this tool decodes, not per-frame) so colours stay consistent frame to frame, with each pixel mapped to its nearest palette entry. No dithering. Nothing is uploaded.

Runs on your device. The file is never uploaded.

Video to GIF samples frames from a clip at 10 frames per second, scales them to 480 pixels wide and stops after 150 frames. It then maps every pixel onto one shared 256 colour palette and does not dither, so gradients band. Frame decoding needs WebCodecs, which Node lacks, so this one runs on the page only.

Input

Options

Questions

Why does my GIF look posterised or banded?

Because GIF has no true colour. Every frame is mapped onto one shared palette of up to 256 colours, built by median cut across every frame the tool decodes, and each pixel is snapped to its nearest palette entry. There is no dithering, so smooth gradients turn into visible bands. Raising colors up to its 256 maximum helps; it cannot remove the limit.

Why is my GIF so large?

Because GIF stores whole frames with no interframe video compression. The defaults exist to hold that down: 10 frames per second, 480 pixels wide and at most 150 frames. Lower fps, a smaller width or a smaller colors value all shrink the result. Clearing width keeps the source width, which gets large fast.

How long a clip can I convert?

Whatever fits inside maxFrames, 150 by default, at the fps you choose. At the default 10 frames per second that is about 15 seconds of video. Frames past the cap are never sampled. Trim the video first if you want a later section, since sampling always starts at the beginning.

Does it need a browser?

Yes. Frames are decoded through WebCodecs, which Node has no equivalent of, so the CLI and MCP surfaces refuse it with "video-to-gif needs a browser (OffscreenCanvas). Use it at /video/video-to-gif instead." WebCodecs has no GIF encoder at all, so the GIF89a bytes are written by this tool itself after the frames come back.

What do the settings mean exactly?

fps is how often a frame is sampled from the source and also sets each frame delay, computed as 1000 divided by fps in milliseconds. width downscales the picture, 480 by default. maxFrames stops the sampling. colors is the palette size and must be a whole number between 2 and 256. The result tells you the frame count, the pixel size and the palette size it used.

Does the GIF loop?

Yes, always. The encoder writes the looping extension into every GIF it makes, and there is no option to turn that off. If you need a single play, that is a property of the player, not something this file can express differently.

Related Video tools