Skip to content

MP4 轉 GIF 教學:FFmpeg 兩階段演算法與畫質最佳化

把 MP4 轉成 GIF 很簡單,但要做出畫質好的 GIF 很難。很多人跑 ffmpeg -i input.mp4 output.gif 得到一個充滿色塊雜訊的 GIF。問題出在 GIF 只支援 256 色。這篇教學解析 FFmpeg 的 palettegen/paletteuse 兩階段演算法,從 GIF 原理到最佳化全包。

為什麼 GIF 轉換很難

GIF 格式的限制:

  • 只有 256 色:MP4 有數百萬色,GIF 只能存 256 色
  • 無壓縮:沒有 H.264 那種幀間壓縮,檔案巨大
  • 沒聲音:只有動態圖片
  • 1 位元透明度:沒有半透明,只有完全透明或完全不透明

核心挑戰: 怎麼把 MP4 的數百萬色縮減成 256 色。這就是色彩量化(Color Quantization),GIF 畫質好壞的關鍵。

方法 1:基本轉換(不推薦)

bash
ffmpeg -i input.mp4 output.gif

這能跑,但畫質差:FFmpeg 會取影片前幾幀生成預設調色盤,套用到整部影片。色彩偏移的影片會在其他場景色彩失真。

方法 2:兩階段演算法(推薦)

原理

兩階段演算法的核心:

  1. 產生調色盤(palettegen):分析整部影片,提取最佳 256 色調色盤
  2. 使用調色盤(paletteuse):用產生的調色盤把每個像素最佳對應

這樣 FFmpeg 會考慮所有場景選出最佳 256 色。

指令

bash
# 步驟 1:產生調色盤
ffmpeg -i input.mp4 -vf "palettegen" palette.png

# 步驟 2:用調色盤轉成 GIF
ffmpeg -i input.mp4 -i palette.png -filter_complex "paletteuse" output.gif

一步指令

bash
ffmpeg -i input.mp4 -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

不產生調色盤檔案,全部在記憶體完成。

畫質最佳化技巧

1. 統計模式選擇

bash
# 考慮所有場景(預設,畫質更好)
ffmpeg -i input.mp4 -vf "palettegen=stats_mode=full" palette.png

# 只考慮每幀差異(快,調色盤小)
ffmpeg -i input.mp4 -vf "palettegen=stats_mode=diff" palette.png

# 單幀(最快,畫質最差)
ffmpeg -i input.mp4 -vf "palettegen=stats_mode=single" palette.png

stats_mode=full 畫質最好但最慢。

2. 抖動演算法

bash
# 可用抖動模式
# bayer: 規則抖動,交叉網紋圖案
# heckbert: 誤差擴散(預設)
# floyd_steinberg: 最高畫質誤差擴散
# sierra2: Sierra-2-4A 誤差擴散
# none: 無抖動,色帶瑕疵

ffmpeg -i input.mp4 -i palette.png -filter_complex "paletteuse=dither=floyd_steinberg" output.gif

floyd_steinberg 最自然,但檔案較大。

3. 解析度和幀率調整

bash
# 480p、15fps(縮小)
ffmpeg -i input.mp4 -vf "scale=480:-1:flags=lanczos,fps=15" -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

# 640p、10fps(更小)
ffmpeg -i input.mp4 -vf "scale=640:-1:flags=lanczos,fps=10" -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

4. 長度剪輯

bash
# 只取 5 秒片段
ffmpeg -t 5 -i input.mp4 -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

# 從第 10 秒取 5 秒
ffmpeg -ss 10 -t 5 -i input.mp4 -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

透明背景 GIF

去背處理

bash
# 綠幕去背
ffmpeg -i input.mp4 -filter_complex "[0:v] colorkey=0x00FF00:0.3:0.2 [greenless]; [greenless] palettegen=reserve_transparent=1 [p]; [greenless][p] paletteuse=alpha_threshold=128" output.gif

參數:

  • 0x00FF00:綠色鍵值
  • 0.3:相似度(0.3 = 容許 30% 色差)
  • 0.2:混合(邊緣混合程度)

黑色背景透明

bash
ffmpeg -i input.mp4 -filter_complex "[0:v] colorkey=0x000000:0.1:0.0 [bgless]; [bgless] palettegen=reserve_transparent=1 [p]; [bgless][p] paletteuse=alpha_threshold=128" output.gif

檔案大小最佳化

1. 降解析度

bash
# 720p → 480p(檔案約縮小 50%)
ffmpeg -i input.mp4 -vf "scale=480:-1:flags=lanczos" -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

2. 降幀率

bash
# 30fps → 15fps(檔案約縮小 50%)
ffmpeg -i input.mp4 -vf "fps=15" -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

3. 剪掉不必要的動作

bash
# 只取前 5 秒
ffmpeg -t 5 -i input.mp4 -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

4. 用 gifsicle 後處理

bash
# gifsicle 最佳化
gifsicle -O3 --lossy=80 -o output.gif input.gif

# 移除透明度縮小
gifsicle --no-extensions -o output.gif input.gif

gifsicle -O3 --lossy=80 通常能縮小 30-50% 檔案,畫質降低不明顯。

實用範本

高畫質 GIF

bash
ffmpeg -i input.mp4 \
  -vf "scale=720:-1:flags=lanczos,fps=24" \
  -filter_complex "[0:v] palettegen=stats_mode=full [p]; [0:v][p] paletteuse=dither=floyd_steinberg" \
  output.gif

網頁用 GIF

bash
ffmpeg -i input.mp4 \
  -vf "scale=480:-1:flags=lanczos,fps=15" \
  -filter_complex "[0:v] palettegen=stats_mode=full [p]; [0:v][p] paletteuse=dither=floyd_steinberg" \
  output.gif

小型 GIF

bash
ffmpeg -t 5 -i input.mp4 \
  -vf "scale=320:-1:flags=lanczos,fps=10" \
  -filter_complex "[0:v] palettegen=stats_mode=full [p]; [0:v][p] paletteuse=dither=sierra2" \
  output.gif

# 再用 gifsicle 最佳化
gifsicle -O3 --lossy=80 -o output-final.gif output.gif

常見問題

問題原因解決方案
GIF 充滿色塊雜訊用預設調色盤用兩階段演算法
GIF 巨大無壓縮格式降解析度和幀率
色彩不準調色盤不適合stats_mode=full
色帶瑕疵抖動不足dither=floyd_steinberg
GIF 卡頓幀率太低fps=15 以上
透明背景有瑕疵1 位元透明度調整 alpha_threshold
轉換慢stats_mode=fullstats_mode=diff

總結

GIF 轉換的核心是兩階段演算法:palettegen 產生調色盤、paletteuse 套用調色盤。基本範本:

bash
ffmpeg -i input.mp4 -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif

高畫質加 stats_mode=fulldither=floyd_steinberg。要縮小檔案就降解析度和幀率。GIF 只適合短動畫,長影片用 MP4 或 WebM。

快速參考:

  • 基本指令: ffmpeg -i input.mp4 -filter_complex "[0:v] palettegen [p]; [0:v][p] paletteuse" output.gif
  • 高畫質:stats_mode=fulldither=floyd_steinberg
  • 縮小檔案: 降解析度和幀率
  • 後處理: gifsicle -O3 --lossy=80 再縮 30-50%

參考資料

Last updated: