mcpField
S
slack-gif-creator

slack-gif-creator

github.com/composiohqクリエイティブ・メディア78.2k4.2k 回インストール14 週間前に更新
リポジトリ

slack-gif-creator について

slack-gif-creatorは、Slack向けのメッセージ用・絵文字用GIFを作るツールキットです。組み合わせ可能なアニメーション素材、組み立て・最適化機能、Slackのサイズや容量を確認するバリデーターを備えています。

主な機能

  1. 01ファイル容量と寸法の検証
  2. 02複数のアニメーション効果の合成
  3. 03GIFBuilderによる組み立てと最適化
  4. 04テキスト、色、視覚効果のユーティリティ
  5. 05絵文字GIF向けの最適化

活用シーン

  1. 01Slackの制限に沿ったメッセージGIFの作成
  2. 02容量制限内の絵文字GIFの作成
  3. 03効果を組み合わせたリアクションGIFの制作

インストール

コマンドをコピーしてターミナルで実行します。

$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 クリエーター - 柔軟なツールキット

Slack 向けに最適化されたアニメーション GIF を作成するためのツールキットです。Slack の制約を確認するバリデーター、組み合わせ可能なアニメーションプリミティブ、任意のヘルパーユーティリティを提供します。創作のビジョンを実現するため、必要に応じてこれらのツールを活用してください。

Slack の要件

Slack では、GIF の用途に応じて具体的な要件が定められています。

メッセージ用 GIF:

  • 最大サイズ:約 2MB
  • 最適な寸法:480x480
  • 一般的な FPS:15-20
  • 色数の上限:128-256
  • 長さ:2-5 秒

絵文字用 GIF:

  • 最大サイズ:64KB(厳格な制限)
  • 最適な寸法:128x128
  • 一般的な FPS:10-12
  • 色数の上限:32-48
  • 長さ:1-2 秒

絵文字用 GIF の作成は難しいです。64KB の制限は厳格です。次の方法が役立ちます。

  • 全体のフレーム数を 10-15 に制限する
  • 色数を最大 32-48 色にする
  • デザインをシンプルに保つ
  • グラデーションを避ける
  • ファイルサイズをこまめに確認する

ツールキットの構成

このスキルでは、次の 3 種類のツールを提供します。

  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
)

カスタムのテキスト描画を実装するには、大きめの GIF で問題なく動作する PIL の ImageDraw.text() を使用してください。

カラー管理

プロフェッショナルな印象の 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

コメント