/dynamic-edit
動かないトーキングヘッドは視聴者を即座に飽きさせ、理由もなく動くものはさらに悪い結果を招きます。このパイプラインは、どのエフェクトをどの単語に配置する価値があるかを決定し、それを人間が拒否権を行使できる計画として書き出し、その後にのみ計算リソースを消費します。
リポジトリルート:
THP_HOME=${THP_HOME:-$(cat ~/.config/talking-head-pipeline/root)}
計画を立てる前に以下を読んでください: $THP_HOME/docs/STYLE_RULES.md (クラフトルール)、$THP_HOME/docs/LAYOUTS.md (ジオメトリとキャプションのセーフゾーン)、references/plan-format.md (スキーマ)、references/qa.md (ゲート)。3D関連: $THP_HOME/docs/3D.md。
入力契約: 映像はすでにカットされていること。 無音除去やフィラーパスはここでは行いません。生テイクはまず /autocut に送り、その clean.mp4 とワークディレクトリ(逐語的な単語リスト用)を持って戻ってきてください。
計画ステップを決してスキップしないでください。 ロトスコープは映像1分あたり約12分かかり、フルレンダリングには数十分かかります。テキスト計画で誤りを発見できれば、コストは実質ゼロです。
ワークフロー
1. プロジェクトをスキャフォールドする
P=<projects dir>/<slug> # ユーザーが動画プロジェクトをどこに保存しているか尋ねること。デスクトップは不可
cp -R "$THP_HOME/template" "$P"
cd "$P"
uv venv --python 3.11 .venv # mediapipe は 3.12 以降のホイールがありません
uv pip install --python .venv/bin/python "mediapipe==0.10.21" opencv-python backgroundremover numpy pillow
scripts/download_models.sh # MediaPipe 顔検出器 (リポジトリには同梱されていません)
(cd remotion && pnpm install) # または npm install
cp "<autocut workdir>/clean.mp4" remotion/public/raw.mp4
python3 "$THP_HOME/scripts/autocut/verbatim_cut_words.py" "<autocut workdir>" -o remotion/public/words.json
16:9のテイクから縦型リールを作成する場合: 最後の2行の代わりに scripts/prep_vertical.sh "<autocut workdir>" "$P" を実行します(顔の中央xで静的9:16クロップ、フォロークロップは行いません)。
2. インベントリ、カット、トラッキング
ffprobe -v error -select_streams v:0 -show_entries stream=width,height,r_frame_rate,nb_frames \
-show_entries format=duration -of default=nw=1 remotion/public/raw.mp4
.venv/bin/python scripts/detect_cuts.py remotion/public/raw.mp4 --out remotion/public/cuts.json
.venv/bin/python scripts/track_head.py remotion/public/raw.mp4 --out remotion/public/track.json --cuts remotion/public/cuts.json
- ズームヘッドルーム = ソース幅 / タイムライン幅 (2560 を 1920 で割ると 1.33倍の余裕)。それを超えるとアップスケールになります。
- アスペクトはプランの幅/高さ (
lib/layouts.tsのプロファイル) から自動検出されます。単一のエンジンであり、フォークはありません。 track.jsonのdetectionRateを確認してください。~0.9 未満の場合、顔にアンカーされた動きは信頼できません。その旨を伝えてください。- カット検出は段階的な変化(アニメーションによる画面共有への切り替えなど)を見逃します。セグメントごとに1フレームをサンプリングし、手動で見つかった境界を
cuts.jsonに追加してください。画面共有セグメントには、パンチイン、キャプションの描画、カードは適用しません(captions.silenceに該当範囲を設定してください)。
3. 単語リストを校正する
words.json 内の固有名詞、ブランド名、ティッカー、スクリプトに登場する人名をすべて確認してください。Whisper系のモデルはこれらを誤認することが多く、文としては流暢に読めてしまうため、レビューでは見逃されがちです。単語ファイルを修正してください(2つのトークンを1つにマージしても問題ありません)。レンダリング自体は修正しないでください。数字は半角数字のままにしてください。
4. 計画を書き、そして止まれ
- まずトランスクリプト全体を読んでください。ナラティブが実際に持つビート(フック、主張、数字、転換、啓示、見せ場、語るよりも示す方が良い瞬間)を見つけてください。
- 以下のエフェクトの選択から、ビートごとにツールを選んでください。多くのビートには何も割り当てません。
scripts/build_plan.example.pyをscripts/build_plan.pyにコピーし、そこに単語アンカー ("phrase@seconds") を使ってビートを記述してください。これによりremotion/plan.jsonとキャプションが生成されます。理由のないイベント、開始と終了の単語アンカーのないイベント、間隔が狭すぎるパンチは拒否されます。- 人間にテーブルを提示してください。1行につき1イベント: 時間、エフェクト、「Xに着地、Yの後に離脱、理由はZ」。さらに、ロト秒数(およびそれに伴うマット処理時間)、ズームヘッドルームを超えるリフレーム、約12秒以上イベントがないストレッチ、必要な3Dレンダリングを含めてください。
- 承認を待ってください。 その後、ディスクから
plan.jsonを読み込み直してください。人間が編集している可能性があります。
もし人間が特定の瞬間に特定のエフェクトを指定した場合、それがそのビートの計画となります。
5. 計画に必要なものだけを構築する
- ロトウィンドウ:
scripts/render_and_qa.shがマットを生成します。またはウィンドウごとにscripts/matte_frames.pyを実行します。 - 3Dヒロイックタイプ / 3Dアセット:
tools/render3d(docs/3D.md を参照)。まずスチル (--stills) で確認し、その後--clip --dir=remotion/public/<name>でレンダリングします。プランイベントのat/untilと同じインフレーム/アウトフレームをショットに設定します。 - サイドカード: 種類は
remotion/src/layouts/cards.tsxにあります。必要に応じて新しい種類を追加してください。 - スクリーンシーンページ:
remotion/src/screen/pages.tsx。ズームインする対象については、UIをコードで再構築してください。スクリーンショットは2倍にするとぼやけます。 - フルスクリーンシーン:
scenes/fullscreen/registry.ts(depth,clip,stage)。 - SFX: 計画が確定した後、
scripts/add_sfx.py "$P" sfx_map.json --library <dir>を実行します。
6. スチルで確認してからレンダリングする
スチルは数秒で済みますが、レンダリングは午後いっぱいかかります:
cd remotion && npx remotion still src/index.ts Edit ../qa/landing.png --frame=<N>
すべてのヒーローランディング(およびランディング+25フレーム)、すべてのレイアウトエントリー、すべてのトランジション、すべての3D到着を確認してください。その後:
scripts/render_and_qa.sh "$P" <name> # ロトウィンドウをマットし、レンダリングし、QAシートを書き出します
レンダリング: --concurrency は4〜6、nice でプロセスを実行し、Config.setChromiumOpenGlRenderer('angle') を維持してください(remotion.config.ts に既にあります。またはWebGLシーンはヘッドレスで失敗します)。yuv420p bt709 で出力してください。yuvj420p ファイルはQuickTimeで空白表示になります。
7. QA (references/qa.md を参照)、その後同期トリム
誰かが確認する前に、references/qa.md のすべてのゲートを実行してください。次に、レンダリングのオーディオ遅延をソースに対して測定しトリミングします(Remotionレンダリングは数十ミリ秒遅れるため、想定せずに測定してください):
"$THP_HOME/scripts/master/sync_trim.sh" renders/<name>.mp4 remotion/public/raw.mp4 renders/<name>_final.mp4 [--loudnorm -14]
最終的な同期差は5ミリ秒未満を目標にしてください。ラウドネスノーマライゼーションは、人間が希望する場合のみ行います(ソーシャルメディアのデフォルトは -14 LUFS)。最終ファイルを人間に公開してください。
8. 納品後の修正: 範囲をパッチし、動画全体を再レンダリングしない
scripts/patch_render.sh --base renders/prev.mp4 --replace 0-1049 --render 0-887 --out renders/next.mp4
--replace は古いレンダリングから破棄する範囲、--render はそれを置き換える現在の計画の範囲です(ソースが再カットされた場合、これらは異なります)。パッチ部分のみがエンコードされ、先頭と末尾はキーフレームでストリームコピーされます。フレーム数は検証されます。計画が存在した後にソースからつまずきを取り除く必要がある場合は、アンカーから計画を再構築(build_plan.py)して、すべてのエフェクトが対応する単語とともに移動するようにしてください。
9. 人間が動画は完了したと言った場合のみ、クリーンアップを行う
まず確認してください。scripts/cleanup.sh は、マットPNG、フレームダンプ、QAシート、ドラフト、venv、node_modules を削除します。計画、ソース、トラック、キャプション、最終レンダリングは保持します。マットの再生成には映像1分あたり約12分かかるため、プロンプトなしで決して実行しないでください。
エフェクトの選択(実行順ではなくツールボックス)
決まった公式はありません。ヒーローワード、ロト、3Dがない動画も妥当な計画です。ストレートなカメラトークは、パンチインとキャプションのみの場合もあります。すべてのエフェクトはスクリプト内の何かによって獲得され、各イベントはその理由(ナラティブ上の役割)、IN(着地する単語。到着する前に動きが始まる)、OUT(離脱する単語:その思考の終わり、次の本当の休止、ソフトナーの前の単語)を指定します。固定ホールドや、「しばらく静かだったから」という理由は決して許されません。
- まず顔。 最初の2〜3秒はスピーカーの顔であり、フレーム0はすでに読めるフック画像であること(黒からのフェードではありません)。フルスクリーングラフィックは約2.5秒より前には配置しません。自動再生はミュートされており、統計から始まるオープニングはインフォグラフィックとして読まれ、スクロールされてしまいます。
- パンチイン:(主力) 文単位で、少数で、目的を持って。キーセンテンスが構築されるにつれて着地し、それを保持し、最後の単語で解放します。一単語のパンチは禁止。タイマーで間隔を空けることも禁止。長編ではトーキングヘッド約30〜45秒に1回程度。ショート動画ではスクリプトが獲得する場合のみ、よりタイトに。トラッキングされた顔にアンカーします。2つのリンクされたフレーズ:ストーリーを伝える半分をパンチします。ネストされたアクセント(サステイン + キーフレーズへの小さなアクセント)が、一文の中での3つのパンチの代わりになります。
- サイドレイアウト:(16:9) 数字、リスト、比較を説明している間、画面に表示し続けるべき場合に使用します。被写体が片側にスライドし、もう片側にコンテンツサイズのカードを置き、カードはその単語で切り替わり、言及されている数字でパンチインします。長編の情報ビートのほとんどはこれを必要とします。
- スクリーンシーン:(16:9) 「これがどのように見えるか」のウォークスルー。動画ごとに1〜2回まで。すべての言及に対して使用しないでください。製品を再現する場合は実際のUIと1対1で対応させ、データのみが変更され、そのデータは実際のものです。
- カード付きオフセットリフレーム: サイドレイアウトの軽量版で、ズームヘッドルーム内で動作します。
- ロト(被写体の背後): オープナーとヒーローモーメントのみ。デフォルト予算は動画あたり15秒。30秒を超える場合は警告。60秒を超える場合は確認が必要。背後を通過するものは、隠す価値があるものでなければなりません。
- 被写体の背後に配置するヒーローワード: フック、ハードターン、名前付きアイデア。頭の上に配置し、すべてのグリフが読めること(ランディング+25フレームのスチルで確認)。動画に1つまで。離れた場所に2つ目のランディングがある場合を除きます。
- 3Dヒロイックタイプ: 頭の横または胸の前に配置する大きな主張や数字。すべてのフレーム端から均等なパディング(幅1080で少なくとも約90ピクセル)を確保。顔の上には決して配置しません。
- 3Dアセット: スピーカーが名前を挙げたロゴやオブジェクトを、顔の横の空きスペースで回転させます。重なる場合は背後でロトします。
- フルスクリーンシーン: 見せる方が説明より明らかに優れている場合のみ。最大2つまで。フェード+ブラーで出入りします。
- キャプション: 固定の下3分の1。トーキングヘッド、サイド、スクリーンのすべてで同じ位置とスタイル。強調はアクセント書体と1.22倍のサイズをフレーズ全体に適用。2つのカードに分割しないでください。ヘッドトラッキングキャプションは、要求されない限りオフ。
- SFX: 可視イベント(トランジション、ヒーローランディング、ハードパンチ、カード、クリック)ごとに1つ。控えめに。
ハードルール
- 顔の上には何も配置しない。 キャプション、カード、チップ、ロゴ、3Dオブジェクトを、そのウィンドウのどのフレームでも顔のボックス上に配置しないでください。移動するか、縮小するか、ロトで背後に配置してください。track.json から測定してください。
- スピーカーの上にボックス化されたテキストチップを配置しない。 カードの片面(上部、左部、任意の端)にアクセントラインを配置しないでください。塗りつぶしの色合いか、完全な均等ボーダーを使用してください。
- フレーム全体のフェードのみ。 タイトルが残っている間にコンテナをフェードさせないでください。
- トランジション: フェード+ブラー(デフォルト)、プレーンフェード、またはリキッドスティンガー。ジグザグ/歯状シャッターは禁止。
- ズームやフレーム端でテキストが切れないようにする。 ズームされたUIはキャプションバンドの上でフェードアウトします(
Worldエッジフェード)。キャプションは決してズームしません。 - リフレームは、それがスペースを確保するためのものと同じレンダリング内で出荷する。 空の壁に向かってカメラを移動させないでください。
- 画面上のすべての数字を、発言内容または保存・取得済みのソースと照合して検証する。 決して捏造しないでください。
- オブジェクトとアイコンは実際のロゴ、または生成・ソースから取得した画像であること。 コードはモーション、テキスト、UI、チャートを描画します。矢印はアセットであり、SVGではありません。
- 画面上にダッシュ(em dash)を表示しない。ユーザーが要求しない限り、「コメントしてね」「DMして」などのコールトゥアクションを表示しない。
- ビデオの上に積み重ねられるすべてのレイヤーは、独自の
AbsoluteFillであること(静的なビデオは絶対配置された兄弟要素の下にペイントされます。これにより、マットの前にグラフィックが配置されることが暗黙的に防がれます)。 - リフレームには
translate + scaleを使用し、transform-originをずらさないでください。
エフェクトパラメータと測定値: references/effects.md。