新しい動画:テイクからマスターまで
開始前に:harness.config.json → configured: true(それ以外の場合は setup スキルを実行)、bash video/scripts/doctor.sh で MISSING がないことを確認。brand-kit.md、editing-taste.md、exemplars.md の「味覚プロファイル」、anti-patterns.md、delivery-specs.md を読め。動画のスタイルはユーザープロファイルのみから決定する: ポスター、カード、ステッカー、Bロール、サウンド、グラフィックの量、テンポはすべてプロファイルに従う。プロファイルに記載がないことはユーザーに確認し、自分で決めるな。コードの出発点は現在の video/src/ とする。
もし video/public/footage.mp4 が前回の動画から残っていて、edits/ にアーカイブされていない場合は、まずアーカイブし(ステップ11)、その後開始せよ。
1. テイクの確認
ffprobe -v error -show_entries format=duration:stream=width,height,r_frame_rate:stream_side_data=rotation -of default=nw=1 takes/1.MOV
向きは rotation を参照し、width は見るな(iPhoneは縦動画を1920x1080+フラグで書き出す)。3~4フレーム確認せよ(ffmpeg -ss N -i … -frames:v 1 out/peek-N.jpg)。三脚で撮影されている場合はスタビライズするな — vidstab はかえってブレを追加する。明らかに手持ちの場合のみ:元動画にスタビライズを適用せよ(vidstabdetect=shakiness=6:accuracy=15 → vidstabtransform=smoothing=25:optzoom=1:interpol=bicubic、-c:a copy;libvidstab 付き ffmpeg が必要)。その後、スタビライズ後の動画を以降の処理に使用せよ。
2. テイクとフライングスタート — カットの前
cd video && python3 scripts/chunks.py ../takes/1.MOV
連続した文字起こしは繰り返しを隠してしまい、視聴者はすぐに気づく。以下の箇所を探せ:同じフレーズを含む隣接セグメント(テイク — 最後のものを残せ)、次のセグメントが最初から言い直している1~2語のセグメント(フライングスタート)。削除予定のリストをタイムコード付きでユーザーに表示し、「はい」の承認を得よ。境界は無音部分内とする。
3. カット
cp public/captions.json out/captions.backup.json 2>/dev/null # cut.py は文字起こしを上書きする
DROP="12.40-15.80" python3 scripts/cut.py ../takes/1.MOV
テンポはプロファイルの cut から取得する(リファレンスに基づいて調整済み)。スクリプトは DURATION、カット箇所、および「カット箇所が発声中でないか」のチェック結果を出力する。ユーザーが希望するテンポに対してカットが少なすぎる場合は、プロファイルの値より低い引数を渡せ(例:… 0.4 0.2、標準 ~0.35 / 0.2);多い場合は高い値を渡せ。カットがまったくない場合 — 部屋がうるさい:QUIET=-46。話すのが速い/テンポが遅い場合 — SPEED=1.1。カット箇所が発声中の場合は、DROP またはパラメータを調整し、そのままにするな。
4. マット処理 — すぐに開始せよ(style.poster.enabled の場合)
TITLE_OUT = cut.py の出力における最初のカット位置(ポスターはここで表示される)、通常4~7秒。マット処理は最も時間がかかる部分(CPUで約8秒/フレーム、2ワーカーで約6フレーム/分)。バックグラウンドで起動し、その間にコードを書け:
python3 scripts/matte.py <TITLE_OUT> 2 > out/matte.log 2>&1 # バックグラウンドで実行(run_in_background)
マット処理中はスチルをレンダリングするな — 負荷が高くなる。終了待機は ps -axo command | grep "[m]atte.py" で行え、pgrep は使うな。スクリプトは処理済みフレームをスキップする — 再起動後は単に再度実行せよ。
5. 文字起こしの修正
public/captions.json を開け(w、s、e は秒、em は強調):
- 聞き間違いを修正せよ:固有名詞、ブランド、専門用語、英単語;頭字語は正しい表記に(
AI、ROI);whisper は末尾の無音部分に「Спасибо за просмотр」/「Thank you.」を入れることが多い — 削除せよ; em: 2(style.captions.highlightがsizeまたはbothの場合)および"accent": 1(colorまたはbothの場合) — 意味に基づき、プロファイルに記載された数と単語に従って設定せよ(brand-kit.md§2、§4)。記載がない場合は、どの単語を強調するかユーザーに確認せよ。
6. ビートシート
自分で、または長時間動画の場合はサブエージェント script-beats を使って、video/SCRIPT.md を作成せよ:
- ポスター —
style.poster.enabledの場合のみ:ユーザーの言葉とトーンで、アクセントとキッカーはプロファイルに従う; - カード —
style.cardsがnoneでない場合、editing-taste.md§3 の密度に従う(数 →count;ステップ →num+head;列挙 →head+linesまたは単語にアイコン付きのrow);from= フレーズの最初の単語 + 4フレーム; - ステッカー
FLOATS—style.stickersの場合のみ:単語1つのキャプション、コンパクトなピクトグラム(ART_NAMES); pain: trueのカード — ユーザーが「それはダメ」と明示した場合のみ。
コードの前に、ビートシートの内容(何がどこに表示されるか)を簡潔にユーザーに示せ — ユーザーの動画、ユーザーの判断。
7. コード
src/Composition.tsx:DURATION、TITLE_OUT、KICKER、TITLE、BEATS、FLOATS;Captions from= ポスターがある場合は2番目のフレーズの開始位置、それ以外は0。src/ui/Footage.tsx:BEATSテーブルは cut.py のカット位置に厳密に従い、フルスケールで表示(クローズアップ 1.16–1.21倍、通常 1.06–1.09倍) —style.motion.punchが自動で弱めるかオフにする。クローズアップを配置する場所はediting-taste.md§4 に従う;クローズアップの後は元のスケールに戻す。戻さないとクローズアップが「張り付く」;ポスターがある場合は最初のカット位置に配置。- 新しいコンポーネントは、カード、ステッカー、
Photo/Clip/Tagのいずれでも表現できない場合のみ作成せよ(その場合はscene-builderを使用)。 - Higgsfield からの Bロール — 接続されており、プロファイルがそれを望む場合(
brand-kit.md§5):<Clip>で表示せよ(事前にトリミングと無音化:ffmpeg -an -t <秒>)。挿入前に生成フレーム上のテキスト/顔/手を確認せよ。まずユーザーに確認し、価格を伝えよ。 - サウンド —
style.sfxの場合のみ:不足しているロール(card、count、end)は、プロファイルの説明に基づいてサブエージェントaudio-agentで生成せよ。 npm run lint— エラーなし。
8. 確認用フレーム(マット処理後)
各カードとステッカーが完全に合成された瞬間のスチル、ポスターは表示中盤(最後の行が髪の上に読める位置)、数フレーズの字幕、最終フレーム をレンダリングせよ:
npx remotion still MyComp out/key/f<N>.png --frame=<N> --scale=0.5 --timeout=120000
それらを4枚横並びに番号付きキャプションで合成し(PIL;キリル文字対応フォント、例:/System/Library/Fonts/Supplemental/Arial Bold.ttf)、ユーザーに表示せよ(SendUserFile)。マスターはユーザーの「OK」を得てから行うこと。 リスト作成は数分、マスターは10~20分かかる。
表示前に自分で確認せよ:キーテキストが下部15% / 上部8%の範囲外であること;要素が重なっていないこと;ステッカーがカードと交差していないこと;最終フレームが空でなく、途切れていないこと;すべてユーザープロファイル通りで、それ以上ではないこと。
9. マスター
npm run master # バックグラウンドで実行;ファイルの存在ではなくプロセスを監視せよ
スクリプトは自動でカットをチェックし、フレーム数を計算し、out/preview.mp4 を生成する。音量を確認せよ:ffmpeg -i out/final-master.mp4 -af ebur128 -f null - 2>&1 | grep -A3 Summary ≈ audio.lufs の目標値。プレビューをユーザーに送信せよ。
マスター後の修正(「このフレーズを削除して」) — マスター自体を編集せよ(ffmpeg の trim + concat を無音部分で行う)。テイクを再カットしたり、全体を再レンダリングしたりするな;事前に ETA を伝えよ。結合部分を確認せよ:前後6秒を切り出して whisper にかけ、意図した2つのフレーズだけが正確に連続していることを確認せよ。
10. サムネイル
プロファイルに指定がない場合、どのようなサムネイルが必要かユーザーに確認せよ:タイトル付きフレーム(Cover)、動画のポスター(PosterCover)、または自作。フレームはユーザーと一緒に選べ:目が開いている鮮明なフレームを3~4枚提案せよ(ffmpeg -ss <秒> -i takes/1.MOV -frames:v 1 -q:v 2 out/cover-N.jpg)。
- 選択したフレーム →
public/cover-bg.jpg。 rembg i -m birefnet-portrait public/cover-bg.jpg out/cover-matte.pngpython3 scripts/cover-sticker.py public/cover-bg.jpg out/cover-matte.png public/cover-cutout.png 20Root.tsx→CoverのdefaultProps.lines:ユーザーの言葉でタイトルを、accent/emはユーザーの希望通り。サイズは自動調整される — フォントサイズは変更するな。npx remotion still Cover out/cover.png --timeout=120000— 表示せよ。
代替案:PosterCover — 動画のポスターをサムネイルとして使用(フレームとその切り抜きを poster-bg.jpg / poster-cutout.png に)。
11. アーカイブ
edits/<N>/(ルートディレクトリ、video/ 内ではない)に保存:Composition.tsx、Footage.tsx、captions.json、SCRIPT.md、cover.png、final-master.mp4、preview.mp4。ユーザーが希望する場合は、次のスキル publish を実行せよ。