Communitygithub.com

Morph Edit (モーショングラフィックB-Roll)

トーキングヘッド動画とその文字起こしから、話者の言葉に合わせてモーフィングするモーショングラフィックB-Roll映像を生成します。1つのシェイプがカットなしで変形し続ける、カーソルとスプリングモーションで駆動するスタイルです。動画と文字起こしを渡して「モーショングラフィック」「B-Roll」「アニメーションカットアウェイ」「オーバーレイ」を依頼されたときに使用します。

Morph Edit (モーショングラフィックB-Roll) とは?

Morph Editは、クリエイターのトーキングヘッド動画に、話者の発言にぴったりと同期したモーショングラフィックB-Rollを生成するためのエキスパートスキルです。出力されるクリップはすべて**1つのシェイプがカットされずに変形し続ける**スタイルで、サイズ、角丸、色が状態ごとに変化し、内容の切り替え時には短いブラーがかかります。カーソルのクリックやドラッグが各変化のトリガーとなり、すべてのモーションが発話された単語に紐づきます。このスキルは、動画の文字起こし(自動文字起こしツールを含む)を解析し、話者が言及した製品、プロセス、数値、比較などの具体的なイメージを、コード、UI操作、チャート、端末のタイピングといったインタラクションとして視覚化します。動画の解像度やフレームレートに合わせたクリップのレンダリング、クリップを合成したプレビュー動画、クリップ一覧ページや比較ページの生成までを自動化します。Claude Code(および類似のエージェント)上で動作し、ユーザーは動画ファイルと文字起こしを提供するだけで、プロフェッショナルなモーショングラフィックを入手できます。

対応~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/mrgoraya/morph-edit/tree/main/skills/morph-edit

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Morph Edit (モーショングラフィック B-Roll)

あなたはクリエイターの動画向けにモーショングラフィッククリップを作成します。すべてのクリップはカットされずに変形し続ける1つのシェイプです。サイズ、角丸、色が状態ごとに変化し、内容の切り替え時には短いブラーがかかります。カーソルが実際のクリックやドラッグで変化を駆動し、すべての変化は発話された単語のタイミングに合わせられます。

出力は、クリエイターが自身のエディターに取り込むためのクリップセットです。また、クリップをカットインしたプレビュー動画レンダリング、クリップをステップ実行するためのHTMLページ、比較用のHTMLページも提供します。

必要なものはすべてこのスキルフォルダに含まれています。

  • engine/: モーションエンジン (motion.js)、ページシェル (base.css)、build.py (クリップ → スタンドアロンHTML)、render.js (フレーム単位レンダリング、モーションブラー対応)、beats.js (静止画コンタクトシート)、フォント (Geist、OFL)。
  • scripts/: setup.sh、inspect_video.py、words.py、composite.py、make_pages.py。
  • reference/engine-api.md: クリップの書き方。最初のクリップを書く前に読んでください。
  • examples/opus-aoe2/: 実際の54秒動画向けの完成済みクリップ6つ。品質基準および出発点として使用してください。

以下、$SKILL はこのスキルのフォルダを意味します。ユーザーのプロジェクト内に motion/ フォルダを作成して作業してください。

1. セットアップ (初回のみ)

bash $SKILL/scripts/setup.sh ./motion

Node、Python 3、ffmpeg の存在を確認し、Playwright + Chromium を motion/node_modules にインストールします。すべてのエンジンスクリプトは NODE_PATH=./motion/node_modules を指定して実行してください。

2. インタビュー

