Slack GIF クリエイター は何をしますか?
Slack向けに最適化されたアニメーションGIFを作成するためのユーティリティと知識を提供するツールキットです。
Slackの要件
寸法:
- 絵文字GIF: 128x128(推奨)
- メッセージGIF: 480x480
パラメータ:
- FPS: 10~30(低いほどファイルサイズが小さい)
- 色数: 48~128(少ないほどファイルサイズが小さい)
- 再生時間: 絵文字GIFは3秒未満に抑える
コアワークフロー
from core.gif_builder import GIFBuilder
from PIL import Image, ImageDraw
# 1. ビルダーを作成
builder = GIFBuilder(width=128, height=128, fps=10)
# 2. フレームを生成
for i in range(12):
frame = Image.new('RGB', (128, 128), (240, 248, 255))
draw = ImageDraw.Draw(frame)
# PILプリミティブを使ってアニメーションを描画
# (円、多角形、線など)
builder.add_frame(frame)
# 3. 最適化して保存
builder.save('output.gif', num_colors=48, optimize_for_emoji=True)
グラフィックの描画
ユーザーアップロード画像の扱い
ユーザーが画像をアップロードした場合、次の意図を考慮してください:
- 直接使用(例:「これをアニメーション化して」「これをフレームに分割して」)
- インスピレーションとして使用(例:「こんな感じのものを作って」)
PILを使って画像を読み込み、操作します:
from PIL import Image
uploaded = Image.open('file.png')
# 直接使用するか、色やスタイルの参考として使う
ゼロからの描画
グラフィックをゼロから描画する場合は、PIL ImageDrawプリミティブを使用します:
from PIL import ImageDraw
draw = ImageDraw.Draw(frame)
# 円/楕円
draw.ellipse([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
# 星、三角形、任意の多角形
points = [(x1, y1), (x2, y2), (x3, y3), ...]
draw.polygon(points, fill=(r, g, b), outline=(r, g, b), width=3)
# 線
draw.line([(x1, y1), (x2, y2)], fill=(r, g, b), width=5)
# 矩形
draw.rectangle([x1, y1, x2, y2], fill=(r, g, b), outline=(r, g, b), width=3)
使用しないもの: 絵文字フォント(プラットフォーム間で信頼性が低い)や、このスキルにプリパッケージされたグラフィックの存在を前提にしないでください。
グラフィックを美しく見せるために
グラフィックは基本的なものではなく、洗練されていてクリエイティブであるべきです。以下のようにします:
太い線を使う - 輪郭や線には必ず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) # PIL Imageを追加
builder.add_frames(frames) # フレームリストを追加
builder.save('out.gif', num_colors=48, optimize_for_emoji=True, remove_duplicates=True)
バリデーター (core.validators)
GIFがSlackの要件を満たしているか確認します:
from core.validators import validate_gif, is_slack_ready
# 詳細な検証
passes, info = validate_gif('my.gif', is_emoji=True, verbose=True)
# クイックチェック
if is_slack_ready('my.gif'):
print("準備完了!")
イージング関数 (core.easing)
リニアではなく滑らかな動きを実現:
from core.easing import interpolate
# 0.0 から 1.0 までの進行度
t = i / (num_frames - 1)
# イージングを適用
y = interpolate(start=0, end=400, t=t, easing='ease_out')
# 利用可能: linear, ease_in, ease_out, ease_in_out,
# bounce_out, elastic_out, back_out
フレームヘルパー (core.frame_composer)
よくあるニーズに対応する便利関数:
from core.frame_composer import (
create_blank_frame, # 単色背景
create_gradient_background, # 縦方向グラデーション
draw_circle, # 円の描画ヘルパー
draw_text, # シンプルなテキスト描画
draw_star # 五芒星
)
アニメーションコンセプト
振動/震え
オブジェクトの位置を振動でずらす:
math.sin()またはmath.cos()をフレームインデックスで使用- 自然な感じにするため小さなランダムな変動を加える
- x および/または y 位置に適用
脈動/鼓動
オブジェクトのサイズをリズミカルに変化させる:
- 滑らかな脈動には
math.sin(t * frequency * 2 * math.pi)を使用 - 鼓動の場合: 2回の短い脈動の後に休止(サイン波を調整)
- 基本サイズの0.8倍から1.2倍の間でスケール
バウンド
オブジェクトが落下し跳ねる:
- 着地には
interpolate()でeasing='bounce_out'を使用 - 落下(加速)には
easing='ease_in'を使用 - 各フレームでy速度を増加させて重力を適用
回転/スピン
オブジェクトを中心に回転させる:
- PIL:
image.rotate(angle, resample=Image.BICUBIC) - ぐらつきの場合: 線形ではなくサイン波を角度に使用
フェードイン/アウト
徐々に表示または非表示にする:
- RGBA画像を作成し、アルファチャンネルを調整
- または
Image.blend(image1, image2, alpha)を使用 - フェードイン: アルファを0から1へ
- フェードアウト: アルファを1から0へ
スライド
オブジェクトを画面外から所定の位置へ移動:
- 開始位置: フレーム境界の外側
- 終了位置: ターゲット位置
- 滑らかに停止するには
interpolate()でeasing='ease_out'を使用 - 行き過ぎを表現するには
easing='back_out'を使用
ズーム
拡大・縮小効果のためのスケーリングと配置:
- ズームイン: 0.1倍から2.0倍にスケール、中央をクロップ
- ズームアウト: 2.0倍から1.0倍にスケール
- ドラマチックな効果のためにモーションブラーを追加可能(PILフィルター)
爆発/パーティクルバースト
放射状に広がるパーティクルを生成:
- ランダムな角度と速度でパーティクルを生成
- 各パーティクルを更新:
x += vx,y += vy - 重力を追加:
vy += gravity_constant - 時間経過でパーティクルをフェードアウト(アルファを減らす)
最適化戦略
ファイルサイズを小さくするよう求められた場合のみ、以下の方法をいくつか実装します:
- フレーム数を減らす - FPSを下げる(20ではなく10)または再生時間を短くする
- 色数を減らす -
num_colors=48を128の代わりに使用 - 寸法を小さくする - 480x480ではなく128x128を使用
- 重複を削除する -
save()でremove_duplicates=Trueを使用 - 絵文字モード -
optimize_for_emoji=Trueで自動最適化
# 絵文字向けの最大最適化
builder.save(
'emoji.gif',
num_colors=48,
optimize_for_emoji=True,
remove_duplicates=True
)
哲学
このスキルは以下を提供します:
- 知識: Slackの要件とアニメーションコンセプト
- ユーティリティ: GIFBuilder、バリデーター、イージング関数
- 柔軟性: PILプリミティブを使ってアニメーションロジックを作成可能
以下のものは提供しません:
- 固定のアニメーションテンプレートや事前定義された関数
- 絵文字フォントのレンダリング(プラットフォーム間で信頼性が低い)
- スキルに組み込まれたプリパッケージグラフィックのライブラリ
ユーザーアップロードに関する注意: このスキルには事前構築されたグラフィックは含まれていませんが、ユーザーが画像をアップロードした場合はPILを使って読み込み・操作してください。リクエストに応じて、画像を直接使用するのか、インスピレーションとして使用するのかを判断します。
クリエイティブに!コンセプトを組み合わせ(バウンド+回転、脈動+スライドなど)、PILの全機能を活用してください。
依存関係
pip install pillow imageio numpy