流媒体相关技术以及FFmpeg 使用经验
一.动图转换
前提知识补充:
WebP 动图、PNG 动图(通常指 APNG)与 GIF 均为支持动态图像的图片格式,三者核心功能都是通过多帧连续播放实现动画效果,但在技术特性、兼容性和应用场景上有显著差异。以下是具体解析:
一、三种格式的技术特性与关系
- GIF(Graphics Interchange Format)
- 诞生背景:1987 年由 CompuServe 推出,是最早普及的动态图像格式,基于 LZW 压缩算法。
- 技术特点
- 最多支持 256 种颜色(8 位色深),色彩表现力有限;
- 支持简单透明(只有 “完全透明” 和 “完全不透明” 两种状态);
- 帧动画通过逐帧切换实现,支持循环播放、帧延迟控制。
- 与其他格式的关系:是动态图像的 “元老”,WebP 动图和 APNG 均为解决 GIF 的缺陷(低色彩、大体积)而设计,可视为 GIF 的 “升级版”。
- WebP 动图(Animated WebP)
- 诞生背景:2010 年由 Google 推出,是 WebP 静态格式的扩展,专为网页优化设计。
- 技术特点
- 支持 24 位真彩色(1600 万色)+ 8 位透明通道(半透明效果),色彩表现力远超 GIF;
- 采用更高效的 VP8 视频编码压缩,同等画质下体积比 GIF 小 50% 以上;
- 支持帧间压缩(类似视频编码,重复内容不重复存储),进一步减小体积。
- 与 GIF 的关系:目标是替代 GIF 成为网页动态图像的主流格式,兼容 GIF 的动画逻辑但技术更先进。
- PNG 动图(APNG,Animated PNG)
- 诞生背景:2004 年由 Mozilla 主导开发,是 PNG 静态格式的动画扩展(PNG 本身不支持动画,APNG 是其增强版)。
- 技术特点
- 支持 24 位真彩色 + 8 位透明通道,色彩和透明度表现与 PNG 一致(优于 GIF);
- 压缩算法基于 PNG 的 DEFLATE,帧动画兼容 PNG 的无损特性,但体积通常比 WebP 动图大;
- 向下兼容静态 PNG(不支持 APNG 的软件会显示第一帧)。
- 与 GIF 的关系:是 PNG 生态下的动态扩展,解决了 GIF 的色彩和透明度缺陷,但压缩效率不及 WebP 动图。
二、兼容性对比:谁的应用范围最广?
GIF 兼容性碾压,是目前应用最广的动态图像格式,具体差异如下:
- GIF:
- 支持所有浏览器(包括 IE6 等老旧浏览器)、操作系统(Windows/macOS/Linux)、图像软件(Photoshop、浏览器原生预览)、社交平台(微信、微博、Twitter 等);
- 几乎没有兼容性门槛,是 “通用动态图像标准”。
- WebP 动图:
- 支持现代浏览器(Chrome、Firefox、Edge、Safari 14+),但老旧浏览器(如 IE 全系、Safari 13 及以下)不支持;
- 图像软件支持有限(Photoshop 需插件,GIMP 原生支持);
- 社交平台兼容性参差不齐(微信、微博已支持,但部分小众平台仍不兼容)。
- APNG:
- 浏览器支持:Firefox、Safari 原生支持,Chrome 需开启实验性选项(默认不支持),IE 完全不支持;
- 软件支持:比 WebP 稍好(如 Photoshop 插件支持,macOS 预览原生支持),但仍不如 GIF 普及;
- 社交平台支持较少(仅部分平台兼容,如 Reddit、Discord)。
三、总结:如何选择?
- 追求兼容性:选 GIF,尤其需要适配老旧设备、全平台场景(如邮件签名、跨平台社交分享)。
- 追求画质与体积平衡:选 WebP 动图,适合现代网页、App 内使用(需做好降级处理:对不支持的浏览器返回 GIF 版本)。
- 需要无损画质 + 透明动画:选 APNG,适合对色彩精度要求高的场景(如图标动画),但需接受其兼容性限制和较大体积。
目前来看,GIF 仍是应用兼容范围最广的动态图像格式,而 WebP 动图凭借高效压缩,正逐步成为现代互联网的主流选择(需配合兼容性方案)。
使用背景:
笔者从网站保存了一些表情包动图,格式为 webp。经验证,发现 QQ 的 NT for PC 因为底层用的 webview 而能适配 Webp 动图动画效果,但是 手机版查看 webp 图片为静态,QQ PC老版本甚至不能显示。所以,我便试着使用 FFmpeg 作为格式转换成 gif,以求让生动的动态表情包能被各端看到。
操作:
因为 FFmpeg 对「动画 WebP」的读取支持很弱,先用 Google 提供的官方工具 libwebp 工具包 来提取帧,再交给 ffmpeg 合成 GIF。否则则会报错:
1 | [webp @ 0x130f06b90] skipping unsupported chunk: ANIM |
这说明:
1.FFmpeg 的内置 webp 解码器 不支持动画 WebP 的容器格式(即使你装了 libwebp,也可能只是用于编码)
2.它跳过了 ANIM / ANMF 块 → 没有图像数据可读 → 解码失败
正确解决方案—— 用 webpmux 提取动图帧
用 webpmux(也是 libwebp 套件里的),它是专门处理 WebP 容器的,支持 ANIM/ANMF 动画结构
🔧 第一步:确认 webpmux 是否可用
1 | webpmux -version |
如果输出类似:
1 | webpmux version: 1.4.0 |
那就好,继续
如果没有这个命令,请重新安装最新版 libwebp:
1 | brew reinstall --build-from-source libwebp |
(有时候直接 install 会装上残缺版,必须从源码编译才能完整功能)
🐾 第二步:用 webpmux 提取动画帧为 PNG 序列
假设你的动图叫 1.webp,我们来一步步拆开它!
1️⃣ 先查看动画信息(确认是动画)
1 | webpmux -info 1.webp |
输出应该像这样:
1 | File: 1.webp |
✅ 出现 “WebP animation” 就说明是动画喵!
2️⃣ 创建帧存放目录
1 | mkdir -p frames_1 |
3️⃣ 用 webpmux 提取每一帧
1 | # 提取所有帧到 frames_1/%06d.webp |
这会生成
frames_1/000001.webp,000002.webp… 每一帧都是一个独立的 WebP 文件喵~
4️⃣ 再用 dwebp 解每一帧成 PNG(这次是静态图,没问题了!)
1 | # 遍历每帧 .webp 并转为 .png |
示例bash代码:
1 |
|
第三步 用 ffmpeg 合成 GIF
示例代码:
1 | ffmpeg -framerate 10 -start_number 0 -i ./webp/1_frames/frame_%d.png -loop 0 output1.gif |
第一个参数(franmerate)建议:帧率(fps)= 总帧数 ÷ 总时长(秒)
常见场景下,28 帧动画的帧率设置有两种情况:
- 若总时长为 1 秒:帧率为 28 fps(但这种情况较少见,因为主流动画帧率多为 12、15、24、30 fps)。
- 若按主流帧率适配
- 若按 14 fps 播放:总时长为 2 秒(28 ÷ 14 = 2);
- 若按 24 fps 播放(接近电影标准):总时长约 1.17 秒(28 ÷ 24 ≈ 1.17);
- 若按 30 fps 播放(接近视频标准):总时长约 0.93 秒(28 ÷ 30 ≈ 0.93)。
实际制作中,28 帧动画通常会按 14 fps 或 24 fps 播放,前者更流畅且符合多数动画的节奏(12-15 fps 是常见的低成本动画帧率),后者更接近自然流畅的视觉体验。你可以根据动画的节奏需求,用上述公式反推合适的帧率(比如希望动画播放 2 秒,就用 14 fps)。
二.剪裁图片
最近 Gemini 的AI 生图模型 nano banana 想必大家都玩过了吧,那么AI 返回了这么一张表情包 9 宫格等等,该怎么对其裁剪成我们需要的一张张表情包呢

1.先检查图片分辨率(是否可以特定的尺寸被整除)
1 | ffmpeg -i emoji.png 2>&1 | grep "Stream #0:0" | grep -oE '[0-9]+x[0-9]+' |
-oE:-o只输出匹配部分,-E启用扩展正则表达式,兼容 macOS 的grep。
需确保:
宽度能被 5 整除(
XXX % 5 == 0);高度能被 3 整除(
YYY % 3 == 0)如果不满足,可先缩放调整(例如缩放到 1200 * 720)
发现分辨率为 1024x572,不满足,那么缩放调整:
1 | ffmpeg -i emoji.png -vf scale=1200:720 emoji_scaled.png |
2.裁剪为 3×5 网格并保存到指定文件夹
执行以下命令(直接拆分并输出 15 张裁剪图):
1 | # 创建目标文件夹(若不存在) |
效果: