animated-message-composer について
Slack 向けの仕様に合わせたアニメーション GIF を作るためのツールキットとガイドです。フレーム作成、仕様検証、視覚効果、アニメーションテンプレートを備え、カスタム画像を作る人を対象としています。
主な機能
- 01画像フレームから GIF を作成
- 02Slack GIF 要件の検証
- 03イージングと視覚効果の適用
- 04既成アニメーションテンプレートの利用
- 05PIL ヘルパーでの描画
- 06ファイルサイズと色数の最適化
活用シーン
- 01カスタム Slack 絵文字アニメーションの作成
- 02Slack メッセージ用 GIF の作成
- 03GIF の Slack 規定への適合確認
- 04アップロード画像へのアニメーション追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ qodex-ai/ ai-agent-skills --skill animated-message-composerインストール後、Claude Code で/animated-message-composerを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
LICENSE.txtrequirements.txtcore/color_palettes.pyeasing.pyframe_composer.pygif_builder.pytypography.pyvalidators.pyvisual_effects.pytemplates/bounce.pyexplode.pyfade.pyflip.pykaleidoscope.pymorph.pymove.pypulse.pyshake.pyslide.pyspin.pywiggle.pyzoom.py詳細
Slack GIF クリエイター
Slack 向けに最適化されたアニメーション GIF を作成するためのユーティリティとナレッジを提供するツールキットです。
Slack の要件
絵文字 GIF(Slack への絵文字のアップロード):
- 最大サイズ:64 KB
- サイズ:128x128 推奨(正方形)
- FPS:10-12
- 色数:32-48
- 長さ:1-2s
メッセージ GIF:
- 最大サイズ:約2 MB
- サイズ:480x480 が一般的
- FPS:15-20
- 色数:128-256
- 長さ:2-5s
基本的なワークフロー
from core.gif_builder import GIFBuilder
from PIL import Image, ImageDraw
# 1. Create builder
builder = GIFBuilder(width=128, height=128, fps=10)
# 2. Generate frames
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
draw = ImageDraw.Draw(frame)
# Draw your animation using PIL primitives
# (circles, polygons, lines, etc.)
builder.add_frame(frame)
# 3. Save with optimization
builder.save('output.gif', num_colors=48, optimize_for_emoji=True)
任意のショートカット:templates/ のアニメーションテンプレートを使うと、すばやくフレームを生成できます。
from templates.shake import create_shake_animation
frames = create_shake_animation(
object_type='circle',
object_data={'radius': 30, 'color': (100, 150, 255)},
num_frames=20,
direction='both'
)
builder.add_frames(frames)
グラフィックの描画
ユーザーがアップロードした画像を扱う
ユーザーが画像をアップロードした場合、次のどちらを希望しているかを検討します。
- 画像をそのまま使う(例:「これをアニメーションにして」「これをフレームに分割して」)
- 画像を参考にする(例:「これに似たものを作って」)
PIL を使って画像を読み込み、処理します。
from PIL import Image
uploaded = Image.open('file.png')
# Use directly, or just as reference for colors/style
ゼロから描画する
グラフィックをゼロから描画する場合は、PIL ImageDraw のプリミティブを使います。
from PIL import ImageDraw
draw = ImageDraw.Draw(frame)
# Circles/ovals
draw.ellipse([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
# Stars, triangles, any polygon
points = [(x1, y1), (x2, y2), (x3, y3), ...]
draw.polygon(points, fill=(r, g, b), outline=(r, g, b), width=3)
# Lines
draw.line([(x1, y1), (x2, y2)], fill=(r, g, b), width=5)
# Rectangles
draw.rectangle([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
絵文字フォントだけに頼るのは避けてください。絵文字フォントはプラットフォームに依存します。draw_emoji または draw_emoji_enhanced を使う場合は、レンダリングに差が生じる可能性があるため、図形やテキストで調整できるようにしておきます。
グラフィックの見栄えを良くする
グラフィックはありきたりなものではなく、洗練され、創造性のあるものにしましょう。方法は次のとおりです。
線を太くする - 輪郭線や線には、必ず width=2 以上を設定します。細い線(width=1)はギザギザに見え、素人っぽい印象になります。
奥行きを加える:
- 背景にグラデーションを使う(
create_gradient_background) - 複数の図形を重ねて複雑さを加える(例:小さな星を内側に描いた星)
図形に工夫を加える:
- 単純な円を描くだけでなく、ハイライト、リング、模様などを加える
- 星に光彩を加える(背後に大きく半透明の星を描く)
- 複数の図形を組み合わせる(星+きらめき、円+リング)
色に注意を払う:
- 鮮やかで、互いに引き立て合う色を使う
- コントラストを加える(明るい図形には濃い輪郭線、暗い図形には明るい輪郭線)
- 全体の構図を考慮する
複雑な図形の場合(ハート、雪の結晶など):
- 多角形と楕円を組み合わせる
- 対称になるよう、点の位置を慎重に計算する
- 細部を加える(ハートにはハイライトの曲線を、雪の結晶には複雑な枝を加える)
創造性を発揮して、細部まで作り込みましょう。質の高い Slack GIF は洗練された見た目で、仮のグラフィックのように見えてはいけません。
利用可能なユーティリティ
GIFBuilder (core.gif_builder)
フレームを組み立て、Slack 向けに最適化します。
builder = GIFBuilder(width=128, height=128, fps=10)
builder.add_frame(frame) # Add PIL Image
builder.add_frames(frames) # Add list of frames
builder.save('out.gif', num_colors=48, optimize_for_emoji=True, remove_duplicates=True)
Validators (core.validators)
GIF が Slack の要件を満たしているか確認します。
from core.validators import (
validate_gif,
is_slack_ready,
check_slack_size,
validate_dimensions
)
# Detailed validation
passes, info = validate_gif('my.gif', is_emoji=True, verbose=True)
# Quick check
if is_slack_ready('my.gif'):
print("Ready!")
# Focused checks
passes, info = check_slack_size('my.gif', is_emoji=True)
passes, info = validate_dimensions(128, 128, is_emoji=True)
Easing Functions (core.easing)
直線的な動きではなく、滑らかな動きを実現します。
from core.easing import interpolate
# Progress from 0.0 to 1.0
t = i / (num_frames - 1)
# Apply easing
y = interpolate(start=0, end=400, t=t, easing='ease_out')
# Available: linear, ease_in, ease_out, ease_in_out,
# bounce_out, elastic_out, back_out
Frame Helpers (core.frame_composer)
よくある用途に便利な関数です。
from core.frame_composer import (
create_blank_frame, # Solid color background
create_gradient_background, # Vertical gradient
draw_circle, # Helper for circles
draw_rectangle, # Helper for rectangles
draw_line, # Helper for lines
draw_text, # Simple text rendering
draw_emoji, # Emoji rendering (platform-dependent)
draw_star # 5-pointed star
)
その他のヘルパーには、draw_emoji_enhanced、draw_circle_with_shadow、draw_rounded_rectangle、add_vignette があります。
カラーパレット (core.color_palettes)
読みやすい色を使うための、厳選されたパレットとヘルパーです。
from core.color_palettes import get_palette, get_text_color_for_background
palette = get_palette('vibrant')
text_color = get_text_color_for_background(palette['background'])
タイポグラフィ (core.typography)
高品質な縁取り文字や影付き文字を作成します。
from core.typography import draw_text_with_outline
draw_text_with_outline(frame, "SALE!", position=(240, 240), font_size=48, centered=True)
視覚効果 (core.visual_effects)
パーティクル、ぼかし、衝撃、モーション効果を扱います。
from core.visual_effects import ParticleSystem
particles = ParticleSystem()
particles.emit(240, 240, count=20)
アニメーションテンプレート (templates/)
すぐに使えるアニメーション(シェイク、バウンス、回転、ズーム、スライド、フェード、反転、爆発など)です。
フレームの生成に使い、その後 GIFBuilder に渡します。
アニメーションの概念
シェイク/振動
振動を使ってオブジェクトの位置をずらします。
- フレームインデックスとともに
math.sin()またはmath.cos()を使う - 自然な動きにするため、小さなランダム変化を加える
- x 座標や y 座標、またはその両方に適用する
パルス/鼓動
オブジェクトのサイズをリズミカルに変化させます。
- 滑らかなパルスには
math.sin(t * frequency * 2 * math.pi)を使う - 鼓動の場合は、短いパルスを2回続けてから停止する(正弦波を調整)
- 基本サイズの0.8〜1.2倍の範囲で拡大縮小する
バウンス
オブジェクトが落下して跳ね返ります。
- 着地には
easing='bounce_out'を指定したinterpolate()を使う - 落下時(加速時)には
easing='ease_in'を使う - 毎フレーム y 方向の速度を増加させ、重力を適用する
回転/スピン
オブジェクトを中心を軸に回転させます。
- PIL:
image.rotate(angle, resample=Image.BICUBIC) - 揺れを表現するには、角度を線形に変化させる代わりに正弦波を使用します。
フェードイン/フェードアウト
徐々に表示または非表示にします。
- RGBA 画像を作成し、アルファチャンネルを調整します。
- または、
Image.blend(image1, image2, alpha)を使用します。 - フェードイン:アルファ値を 0 から 1 にします。
- フェードアウト:アルファ値を 1 から 0 にします。
スライド
オブジェクトを画面外から所定の位置に移動します。
- 開始位置:フレームの範囲外
- 終了位置:目標の位置
easing='ease_out'を指定してinterpolate()を使用すると、滑らかに停止します。- オーバーシュートさせるには、
easing='back_out'を使用します。
ズーム
ズーム効果を出すために、拡大縮小と位置を調整します。
- ズームイン:倍率を 0.1 から 2.0 にし、中央を切り抜きます。
- ズームアウト:倍率を 2.0 から 1.0 にします。
- 劇的な効果を加えるために、モーションブラーを追加できます(PIL フィルター)。
爆発/パーティクルのバースト
外側に広がるパーティクルを作成します。
- ランダムな角度と速度を持つパーティクルを生成します。
- 各パーティクルを更新します:
x += vx、y += vy - 重力を加えます:
vy += gravity_constant - 時間の経過とともにパーティクルをフェードアウトさせます(アルファ値を減らします)。
最適化の方法
ファイルサイズを小さくするよう依頼された場合に限り、以下の方法をいくつか実装してください。
- フレーム数を減らす - FPS を下げる(20 ではなく 10 にする)か、再生時間を短くします。
- 色数を減らす - 128 ではなく
num_colors=48にします。 - サイズを小さくする - 480x480 ではなく 128x128 にします。
- 重複を削除する -
save()でremove_duplicates=Trueを指定します。 - 絵文字モード -
optimize_for_emoji=Trueで自動的に最適化します。
# Maximum optimization for emoji
builder.save(
'emoji.gif',
num_colors=48,
optimize_for_emoji=True,
remove_duplicates=True
)
方針
このスキルが提供するもの:
- 知識:Slack の要件とアニメーションの概念
- ユーティリティ:GIFBuilder、バリデーター、イージング関数
- 柔軟性:PIL のプリミティブを使ってアニメーションのロジックを作成できます。
このスキルが提供しないもの:
- 固定的なアニメーションテンプレートや、あらかじめ用意された関数
- 絵文字フォントのレンダリング(プラットフォーム間で安定しないため)
- スキルに組み込まれた、あらかじめパッケージ化されたグラフィックのライブラリ
ユーザーがアップロードした画像について:このスキルにはあらかじめ用意されたグラフィックは含まれていませんが、ユーザーが画像をアップロードした場合は、PIL で読み込んで加工してください。その画像を直接使うのか、インスピレーションとして使うだけなのかは、ユーザーの依頼に基づいて判断してください。
自由に工夫してください!複数の概念(バウンド+回転、パルス+スライドなど)を組み合わせ、PIL の機能を最大限に活用してください。
依存関係
pip install pillow imageio numpy