你在 Slack 里加过自定义表情吗。大多数人干的事都一样:从某处扒一段视频,转成 GIF,拖进上传框,完事。然后发现表情位里那个东西要么糊成一团马赛克,要么动起来像幻灯片卡帧,要么文件大得 Slack 直接给你压成静态图。问题不在你手笨,在于 Slack 对 GIF 有一套冷冰冰的硬约束,而几乎没人把这些约束当回事。
Anthropic 把这个痛点做成了技能,名字就叫 slack-gif-creator。它不花哨,核心就一句话:把 Slack 的动图规范,从尺寸、帧率到色彩数和时长上限,从“文档里的一行小字”变成代码里跑得通的默认值。你不用背规范,GIFBuilder 帮你背着。

我和这类“教模型怎么干一件具体小事”的技能打交道不少,cookbook-audit 是反方向的(定义什么叫好),这个是正方向的(把一件事做对)。它最有意思的地方不是功能多强,而是它刻意不做的事。后面拆开讲。
工作流拆解
整个创建流程被压成了五步,前一步的输出是后一步的输入,没有分叉。第一次用会觉得它啰嗦,跑通一次才明白:约束前置,后面全顺。

第一步永远是定约束。Slack 给两类用途划了明确的线:表情位(emoji)建议 128×128,消息位(message)建议 480×480;帧率 10 到 30,色彩 48 到 128,表情 GIF 时长压在 3 秒以内。这些不是建议,是上传后不崩、不糊、不被压成静图的底线。
第二步用 PIL 逐帧画。技能不提供任何现成图形,所有形状都靠 ImageDraw 的几个基础图元拼出来:
-
圆 / 椭圆: draw.ellipse(...) -
多边形 / 星形: draw.polygon(...) -
线: draw.line(...) -
矩形: draw.rectangle(...)
下面这段是它的标准骨架:
from core.gif_builder import GIFBuilder
from PIL import Image, ImageDraw
# 1. 先按 Slack 约束建 builder
builder = GIFBuilder(width=128, height=128, fps=10)
# 2. 逐帧画
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
draw = ImageDraw.Draw(frame)
# 用 PIL 原语画你的动画
builder.add_frame(frame)
# 3. 带优化地保存
builder.save('output.gif', num_colors=48, optimize_for_emoji=True)
第三步把每一帧 add_frame() 塞进 GIFBuilder,攒够一叠再统一处理。第四步才是关键差异点,保存时你给它三个开关:
-
num_colors=48:降色,颜色越少文件越小 -
optimize_for_emoji=True:按表情位特性优化 -
remove_duplicates=True:删掉相邻重复帧
这三个开关直接决定文件大小。而文件大小决定 Slack 收不收,收了之后糊不糊。
第五步用校验器兜底。技能给了两个入口:validate_gif('my.gif', is_emoji=True, verbose=True) 返回详细诊断,is_slack_ready('my.gif') 给一个布尔快判。我特别喜欢这个设计,它把“我以为传上去了”和“真的传上去了且长得对”之间的落差,提前在你本地就暴露掉。
上手示例:一个会呼吸的星形表情
骨架有了,来段能直接跑的。下面做一个 128×128 的星形 emoji,用 core.easing 的 ease_in_out 控制缩放呼吸,用 core.frame_composer 的 draw_star 画形状:
from core.gif_builder import GIFBuilder
from core.easing import interpolate
from core.frame_composer import create_blank_frame, draw_star
builder = GIFBuilder(width=128, height=128, fps=12)
for i in range(24):
t = i / 23
scale = interpolate(0.8, 1.2, t, easing='ease_in_out')
frame = create_blank_frame(128, 128, (240, 248, 255))
draw_star(frame, cx=64, cy=64, r=40 * scale, color=(255, 200, 80))
builder.add_frame(frame)
builder.save('breathing_star.gif', num_colors=48,
optimize_for_emoji=True, remove_duplicates=True)
24 帧配 12 FPS,是个不到 2 秒的呼吸动画。scale 在 0.8 到 1.2 之间往返,星形就跟着胀缩。把 ease_in_out 换成 bounce_out,它立刻变成弹跳落地。这就是技能的核心玩法:图形来自 PIL,动感来自缓动函数,参数全在你手里。选 24 帧是让呼吸够顺,降到 12 帧也行,只是会顿一点;fps 和帧数一起降,文件体积跟着掉,这是 Slack 表情最划算的压缩杠杆。
技能还顺手给了八个现成的动画套路,个个附了思路公式,照着改就能用:
-
shake 抖动 / pulse 心跳 / bounce 弹跳 -
spin 自转 / fade 淡入淡出 / slide 滑入 -
zoom 缩放 / explode 粒子炸开
内部架构与关键设计
技能的文件结构很薄,但分层干净:知识在 SKILL.md,工具在 core.*,画笔在 PIL,约束在最外层的 Slack 规范。四层各管一摊,互不越界。

