用 awesome-codex-skills 的 slack-gif-creator 为 Slack 构建合规动态 GIF:验证器、动画原语与优化实战
2026/9/15 13:18:07 网站建设 项目流程

用 awesome-codex-skills 的 slack-gif-creator 为 Slack 构建合规动态 GIF:验证器、动画原语与优化实战

【免费下载链接】awesome-codex-skillsA curated list of practical Codex skills for automating workflows across the Codex CLI and API.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-codex-skills

Slack 对 GIF 有严格的体积与尺寸限制(消息 GIF 约 2MB、表情 GIF 64KB),手工制作的动图经常上传失败。本文以 slack-gif-creator/SKILL.md 为核心,系统讲解 Slack 官方约束、校验器 API、13 类可组合动画原语,以及从帧组装到颜色量化、去重优化、最终校验的完整工作流,帮助你用 Python 快速产出可直接上传的 Slack 消息 GIF 与表情 GIF。

Slack 的硬性约束:消息 GIF 与表情 GIF 的两套标准

Slack 对不同用途的 GIF 有不同的技术门槛,套用同一套参数必然失败。先把约束写进设计阶段:

指标消息 GIF表情 GIF
最大体积约 2MB64KB(严格限制)
最佳尺寸480x480128x128
典型帧率15-20 FPS10-12 FPS
颜色数128-25632-48
时长2-5 秒1-2 秒

表情 GIF 是最难啃的骨头:64KB 是硬上限,一旦超限上传即失败。实践中有效的策略包括:

  • 总帧数控制在 10-15 帧以内;
  • 颜色数不超过 32-48 色;
  • 保持设计简洁,避免渐变(渐变是体积杀手);
  • 频繁校验文件体积,而不是到最后才检查。

校验器源码把这一约束落成了可直接复用的 API(见 core/validators.py):is_emoji=True时体积上限取64 KBis_emoji=False时取2048 KB,判定逻辑清晰可读。

Toolkit 结构:三类可自由组合的工具

本 skill 将工具分为三层,全部服务于"在 Slack 约束内实现创作自由":

  1. Validators(校验器)——检查 GIF 是否满足 Slack 要求;
  2. Animation Primitives(动画原语)——shake、bounce、move、kaleidoscope 等可组合的动效积木;
  3. Helper Utilities(辅助工具)——文本、配色、特效等按需使用、可替换的通用函数。

这些工具不是固定配方,而是积木。如何组合完全由创意目标决定。

核心校验器:尺寸、维度与一键就绪判断

文件体积校验

from core.validators import check_slack_size # 检查 GIF 是否满足体积上限 passes, info = check_slack_size('emoji.gif', is_emoji=True) # 返回: (True/False, 含体积详情的 dict)

返回的info字典包含size_bytessize_kbsize_mblimit_kblimit_mbpassestype等字段;超限时控制台还会输出超出多少 KB 及超出百分比,并给出"减少帧数/颜色、简化设计"的提示(见 core/validators.py)。

尺寸校验

from core.validators import validate_dimensions passes, info = validate_dimensions(128, 128, is_emoji=True) # 返回: (True/False, 含尺寸详情的 dict)

表情 GIF 的理想尺寸是128x12864-128的正方形视为"可接受";消息 GIF 则要求大致方形(宽高比 ≤ 2:1)且短边在 320-640 之间(见 core/validators.py)。

完整校验与一键判断

from core.validators import validate_gif, is_slack_ready # 运行全部校验(体积 + 尺寸 + 帧数/时长统计) all_pass, results = validate_gif('emoji.gif', is_emoji=True) # 或者快速判断 if is_slack_ready('emoji.gif', is_emoji=True): print("Ready to upload!")

validate_gif会逐帧读取 GIF,统计帧数与时长,返回包含sizedimensionsframe_countduration_secondsfps的完整报告(见 core/validators.py)。校验失败时,get_optimization_suggestions会根据结果生成针对性的优化建议清单(见 core/validators.py)。

动画原语:13 类可组合的动效积木

所有原语都遵循同一模式:调用create_*函数、传入对象数据与动效参数、返回帧列表。下面按类别给出完整可运行示例。

Shake(抖动)

