リール モーショングラフィックス編集
生の縦型動画を完成されたモーショングラフィックス編集に変換します:
セットアップ → 分析 → 質問:スタイル(スタイルボード) + 準備オプション → ビートシート → plan.json
→ チェック + プレビューループ → オーバーレイレンダリング → コンポーズ → 確認 → 提案:字幕 + 追加機能
オーバーレイは、透明背景のHTML/GSAPでフレームごとにレンダリングされるため(assets/engine.html)、ペルシア語の字形、フォント、グラデーションがピクセルパーフェクトに再現されます。アニメーションコードを手書きする必要はありません。コンポーネントとその時間をリストしたplan.jsonを記述します。エンジンは選択されたスタイルプリセットに従ってアニメーションを生成し、これによりルック、モーション、トランジション、サウンドパレットが設定され、各コンポーネントにデフォルトの効果音が与えられます。
ユーザーとはその言語(通常はペルシア語)で会話してください。進捗状況の更新は簡潔に保ちます。
編集が「ぴったり」であるべき理由 ― そして単調にならないようにするために
視聴者は、グラフィックや効果音が0.5秒ずれていたり、話されている内容と無関係であることに気づきます。それが編集を素人っぽく見せる原因です。以前の編集はまさにその点で批判されました。話している内容と合わない装飾的なバッジが話者の顔の上に表示されました。その後、ユーザーは編集が繰り返しに見え始めたとも言いました。4つのアイデアで両方の問題を解決し、ツールはそのほとんどを強制します:
- 言葉にアンカーする。 発言を反映するテキストは単語アンカー(
"t": "w:رایگان")を使用して、近くではなく音節に合わせて表示します。手入力の秒数は純粋に視覚的なイベントにのみ使用します。 - 映像にアンカーする。 クリック、ページ変更、レイアウトズームは
motion.jsonのイベント("t": "m:m12")と、自身で読み取ったタイムスタンプ付きコンタクトシートから取得します。目に見えるクリックがないクリック効果音はノイズです。 - 顔を保護する。 顔とPIPの矩形を
plan.avoidで宣言します。render.js checkはそれらを覆う要素をフラグします。レンダリング前にすべてのCOVERS警告を修正します。 - ユーザーにルックを選ばせ、その中でバリエーションを持たせる。 デザイン前にスタイルを尋ねます(ステップ2)。毎回同じレシピに頼らず、フックの形式、アイデアを伝えるコンポーネント、トランジションを変えます。
references/styles.mdにスタイルごとのプレイブックとフック形式のリストがあります。
ステップ0 — セットアップ(マシンでの初回実行)
python <skill>/scripts/setup.py
faster-whisper、puppeteer-core、gsapを ~/.cache/reel-motion-edit/ にインストールし、SFXライブラリを合成し、Whisperモデル(large-v3-turbo、約1.6 GB)をダウンロードします。huggingface.coがブロックまたは切断された場合は再開してhf-mirror.comにフォールバックします。これは「必要なものをダウンロードする」ステップなので、確認せずに実行します。ダウンロード内容を1行でユーザーに伝えます。バックグラウンドで実行します:モデルは接続が遅いと時間がかかる場合があります。その間に analyze.py --no-transcript で視覚分析を行い、後でトランスクリプト用に再実行できます。スキル更新後は scripts/sfx.py ~/.cache/reel-motion-edit/sfx を再実行して、新しいスタイルのサウンドが存在するようにします。
便利な追加アセット(フォント、アイコンセット、ロイヤリティフリーのSFXや音楽トラック)を見つけた場合は、作業ディレクトリにダウンロードします。ライセンスを <workdir>/CREDITS.txt に記録します。OFL/CC0ソース(Google Fonts、Pixabay/Freesound CC0)を優先します。バンドルフォント:Vazirmatn(本文)、Lalezar(表示)、Changa(テクニカル)、Lemonada(遊び心)、Noto Kufi Arabic(フォーマル)。ユーザーがローカルにインストールしているフォント(例:Morabba、IRANSansX、Yekan Bakh)は plan.fonts で追加でき、多くの場合、ブランドに最も合った選択肢です。%LOCALAPPDATA%\Microsoft\Windows\Fonts と C:\Windows\Fonts を確認します。
ブランドキット。 ~/.config/reel-motion-edit/brand.json が存在する場合、render.js が自動的に適用します:style、theme(ブランドカラー)、fonts、handle(@ユーザー名透かし)、handleCorner、logo。plan.jsonでオーバーライドできます。"brand": false は1つのビデオでブランドキットを無視します。ユーザーが永続的な好み(ハンドル、常に希望するスタイル、ブランドカラー)を伝えた場合は、そこに保存することを提案します。
ステップ1 — 分析
動画の隣に作業ディレクトリを作成します(<video dir>/<video name>_edit/)。次を実行:
python <skill>/scripts/analyze.py "<video>" "<workdir>" --lang fa
次に analysis/transcript.txt とすべての analysis/sheets/sheet_*.jpg(各10秒、セルあたり0.5秒、タイムスタンプ付き)を読みます。スクリプトによって出力されたモーションイベント(m0 … mN、cut/change)は候補です。それぞれをシートと照合して確認します。スクロールも「change」として表示されるためです。
Whisperはペルシア語や英語の製品名を誤って綴ることがあります。修正をメモします(キャプションや単語アンカーに重要:Whisperが単語を綴った方法でアンカーします)。
ステップ2 — ユーザーに質問:スタイル + 準備オプション(デザイン前)
動画や視聴者によって求めるルックは異なり、ユーザーは選択したいと考えています。スタイルボードを作成します:ユーザーの動画の代表的なフレームを7つのプリセットすべてでレンダリングし、タイトル、ステップチップ、ステッカー、字幕行を含めます。最初に最小限のplan.json(動画 + タイトル + 1つのキーワード + 動画にステップがあればステップ)を書き、次を実行します:
node <skill>/scripts/render.js "<workdir>/plan.json" styleboard <T> # → build/styleboard.jpg
フレームが典型的なTを選びます(トランジション中ではない)。画像をユーザーに送信し(SendUserFile、display render)、AskUserQuestionで質問します。ブランドキットにすでに style がある場合は、ユーザーが別のものを求めない限り、スタイルの質問をスキップします。
- Q1 — スタイル(最大4オプション:このコンテンツに最適なものを最初に推奨し、1行の理由を添え、3つの対照的な選択肢を提示します。その他は「その他」と入力できると言います)。プリセット:
gradientモダングラデーション、boldポップ/Hormozi、neonテック/サイバー、minimalクリーンなApple風、doodle手描き、retroVHS、newsブロードキャスト。説明はassets/styles.json(label、feel)にあります。 - Q2 — 準備オプション(複数選択)、該当するもののみ:
- ポーズのトリミング(ジャンプカット):
tighten.pyが約0.45秒より長い無音を削除します。トーク動画に最適。画面録画の場合、無音部分がクリックが発生する場所である可能性があると警告します。タイムラインが変更されるため、分析前に実行します:トリミングされたファイルで分析を再実行します。 - 音声クリーンアップ:
"voice": "enhance"(ノイズ除去、ランブルカット、プレゼンス、軽いコンプレッション)。電話や部屋の音声に推奨します。 - @ハンドル透かし:ブランドキットにない場合はハンドルを尋ねます。
- 背景音楽:ユーザーがトラックを持っているか、CC0のものを見つけてほしい場合のみ。自動的に音声の下にダッキングされます。
- ポーズのトリミング(ジャンプカット):
ユーザーが編集をただ望み、こだわりがない場合は、ユーザーに代わって選択し、どのスタイルを選んだかとその理由を伝えて進みます。
ステップ3 — ビートシート(デザイン前に考える)
<workdir>/beats.md を書きます:各ビートを1行に、時間範囲、言われていること、表示されていること、レイアウト(顔全体 / 画面 + PIP左下 / 手持ち画面 / …)を記載します。以下をマーク:
- フック(最初の1~3秒):
references/styles.mdからフック形式を選びます。前回と異なるものを選びます(わかっている場合) - 話者が説明する各ステップ / アイデア
- ペイオフの瞬間(結果が表示される:「接続完了」、「完了」、数字)
- 最後のCTA
- レイアウト変更(カメラと画面間のズーム):トランジションポイント
- レイアウトごとの安全ゾーン:オーバーレイが顔、カーソル、実演中のものを隠さずに配置できる場所
references/styles.md(選択したスタイルのプレイブック)と references/creative-direction.md(ペーシング、配置、SFXルール)を読みます。これらは短く、「ごちゃごちゃ」と「プロフェッショナル」の違いを生み出します。
ステップ4 — plan.json
<workdir>/plan.json を書きます。すべてのコンポーネント、そのプロパティ、デフォルトSFXは references/components.md にあります。plan.jsonを書く前にそれを読みます。最小限の形状:
{
"video": "D:/videos/vpn firefox.mp4",
"size": [1080, 1920], "fps": 30,
"style": "neon",
"voice": "enhance",
"handle": {"text": "@your_handle", "corner": "tl"},
"avoid": [{"name": "face", "from": 0, "to": 14.6, "rect": [200, 420, 680, 900]},
{"name": "pip", "from": 15, "to": 29.1, "rect": [0, 1300, 510, 620]}],
"elements": [
{"type": "title", "t": 0, "d": 3.8, "y": 90, "kicker": "آموزش ۶۰ ثانیهای", "lines": ["`VPN` *رایگان*"], "sub": "با سرورهای فایرفاکس"},
{"type": "transition", "t": "m:m3-0.1"},
{"type": "steps", "items": [{"t": "w:گوگل", "label": "جستجو در گوگل", "sub": "`vpn firefox github`"}], "hide": [[29.0, 34.1]]},
{"type": "keyword", "t": "w:رایگان", "x": 540, "y": 1640, "text": "رایگان", "emoji": "🎁"},
{"type": "success", "t": "w:وصل", "x": 405, "y": 678, "title": "وصل شدی!"},
{"type": "cta", "t": 57.4, "items": [{"text": "سیو کن", "icon": "save"}, {"text": "فالو کن", "icon": "follow"}]}
],
"camera": [{"t": "w:رایگان", "d": 1.2, "type": "punch", "scale": 1.12, "cx": 540, "cy": 700}],
"sfx": [{"t": 16.2, "name": "typing", "db": -8}],
"cover": {"lines": ["`VPN` *رایگان*"], "sub": "آموزش ۶۰ ثانیهای"}
}
ルックはスタイルに決めさせます。 視覚的なプロパティ(theme カラー、キーワード style/rotate/from、トランジション kind、タイトル anim、キャプションスタイル)は、意味的な理由(エラーに赤、ブランドカラー)がない限り設定しないでください。プリセットがそれらを埋め、それがスタイルに違いを生じさせます。kind のないトランジションはスタイルのトランジションをサイクルします。plan.jsonの theme はプリセットをオーバーライドするだけです(例:製品のブランドカラー)。
テキスト構文:*word* または *two words* = ハイライト、`latin` = 分離されたLTR実行("VPN"/URLがRTLテキスト内で反転するのを防ぎます)。
ステップ5 — チェック、プレビュー、修正(ループ)
node <skill>/scripts/render.js "<workdir>/plan.json" check
node <skill>/scripts/render.js "<workdir>/plan.json" preview 1 5.5 15.8 21.1 27.4 54
check は解決されたタイムラインを出力し、以下をリントします:
COVERS:要素が保護ゾーンにかぶっているOFFFRAMECLUTTER:同時に3つ以上のオーバーレイSFXPILE:0.35秒以内に効果音が重なっているORDER:単語アンカーが以前の出現にヒットしたため、w:word#2を使用
すべての問題を修正します。次に build/preview.jpg を見ます:各重要な要素のアニメーション中の時間を選び、吹き出しやリップルがターゲットに正確に配置されているか確認します。サムネイルから推測するのではなく、フル解像度フレーム(ffmpeg -ss T -i video -frames:v 1 f.png)から座標を読み取ります。正しくなるまで繰り返します。プレビューは安価ですが、フルレンダリングはそうではありません。
ステップ6 — レンダリングとコンポーズ
node <skill>/scripts/render.js "<workdir>/plan.json" full # build/overlay.mov(動画1分あたり約3~6分)
python <skill>/scripts/compose.py "<workdir>/plan.json" --out "<video dir>/<name> - edit.mp4"
node <skill>/scripts/render.js "<workdir>/plan.json" cover <T> # build/cover.jpg — 投稿カバー(フレームTのぼかし + タイトル)
フルレンダリングはバックグラウンドで実行します。compose.py は以下を行います:
- カメラ移動を動画にのみ適用
- グラフィックスをオーバーレイ
- 設定されている場合、
voiceクリーンアップを適用 - SFXベッドを音声の下にミックスし、設定されている場合は音楽をダッキングありでミックス:
"music": {"file": "...", "db": -20} - −14 LUFSにノーマライズ
ソース動画を上書きしないでください。新しいファイルを書き込み、再レンダリング時にはバージョン接尾辞(- edit v2)を付けます。
ステップ7 — 確認
出力のコンタクトシートを作成します(ffmpeg -i out.mp4 -vf "fps=1/2,scale=216:-1,tile=10x3" sheet.jpg)。それを確認します。長さが一致し、オーディオが存在することを確認します。確認したこと(フレーム)とできなかったこと(リスニングは不可。SFXタイミングはイベントリストと照合して検証し、耳では検証しない)を正直に報告します。
ステップ8 — 字幕と追加機能を提案(常に最後に)
編集が提供されたら、AskUserQuestionで質問します(該当する場合は複数選択)。まだ行われていないものだけを提案します:
- 字幕:
references/caption-styles.mdから3~4スタイル。選択したスタイルのデフォルト(styles.jsonのcaptions)を最初に推奨し、理由をこの動画に基づいて説明します。 - 投稿用のカバー画像(
render.js cover)。 - Instagramキャプション文:トランスクリプトから
<workdir>/post.txtを書きます:フック行、2~4行の価値ある短い行、CTA、話者が言及したリンクまたはコメントキーワード、8~15の関連するペルシア語 + 英語のハッシュタグ。 - ブランドキットに保存:選択したスタイル、ハンドル、カラーを保存し、次の動画がそこから始まるようにします。
- 別のスタイルバージョン:同じplan.jsonを異なる
styleで再レンダリングしてA/Bテスト(オーバーレイのみ変更)。
字幕の場合:
python <skill>/scripts/captions.py "<workdir>" --style karaoke --zones "0-14.6:1400,29.4-33.8:1400" --default-y 1170 --keywords "رایگان,VPN" --fix "غلط=درست,وی پی این=VPN"
出力されたチャンクを校正します。--fix でWhisperのスペルミスを修正します。複数単語のソースはトークンをマージします。"captions": {"file": "captions.json"} をplan.jsonに追加し(スタイルはデフォルトでプリセットのものに設定。"style" でオーバーライド)、check を実行し(字幕も顔やステッカーを覆ってはいけません)、新しいバージョンとして再レンダリングとコンポーズを行います。
注意点
- 画面座標の要素(クリック、ハイライト、コールアウト矢印)は、カメラ移動で同じセクションがズームされると位置がずれます。トーク動画セクションでのみカメラ移動を使用します。
- Camtasiaスタイルの顔と画面間のアニメーションズームは約0.5秒続きます。トランジション要素をズームの開始に配置し、そのウィンドウ内にテキストを配置しないでください。
steps.hideは、顔全体のセクション中にステップチップを非表示にし、その後再表示します。- Whisperの単語タイムスタンプは、ポーズ後の最初の単語で約0.1秒遅れることがあります。ハードヒット(タイトルスラム)の場合は、
-0.05で調整します。 - 1080×1920ではないソース(例:608×1080の電話書き出し)は、コンポーズとプレビューによってプランサイズにアップスケール/クロップされます。プラン座標は常にプランサイズのピクセル単位なので、ソースフレームから読み取った座標に
1080 / source_widthを掛けます。 - モニターの手持ち電話映像:画面が動くため、画面に固定された要素(クリック、ハイライト、矢印)はターゲットに留まりません。代わりに構造(ステップ)、マージンの単語アンカーステッカー、全フレームトランジションを使用します。
- タイトルにはデフォルトで上部の暗いスリムが付きます(
"scrim": falseで削除)。明るい画面上で読みやすくします。 - 話者自身の声はそのままにします(ラウドネスノーマライゼーションを超えるEQ/圧縮は行いません)。
ワークフロー図
graph TD
A[動画ファイル] --> B[セットアップ]
B --> C[分析:トランスクリプト + コンタクトシート]
C --> D[スタイルボードの質問]
D --> E[ビートシート作成]
E --> F[plan.json作成]
F --> G[チェック/プレビューループ]
G -->|問題あり| F
G -->|OK| H[フルレンダリング]
H --> I[コンポーズ]
I --> J[確認]
J --> K[字幕/追加機能の提案]
K --> L[最終編集]
クイックリファレンス
| コマンド | 説明 |
|---|---|
setup.py | 依存関係のインストール(初回のみ) |
analyze.py | トランスクリプト + モーション分析 |
render.js check | plan.jsonのリンティング |
render.js preview | プレビューフレームのレンダリング |
render.js full | フルオーバーレイ動画のレンダリング |
render.js styleboard | スタイル比較ボード |
render.js cover | カバー画像 |
compose.py | 最終動画のコンポーズ |
captions.py | 字幕生成 |
sfx.py | SFXライブラリの更新 |
tighten.py | ポーズのトリミング |