MP4 转 GIF 怎么配才不糊?帧率、颜色数、抖动算法的实际取舍
关于我
我是 EZ 在线工具网 的站长,站里的 MP4 转 GIF 工具 就是下面要拆的这个。所以参数怎么来的、哪一档适合干什么,我讲得会比转述清楚一点。
先接受一个前提:GIF 糊是必然的
GIF 最多 256 色,没有音频,没有帧间预测。MP4 一帧能存 1677 万色,还能靠前后帧的差值只存变化的部分;GIF 的每一帧都得独立映射到那张 256 色的表上,再套一层 LZW 无损压缩。
差着两个量级的信息密度,糊是躲不掉的。你能控制的只是糊到什么程度,以及为它付多少体积。
体积大致是怎么涨上去的
不用记公式,记住它是乘法关系就行。总编码量近似正比于 像素数 × 帧数 × 画面复杂度:
- 分辨率减半,像素数变成原来的四分之一
- 帧率减半,帧数减半
- 时长减半,帧数减半
拿个具体点的例子算:1080p、25fps、10 秒,一共 250 帧,每帧约 200 万像素,两阶段滤镜得处理五次亿量级的像素点。把缩放调到 50%,像素数降到四分之一,等于凭空省掉四分之三的计算和体积。
所以标题里说的"不糊",实际是在这四个旋钮之间做交换:时长、分辨率、帧率、颜色数。下面讲怎么定顺序。
两阶段调色板,多跑一遍但值
GIF 的颜色表叫调色板(palette),最多 256 个槽位。问题来了:这张表从哪来?
一步法的做法是拿首帧、或者均匀抽几帧去算,然后全片都用它。这在单一场景的短片段上凑合能用,一旦镜头里从室内切到室外,或者从冷色调切到暖色调,颜色表就对不上了,画面开始全体偏色、色带横飞。
两阶段的做法是先扫一遍:palettegen 把整段视频(或者你框选的那一段)的颜色分布统计出来,生成一张针对这段素材优化的表;paletteuse 再拿这张表去逐帧映射。多跑一遍全片,换来的是一个档次的画质差。我们工具里跑的就这么两条命令:
# 阶段一:扫全片,产出调色板
ffmpeg -i input.mp4 -ss 3 -to 6 \
-vf "fps=10,scale=iw*0.5:ih*0.5:flags=lanczos,palettegen=max_colors=128" \
palette.png
# 阶段二:用这张调色板映射每一帧
ffmpeg -i input.mp4 -i palette.png -ss 3 -to 6 \
-lavfi "[0:v]fps=10,scale=iw*0.5:ih*0.5:flags=lanczos[v];[v][1:v]paletteuse=dither=sierra2" \
output.gif注意两条命令用的区间必须一致。调色板取自 3 到 6 秒、成品却拿整段视频去映射,出来的是全片 GIF 配一张只懂 3 秒内容的色表。这种错挺隐蔽的,画面能看,就是颜色说不出的怪。
四个档位,重点在抖动算法
界面上画质只有四档,背后是颜色数和抖动(dither)两个参数在配对:
| 档位 | 颜色数 | 抖动算法 | 什么时候用 |
|---|---|---|---|
| 高画质 | 256 | sierra2_4a | 渐变多、有肤色、要展示细节 |
| 中等画质 | 128 | sierra2 | 默认,绝大多数场景的平衡点 |
| 低画质 | 64 | bayer:b=6 | 纯色块、文字、图标动画 |
| 极小体积 | 32 | 关闭 | 极致压体积,两三个色块的简单动画 |
抖动是干什么的?它拿有限的 256 个颜色去"骗"眼睛。天空在真实画面里是从深蓝到浅蓝的连续过渡,色表里可能只有五个蓝。直接把每个像素换成最近的蓝,画面上会出现五条硬边。抖动的做法是在过渡区域按特定规则交替使用相邻的两个颜色,隔远看就混成了中间色。
两种抖动思路完全不一样:
sierra2 / sierra2_4a 属于误差扩散。 它逐像素处理,把量化产生的误差摊给右边和下面的邻居像素。优点是过渡自然、噪点分布像胶片颗粒;缺点是慢,而且它撒出来的"噪点"是随机的。
bayer 属于有序抖动。 用一张固定的矩阵去决定每个像素往哪边偏,出来的纹理规律性很强,看着没那么"高级",但计算快、图案稳定。
这里有个反直觉的地方:颜色数低的时候,我们反而把抖动换成 bayer,甚至直接关掉。
原因是 LZW。GIF 用的是无损压缩,压缩率取决于画面里有多少重复模式。误差扩散抖出来的随机噪点,等于往每一帧里撒了几万个"不一样"的像素,LZW 就压不动了,体积能给你涨回去一大截。颜色本来就只剩 32 个,你换来的不是画质,是更大的文件。
所以在低色数档位上关抖动,不是偷懒,是为了让文件真的变小。
按这个顺序砍参数
第一步,砍时长。 收益线性,损失最小。一段 30 秒的录屏做成动图没人看得完,圈出最有信息量的 3 到 5 秒。这一步能砍掉量级的体积,还不影响清晰度。
第二步,砍分辨率。 收益是平方级的。砍之前先想清楚这张 GIF 最终在哪儿显示:微信表情包的实际显示宽度就几百像素,你做 1920 宽再压到 50%,纯属浪费。反过来,要放进 PPT 或者文档放大看,就别砍到 25%。
第三步,定帧率。 8 到 12 帧是动图的甜点区。低于 8 帧有明显顿挫感;高于 15 帧对表情包、操作演示这类内容基本是浪费——GIF 每多一帧就是完整一帧的像素量。真正的视频转成 10 帧,观感上完全够用。
最后才动颜色数和抖动。 只有前面三步砍完体积还不满意,再去调色数。因为色数一降,色带和色块是肉眼可见的,属于"伤画质"的操作,能不做就不做。
三套现成配方
聊天用的表情包:缩放 25% 到 37.5%、10fps、64 色(bayer)、时长压在 3 秒内。重点是体积小、发送快,画面糙一点没人介意。
README / 文档演示图:缩放 50%、12 到 15fps、128 色。宽度控制在 800 像素左右,放在文档里不横向溢出,体积也还算克制。
产品动效展示:缩放 75%、15fps、256 色。这种场景就是要好看,接受体积大一点;如果对方能打开视频,直接发 MP4 更划算。
操作步骤
- 上传 MP4 或 MOV,单个文件不超过 1GB
- 在「分辨率缩放」里选比例,选项是原始、75%、50%(推荐)、37.5%、25%
- 在「帧率」里选 5、10(推荐)、15、20、25 帧
- 在「画质质量」里选高画质(256 色)、中等画质(128 色,推荐)、低画质(64 色)、极小体积(32 色)
- 只想转某一段,勾上「启用时间裁剪」,填起始和结束时间(单位秒)
- 点「开始转换」,等两个阶段跑完。结果区会给出原文件大小、输出大小、转换耗时和处理速度,拿这几个数一对比就知道参数该怎么微调
第一次点转换要等久一点,因为浏览器得先把 22MB 左右的转码内核拉下来,之后走缓存。进度停在 10% 或者 40% 不动是正常的,那两个位置分别在跑调色板和 GIF 合成。
有些场合你根本不该用 GIF
这条比参数更值得看。
GIF 是 1987 年的格式,它当年解决的是"在没法放视频的地方放动图"。现在网页、GitHub README、绝大多数博客都支持 <video> 标签,你完全可以让一段无声循环的视频干同样的活:
<video autoplay loop muted playsinline src="demo.mp4"></video>同样的画面,MP4 或 WebM 通常比 GIF 小一个数量级,还没有 256 色的限制,没有色带。很多人做网站动图还在用 GIF,纯粹是习惯没改过来。
GIF 真正该用的地方是:聊天软件、邮件、以及任何塞不进 video 标签的文档。这些场景里它是唯一选择,那就老老实实按上面的顺序砍参数。
排错
- 卡在 10% 或 40% 很久:第一阶段在扫全片统计颜色分布,源视频越长越慢。先用时间裁剪圈出需要的片段,比什么都管用。
- 页面白掉或者报内存错误:文件太大或时长太长。GIF 是在你本地浏览器的内存里拼的,数据量比源视频膨胀得厉害。先剪再转。
- 发到微信里不动了:多半是体积超过平台限制。往下压分辨率,缩短时长。
- 渐变区域出现明显色阶:色数太低,换 128 或 256 色,抖动保持 sierra。反过来,如果画面本来就是纯色块和文字,用 64 色加 bayer 就够了。
我们做不到的部分
- 输入只认 MP4 和 MOV。内部的 H.264、H.265、VP9 都能正确解码,但容器得是这两个。
- 没有声音。GIF 格式本身不支持音频轨道,这不是工具的限制。
- 单文件上限 1GB。而且是纯浏览器本地跑,内存吃紧,手机端别扔大文件进去。
- 文件不上传。转码在你的浏览器里完成,我们碰不到你的素材,这点在 隐私政策 里也写了。代价是速度取决于你的设备,跟服务器性能没关系。
就这样
参数先按这套顺序动:时长 → 分辨率 → 帧率 → 颜色数,八成问题都能解决。
真需要一帧帧调参数的话,直接去 MP4 转 GIF 工具 试,本地方案的好处就是随便试,一次不满意换个参数再来,不用担心流量和次数。
如果你要的是"把视频变小然后发出去",而不是非得做成动图,那 视频压缩工具 是对的路子——同画质下 MP4 能压到 GIF 的零头。静图压缩就交给 图片压缩工具。
📌 相关文章
- H.264 vs H.265 vs AV1:三大编码深度对比 —— 为什么视频格式能比 GIF 小那么多,看完就懂
- M3U8 视频如何合并为 MP4(4 种方法) —— 同一个思路的另一面:只换壳不重编码,体积几乎不变
- MKV 转 MP4 怎么转?3 步免费完成 —— 也是容器层的事,和 GIF 调参属于两个世界
- TS 合并失败、无法播放怎么办?7 类排查指南 —— 同样是"跑完了但结果不对"的排查思路
🚀 推荐阅读
- 浏览器根本不支持 RTMP:所谓“RTMP 在线播放器”到底在播什么 —— 另一个被叫错名字的东西,底下其实是 HTTP-FLV
- 一文搞懂 HLS.js 使用指南与最佳实践 —— 动图之外的动态内容,网页里通常用这套
- M3U8 转 MP4 失败?黑屏、加密、403 全攻略 —— 参数调不出来时,先确认素材本身没问题
- Mac/Win 通用:把网页 M3U8 视频流保存为本地 MP4 —— 想剪 GIF 之前,总得先把素材存下来