AskUserQuestion ツールを使用し、1ラウンドで収めてください。必要な情報:

  • 動画のパス。 パスを取得し、motion/work/source.* としてコピーまたは参照します。
  • 文字起こし。 任意。存在しない場合(またはプレーンテキストのみの場合)、scripts/transcribe.py で音声を文字起こしします(ステップ3参照)。これにより、SRTの推定値よりも正確な単語タイムスタンプが得られます。
  • 密度:
    • ライト:毎分2〜4クリップ、最も強い瞬間のみ。
    • ミディアム(デフォルト):毎分4〜7クリップ。
    • ヘビー:ほとんどのラインをカバーし、短い顔のギャップを残す。
  • ルック:
    • デフォルトパレット:ウォームグレーのキャンバス、白黒のコンポーネント、1つのオレンジアクセント。
    • またはユーザーのブランド:色、オプションでフォント。ロゴ、スクリーンショット、ブランドカラーを motion/inputs/ にドロップしてもらい、それを参照します。
  • 避けるべきもの、含めるべきもの。 顔を残すライン、表示する実際の数値や名前、再現する製品スクリーンショット。

ユーザーが既に回答した質問はスキップします。

3. フッテージの検査

python3 $SKILL/scripts/inspect_video.py motion/work/source.mp4 motion/work
python3 $SKILL/scripts/words.py transcript.srt > motion/work/words.txt
# 文字起こしがない場合(または正確な単語タイミングが必要な場合):代わりに音声を文字起こし
motion/.venv/bin/python $SKILL/scripts/transcribe.py motion/work/source.mp4 motion/work

transcribe.py は words.txt と transcript.srt を書き出します。計画を立てる前に、聞き間違いや用語の修正ができるよう、文字起こしをユーザーに提示してください。

自分で motion/work/contact.png を確認してください。video.json は解像度、fps、レイアウトセクションを提供します:

  • full: 話者がフレーム全体を占めます。
  • pip: 話者がボックス内に表示され、残りは空です。ボックスの位置と、ボックスサイズが変化または移動する場合の警告が含まれます。

クリップは動画の解像度とfpsに一致する必要があります。SRTからの単語タイミングは推定値(±0.2秒)です。そのように扱ってください。

4. 計画し、コードを書く前に承認を得る

クリップごとに1行のテーブルを表示します:

| # | In–Out | カバーするライン | どの単語でシェイプが何をするか | 処理 | 理由 |

クリエイティブディレクション:各クリップがフレームのどの程度を占めるかを決定します。 これは最も重要な判断です。クリップごとに決定し、理由を述べてください。

  • 全フレームカットアウェイ。 フレーム全体が話者であり、そのラインが何かを 見せる 場合:製品、プロセス、比較、数値、チャプターの切り替え。
    • アイデアの長さ(3〜10秒)だけカットアウェイし、その後顔に戻ります。
    • フックの最初の1秒、または個人的・感情的・意見のラインではカットアウェイしないでください。
    • カットアウェイの間には最低約2秒の顔を残してください。
  • 空きスペースのパネル。 既に編集でスペースが確保されている場合:PiPボックス、分割、プレーンな領域。
    • 空き領域の中央に配置された透過クリップ(bg:null)をレンダリングし、すべての瞬間で話者のボックスにかからないサイズにします。
    • 話者が画面に表示され続けるため、1つの連続モーフとして長時間(15秒以上)実行できます。
    • inspect_video.py がボックスの変化を報告した場合、それが意図的かどうかを尋ね、最大のボックスにサイズを合わせるか、変化点でパネルを分割します。
  • 何もしない。 そのラインが話者についてのものか、別のクリップに近すぎる場合。

コンテンツルール:

  • 被写体の実際のオブジェクト(フォルダ、端末、ファイル、製品、結果)を表示します。それらを言葉から引き出します。各アイデアを、reference/engine-api.md の語彙(ピル+クリック、進捗、チェック、ステータスアイランド、カード+ドラッグ、スライダー、トグル、タブ、チャート+ツールチップ、検索/フィルター、ファイルドラッグ&ドロップ、端末タイピング、サイドバイサイド比較、チャプターカード)からのインタラクションにマッピングします。
  • 数値、引用、価格、結果を決して発明しないでください。 相対的なバー、スケルトンテキスト行、または文字起こしから取ったラベルを使用し、何が例示であるかを明記します。実際の数値は、ユーザーから提供された場合のみ使用します。
  • クリップあたり1つのアイデア。連続した部分(PiPセクション全体)は、複数のステートを持つ1つの長いクリップにできます。
  • 音楽ではなく発話に合わせてペースを調整します:1拍あたり1回の変化、約0.4〜1.2秒間隔。

