mcpField
S
slack-gif-creator

slack-gif-creator

github.com/composiohq创意与媒体78.2k4.2k 次安装14 周前更新
代码仓库

关于 slack-gif-creator

slack-gif-creator 是用于制作 Slack 动图的工具包,适合需要生成消息 GIF 或表情 GIF 的创作者。它提供可组合的动画构件、组装优化工具及 Slack 尺寸和文件大小验证器。

主要功能

  1. 01验证文件大小和尺寸
  2. 02组合多种动画效果
  3. 03使用 GIFBuilder 组装与优化
  4. 04提供文本、颜色和视觉效果工具
  5. 05针对表情 GIF 优化

适用场景

  1. 01制作符合 Slack 限制的消息 GIF
  2. 02创建体积受限的表情 GIF
  3. 03组合动画效果制作反应动图

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/composiohq/awesome-claude-skills --skill slack-gif-creator

安装后在 Claude Code 中输入/slack-gif-creator确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

LICENSE.txt
requirements.txt
core/
color_palettes.py
easing.py
frame_composer.py
gif_builder.py
typography.py
validators.py
visual_effects.py
templates/
bounce.py
explode.py
fade.py
flip.py
kaleidoscope.py
morph.py
move.py
pulse.py
shake.py
slide.py
spin.py
wiggle.py
zoom.py

详细介绍

Slack GIF Creator - 灵活工具包

一个用于创建针对 Slack 优化的动画 GIF 的工具包。提供用于检查 Slack 限制的验证器、可组合的动画基元,以及可选的辅助工具。可按需应用这些工具,实现创意构想。

Slack 的要求

Slack 会根据 GIF 的用途设定具体要求:

消息 GIF:

  • 最大大小:约 2MB
  • 最佳尺寸:480x480
  • 常见 FPS:15-20
  • 颜色限制:128-256
  • 时长:2-5s

表情 GIF:

  • 最大大小:64KB(严格限制)
  • 最佳尺寸:128x128
  • 常见 FPS:10-12
  • 颜色限制:32-48
  • 时长:1-2s

表情 GIF 的制作颇具挑战——64KB 的限制非常严格。以下策略有助于控制大小:

  • 总帧数限制在 10-15 帧
  • 最多使用 32-48 种颜色
  • 保持设计简洁
  • 避免渐变
  • 经常验证文件大小

工具包结构

此技能提供三类工具:

  1. 验证器 - 检查 GIF 是否符合 Slack 的要求
  2. 动画基元 - 可组合的运动构建模块(抖动、弹跳、移动、万花筒)
  3. 辅助工具 - 用于常见需求的可选函数(文本、颜色、效果)

如何应用这些工具,完全由你自由决定。

核心验证器

要确保 GIF 符合 Slack 的限制,请使用以下验证器:

from core.gif_builder import GIFBuilder

# After creating your GIF, check if it meets requirements
builder = GIFBuilder(width=128, height=128, fps=10)
# ... add your frames however you want ...

# Save and check size
info = builder.save('emoji.gif', num_colors=48, optimize_for_emoji=True)

# The save method automatically warns if file exceeds limits
# info dict contains: size_kb, size_mb, frame_count, duration_seconds

文件大小验证器:

from core.validators import check_slack_size

# Check if GIF meets size limits
passes, info = check_slack_size('emoji.gif', is_emoji=True)
# Returns: (True/False, dict with size details)

尺寸验证器:

from core.validators import validate_dimensions

# Check dimensions
passes, info = validate_dimensions(128, 128, is_emoji=True)
# Returns: (True/False, dict with dimension details)

完整验证:

from core.validators import validate_gif, is_slack_ready

# Run all validations
all_pass, results = validate_gif('emoji.gif', is_emoji=True)

# Or quick check
if is_slack_ready('emoji.gif', is_emoji=True):
    print("Ready to upload!")

动画基元

这些是可组合的运动构建模块。可对任意对象以任意组合方式应用:

抖动
from templates.shake import create_shake_animation

# Shake an emoji
frames = create_shake_animation(
    object_type='emoji',
    object_data={'emoji': '😱', 'size': 80},
    num_frames=20,
    shake_intensity=15,
    direction='both'  # or 'horizontal', 'vertical'
)
弹跳
from templates.bounce import create_bounce_animation

# Bounce a circle
frames = create_bounce_animation(
    object_type='circle',
    object_data={'radius': 40, 'color': (255, 100, 100)},
    num_frames=30,
    bounce_height=150
)
旋转
from templates.spin import create_spin_animation, create_loading_spinner

# Clockwise spin
frames = create_spin_animation(
    object_type='emoji',
    object_data={'emoji': '🔄', 'size': 100},
    rotation_type='clockwise',
    full_rotations=2
)

# Wobble rotation
frames = create_spin_animation(rotation_type='wobble', full_rotations=3)

# Loading spinner
frames = create_loading_spinner(spinner_type='dots')
脉动 / 心跳
from templates.pulse import create_pulse_animation, create_attention_pulse

