录了一段 5 秒的操作演示,导出成 GIF,一看大小:18 MB。
想贴进文档、发到群里、放进 README,不是上传失败,就是加载半天转圈。
一张「动图」凭什么比一段视频还大?又该怎么把它压小,还不让它变得满屏噪点?
先搞清楚:GIF 为什么这么大
GIF 是 1987 年的格式,它的几个先天设定决定了它「胖」:
- 每一帧都是一张完整的图片。没有视频那种「只记录变化」的帧间压缩——除非导出时专门做了优化,否则 100 帧就是 100 张图。
- 压缩算法很老。GIF 只用 LZW 无损压缩,擅长的是「连续一样的颜色」,遇到渐变、照片、细碎纹理就几乎压不动。
- 每帧最多 256 色。颜色不够,导出工具就用「抖动」(dithering)——用密密麻麻的杂色点模拟过渡。这些噪点肉眼看是平滑的,对 LZW 来说却是最难压的数据。
所以一张 GIF 的体积,大致取决于:尺寸 × 帧数 × 每帧画面有多「碎」。下面所有办法,都是在对这三项下手。
六种办法,按画质损失从小到大
1. 帧优化:只存「变了的那块」(无损)
很多录屏工具、设计软件导出的 GIF,每帧都存了整张画面。但一段操作演示里,往往只有鼠标和一小块区域在动。
帧优化做的事是:每一帧只保留和上一帧不同的矩形区域,没变的部分用透明像素表示。透明像素连成一片,LZW 压起来非常高效。
画面一个像素都不变,动画效果完全一样,只是存储方式更聪明。对「背景不动、局部在动」的 GIF(录屏、UI 演示、表情包),这一步就能省下不少。
2. 有损 LZW:在压缩算法里「放一点水」(视觉无损)
这是 gifsicle 的 --lossy 参数带来的思路:编码时允许颜色有极小的偏差,让更多像素被当作「同一种颜色」连起来,LZW 的效率就大幅提高。
它的特点是:不减少颜色数、不改尺寸、不动帧,代价是画面里出现一点轻微的颗粒感。数值越大,省得越多,颗粒越明显。轻度使用时(比如 --lossy=30~40),在正常观看距离下很难察觉。
3. 减色:256 色降到 128 或 64
把调色板从 256 色减到 128 色甚至 64 色,每个像素需要的信息变少,压缩效率随之提升。
对扁平风格的插画、图标动画、UI 录屏,颜色本来就不多,减色几乎没有损失;但对照片类、渐变多的画面,减色会出现明显的色带和斑块。
4. 抽帧:降低帧率
很多 GIF 是按 30 fps 甚至 60 fps 导出的,但 GIF 本身并不擅长高帧率,很多场景 10~15 fps 已经够用。
帧数砍一半,体积通常也接近砍一半。代价是动作没那么顺滑——对操作演示影响不大,对需要流畅感的动画就比较明显。
5. 缩小尺寸
体积和像素数基本成正比:宽高各缩一半,像素数只剩四分之一。
在 Retina 屏上录的屏,原始宽度动辄 2000 多像素,而它最终往往只显示在 600~800 像素宽的位置。按实际显示尺寸导出,常常是收益最大的一步。代价是放大看会变糊,文字类内容要留意可读性。
6. 换格式:GIF 换成视频或 WebP
如果平台允许,最彻底的办法是不用 GIF:
- MP4 / WebM:现代视频编码有帧间压缩,同样的内容,体积往往只有 GIF 的几分之一。网页里用
<video autoplay loop muted playsinline>就能做出和 GIF 一样的效果。 - 动态 WebP / APNG:支持更多颜色和更好的压缩,现代浏览器都能播放。
代价是兼容性:不少聊天软件、论坛、文档工具、邮件客户端只认 GIF,换了格式可能直接显示不出来,或者不会自动播放。
一张表看清取舍
| 办法 | 画质影响 | 适合 | 不适合 |
|---|---|---|---|
| 帧优化 | 无,像素不变 | 所有 GIF,尤其录屏和局部动画 | ——(应该总是做) |
| 有损 LZW(轻度) | 极轻微颗粒 | 绝大多数 GIF | 对颗粒极敏感的像素画 |
| 减色 | 渐变处出现色带 | 扁平插画、图标、UI | 照片、渐变多的画面 |
| 抽帧 | 动作变卡 | 操作演示、静态居多的动画 | 需要流畅感的动画 |
| 缩小尺寸 | 细节变少 | 原图明显大于显示尺寸 | 需要看清小字的内容 |
| 换格式 | 通常更好 | 网页、自己能控制的平台 | 只认 GIF 的平台 |
顺序的逻辑是:先做不损失或几乎不损失的,再按需要往下走。前两步做完如果已经够小,就不必牺牲颜色、帧率和尺寸。
前两步,ImgZilla 可以替你批量做完
如果你手里是一堆 GIF——表情包收藏、文档里的演示动图、网站素材目录——一张张丢进在线工具调参数实在太累。
ImgZilla 是一款 macOS 图片压缩工具,处理 GIF 时用的正是上面表格的前两项:
- 基于 gifsicle:先做最高级别的帧优化(相当于
-O3),再叠加轻度有损 LZW(相当于--lossy=40)。 - 不减色、不抽帧、不改尺寸、不改循环设置。动画还是原来那个动画,帧率、时长、分辨率都不变,只是文件更小。
- 原地压缩:文件名、路径、格式都不变。文档、网页、Markdown 里引用的
demo.gif压完还是demo.gif,不用改任何链接。 - 整个文件夹拖进去即可:递归扫描子目录,GIF 和 JPG、PNG、WebP 等其他图片一起处理。
- 压不动的不硬压:已经被优化过、压缩率不足 0.4% 的文件会标为「已最小」,原样保留,也不扣免费额度。
- 原图默认移入废纸篓:觉得哪张效果不满意,右键「放回原处」即可还原。
- 全程本地运行,不上传任何服务器,也没有在线工具那种单张大小和张数的限制——几十 MB 的录屏 GIF 也照样处理。
能省多少,取决于 GIF 原来是怎么导出的。没做过帧优化、画面大部分静止的录屏 GIF,通常省得最多;已经被专业工具压过的 GIF,可能只剩一点余量,甚至直接被标为「已最小」——这都是正常的。
ImgZilla 不做的事
为了「动画看起来不变」,ImgZilla 不会替你做第 3~6 步。如果前两步压完还是太大,比如必须压到某个平台的上限以内,就需要你自己决定牺牲什么:
bash
# 用 gifsicle 命令行:减到 128 色、宽度缩到 640、更强的有损压缩
gifsicle -O3 --lossy=80 --colors 128 --resize-width 640 input.gif -o output.gif
# 用 ffmpeg 把 GIF 转成 MP4(体积通常小得多)
ffmpeg -i input.gif -movflags +faststart -pix_fmt yuv420p \
-vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" output.mp4
抽帧、裁剪时长这类需要逐帧挑选的操作,用 ezgif 这类在线编辑器会更直观。
一个更好的习惯:在源头就别导出太大的 GIF
最后三条建议,能让你以后少压很多次:
- 录屏前先缩小窗口,只录需要的区域,而不是整块 Retina 屏幕。
- 导出时选 10~15 fps,大多数演示已经足够。
- 导出后顺手压一遍,把帧优化和轻度有损做掉——这一步不需要任何判断,适合交给工具批量完成。
GIF 是个老格式,但它依然是「到处都能自动播放」的最大公约数。与其纠结要不要放弃它,不如让每一张 GIF 都只占它该占的空间。
ImgZilla 目前仅支持 macOS(12.3 及以上),可在 Mac App Store 下载。免费版每天可压缩 10 张,只有压缩成功才计入额度——把存满 GIF 的文件夹拖进去,看看能省下多少。