ユーザーが計画を承認または編集するのを待ちます。

5. ビルド

reference/engine-api.md とサンプルに従って、motion/clips/NN-name.html にクリップごとに1つのフラグメントを記述します。その後ビルド:

python3 $SKILL/engine/build.py motion/dist motion/clips/*.html

各ステート変更を対応する単語に配置します:クリップローカル時間 = 単語時間 − クリップのイン点。

6. キーワードでの静止画確認

NODE_PATH=./motion/node_modules node $SKILL/engine/beats.js motion/dist/NN-name.html motion/work/NN.png 0.4 1.2 2.1 …

各ステートが落ち着いた時間と、モーフィング途中の瞬間をいくつか選びます。自分ですべてのシートを確認してください。詰まり、クリップ、読みにくさ、単語との不一致、またはカーソルがフレームからはみ出る箇所を修正します。その後もう一度確認します。パネルクリップはシート上で黒背景でレンダリングされるため、その状態で判断できます。

7. レンダリング

NODE_PATH=./motion/node_modules node $SKILL/engine/render.js motion/dist/NN-name.html motion/out/NN-name_0m32s40.mp4 30000/1001
  • 動画のfpsを使用します。
  • パネルクリップ(bg:null)は .mov で書き出す必要があります。これによりアルファチャンネル付きのProRes 4444が得られます。
  • 各ファイルの名前は、タイムライン上のイン点(0m32s40 = 0:32.40)に基づいて付けます。
  • レンダリングは1フレームあたり4サブフレームを生成するため、リアルタイムより遅くなります。マルチコアマシンでは2つのクリップを並行して実行してください。

8. 納品

motion/plan.json を書き出します(スキーマは reference/engine-api.md)。UI効果音については、各クリップにキューから取得した "sfx": [[クリップローカル時間, 種類], ...] リストを付けます:カーソルクリックに click と toggle、ドラッグ開始/解放に pickup/drop、シェイプモーフに whoosh、イントロとバッジに pop、バーに rise/fall、タイピングに type、アイテム出現に tick、スクリーンショットに shutter、チェックに success。その後:

python3 $SKILL/scripts/composite.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/sfx.py motion/plan.json motion/out/preview.mp4   # UI効果音(ユーザーが希望する場合)
python3 $SKILL/scripts/make_pages.py motion/plan.json motion/out/preview.mp4
python3 $SKILL/scripts/make_gallery.py motion/plan.json motion/out/preview.mp4

すべて motion/out/ 内でユーザーが受け取るもの:

  • クリップ
  • TIMING.md: ファイル、イン、アウト、カバーするライン、処理、例示しているもの
  • preview.mp4: クリップがカットインされた動画、ハードカット、元の音声(SFX使用時はSFX付き)
  • sfx/: 各クリップの効果音を個別のWAVファイルとして。エディターでミキシングするため
  • index.html: すべてのクリップをグリッドで同時再生、フルプレビューと他のページへのリンク(最初に開く)
  • viewer.html: クリップをステップ実行
  • compare.html: オリジナルとプレビューを同期させて、サイドバイサイド、重ね、ワイプで比較

プレビューはレビュー用であることを明確に伝えてください。最終的なカットでは、クリエイターが自身のエディターでクリップを配置し、タイミング調整、トランジション追加、オーディオミキシングを行います。

購読カード(オプション)

クリエイターに、コールトゥアクションのラインにエンドカードの購読カードと、1〜2つの短いリマインダーを追加するかどうかを尋ねます。テンプレートは $SKILL/templates/subscribe/ 内のクリップフラグメントです(end-card.html、reminder.html)。1つを motion/clips/ にコピーし、その後:

  • __CHANNEL__、__HANDLE__、__AVATAR__(データURIとしてのクリエイターのロゴまたは写真、画像がない場合はサークル内の文字)を置き換えます。これらは必ず尋ねてください。名前やハンドルを推測しないでください。
  • <script> の先頭にある定数(IN、クリック時間、T)をクリエイター自身の言葉に再調整します。エンドカードは、クリエイターが発話した単語に合わせて「共有」「購読」「ベル」「いいね」「コメント」をクリックします。リマインダーは「購読」と「ベル」をクリックします。
  • 他のクリップと同様にビルド、静止画確認、レンダリング、plan.json への追加を行います。カードは透過 .mov パネルとしてレンダリングされるため、フッテージの上に配置されます。

キャプション(オプション)

発話言語のSRTと英語のSRTを作成します(焼き込みではなく、クローズドキャプションとしてアップロードするため)。motion/work/cap/ で作業:

  1. motion/.venv/bin/python $SKILL/scripts/captions/find_gaps.py motion/work/words.txt "<video>": Whisperは長い動画では発話の連続部分全体を落とすことがあります。ギャップを出力するので、retx.py "<video>" "<gaps list>" motion/work/gapwords.json [language] で再文字起こしします。
  2. python3 $SKILL/scripts/captions/make_cues.py motion/work/words.txt motion/work/gapwords.json motion/work/cap がキューと4つのチャンクを書き出します。
  3. templates/caption_brief.md を使用して、4つのサブエージェント(チャンクごとに1つ)でチャンクを並行翻訳します。各エージェントは、すべてのキューに対して {"i","orig","en"} を含む out1..4.json を書き出します。
  4. フラグが付いたキューを修正し、python3 $SKILL/scripts/captions/build_srt.py motion/work/cap motion/out/captions で captions_original.srt と captions_english.srt(各行最大42文字のバランスの取れた2行)を書き出します。
  5. 公開前にVLCまたは限定公開アップロードでSRTをテストするようクリエイターに伝えます。

スタイルデフォルト

ユーザーのブランドがこれらを上書きします。

  • 色: キャンバス #E9E7E2、インク #0B0B0B、白いコンポーネント、アクセント1色 #FF5A1F。暗いフッテージ上のパネルクリップは明るいシェイプ(#F4F2EE)を使用します。
  • タイプとアイコン: UIテキストはGeist、コード・ファイル名・端末はGeist Mono。1つのアイコンセット、1つのストロークウェイト(M.icon)。
  • モーション: せいぜい小さなオーバーシュートのスプリング。リーディングエッジとトレーリングエッジは異なるスプリングに乗るため、インジケーターが伸びます。各ステートがフレームを埋めるようにカメラがズームします。
  • 禁止: バウンシーなイージング、パーティクル、グロー、UIクロームのグラデーション、混合されたアイコンストローク、デッドタイム、テンプレートのように見えるもの、捏造されたデータ。

注意点

  • カメラが拡大縮小する要素に will-change を決して設定しないでください。テキストがぼやけてレンダリングされます。
  • モーフィング中のコンテナ内でのテキスト入れ替えには、独自の出入りタイミング(M.vis din/lin/lout)が必要です。そうしないと、古いテキストと新しいテキストが重なります。
  • mix-blend-mode: difference ラベルは、ブレンドモード自体を持つレイヤーに配置する必要があります。フィルターをかけた親要素がそれらを分離します。
  • ハイライトの下をスライドするアイテムには M.FAST スプリングが必要です。そうしないと、ハイライト行が一瞬空になります。
  • モーフィング中を含め、すべてのカメラズームでカーソルをフレーム内に維持します。
  • SRTからの単語推定値はキュー内でドリフトします。可能な場合は、重要な変更をキューの最初または最後の単語に配置します。
  • クリップは最後のステートを保持して終了します。コンポジットは、クリップのスロットがより長い場合、最後のフレームを保持します。

関連スキル