from templates.shake import create_shake_animation frames = create_shake_animation( object_type='emoji', object_data={'emoji': '😱', 'size': 80}, num_frames=20, shake_intensity=15, direction='both' # 或 'horizontal', 'vertical' )

源码中direction控制位移方向,shake_intensity是最大位移像素数,object_type支持circleemojitextcustom(见 templates/shake.py)。

Bounce(弹跳)

from templates.bounce import create_bounce_animation frames = create_bounce_animation( object_type='circle', object_data={'radius': 40, 'color': (255, 100, 100)}, num_frames=30, bounce_height=150 )

Spin / Rotate(旋转)

from templates.spin import create_spin_animation, create_loading_spinner # 顺时针旋转 frames = create_spin_animation( object_type='emoji', object_data={'emoji': '🔄', 'size': 100}, rotation_type='clockwise', full_rotations=2 ) # 摇摆式旋转 frames = create_spin_animation(rotation_type='wobble', full_rotations=3) # 加载动画(圆点) frames = create_loading_spinner(spinner_type='dots')

Pulse / Heartbeat(脉冲/心跳)

from templates.pulse import create_pulse_animation, create_attention_pulse # 平滑脉冲 frames = create_pulse_animation( object_data={'emoji': '❤️', 'size': 100}, pulse_type='smooth', scale_range=(0.8, 1.2) ) # 心跳(双跳) frames = create_pulse_animation(pulse_type='heartbeat') # 表情 GIF 专用注意力脉冲 frames = create_attention_pulse(emoji='⚠️', num_frames=20)

Fade(淡入淡出)

from templates.fade import create_fade_animation, create_crossfade frames = create_fade_animation(fade_type='in') frames = create_fade_animation(fade_type='out') # 两个 emoji 之间交叉淡化 frames = create_crossfade( object1_data={'emoji': '😊', 'size': 100}, object2_data={'emoji': '😂', 'size': 100} )

Zoom(缩放)

from templates.zoom import create_zoom_animation, create_explosion_zoom # 戏剧性放大(带运动模糊) frames = create_zoom_animation( zoom_type='in', scale_range=(0.1, 2.0), add_motion_blur=True ) frames = create_zoom_animation(zoom_type='out') # 爆炸式放大 frames = create_explosion_zoom(emoji='💥')

Explode / Shatter(爆炸/碎裂)

from templates.explode import create_explode_animation, create_particle_burst frames = create_explode_animation(explode_type='burst', num_pieces=25) frames = create_explode_animation(explode_type='shatter') frames = create_explode_animation(explode_type='dissolve') frames = create_particle_burst(particle_count=30)

Wiggle / Jiggle(扭动)

from templates.wiggle import create_wiggle_animation, create_excited_wiggle frames = create_wiggle_animation(wiggle_type='jello', intensity=1.0, cycles=2) frames = create_wiggle_animation(wiggle_type='wave') frames = create_excited_wiggle(emoji='🎉')

Slide(滑动)

from templates.slide import create_slide_animation, create_multi_slide # 从左滑入,带过冲效果 frames = create_slide_animation(direction='left', slide_type='in', overshoot=True) # 横穿画面 frames = create_slide_animation(direction='left', slide_type='across') # 多对象依次滑入(交错延迟 5 帧) objects = [ {'data': {'emoji': '🎯', 'size': 60}, 'direction': 'left', 'final_pos': (120, 240)}, {'data': {'emoji': '🎪', 'size': 60}, 'direction': 'right', 'final_pos': (240, 240)} ] frames = create_multi_slide(objects, stagger_delay=5)

Flip(翻转)

from templates.flip import create_flip_animation, create_quick_flip frames = create_flip_animation( object1_data={'emoji': '😊', 'size': 120}, object2_data={'emoji': '😂', 'size': 120}, flip_axis='horizontal' ) frames = create_flip_animation(flip_axis='vertical') # 表情 GIF 快速翻转 frames = create_quick_flip('👍', '👎')

Morph / Transform(变形)

from templates.morph import create_morph_animation, create_reaction_morph frames = create_morph_animation( object1_data={'emoji': '😊', 'size': 100}, object2_data={'emoji': '😂', 'size': 100}, morph_type='crossfade' ) frames = create_morph_animation(morph_type='scale') frames = create_morph_animation(morph_type='spin_morph')

Move Effect(移动)

from templates.move import create_move_animation # 线性移动(缓出) frames = create_move_animation( object_type='emoji', object_data={'emoji': '🚀', 'size': 60}, start_pos=(50, 240), end_pos=(430, 240), motion_type='linear', easing='ease_out' ) # 抛物线轨迹 frames = create_move_animation( object_type='emoji', object_data={'emoji': '⚽', 'size': 60}, start_pos=(50, 350), end_pos=(430, 350), motion_type='arc', motion_params={'arc_height': 150} ) # 圆周运动 frames = create_move_animation( object_type='emoji', object_data={'emoji': '🌍', 'size': 50}, motion_type='circle', motion_params={'center': (240, 240), 'radius': 120, 'angle_range': 360} ) # 波浪运动 frames = create_move_animation( motion_type='wave', motion_params={'wave_amplitude': 50, 'wave_frequency': 2} )

需要更底层控制时,可直接使用缓动函数:

from core.easing import interpolate, calculate_arc_motion for i in range(num_frames): t = i / (num_frames - 1) x = interpolate(start_x, end_x, t, easing='ease_out') # 或者抛物线: x, y = calculate_arc_motion(start, end, height, t)

calculate_arc_motion在 x 方向线性插值、y 方向叠加峰值于中点的抛物线偏移(arc_offset = 4 * height * t * (1 - t)),实现自然的抛体轨迹(见 core/easing.py)。

Kaleidoscope(万花筒)

from templates.kaleidoscope import apply_kaleidoscope, create_kaleidoscope_animation # 单帧应用(8 段镜像) kaleido_frame = apply_kaleidoscope(frame, segments=8) # 或生成动画 frames = create_kaleidoscope_animation( base_frame=my_frame, # 或 None 使用演示图案 num_frames=30, segments=8, rotation_speed=1.0 ) # 更快的简单镜像(quad = 4 向镜像) from templates.kaleidoscope import apply_simple_mirror mirrored = apply_simple_mirror(frame, mode='quad') # modes: 'horizontal', 'vertical', 'quad', 'radial'

apply_kaleidoscope按角度把画面切成若干扇区,再对奇偶扇区交替镜像、映射回源像素,生成对称图案;apply_simple_mirror则直接裁剪并翻转象限,速度更快(见 templates/kaleidoscope.py)。

自由组合的通用模式

原语之间可以任意混搭,核心模式是:每帧创建空白画布 → 用缓动计算位置/缩放 → 绘制对象 → 交给 builder 收帧:

# 示例:弹跳 + 落地震动 for i in range(num_frames): frame = create_blank_frame(480, 480, bg_color) # 弹跳运动 t_bounce = i / (num_frames - 1) y = interpolate(start_y, ground_y, t_bounce, 'bounce_out') # 落地瞬间叠加横向震动 if y >= ground_y - 5: shake_x = math.sin(i * 2) * 10 x = center_x + shake_x else: x = center_x draw_emoji(frame, '⚽', (x, y), size=60) builder.add_frame(frame)

辅助工具:装配、文本、配色、特效与帧合成

GIF Builder(帧装配与优化)

from core.gif_builder import GIFBuilder builder = GIFBuilder(width=480, height=480, fps=20) for frame in my_frames: builder.add_frame(frame) builder.save('output.gif', num_colors=128, optimize_for_emoji=False)

save()返回的info字典包含pathsize_kbsize_mbdimensionsframe_countfpsduration_secondscolors,并会在超限时自动打印警告(见 core/gif_builder.py)。核心能力:

  • 自动颜色量化optimize_colors()默认采样前 5 帧生成全局调色板再应用,比逐帧量化压缩率更高(见 core/gif_builder.py);
  • 重复帧移除deduplicate_frames()按相似度阈值(保存时默认 0.98)删除连续近似帧(见 core/gif_builder.py);
  • Slack 体积预警:保存后自动比对 64KB/2MB 阈值并提示;
  • Emoji 模式optimize_for_emoji=True时自动把画面缩到 128x128、颜色数压到 48 以内、帧数压到约 12 帧(见 core/gif_builder.py)。

文本渲染

小尺寸 GIF 里文字可读性差,常见解法是加描边:

from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE draw_text_with_outline( frame, "BONK!", position=(240, 100), font_size=TYPOGRAPHY_SCALE['h1'], # 60px text_color=(255, 68, 68), outline_color=(0, 0, 0), outline_width=4, centered=True )

TYPOGRAPHY_SCALE提供了一套按 480x480 参考画布设计的比例字号系统:h1=60h2=48h3=36title=50body=28small=20tiny=16(见 core/typography.py)。描边通过多方向偏移绘制实现,确保任意背景上都清晰可读;另有阴影、发光、半透明底框等变体(draw_text_with_shadow/draw_text_with_glow/draw_text_in_box)。scale_font_for_frame()可按画布尺寸比例缩放字号,适配不同 GIF 尺寸(见 core/typography.py)。大尺寸 GIF 也可直接用 PIL 的ImageDraw.text()自定义渲染。

配色管理

专业观感来自协调的配色:

from core.color_palettes import get_palette palette = get_palette('vibrant') # 或 'pastel', 'dark', 'neon', 'professional', 'warm', 'cool', 'monochrome' bg_color = palette['background'] text_color = palette['primary'] accent_color = palette['accent']

每种调色板都提供primary/secondary/accent/success/background/text/text_light七个角色(见 core/color_palettes.py)。还有配套的亮度对比计算(get_text_color_for_background)、互补色、亮化/暗化、混合、渐变与冲击色工具,以及为 64KB 表情 GIF 设计的精简色板get_emoji_palette('simple')(6 色)和'vibrant_emoji'(8 色)(见 core/color_palettes.py)。需要自定义时直接用 RGB 元组即可。

视觉特效

from core.visual_effects import ParticleSystem, create_impact_flash, create_shockwave_rings particles = ParticleSystem() particles.emit_sparkles(x=240, y=200, count=15) particles.emit_confetti(x=240, y=200, count=20) # 每帧更新并渲染 particles.update() particles.render(frame) # 闪光 frame = create_impact_flash(frame, position=(240, 200), radius=100) # 冲击波圆环 frame = create_shockwave_rings(frame, position=(240, 200), radii=[30, 60, 90])

粒子系统内置重力(默认 0.5 像素/帧²)与阻尼(默认 0.98),支持圆形、方形、星形三种形状,emit_confetti用更轻的重力模拟飘落彩带(见 core/visual_effects.py)。特效模块还提供运动模糊(与上一帧混合)、爆炸、辉光、投影、速度线、全屏震动(apply_screen_shake)等能力(见 core/visual_effects.py)。

缓动函数

自然运动依赖缓动而非线性插值:

from core.easing import interpolate # 下落(加速) y = interpolate(start=0, end=400, t=progress, easing='ease_in') # 落地(减速) y = interpolate(start=0, end=400, t=progress, easing='ease_out') # 弹跳 y = interpolate(start=0, end=400, t=progress, easing='bounce_out') # 弹性过冲 scale = interpolate(start=0.5, end=1.0, t=progress, easing='elastic_out')

可用缓动包括:linearease_inease_outease_in_outbounce_inbounce_outbounceelastic_inelastic_outelasticback_inback_outback_in_out(后三者还有anticipateovershoot别名),完整映射见 core/easing.py 与 core/easing.py。另外apply_squash_stretch()可在保持体积感的前提下做挤压拉伸变形(见 core/easing.py)。

帧合成基础工具

from core.frame_composer import ( create_gradient_background, # 渐变背景 draw_emoji_enhanced, # 带可选阴影的 emoji draw_circle_with_shadow, # 带深度感的形状 draw_star # 五角星 ) frame = create_gradient_background(480, 480, top_color, bottom_color) draw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)

frame_composer还提供空白画布、圆/矩形/圆角矩形/线条、文本、emoji、图层合成(带透明度)、火柴人、暗角(vignette)等绘制原语(见 core/frame_composer.py)。

体积超限时的优化策略

消息 GIF 超 2MB 时:

  1. 降低帧数(降 FPS 或缩短时长);
  2. 减少颜色(128 → 64 色);
  3. 缩小尺寸(480x480 → 320x320);
  4. 开启重复帧移除(remove_duplicates=True)。

表情 GIF 超 64KB 时必须更激进:

  1. 总帧数控制在 10-12 帧;
  2. 颜色数最多 32-40 色;
  3. 避免渐变(纯色压缩率更高);
  4. 简化设计(元素更少);
  5. 保存时开启optimize_for_emoji=True

三个可直接运行的完整示例

简单反应(脉冲)

builder = GIFBuilder(128, 128, 10) for i in range(12): frame = Image.new('RGB', (128, 128), (240, 248, 255)) # 脉冲缩放 scale = 1.0 + math.sin(i * 0.5) * 0.15 size = int(60 * scale) draw_emoji_enhanced(frame, '😱', position=(64-size//2, 64-size//2), size=size, shadow=False) builder.add_frame(frame) builder.save('reaction.gif', num_colors=40, optimize_for_emoji=True) # 校验 from core.validators import check_slack_size check_slack_size('reaction.gif', is_emoji=True)

冲击动作(弹跳 + 闪光)

builder = GIFBuilder(480, 480, 20) # 阶段 1:物体下落 for i in range(15): frame = create_gradient_background(480, 480, (240, 248, 255), (200, 230, 255)) t = i / 14 y = interpolate(0, 350, t, 'ease_in') draw_emoji_enhanced(frame, '⚽', position=(220, int(y)), size=80) builder.add_frame(frame) # 阶段 2:冲击 + 闪光 + 文字 for i in range(8): frame = create_gradient_background(480, 480, (240, 248, 255), (200, 230, 255)) # 前几帧闪光 if i < 3: frame = create_impact_flash(frame, (240, 350), radius=120, intensity=0.6) draw_emoji_enhanced(frame, '⚽', position=(220, 350), size=80) # 文字出现 if i > 2: draw_text_with_outline(frame, "GOAL!", position=(240, 150), font_size=60, text_color=(255, 68, 68), outline_color=(0, 0, 0), outline_width=4, centered=True) builder.add_frame(frame) builder.save('goal.gif', num_colors=128)

组合原语(移动 + 震动)

from templates.shake import create_shake_animation # 生成震动帧 shake_frames = create_shake_animation( object_type='emoji', object_data={'emoji': '😰', 'size': 70}, num_frames=20, shake_intensity=12 ) builder = GIFBuilder(480, 480, 20) for i in range(40): t = i / 39 if i < 20: # 触发前:物体移动,配角待命 frame = create_blank_frame(480, 480, (255, 255, 255)) x = interpolate(50, 300, t * 2, 'linear') draw_emoji_enhanced(frame, '🚗', position=(int(x), 300), size=60) draw_emoji_enhanced(frame, '😰', position=(350, 200), size=70) else: # 触发后:使用震动帧,汽车停在最终位置 frame = shake_frames[i - 20] draw_emoji_enhanced(frame, '🚗', position=(300, 300), size=60) builder.add_frame(frame) builder.save('scare.gif')

创作哲学:约束之内的自由

处理一个 GIF 需求时遵循五步流程:

  1. 理解创意愿景——画面要发生什么?情绪基调是什么?
  2. 设计动画——拆解为阶段(铺垫、动作、反应);
  3. 按需应用原语——shake、bounce、move、特效自由混搭;
  4. 校验约束——检查体积,尤其表情 GIF;
  5. 必要时迭代——超限就减帧、减色。

目标是在 Slack 的技术约束内实现创作自由。工具的定位是"积木而非配方"——先想清楚要表达什么,再挑合适的原语组装,最后用校验器收口。

运行依赖

该 skill 的依赖清单见 requirements.txt:

pip install pillow imageio numpy

其中imageio承担 GIF 编码(imageio.v3),PIL/Pillow承担帧绘制与量化,numpy承担帧数组运算与去重比对。核心模块集中在 core 目录(校验、构建、缓动、排版、配色、合成、特效),动画原语位于 templates 目录,安装依赖后即可把上述代码段串成完整脚本运行。

【免费下载链接】awesome-codex-skillsA curated list of practical Codex skills for automating workflows across the Codex CLI and API.项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-codex-skills

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询