# Smooth pulse
frames = create_pulse_animation(
    object_data={'emoji': '❤️', 'size': 100},
    pulse_type='smooth',
    scale_range=(0.8, 1.2)
)

# Heartbeat (double-pump)
frames = create_pulse_animation(pulse_type='heartbeat')

# Attention pulse for emoji GIFs
frames = create_attention_pulse(emoji='⚠️', num_frames=20)
淡入淡出
from templates.fade import create_fade_animation, create_crossfade

# Fade in
frames = create_fade_animation(fade_type='in')

# Fade out
frames = create_fade_animation(fade_type='out')

# Crossfade between two emojis
frames = create_crossfade(
    object1_data={'emoji': '😊', 'size': 100},
    object2_data={'emoji': '😂', 'size': 100}
)
缩放
from templates.zoom import create_zoom_animation, create_explosion_zoom

# Zoom in dramatically
frames = create_zoom_animation(
    zoom_type='in',
    scale_range=(0.1, 2.0),
    add_motion_blur=True
)

# Zoom out
frames = create_zoom_animation(zoom_type='out')

# Explosion zoom
frames = create_explosion_zoom(emoji='💥')
爆炸 / 粉碎
from templates.explode import create_explode_animation, create_particle_burst

# Burst explosion
frames = create_explode_animation(
    explode_type='burst',
    num_pieces=25
)

# Shatter effect
frames = create_explode_animation(explode_type='shatter')

# Dissolve into particles
frames = create_explode_animation(explode_type='dissolve')

# Particle burst
frames = create_particle_burst(particle_count=30)
摆动 / 抖动
from templates.wiggle import create_wiggle_animation, create_excited_wiggle

# Jello wobble
frames = create_wiggle_animation(
    wiggle_type='jello',
    intensity=1.0,
    cycles=2
)

# Wave motion
frames = create_wiggle_animation(wiggle_type='wave')

# Excited wiggle for emoji GIFs
frames = create_excited_wiggle(emoji='🎉')
滑动
from templates.slide import create_slide_animation, create_multi_slide

# Slide in from left with overshoot
frames = create_slide_animation(
    direction='left',
    slide_type='in',
    overshoot=True
)

# Slide across
frames = create_slide_animation(direction='left', slide_type='across')

# Multiple objects sliding in sequence
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)
翻转
from templates.flip import create_flip_animation, create_quick_flip

# Horizontal flip between two emojis
frames = create_flip_animation(
    object1_data={'emoji': '😊', 'size': 120},
    object2_data={'emoji': '😂', 'size': 120},
    flip_axis='horizontal'
)

# Vertical flip
frames = create_flip_animation(flip_axis='vertical')

# Quick flip for emoji GIFs
frames = create_quick_flip('👍', '👎')
变形 / 转换
from templates.morph import create_morph_animation, create_reaction_morph

# Crossfade morph
frames = create_morph_animation(
    object1_data={'emoji': '😊', 'size': 100},
    object2_data={'emoji': '😂', 'size': 100},
    morph_type='crossfade'
)

# Scale morph (shrink while other grows)
frames = create_morph_animation(morph_type='scale')

# Spin morph (3D flip-like)
frames = create_morph_animation(morph_type='spin_morph')
移动效果
from templates.move import create_move_animation

# Linear movement
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'
)

# Arc movement (parabolic trajectory)
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}
)

# Circular movement
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  # full circle
    }
)

# Wave movement
frames = create_move_animation(
    motion_type='wave',
    motion_params={
        'wave_amplitude': 50,
        'wave_frequency': 2
    }
)

# Or use low-level easing functions
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')
    # Or: x, y = calculate_arc_motion(start, end, height, t)
万花筒效果
from templates.kaleidoscope import apply_kaleidoscope, create_kaleidoscope_animation

# Apply to a single frame
kaleido_frame = apply_kaleidoscope(frame, segments=8)

# Or create animated kaleidoscope
frames = create_kaleidoscope_animation(
    base_frame=my_frame,  # or None for demo pattern
    num_frames=30,
    segments=8,
    rotation_speed=1.0
)

# Simple mirror effects (faster)
from templates.kaleidoscope import apply_simple_mirror

mirrored = apply_simple_mirror(frame, mode='quad')  # 4-way mirror
# modes: 'horizontal', 'vertical', 'quad', 'radial'

如需自由组合基元,请遵循以下模式:

# Example: Bounce + shake for impact
for i in range(num_frames):
    frame = create_blank_frame(480, 480, bg_color)

    # Bounce motion
    t_bounce = i / (num_frames - 1)
    y = interpolate(start_y, ground_y, t_bounce, 'bounce_out')

    # Add shake on impact (when y reaches ground)
    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 构建器(组装与优化)
from core.gif_builder import GIFBuilder

# Create builder with your chosen settings
builder = GIFBuilder(width=480, height=480, fps=20)

# Add frames (however you created them)
for frame in my_frames:
    builder.add_frame(frame)

# Save with optimization
builder.save('output.gif',
             num_colors=128,
             optimize_for_emoji=False)

