mcpField
M
meme-creator

meme-creator

github.com/daymadeクリエイティブ・メディア1.5k115 回インストール今日更新
リポジトリ

meme-creator について

meme-creatorは、動画内の動く対象に画像を重ね、MP4とGIFに書き出すスキルです。素材の識別、トラッキングの確認、エンコード後の成果物の検証を重視します。

主な機能

  1. 01素材取得前の本人・対象確認
  2. 02フレーム単位の対象トラッキング
  3. 03静止画や長回し向けの手動キーフレーム
  4. 04オーバーレイの表示とフェード制御
  5. 05MP4とGIFの書き出し・サイズ調整

活用シーン

  1. 01動く対象にロゴやアバターを重ねる
  2. 02手動位置指定で静止画ミームを作成
  3. 03シーン切り替え時のオーバーレイを確認
  4. 04チャット向けサイズのGIFを作成

インストール

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

$npx skills add https://github.com/daymade/claude-code-skills --skill meme-creator

インストール後、Claude Code で/meme-creatorを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
asset-binding.md
tracking-playbook.md
scripts/
encode_outputs.sh
make_sheets.py
render_overlay.py
track_boxes.py

詳細

ミームクリエイター

動画クリップをミームに変換します。画像(ロゴ、アバター、ステッカー)を動くオブジェクトに貼り付け、フレームごとに動きを追従させ、MP4 と GIF で出力します。

これを台無しにする失敗は、トラッキングのズレではありません。名前を最初に見つかったもっともらしいアカウントに紐付けた結果、画面に別人のアバターを貼り付けてしまうことです。そのため、ステップ 0 で確認するのはツールではなく本人確認です。

静止画ミームの場合は、トラッキングをすべて省略できます。オーバーレイ設定の各ターゲットに manual_keys エントリーを 1 つずつ([[1, [x, y, w, h]]])指定し、そのフレームだけをレンダリングします。位置がすべてキーから取得される場合、--tracks は省略可能です。

要件

  • PATH 上に ffmpeg があること
  • uv — 同梱の Python スクリプトにはインライン依存関係が含まれています。uv run <script> で実行すると、依存関係は自動的に解決されます
  • ダウンロードする場合のみ yt-dlp(uv run --with yt-dlp yt-dlp ...)
  • SVG ロゴをラスタライズする場合のみ Chrome/Chromium(asset-binding.md)
  • 以下のスクリプトパスは、このスキルのバンドルディレクトリからの相対パスとして scripts/… と記載しています。バンドルパスを一度解決し(SKILL_DIR=<path to this skill>)、"$SKILL_DIR"/scripts/make_sheets.py … を実行してください。作業ディレクトリはバンドルではなく、一時作業用ディレクトリです。

パイプライン

一時作業用ディレクトリ(/tmp/<meme-name>/ など)内で作業し、最終的な MP4 と GIF のみを納品します。

0. アセットを取得する前に本人を特定する

ユーザーが画面に登場させる人物やもの(「Codex、Claude、Tibo のアバター」など)を指定した場合、曖昧な名前はすべて references/asset-binding.md の照合手順を通過させる必要があります。ハンドル名を使わずに検索して候補を列挙し、依頼の文脈(特に、同時に挙げられている他の人物やもの)を手がかりに区別してください。文脈だけで判断できない場合は、ユーザーに確認してください。このファイルでは、ロゴやアバターの入手方法、ヘッドレス Chrome を使って実際に透過した PNG に変換する方法、バッジのスタイルについても説明しています。合成する前に、すべての画像を取得して目視で確認してください。

1. ソースを取得する

ローカルファイルの場合は、そのまま使用します。URL の場合は、yt-dlp で bilibili(b23.tv の短縮リンクを含む)、YouTube、およびほとんどのサイトに対応できます。

uv run --with yt-dlp yt-dlp -f "bv*+ba/b" --merge-output-format mp4 -o "source.%(ext)s" "<url>"

中国国内サイトでプロキシトンネルエラーが発生した場合は、--proxy "" を付けて再試行してください(ローカル HTTP プロキシが一部の国内 CDN で問題を起こすことがあります)。海外サイトでタイムアウトする場合は、ローカルプロキシを使用して再試行してください。

再生時間を確認します:ffprobe -v error -show_entries format=duration -of csv=p=0 source.mp4

2. セグメントを特定する

動画全体をトラッキングしてはいけません。1~2 fps のコンタクトシートを作成して正確なシーンを見つけ、その前後に範囲を広げます。

ffmpeg -v error -ss <start_s> -t 40 -i source.mp4 -vf "fps=1,scale=240:-1,tile=5x8" -frames:v 1 contact.png

シートを確認し、動きの区切り(登場 → 動作 → 退場)を選んで、前後に 1 秒ずつ余裕を持たせて最終セグメントを切り出します。フレームを元の fps で抽出します。

