Index / Media
Video to GIF
Takes a few seconds out of a video and writes an animated GIF. Your browser decodes the video; the palette, the dithering and the GIF itself are built by this page. When it has finished it reads its own output back with a separate decoder and tells you whether the two agree.
The video does not leave your browser.
It is decoded, drawn to a canvas and encoded again in this tab. The page
has no network code, and the site's content security policy sets
connect-src 'none', so it could not upload the file even if
it tried. The settings below go in the URL so a link can carry them;
nothing read out of the video does.
Source video
Drop a video here, or choose a file.
Scrub the video, then set the start of the clip to where it is.
The clip
Counted from the beginning of the video.
At most 30. A GIF stores every frame as a whole
picture, so length costs more here than it does in a video.
1 to 50. Above 50 the delay between frames rounds
to less than two hundredths of a second, which browsers ignore.
32 to 640. The height follows the video's aspect
ratio. Never scaled up past the video's own width.
One palette for the whole clip, chosen by median
cut. 256 is the most a GIF can hold.
Floyd–Steinberg. Hides banding in gradients,
costs file size, and makes fewer pixels repeat between frames.
Unticked, it plays once and stops on the last
frame.
Result
What the GIF says when it is read back
Check
Result
Frames the decoder found
--
Frames that did not match
--
Colour shift against the source
--
Pixels left unchanged between frames
--
Worst seek error
--
Total run time the GIF asks for
--
What a GIF can and cannot do, and what this page did about it
256 colours, once. A GIF frame indexes into a palette of at most
256 entries. This page builds one palette for the whole clip by
median cut — repeatedly splitting the box of colours holding the
most pixels, along its longest axis, at the median — and each entry
is the pixel-weighted average of the colours in its box. Colours are
counted in a histogram at 6 bits per channel, and the nearest palette
entry for a pixel is resolved at that same 6 bits and cached, so a colour
may occasionally be matched to a neighbour of the true nearest entry.
The averages themselves are exact. If the clip turns out to use fewer
distinct colours than the palette has room for, the palette is those
colours exactly and nothing is approximated.
Hundredths of a second. Frame delays are stored in centiseconds, so 12 frames a second is 8.33 of them. The delays alternate between the two nearest whole numbers so the clip lasts the right length of time rather than drifting, and the figure above says what the average came to. Browsers ignore a delay below 2 centiseconds and substitute 10, which is why the frame rate stops at 50.
Only what changed. After the first frame, pixels whose palette index is the same as the frame before are written as a transparent index and left showing the frame underneath, and only the rectangle containing the changed pixels is stored. That is where most of the size saving comes from, and it is why one palette slot holds no colour. Dithering defeats it: error diffusion changes almost every pixel slightly, so far fewer repeat. Frames that are identical to the one before are dropped and their delay added to it.
Downscaling halves the frame repeatedly and takes the last partial step, rather than making one large jump, which is what the image converter here does and for the same reason.
What your browser will open. The video is decoded by the browser, not by this page, so the formats that work are the ones it can already play — in practice MP4/H.264 and WebM everywhere, and MOV, HEVC or AV1 only where the browser has the decoder. There is no format this page could add without sending your file somewhere, which it will not do.
Caps. 640 pixels wide, 30 seconds, 50 frames a second, 600 frames. Anything above these is clamped and said so in a note. Sizes here use 1 KB = 1,024 bytes.
Hundredths of a second. Frame delays are stored in centiseconds, so 12 frames a second is 8.33 of them. The delays alternate between the two nearest whole numbers so the clip lasts the right length of time rather than drifting, and the figure above says what the average came to. Browsers ignore a delay below 2 centiseconds and substitute 10, which is why the frame rate stops at 50.
Only what changed. After the first frame, pixels whose palette index is the same as the frame before are written as a transparent index and left showing the frame underneath, and only the rectangle containing the changed pixels is stored. That is where most of the size saving comes from, and it is why one palette slot holds no colour. Dithering defeats it: error diffusion changes almost every pixel slightly, so far fewer repeat. Frames that are identical to the one before are dropped and their delay added to it.
Downscaling halves the frame repeatedly and takes the last partial step, rather than making one large jump, which is what the image converter here does and for the same reason.
What your browser will open. The video is decoded by the browser, not by this page, so the formats that work are the ones it can already play — in practice MP4/H.264 and WebM everywhere, and MOV, HEVC or AV1 only where the browser has the decoder. There is no format this page could add without sending your file somewhere, which it will not do.
Caps. 640 pixels wide, 30 seconds, 50 frames a second, 600 frames. Anything above these is clamped and said so in a note. Sizes here use 1 KB = 1,024 bytes.