FFmpeg recipe
FFmpeg: Convert MP4 to GIF with Custom Palette
Default ffmpeg GIF uses the web palette and looks posterized. Custom palette extraction picks the optimal 256 colors for your specific clip.
Command
ffmpeg -i input.mp4 -vf "fps=15,scale=480:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -y output.gifPrefer no terminal?
Use the Video to GIF in your browser
What each flag does
| -i | Input file. Can be a video, audio, or image. Repeat for multiple inputs. |
|---|---|
| -y | Overwrite output file without confirmation. |
| -vf "..." | Filter chain: set FPS, resize, then split → palettegen → paletteuse for optimal color quality. |
| fps=15 | 15 fps is the GIF sweet spot — smooth enough, file size half of 30 fps. |
| scale=480:-1 | Resize to 480 px wide, height auto. Smaller width = much smaller GIF. |
| palettegen | Build a custom 256-color palette tuned to this clip. |
Notes & gotchas
- Drop FPS to 12 or width to 360 for stricter file size budgets.
- Add dither=bayer:bayer_scale=5 to paletteuse for smoother gradients (slightly larger file).
Check it worked
ffprobe -v error -show_entries stream=width,height,nb_frames -of csv=p=0 output.gifThe width you asked for, and frames equal to duration times frame rate. A huge frame count means the fps filter did not apply.
What to change
| Width matters more than fps | Halving the width quarters the pixels. Dropping 15 fps to 12 saves a fifth. Resize before you cut frames. |
|---|---|
| Always generate a palette | A single-pass GIF uses a generic 216-colour palette and looks it. palettegen plus paletteuse builds one from your clip. |
| Dithering trades noise for banding | bayer is smaller and patterned; sierra2_4a is smoother and larger because neighbouring frames stop compressing well. |
If it fails
The GIF is enormous, sometimes larger than the video.
Why: GIF stores every frame as its own palettised image with no compression between frames.
Fix: Cut the duration first, drop to 10 or 15 fps, and reduce the width. Those three together usually cut the file by an order of magnitude.
Colours look banded or dirty.
Why: The default palette is generic rather than derived from this clip.
Fix: Use the two-pass form: palettegen into a PNG, then paletteuse with that palette, which builds 256 colours from the clip itself.