让博客里那张图动起来:GIF 是不是还得自己拼
我一直觉得博客里全是静态图有点闷。给文章配图时看着一张"桌面上的插画",突然想:要是它能动一点、像个小角色站在那里呼吸,是不是就有精神了。
于是试着让模型直接出一个动图。
结论先说:模型不会动
我用的 AI 生图大模型,输出格式只有 png、jpeg、webp 三种。我特意拿 output_format: gif 去试,接口回得很干脆:invalid output_format。
所以这条路不通,不是"效果不够好",是接口层面就没有动图这个选项。模型列表里也只有文本模型和图像模型,没有视频或多帧能力。
想让图动,只能自己造。下面是我试的三条路,两条走进死胡同,一条能用。
第一条路:让它画十帧(没成)
我挑了个最简单的题材:桌上一叠书,从一本长到十本,每帧多一本,拼起来就是"书在长高"。
提示词里每一帧只改数量。结果模型根本不理:我写 1 本到 10 本,出来的是 4、2、3、4、5、6、5、6、7、8、10 本——第 2 帧比第 1 帧还少。机位也在飘,十帧连起来像十张画在闪。
结论很直接:图像模型控不住帧与帧之间的连续性,逐帧动画不适合它。
第二条路:让手臂真的挥起来(也没成)
第二次我用一张全身站立的机器人做底图,想把举起的那条手臂单独驱动:绕肩关节旋转,让权重随距离衰减——肩部不动,越往手越转得多。
听起来挺合理,实际跑出来是灾难:手臂被拉成环状鼓包、边缘拖出残影、肩部出现空洞。原因很朴素——这张图是一条整的像素网格,手臂和背景连在一起。 转手臂的时候,原来手臂待的位置得从别处采样来填,填的就是背景和拉丝。
要做干净,得先把手臂用分割模型抠成独立图层,再贴回去。这一步超出了我这次想花的时间,先绕过去。
第三条路:整体待机动效(能用了)
既然局部动不了,就让整张图"活"起来。底图是一张深色科技风的机器人,近黑背景、绿眼睛、胸口一圈蓝环。
一共叠了四层动效:
镜头推拉。 8 秒一个完整来回,从 1.0 推到 1.18 再退回来,缓入缓出。这是最有效的一层——画面自己在动,观众立刻能感到不是静图。
发光呼吸。 先算出"又亮又偏绿偏蓝"的像素做掩膜(眼睛、胸环、轮廓线),然后让这层掩膜周期性提亮。整张图不变亮,只有会发光的地方在明暗呼吸,像真的在通电。
粒子漂浮。 四十多颗绿色光尘按各自的相位缓慢上浮、闪烁,背景就有了空气感。
扫描光带。 一条很淡的竖直亮带每四秒从头扫到尾。压得很低,只在暗部能看出来,多了会廉价。
拼装:ffmpeg 打底,gifsicle 收尾
72 帧 PNG 出来之后,第一道工序是 ffmpeg:
ffmpeg -framerate 9 -i f%03d.png \
-vf "split[a][b];[a]palettegen=max_colors=48[p];[b][p]paletteuse=dither=bayer:bayer_scale=3" \
out.gif
palettegen / paletteuse 是给 GIF 生成专用调色板。GIF 只有 256 色,深色渐变最容易压出条纹;先按整段统计一套 48 色调色板,再用抖动还原,暗部层次能保住。
这一版跑出来 3.3MB,还是重。第二道工序交给 gifsicle:
gifsicle -O3 --lossy=90 --colors 48 out.gif -o final.gif
它会把相邻帧里重复的区域裁掉、只存变化的部分,再允许一点有损压缩。3.3MB 掉到 1.4MB,肉眼看不出区别。
长动图几乎一定要过这一道。 体积和时长是死结:8 秒的循环靠 ffmpeg 压不进 2MB,gifsicle 的帧间差分才是真正的省法。
一个要提前知道的坑
图走外链图床的话,小程序那边有白名单:图片域名得加进"downloadFile 合法域名",否则网页能看、小程序里一片空白。
这次我顺便把这条也测了——手机浏览器、iPad、电脑、小程序各看一遍。GIF 格式本身没问题,卡住的往往只是域名。
最后
三条路走下来,摸清了一件事:动效的关键不在画得多好,在于帧与帧能不能对齐。
让它一次画十帧,控制权交出去了,出来的是乱序;让局部位移去模拟挥手臂,像素网格会撕裂;只有整张图级的动效——推拉、发光、粒子、扫描——既能做到 8 秒不穿帮,也压得进 1.4MB。
想要真正的角色动画,答案是先做图层分割,把手臂腿拆出来再驱动。这条路我留着下次试。