主要功能:

  • 自动量化颜色
  • 移除重复帧
  • 针对 Slack 限制发出大小警告
  • 表情模式(激进优化)
文本渲染

对于表情等小型 GIF,文本可读性较难保证。常见的解决方法是添加描边:

from core.typography import draw_text_with_outline, TYPOGRAPHY_SCALE

# Text with outline (helps readability)
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
)

如需实现自定义文本渲染,可使用 PIL 的 ImageDraw.text(),它适用于较大的 GIF。

颜色管理

专业美观的 GIF 通常使用协调统一的调色板:

from core.color_palettes import get_palette

# Get a pre-made palette
palette = get_palette('vibrant')  # or 'pastel', 'dark', 'neon', 'professional'

bg_color = palette['background']
text_color = palette['primary']
accent_color = palette['accent']

如需直接处理颜色,可使用 RGB 元组——选择适合具体场景的方式即可。

视觉效果

可在强调时刻使用的可选效果:

from core.visual_effects import ParticleSystem, create_impact_flash, create_shockwave_rings

# Particle system
particles = ParticleSystem()
particles.emit_sparkles(x=240, y=200, count=15)
particles.emit_confetti(x=240, y=200, count=20)

# Update and render each frame
particles.update()
particles.render(frame)

# Flash effect
frame = create_impact_flash(frame, position=(240, 200), radius=100)

# Shockwave rings
frame = create_shockwave_rings(frame, position=(240, 200), radii=[30, 60, 90])
缓动函数

平滑运动使用缓动,而非线性插值:

from core.easing import interpolate

# Object falling (accelerates)
y = interpolate(start=0, end=400, t=progress, easing='ease_in')

# Object landing (decelerates)
y = interpolate(start=0, end=400, t=progress, easing='ease_out')

# Bouncing
y = interpolate(start=0, end=400, t=progress, easing='bounce_out')

# Overshoot (elastic)
scale = interpolate(start=0.5, end=1.0, t=progress, easing='elastic_out')

可用的缓动包括:linear、ease_in、ease_out、ease_in_out、bounce_out、elastic_out、back_out(过冲),以及 core/easing.py 中的更多函数。

帧合成

如有需要,可使用以下基础绘图工具:

from core.frame_composer import (
    create_gradient_background,  # Gradient backgrounds
    draw_emoji_enhanced,         # Emoji with optional shadow
    draw_circle_with_shadow,     # Shapes with depth
    draw_star                    # 5-pointed stars
)

# Gradient background
frame = create_gradient_background(480, 480, top_color, bottom_color)

# Emoji with shadow
draw_emoji_enhanced(frame, '🎉', position=(200, 200), size=80, shadow=True)

优化策略

当 GIF 文件过大时:

消息 GIF(>2MB):

  1. 减少帧数(降低 FPS 或缩短时长)
  2. 减少颜色(从 128 种降至 64 种)
  3. 缩小尺寸(从 480x480 降至 320x320)
  4. 启用重复帧移除

表情 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))

    # Pulsing scale
    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)

# Validate
from core.validators import check_slack_size
check_slack_size('reaction.gif', is_emoji=True)
带冲击效果的动作(弹跳 + 闪光)
builder = GIFBuilder(480, 480, 20)

# Phase 1: Object falls
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)

# Phase 2: Impact + flash
for i in range(8):
    frame = create_gradient_background(480, 480, (240, 248, 255), (200, 230, 255))

    # Flash on first frames
    if i < 3:
        frame = create_impact_flash(frame, (240, 350), radius=120, intensity=0.6)

    draw_emoji_enhanced(frame, '⚽', position=(220, 350), size=80)

    # Text appears
    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

# Create shake animation
shake_frames = create_shake_animation(
    object_type='emoji',
    object_data={'emoji': '😰', 'size': 70},
    num_frames=20,
    shake_intensity=12
)

# Create moving element that triggers the shake
builder = GIFBuilder(480, 480, 20)
for i in range(40):
    t = i / 39

    if i < 20:
        # Before trigger - use blank frame with moving object
        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:
        # After trigger - use shake frame
        frame = shake_frames[i - 20]
        # Add the car in final position
        draw_emoji_enhanced(frame, '🚗', position=(300, 300), size=60)

    builder.add_frame(frame)

builder.save('scare.gif')

理念

这个工具包提供的是构建模块,而非固定配方。处理 GIF 请求时:

  1. 理解创作构想 - 需要发生什么?氛围如何?
  2. 设计动画 - 将其拆分为多个阶段(预备、动作、反应)
  3. 按需应用基本元素 - 抖动、弹跳、移动、特效——自由组合
  4. 验证限制 - 检查文件大小,尤其是表情符号 GIF
  5. 按需迭代 - 如果超出大小限制,则减少帧数或颜色

目标是在 Slack 的技术限制内释放创作自由。

依赖项

使用此工具包前,仅在尚未安装这些依赖项时进行安装:

pip install pillow imageio numpy

评论

支持 Markdown