mkdir -p seq && ffmpeg -v error -ss <seg_start> -i source.mp4 -t <seg_dur> seq/f_%04d.png
ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate -of csv=p=0 source.mp4
3. オーバーレイ用アセットを準備する

各ターゲットにつき、アルファチャンネル付きの PNG 画像を 1 枚用意します。異なる種類のアセット(アプリアイコン、ロゴマーク、写真のアバター)は circle-white バッジに統一します。その理由とアバターの円形マスク処理については、asset-binding.md を参照してください。

4. ターゲットをトラッキングする

手順の全容と失敗の分類については、 references/tracking-playbook.md を参照してください。概要は以下のとおりです。

  1. すべてのターゲットが完全に見えているフレームを 1 枚、グリッド表示します。 uv run scripts/make_sheets.py grid --frames 'seq/f_%04d.png' --index 30 --out grid.png グリッド上で各ターゲットの [x, y, w, h] ボックスを読み取ります。
  2. トラッキング設定(ターゲットと初期フレーム)を作成し、実行します。 uv run scripts/track_boxes.py --frames 'seq/f_%04d.png' --config track.json --out tracks.json --last <N>
  3. 確認します。 uv run scripts/make_sheets.py tile --frames 'seq/f_%04d.png' --tracks tracks.json --start 1 --end <N> --step-frames 15 --out verify.png すべてのタイルを確認します。
  4. タイルに表示された問題を修正します。後の区間で再度アンカーを設定する(ショットの切り替わり、急な拡大、ズレ)か、滑らかで長いショットでは manual_keys に切り替えます。2~3 回の調整を想定してください。その後、すべての退場、登場、何も映らない区間に visible/fade_in/fade_out を設定します。何も映っていないフレームにロゴが表示されたままになるのは、もっとも目立つ不具合です。
5. レンダリング
uv run scripts/render_overlay.py --frames 'seq/f_%04d.png' --tracks tracks.json \
  --overlays overlays.json --out 'out/o_%04d.png' --last <N>

エンコードする前に、レンダリング済みのコンタクトシート(out/ に対して make_sheets.py tile を実行)を抜き取り確認します。再エンコードするより、はるかに低コストです。

6. エンコードとサイズの上限
scripts/encode_outputs.sh --frames 'out/o_%04d.png' --fps <native_fps> \
  --source source.mp4 --ss <seg_start> --t <seg_dur> --mp4 meme.mp4 \
  --gif meme.gif --gif-width 400 --gif-fps 10 --gif-colors 96

GIF のサイズは、パレットサイズではなく、フレーム数 × ディザノイズで決まります。チャットアプリの約 10 MB の上限に収めるには、次の順に設定値を下げます。--gif-fps(15→12→10)、次に --gif-width(480→400)、最後に --gif-colors(128→96)。

7. エンコード済みの成果物を確認してから納品する

最終版の MP4 と最終版の GIF からフレームを抽出し(ffmpeg -ss <t> -frames:v 1)、目視で確認します。それまでの確認では中間ファイルを検証していましたが、ここでは受け取り側が実際に見るファイルを検証します。両方のファイルを正確なパスで納品します。

トラブルシューティング

症状原因対処方法
国内サイトで yt-dlp が Tunnel connection failed 503 を出すローカル HTTP プロキシによる割り込み--proxy "" を追加します
cairosvg/svglib が no library called cairo でクラッシュするシステムに cairo がないヘッドレス Chrome を使って SVG をラスタライズします(asset-binding.md)
ショットの切り替わりと同時にトラッカーが停止するCSRT はカットをまたげない新しいショットの最初のフレームに新しい segments エントリーを追加します
約 1 分かけてボックスが徐々にターゲットからずれるテンプレートの汚染トラッカー自身の直近の正常なボックスで再アンカーするか、manual_keys を使います
被写体が画面から退出した後もロゴがフレーム中央に残る可視範囲の設定がない退出前に fade_out を設定し、その後に visible 範囲を設定しません
GIF がサイズ上限を大幅に超えるディザノイズ × フレーム数最初に --gif-fps を下げ、次に幅、最後に色数を下げます
PNG では問題ないロゴが GIF では崩れる中間ファイルしか確認していないエンコード済みファイルからフレームを抽出して必ず確認します(手順 7)
エンコード時に Failed to set value '1:a' for option 'map' が発生するソースクリップに音声ストリームがない同梱スクリプトでは 1:a?(任意)をマッピングします。ffmpeg を手動で実行する場合も同様にするか、--source を削除します

参考資料

  • references/asset-binding.md — 識別情報の曖昧さを解消するためのゲート、ロゴ/アバターの取得、透明度、バッジのスタイル設定
  • references/tracking-playbook.md — CSRT の障害分類、再アンカーによる復旧、手動キーフレーム、フェード、検証ループ

コメント