工具层是四个模块,拆开看各自只干一件事:
-
core.gif_builder:组装帧 + 优化保存。它把所有压缩开关(num_colors、optimize_for_emoji、remove_duplicates)收口在一处,你不必到处记参数。 -
core.validators:合规校验。把 Slack 那几条硬指标变成可运行的检查,而不是让你肉眼比对。 -
core.easing:缓动函数。提供linear / ease_in / ease_out / ease_in_out / bounce_out / elastic_out / back_out,让你用一行interpolate()替代手写三角函数,运动质感立刻不一样。 -
core.frame_composer:帧助手。封装了create_blank_frame、create_gradient_background、draw_circle、draw_text、draw_star这些高频操作,省得每帧重写样板代码。
绘图原语层就是 PIL 本尊。技能明确告诉你两件事:emoji 字体别碰,跨平台渲染不可靠;预制图形别指望,技能里一个都没塞。一切从 ImageDraw 的基础图元起步,前面列过的那几个原语就是全部家当。这条规矩初看严苛,实则是质量的护城河。一旦允许“套用预制素材”,出来的东西就千篇一律,而且跨平台崩给你看。
我觉得最值得玩味的是缓动函数的存在。core.easing 单独占一个模块,说明作者在意“动得自不自然”,而不只是“动没动”。线性位移的 GIF 看着像 PPT 翻页,加了 ease_out 和 bounce_out 才有“活物感”。这个细节暴露了技能的定位:它要的是好看的动图,不是能动的图。
使用场景
最对味的场景,是你想给团队 Slack 做一套统一的自定义表情或消息动图。比如产品上线时发个会跳的火箭,运维告警时发个会闪的红灯。以前这种东西要么外包、要么随手做、质量随缘;现在把 Slack 约束编码进流程,出品下限被抬住了。
表情位和消息位的选择,直接决定后面所有参数,这个分叉点必须先定:

选表情位(128×128),就老老实实 optimize_for_emoji=True 加 remove_duplicates,小方图里塞不下复杂场景,靠去重和降色腾体积。选消息位(480×480),空间大些,但同样要把体积当祖宗供,否则 Slack 照样给你压。
其余两类场景也顺手:
-
个人创作:想做个会转的 logo 当表情,照着五步走,比在在线 GIF 工具里瞎调参数可控得多 -
教学演示:它本身就是一个“约束驱动设计”的好例子,拿来教新人什么叫“先定规范再动手”
还有个实操提醒:表情位只有 128×128,别往里塞写满字的长句。那个尺寸下文字必糊,老老实实做纯图形或极短标签。想在动图里放字,走消息位 480×480,并且把字号往上提。这条经验技能不会主动告诉你,但踩过一次就忘不掉。
不适合的场景也得说清:它是做 Slack 动图的,不是通用 GIF 引擎。你要做网页 banner 动图、做超长循环片头,它不接这活。它也不替你画图,创意和逐帧逻辑是你的,它只管收口和校验。
洞察与反思
用下来最让我意外的是它的“减法哲学”。技能白纸黑字写明了三件它不做的事:不提供僵化的动画模板、不渲染 emoji 字体、不内置任何预制图形。这在一个“帮你做图”的技能里几乎是反直觉的。但正是这三道减法,逼着使用者自己掌控动画逻辑,成品反而千变万化。
这和很多 AI 工具的方向正好相反。多数工具拼命往上堆预制模板,恨不得你点一下就出图。短期爽,长期所有产出长一个样。slack-gif-creator 把“画什么、怎么动”的决策权全留给你,自己只守两道关:Slack 能不能收,文件够不够小。这种“工具做工具擅长的事,人做人的事”的分工,是我眼里它最聪明的地方。
还有一点容易被忽略:它把优化做成了“可做可不做”的开关,而且明确说“只在你要求缩小时才上优化策略”。这很克制。很多工具默认把你图压到亲妈不识,它不。num_colors、remove_duplicates 都是显式参数,你清楚每一分体积是怎么省下来的。这种透明性,在动图这种对体积极度敏感的载体上,比自动魔法更可靠。
当然它也有边界。逐帧逻辑要你自己写,纯新手面对空白画布会懵。它假设你懂一点 PIL,或者愿意学一点。动画概念(shake、pulse、bounce 那些)给了思路和公式,但不是复制粘贴就能跑的成品。它不是“零基础做动图”,是“懂点 Python 的人做高质量 Slack 动图”。
它要求你会一点 PIL,这不该被当成缺陷,反而是一道聪明的筛选。会写 Python 的人拿到的是一把手术刀,不会的人拿到的是一块空白画布。技能明智地没去填平这道坎,因为一旦它开始替你自动生成图形,它就从工具退化成黑箱,你失去了对每一帧的掌控。
还有个被低估的好处:它产出的不是一段视频,而是一份能放进 git 的 Python 脚本。哪天表情要改配色、改节奏,改两行参数重新跑就行,不依赖任何图形界面的手动拖拽。这种确定性,是那些“上传一张图自动生成动图”的 AI 工具给不了的。能复现,能 diff,也能回滚,这才是工程化做内容的底色。
资源地址
| 资源 | 地址 |
|---|---|
| Smithery 技能页 | https://smithery.ai/skills/anthropics/slack-gif-creator |
| 依赖安装 | pip install pillow imageio numpy |
总结
slack-gif-creator 不是一个“帮你画 GIF”的技能,它是一个“把 Slack 动图规范变成默认值”的技能。它的价值不在功能多,在于它替你记住了那些你总会忘、忘了就糊的硬约束,又把创意空间原封不动留给你。
只要你的产出是 Slack 里的表情或消息动图,我都建议把它当起点。重点不是抄它的代码,是抄它“约束前置、优化显式、创意归人”的三层思路。
最后提醒一句:它要你写逐帧逻辑,不替你画图;依赖三个库(pillow、imageio、numpy),装好再跑。工具再好,第一帧还是得你自己下笔。

