mcpField
S
slack-gif-creator

slack-gif-creator

github.com/alleneeeクリエイティブ・メディア27345 回インストール31 週間前に更新
リポジトリ

slack-gif-creator について

slack-gif-creator は、Slack のメッセージや絵文字の制約に合わせたアニメーション GIF を作るスキルです。仕様検証、組み合わせ可能なアニメーション部品、任意で使える組み立て・最適化用の補助機能を備えています。

主な機能

  1. 01Slack のファイルサイズと寸法の検証
  2. 02再利用可能なアニメーション部品の組み合わせ
  3. 03GIF フレームの組み立てと最適化
  4. 04文字・配色・効果の補助機能
  5. 05絵文字 GIF 固有の制約確認

活用シーン

  1. 01Slack メッセージ用 GIF の作成
  2. 02サイズ制限内の絵文字 GIF の制作
  3. 03アップロード前の GIF 検証と最適化

インストール

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

$npx skills add https://github.com/alleneee/skill-agent --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

コメント