TechEarl

How to Change the Speed of an Animated GIF (gifsicle and ffmpeg)

Speed up or slow down an animated GIF from the command line: set a uniform per-frame delay with gifsicle, re-time it with ffmpeg's setpts filter, and avoid the browser delay floor that quietly caps how fast a GIF can play.

Ishan Karunaratne⏱️ 8 min readUpdated
Share thisCopied
Change the speed of an animated GIF from the command line with gifsicle's per-frame delay or ffmpeg's setpts filter, and work around the browser minimum-delay floor.

The fastest way to change an animated GIF's playback speed from the command line is gifsicle: every frame in a GIF carries a delay value, and --delay overwrites all of them at once. Lower delay means a faster GIF:

bash
# Speed it up: 5 centiseconds per frame (20 fps)
gifsicle --delay 5 in.gif -o out.gif

# Slow it down: 20 centiseconds per frame (5 fps)
gifsicle --delay 20 in.gif -o out.gif

That is the whole job for most cases. The rest of this page is the detail: what that delay number actually means, the floor that makes very low delays misbehave, and when to reach for ffmpeg instead.

How GIF speed actually works

A GIF has no frame rate the way a video does. Each frame stores its own delay: how long it stays on screen before the next is drawn, measured in hundredths of a second (centiseconds). A delay of 10 holds each frame for 0.1 second (10 fps); a delay of 4 is 0.04 second (25 fps).

So changing a GIF's speed means changing those per-frame delays. There is no separate speed knob: lower the delay and it plays faster, raise it and it plays slower. gifsicle's --delay sets one uniform delay across every frame, which is what you want almost every time.

To see what a GIF currently uses, ask gifsicle for its info:

bash
gifsicle --info in.gif

Each frame line shows its delay, so you can see whether the source already has uniform timing or a mix of per-frame delays.

The delay floor that catches everyone

Here is the gotcha that sends people in circles: you can set --delay 1 and the file will store that 1-centisecond delay, but it will not play at 100 fps in a browser. Every major browser clamps very small delays up to a minimum. Modern Chrome and Firefox use a duration of 100 ms (10 fps) for any frame whose delay is 10 ms or less, that is, a delay value of 0 or 1 (a comment in Chromium's GIF decoder spells this out: ad-style frames asking for a near-zero duration get forced to 100 ms). A delay of 2 (20 ms) is the smallest value they honor, so the fastest a GIF reliably plays in a current browser is about 50 fps. Older Internet Explorer and early Firefox used a much higher floor, clamping anything under 100 ms up to 100 ms.

The practical consequence: a delay of 0 or 1 makes a slow GIF, not a blazing-fast one, because the renderer ignores your tiny value and falls back to its 10 fps default. For a genuinely fast GIF that plays consistently, keep the delay at 2 or higher. A delay of 2 is the floor on modern browsers; if you also care about ancient renderers, 3 is a conservative choice but it does not buy you anything on current Chrome or Firefox.

bash
# This does NOT play at ~100 fps. Browsers clamp delay 0 or 1 back to ~10 fps.
gifsicle --delay 1 in.gif -o too-fast.gif

# Delay 2 (20 ms, ~50 fps) is the fastest modern browsers actually honor.
gifsicle --delay 2 in.gif -o fast.gif

This is a property of the GIF format and the renderers, not of gifsicle. ffmpeg's approach runs into the same wall, because the output is still a GIF being drawn by the same renderers.

Changing speed with ffmpeg (setpts)

If ffmpeg is already in your pipeline, its setpts filter re-times the clip by rewriting each frame's presentation timestamp. A multiplier below 1 speeds it up; above 1 slows it down:

bash
# Double the speed (half the duration)
ffmpeg -i in.gif -vf "setpts=0.5*PTS" out.gif

# Half the speed
ffmpeg -i in.gif -vf "setpts=2.0*PTS" out.gif

setpts=0.5*PTS halves each frame's timestamp, so the whole animation runs in half the time. It is the opposite approach to gifsicle: gifsicle edits the stored delays directly, while ffmpeg re-times the stream and re-encodes the GIF from it.

Because re-encoding drops a GIF back to 256 colors, run a palette pass when quality matters, the same two-step flow used to convert a video to a GIF:

bash
ffmpeg -i in.gif -vf "setpts=0.5*PTS,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" out.gif

For a simple speed change with no other editing, gifsicle is the lighter tool: it rewrites the timing in place without a full re-encode, so it is faster and does not touch the palette.

Speed up without changing the timing: drop frames

There are two distinct ways to make a GIF "faster," and they are not the same thing:

  • Change the delay (gifsicle --delay, ffmpeg setpts): the same frames play in less time. Smooth, but a very low delay hits the browser floor above.
  • Drop frames: keep the per-frame delay, but throw away every other frame so there is less to play. This shortens the GIF and shrinks the file, at the cost of looking choppier.

Dropping frames is the move when a GIF is already near the delay floor and lowering the delay cannot speed it up further. With gifsicle you select the frames to keep:

bash
# Keep frames 0,2,4,... (every other frame), then re-time the survivors
gifsicle in.gif $(seq -f '#%g' 0 2 98) --delay 4 -o out.gif

That keeps half the frames and sets a 4-centisecond delay on what remains. ffmpeg does the same with its fps or select filter if you prefer one pipeline. Frame-dropping plus a sane delay is also the core of shrinking a GIF's file size, covered in optimizing a GIF from the command line.

Rule of thumb: lower the delay first (down to 2, the modern browser floor), and only start dropping frames once you have hit that floor and still need it faster or smaller.

FAQ

Lower its per-frame delay. With gifsicle: gifsicle --delay 5 in.gif -o out.gif sets every frame to 5 centiseconds (20 fps). A smaller number plays faster, but do not go below 2, because browsers clamp very small delays back up to about 10 fps.

Hundredths of a second (centiseconds). A delay of 10 holds each frame for 0.1 second, which is 10 frames per second. gifsicle's --delay uses this unit.

Browsers enforce a minimum frame delay. Modern Chrome and Firefox clamp any frame whose delay is 10 ms or less, meaning a delay value of 0 or 1, up to 100 ms, so it plays at about 10 fps instead of the speed you set. A delay of 2 (20 ms) is the smallest they honor, which is about 50 fps. Keep the delay at 2 or higher for consistent, fast playback.

gifsicle for a pure speed change: it rewrites the stored delays in place without re-encoding, so it is faster and keeps the original palette. ffmpeg's setpts filter is the better fit when speed is one step in a larger pipeline, since it re-times and re-encodes, in which case add a palettegen and paletteuse pass to protect quality.

Changing the delay keeps every frame and plays them in less time, which stays smooth until you hit the browser floor. Dropping frames removes some frames entirely, which shortens the GIF and shrinks the file but looks choppier. Lower the delay first, then drop frames only once you cannot speed it up any further.

See also

Sources

Authoritative references this article was fact-checked against.

TagsgifsicleffmpegGIFanimated gifCLIsetptsframe delay

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Software Systems Architect · Senior Software Engineer · Engineering Leadership

Software systems architect and senior software engineer with more than two decades designing, building, and running production software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Now a CTO, though what I write here is drawn from the full arc of that work, across architecture, engineering, and operations, not any single job.

Keep reading

Related posts