エクスポート(完成品)
これはチェーンの最後のセクションであり、製品全体で唯一実際にピクセルを描画する場所です。
それ以前はすべて注釈です。台帳は「どの単語を読むか」を記録し、字幕は「画面に何を書くか」を記録し、ビジュアルは「どのレイヤーを重ねるか」を記録します。 プレビューはこれら3つをリアルタイムで合成して人間に見せますが、ディスクには書き込みません。エクスポートはそれらを1つのファイルに焼き付けます。
必要 edit-list.json(必須)、subtitles.json、visuals.json + modules/
出力 完成品.mp4
前提ツール:マシンに Google Chrome が必要です(字幕とアニメーションを画像として描画するため)。デスクトップインストールによる
FFmpeg / FFprobe は既に App の Product 管理ディレクトリ内にあります。純粋な CLI インストールの場合はシステムに
ffmpeg ≥ 6 が必要です。Chrome がない場合は明示的にエラーを報告します。回避しようとしないでください。Chrome がなければ字幕レイヤーとアニメーションレイヤーは生成されません。
最初に ビジネススキルのフェーズコントラクト の 「結論レベル」セクションを読み、実行します。エクスポートは編集ステートマシンには入りません。プロジェクトファイルを変更せず、 CAS 書き込みも行わず、ステージを進めません。出力は新しいファイルであり、再実行すると上書きされます。 そのため、確認カードは必要ありません。
0. 準備
まず アップデートの確認 の「準備チェック」を実行します。スキルが最新か、
Runtime が対応しているか。プラグインルート もそこで特定します(このドキュメントのコマンド内の <プラグインルート> はすべて
そのリテラルパスに置き換えます)。「準備完了」の場合のみ続行します。「新しいセッションが必要」または「停止」の場合は、その指示に従って処理します
(「代替インターフェースの自作禁止」を含む)。ビジネススキル自体に環境ロジックは含まれません。
準備結果が runtime.kind=desktop-managed の場合、デスクトップアプリに既にインストールされている安定版 CLI、
メディアツール、および同一の launchd/windows-task サービスを直接再利用します。Electron のパスを解決したり、
別途 FFmpeg/Bun をインストールしたり、2つ目の Runtime を起動したりしないでください。
コマンド
node "<プラグインルート>/scripts/ensure-running.cjs" --json
node "<プラグインルート>/scripts/videocut-cli.cjs" export <project> --dry-run --json # まず計画を確認、エンコードしない
node "<プラグインルート>/scripts/videocut-cli.cjs" export <project> --json # 完成品を出力(デフォルト 2 倍、ソースフレームレート)
node "<プラグインルート>/scripts/videocut-cli.cjs" export <project> --out /path/完成品.mp4 --json
node "<プラグインルート>/scripts/videocut-cli.cjs" export <project> --scale 1 --json # ソースサイズのみ
node "<プラグインルート>/scripts/videocut-cli.cjs" export <project> --keep-work --json # 中間ファイルとフレーム PNG を残して調査用
ensure-running で ID 不一致、ポート競合、またはサービス不健康の場合は直ちに停止します。フォアグラウンドで
一時的に代用してからエクスポートを続行することは許可されません。
2ステップ、2番目のステップだけ実行しないこと
① --dry-run で最初に計画を報告 長さ、フレーム数、字幕画面数、ビジュアルレイヤー数、ズームインセグメント数、出力サイズ
ユーザーに読み上げます。数字が正しくない場合は上流の問題です。10分のエンコードでは修正できません
② 実際に実行 assemble → overlay → compose → verify の4段階の進捗
--dry-run 内の warnings はそのまま伝える必要があります。これは1種類のことだけを報告します:一部の字幕画面やビジュアルレイヤーの単語が
すでにカットされているため、完成品には表示されません。これは上流が決定すべきことであり、エクスポートが黙って飲み込むべきものではありません。
解像度:ソース映像が上限、まずソースを確認してから拡大を検討
エクスポート前にソース解像度を確認します(--dry-run の source フィールドにあります):
ソース幅 ≥2560(Retina ネイティブ画面録画) → --scale 1、出力はネイティブピクセル、これが最良のケース
ソース幅 <1920(例:960×720) → まず停止:ユーザーに同じ録画の高解像度エクスポートがあるか確認します。
録画ツールは多くの場合、同じ録画を3倍の解像度で再エクスポートできます。
ソースを交換する方がどの後処理よりも効果的です(次のセクション参照)。本当にない場合 → --scale 2
--scale 2 が低解像度ソースに有効な理由:元の映像を拡大しても鮮明にはなりませんが、字幕とアニメーションは出力サイズに合わせて
再描画されます。視聴者が実際に読んでいるのはこれらです。プラットフォームが再圧縮する際、大きな画像にはより高いビットレートが割り当てられます。
「より鮮明にする」ために --fps を調整しないでください。 フレームレートはソース映像に従います。変更すると、アニメーションのサンプリングと
画面録画が一致しなくなります。
ソース交換:ユーザーが同じ録画の高解像度版を用意した場合
これはエクスポートフローの一部ではありません。エクスポート自体は常に読み取り専用です。ソース交換は、ユーザーが明示的に承諾した後の 独立した素材操作であり、完了後に通常のエクスポートに戻ります。
まず同じ録画かどうかを判定します(最初の2つで十分に確実です):
ffprobe -v error -show_entries format=duration -of csv=p=0 <2つのファイル> # 長さがミリ秒単位で同一
ffmpeg -v error -i <ファイル> -map 0:a:0 -c copy -f md5 - # オーディオストリームがビット単位で同一
# さらに2〜3フレームを抽出して画面内容を比較、目視確認
オーディオがビット単位で同一 = タイムラインが同一:すべての単語スクリプト、台帳、字幕、ビジュアルレイヤーは単語IDにバインドされており、 何も変更する必要がありません。これこそが「単語にバインドし、秒にバインドしない」という原則がソース交換で実現される点です。
ソース交換の4ステップ(2026-07-29 に実際に1回実行しました。その際、ステップ③を忘れて、クリッププレビューが即座に 「生成失敗」と報告しました。フィンガープリント記録は1箇所だけではなく、grep で古いフィンガープリントをすべて見つけてから 対処してください):
① ファイルを交換 input/source.mp4 と uploads/source.mp4 はハードリンクのペアです。
両方を削除し、新しいファイルを input/ にコピーし、ハードリンクを uploads/ に再作成します
(macOS は ln を使用;Windows は New-Item -ItemType HardLink を使用)
② フィンガープリントを更新 project.json の source.sha256 を新しいファイルのものに変更します
③ もう1箇所を確認 workbench.json の sourceSha256 にもソース映像のフィンガープリントが記録されています。
クリッププレビューパイプラインが検証するのはまさにこのファイルです。
これを忘れると、プレビューは生成を拒否します
(これは製品の正しい動作です:フィンガープリントが一致しない場合は失敗する方が、古いプレビューを偽装するより良い)
④ 再エクスポート --scale 1 —— ソース交換の目的はネイティブピクセルを得ることです。これ以上拡大しないでください
安全策:検索ツールを使用して <プロジェクトディレクトリ> 内のすべての *.json から古いフィンガープリントの最初の8文字を検索し、 リストされたすべての箇所を処理します(キャッシュレコード(例:preview-edited/current.json)は自動的に再計算されるため、手動で変更する必要はありません)。
オーディオが異なる場合(再録音、カット、長さの変更)は、ソース交換ではなく、新しいプロジェクトです。 単語スクリプトを再変換する必要があり、すべての注釈は無効になります。無理に適用しないでください。
検収:3つの項目、1つでも欠ければエクスポート完了とは見なされない
① コマンドが正常に戻る 製品が完成品のサイズ、フレーム数、オーディオトラックをカウントし、計画と項目ごとに比較します。
一致しない場合は readback_mismatch エラーが報告され、ファイルはディスク上に証拠として残り、
エクスポート完了とは見なされません
② フレームを抽出してピクセルを確認 完成品からフレームを抽出し、目視で確認します。少なくとも以下をカバー:1つのズームインセグメント、
1つの全画面アニメーションセグメント、1つの字幕のみのセグメント、1つのレイヤー間の境界
③ 人間の聴覚チェック 実際に聞いた人は誰もいません。常に human listening UNVERIFIED と記録します
② の代わりにプレビュースクリーンショットを使用しないでください。プレビューと完成品は2つの異なるレンダリングパスであり、 検収で確認すべきはそれらが一致するかどうかです。プレビューの画像を完成品の証拠として使用することは、 検証すべきことを前提としてしまうことになります。
ズームインの判定には判別可能なランドマークを見つける必要があります。全体的な印象は誤解を招く可能性があります (2026-07-29 に実際に遭遇しました):1.6倍ズームイン後の画面ページは依然として「1ページ全体」のように見え、サムネイルでは 全体図とほとんど違いがありません。正しいズームインフレームを「ズームインが欠落している」と誤判定し、30分無駄に追跡し、 2回再エクスポートしました。正しい判定方法は、クロッピングによってのみ発生する証拠を見つけることです: 半分に切り取られた要素(バブルの途中で切れている)、消えたエッジ要素(サイドバー、タイトルバー)。 ソース映像の同じ時刻のフレームと比較すれば、一目で判定できます。
フレーム抽出には ffmpeg を使用します:
ffmpeg -v error -ss 8.84 -i 完成品.mp4 -frames:v 1 -y frame.png
問題が発生した場合の調査方法
--keep-work を使用すると、プロジェクトの .chengfeng-videocut/export/ ディレクトリに3つのアイテムが残り、
「どの半分が間違っているか」を直接分離します:
assembled.mkv カットのみ。オーバーレイは一切なし。これが間違い = 台帳またはセグメントカットの誤り
overlay/*.png オーバーレイのみ。透明背景。これが間違い = 字幕スタイルまたはモジュールの誤り
spans/*.mp4 合成後のセグメント。これが間違い = ズームインまたはアライメントの誤り
対応表:
完成品に字幕/アニメーションがない overlay PNG はすべて透明か?モジュールが seek に応答しなかったか?
アニメーションが最初のフレームで停止している モジュールが seek を実装していないか、GSAP タイムラインが paused になっていない
画面全体が白い モジュールに `:root { color-scheme: dark }` がない
ズームインのフレームが歪んでいる モジュールの viewBox とレイヤーの zoom が同じ数値セットではない
完成品が計画より短い あるスパンのフレーム数が不足している。compose フェーズのエラーを確認
レイヤー境界で元の映像が一瞬表示される overlay スクリーンショットが古い(フレームマーク検証が無効)。製品はページ上部の
フレームマークバーで各スクリーンショットがどのフレームに属するかを証明する。再発した場合は、まず
overlay PNG の上部にマークバーがあること、compose がそれをクロッピングすること(crop)を確認
Chrome が見つからない Google Chrome をインストールする。別のレンダリングパスに変更しないこと
禁止事項
- 「エクスポート成功」を「検収合格」と言わないこと。コマンドが正常に戻ったことは製品が自分自身と一致したことを意味するだけで、画面の一致を意味しない
- プレビュースクリーンショット、DOM、ログを完成品のフレーム抽出の代わりに使用しないこと
- 誰も聞いていないのに human listening PASS と報告しないこと
- エクスポートを通すためにプロジェクトファイルを変更しないこと(字幕の変更、レイヤーの削除、台帳の操作)。エクスポートは読み取り専用であり、書き込まない
- エクスポートで上流の作業を代行しないこと:字幕がないなら字幕を書き、ビジュアルがないならビジュアルを作成する。このセクションで一時的にごまかさないこと