MpegFlowBlogBack to home
← Recipes·Video → GIF·video operations

Create high-quality GIF from video with FFmpeg: palette generation matters

Convert video clips to animated GIFs with proper palette generation. The two-pass technique that produces small, sharp GIFs vs the one-pass approach that produces blurry mess.

ByMpegFlow Engineering Team·FFmpeg recipe
·2 variants·May 9, 2026

When to use this

You convert video to GIF for social-media previews, README demos, documentation walkthroughs, or content-marketing assets where the autoplay behavior of GIFs matters. GIFs are inefficient compared to MP4 (10-20× larger) but autoplay everywhere without controls. The choice: better-sharper-larger GIF (palette generation), or smaller-blurrier GIF (single-pass). For anything customer-facing, palette generation is non-negotiable.

Command variants

Two-pass with palette (production quality)
# Pass 1: generate palette
ffmpeg -ss 00:00:05 -t 5 -i input.mp4 \
  -vf "fps=15,scale=480:-1:flags=lanczos,palettegen=stats_mode=diff" \
  palette.png

# Pass 2: use palette
ffmpeg -ss 00:00:05 -t 5 -i input.mp4 -i palette.png \
  -filter_complex "fps=15,scale=480:-1:flags=lanczos[x];[x][1:v]paletteuse=dither=bayer:bayer_scale=5:diff_mode=rectangle" \
  output.gif

Two-pass produces dramatically better GIFs. ~3× smaller file size at much sharper quality vs one-pass.

Single-pass (quick, lower quality)
ffmpeg -ss 00:00:05 -t 5 -i input.mp4 \
  -vf "fps=15,scale=480:-1:flags=lanczos" \
  output.gif

Faster but produces visibly blurrier GIFs at larger file sizes. Use for quick previews; never for production assets.

What each parameter does

  • fps=15

    GIF framerate. 15-20 is the production sweet spot — higher rates produce visible quality issues in GIF format.

  • scale=480:-1

    Width 480px, auto-calculate height. GIFs are size-sensitive; 480px is typical max for social/README assets.

  • palettegen=stats_mode=diff

    Generate optimized palette focused on changing regions (vs static background). Produces sharper output for motion-heavy clips.

  • paletteuse=dither=bayer

    Use the generated palette with Bayer dithering. Reduces banding artifacts in gradients.

  • bayer_scale=5

    Dithering scale. Higher values reduce banding more but introduce visible patterns. 5 is the standard balance.

What this outputs

An animated GIF. Two-pass output is typically 200-500 KB for a 5-second clip at 480p×15fps. Single-pass output is 600 KB - 2 MB at the same parameters with worse quality.

Pitfalls

  1. Single-pass produces unacceptably bad GIFs for any customer-facing use. Always use two-pass with palette generation.
  2. GIFs are 8-bit color (256 colors). Sources with smooth gradients (sunsets, soft shadows) banding visibly. Lower bayer_scale (1-3) helps but introduces visible patterns.
  3. Long GIFs (>10 seconds) get huge fast. For longer demos, use MP4 with autoplay attribute or WebM if browser support permits.
  4. High framerate (>20fps) GIFs produce minimal quality improvement at significant file-size cost. Stick to 15-18fps.
  5. GIF resolutions above 720p are usually wasteful — viewers don't scrutinize GIFs the way they do video. 480p is typical, 720p is the practical max.

At production scale

GIF generation is libavfilter-bound. Two-pass is roughly 2× the cost of one-pass. For social-content pipelines generating thousands of GIFs from video clips daily, batch the palette-generation pass and reuse palettes across similar clips when possible. Above ~10K GIFs/day, consider serving WebM with the autoplay attribute instead — same UX, much smaller files, but requires modern browsers.

How MpegFlow handles this

MpegFlow models GIF generation as a 2-stage DAG (palette → output) so failed second-pass operations don't lose the palette work. The caching pattern: similar source clips can share palettes, saving compute at scale.

Topics
  • FFmpeg
  • gif
  • video-operations
  • social
See also
  • Recipe
    Extract Frames Thumbnails
  • Recipe
    Trim Cut Video
Running this at scale?

Get the orchestration layer for free.

The video → gif command above is the easy part. The queue, retries, audit trail, encoder-version pinning, and multi-tenant security around it are what every video team rebuilds from scratch. We did the rebuild — design partners run it free during beta.

Apply More recipes
© 2026 MpegFlow, Inc. · Trust & complianceAll systems nominal·StatusPrivacy