GIF to MP4: why you should, and how to do it right
GIF is a 256-color, 30× larger format than MP4. Here is when to convert, when not to, and the parameters that matter.
The most-shared format on the modern web is not, technically, video. GIF is a 1987 image format with a delay attribute on each frame. Every loop you have ever seen on Twitter or Slack is a sequence of still GIFs cycling at a frame rate the format pretends not to have.
This is fine for stickers. For anything longer than two seconds or larger than 480px, GIF is the wrong format. Here is the conversion to MP4, and the parameters that actually matter.
What GIF gives up
The constraints baked into GIF, in order of how much they hurt:
- 256 colors per frame. Every frame is palette-indexed. Gradients band. Skin tones look like illustrations.
- No inter-frame compression. Each frame is encoded mostly independently. A 5-second loop is ~30× the bytes of equivalent H.264.
- No alpha. GIF has 1-bit transparency, which is why "transparent" GIFs have white halos.
- No audio. Obvious. Sometimes forgotten.
MP4 fixes all four. The size difference is the easy sell: a 480p, 5-second GIF that is 4MB becomes a 200KB MP4 with identical visual quality. The color and gradient improvements are the real sell once you see them side-by-side.
When to convert
Convert if any of these are true:
- The asset is over 1MB as a GIF.
- The asset has gradients, photographs, or skin tones.
- The asset is over 3 seconds long.
- The target platform supports MP4 autoplay (Twitter, LinkedIn, Discord, modern web).
Do not convert if:
- The target is email. Most email clients still strip
<video>and many do not render H.264. - The asset is a 200×200 sticker that already weighs 80KB. The savings are not worth the toolchain.
The parameters that actually matter
The conversion is ffmpeg -i input.gif output.mp4. Done. Except — the defaults are wrong for the web. The four flags that change everything:
ffmpeg -i input.gif \
-movflags +faststart \
-pix_fmt yuv420p \
-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" \
-crf 23 \
output.mp4What each one does:
+faststart— moves the moov atom to the front of the file so the browser starts playback before the whole file downloads. Without this, your "instant" autoplay has a perceptible delay.yuv420p— universal pixel format. Without it, Safari and many TVs will refuse to decode.scale=trunc(iw/2)*2:trunc(ih/2)*2— rounds odd dimensions to even. H.264 requires even dimensions; without this you will hitwidth not divisible by 2mid-encode.-crf 23— quality. 18 is visually lossless, 23 is "very good," 28 is "fine for thumbnails." Default is 23 in most builds, but pin it explicitly so the result is reproducible.
Size, side-by-side
The comparison most people do not believe until they see it: a 5-second GIF on the left, the equivalent MP4 on the right, plotted by file size.
The MP4 is also better looking — no banding on the gradient, no halo on the edges, no palette flicker.
The hard cases
A few cases that bite:
- Pixel art. If the GIF is 8-bit retro sprite work, MP4 will smooth it. Use CRF 18 and disable any pre-scaling.
- Single-color backgrounds. If you need true transparency, MP4 cannot help — use WebM with alpha (VP9) instead.
- Slack. Slack auto-plays GIFs but requires a hover-tap on MP4. Worth knowing before you migrate your meme library.
Reverse direction: when MP4 → GIF
Sometimes you need to go the other way (email, retro contexts). The reverse conversion is also one command, but the quality loss is enormous. Two-pass palette extraction helps:
ffmpeg -i in.mp4 -vf "fps=15,scale=480:-1:flags=lanczos,palettegen" palette.png
ffmpeg -i in.mp4 -i palette.png -filter_complex "fps=15,scale=480:-1:flags=lanczos,paletteuse" out.gifIf you find yourself doing this often, consider whether the email is the wrong constraint, not the MP4.
The version-control angle
The honest case for MP4 over GIF for any generated video is that MP4 fits the pipeline. If you generate your video from HTML — which is what HyperFrames does — the natural output is MP4. The GIF is a downgrade for distribution; the MP4 is the source of truth.
This is the same pattern as PNG vs JPEG for design exports — keep the lossless, versionable source; export the lossy distribution format on demand. For video, the lossless source is the HTML template; the distribution format is MP4. GIF, if you need it at all, comes last.
See from DOM to MP4 for the full pipeline, and the developer integration docs if you want to wire conversion into your CI.
What to do this week
If you have an assets/ folder full of GIFs over 1MB, this is a Tuesday afternoon project. Convert them. Replace <img src="X.gif"> with <video src="X.mp4" autoplay muted loop playsinline>. Watch your page weight drop by an order of magnitude. The conversion is reversible — keep the GIFs around for a week in case anything breaks — but in practice, nothing does.
Cite this postBibTeX · APA · Markdown
@misc{tanaka2026should,
author = {Kira Tanaka},
title = {GIF to MP4: why you should, and how to do it right},
year = {2026},
url = {https://hyperframes.video/blog/gif-to-mp4-the-right-way},
note = {HyperFrames blog}
}Kira Tanaka. (2026, May 6). GIF to MP4: why you should, and how to do it right. HyperFrames. https://hyperframes.video/blog/gif-to-mp4-the-right-way
[GIF to MP4: why you should, and how to do it right](https://hyperframes.video/blog/gif-to-mp4-the-right-way) — Kira Tanaka, 2026
Kira works on the render core: headless Chromium scheduling, frame capture, and the encoder pipeline. She cares about reproducible builds and small numbers next to the word "variance."
MP4 vs WebM vs GIF in 2026 — the practical guide for product engineers
When to use MP4 vs WebM vs GIF for product videos in 2026. Browser support, file size, transparency, autoplay rules, and the right call per use case.
Animated flight itinerary cards in HTML
Build an animated boarding pass video: a plane traces an arc from origin to destination, gate and time settle in, the pass folds out — rendered as MP4.
Animated job listing videos for LinkedIn
Build a job listing video for LinkedIn: company logo lands, title fades up, requirements stagger in, and an Apply button pulses — exported as deterministic MP4.
Building with HyperFrames? Come hang out.
We're on GitHub, in Discord, and the playground is one click away. Bring weird ideas — we collect them.