シリーズ解説動画全工程自動化
「一つのテーマ」を「一本の完成動画」に変換:企画 → ページ編集(HTMLアニメーション) → ナレーション原稿 → 音声合成 → 字幕 → 1080p MP4 → 抖音カバー(横16:9 + 縦9:16)。 デフォルトスタイルは『道徳経』解説動画シリーズの実績に基づく(新中式水墨 / 雲健男性声 / 白文字黒光字幕)。一式使い回し可能で、個別項目は上書き可能。
画面制作ルート(v2.0以降はHTMLアニメーションがデフォルト、v2.1は図文連携):
- デフォルト:HTMLアニメーションページ — ナレーション原稿から、入場アニメーションとページ間クロスフェードを備えたHTMLプレゼンページを生成。確定論的にフレームレンダリングして動画化、アニメーションは100%完成動画に同期(方式と編集ルールは
references/html-animation.md参照)。 - v2.1 図文連携:内蔵の水墨SVGシーンライブラリ(水紋の舟/さざ波/山並み/墨竹/月見/錦鯉)+項目アイコン+外部画像リンクに対応。ナレーション原稿に応じて自動マッチングまたは明示指定。グラフィックパーツのタイミング差動とテキストアニメーションを統一的に編集。
- フォールバック:静的PPTフレーム + xfade(ネイティブPPTのテーブル/複雑レイアウトが必要な場合、またはユーザーが .pptx を明示的に要求した場合に使用)。
v2.3以降、毎回の動画で抖音カバーが標準装備:横版16:9 + 縦版9:16、テーマに合わせてAI生成一式(横版アンカー→ユーザー確認→縦版派生)。動画フレームは使用しません。手順はフェーズ⑥と references/douyin-covers.md を参照。
開始時の5つの質問(毎回動画制作開始時に確認。ユーザーが「前回と同じ」「いつも通り」と言った場合はすべてデフォルトで開始)
- 今回は何を解説しますか?(テーマ / 経典の章)
- 内容の深さ:詳細解説 / ポイント解説?(デフォルト:詳細解説)
- 完成動画の目標時間?(デフォルト 6-7分)
- PPTスタイルは新中式水墨を継続?(デフォルト:はい)
- 音声は雲健、字幕は白文字黒光を継続?(デフォルト:はい)
スタイル設定(ユーザーが指定しない場合はデフォルト値を採用)
| 項目 | デフォルト値 |
|---|---|
| PPTスタイル | 新中式水墨:半紙アイボリー + 墨黒 + あい色 + 朱砂 |
| フォント | タイトル SimSun(宋体)、本文 Microsoft YaHei(SlideDSLでは一律英語 font-family を使用) |
| 画面要素 | SVG水墨イラスト(AI生成画像は不使用、完全再現性あり、変更容易) |
| アニメーション | HTMLアニメーションページ:タイトル blur-in / 項目ずらし fade-up / ページ間クロスフェード / cue強調(旧来の「要素アニメーション却下」はffmpeg重ね合わせ方式を対象。HTML確定レンダリングルートはv2.0で実証済み) |
| 音声 | zh-CN-YunjianNeural(雲健・男性・低音) |
| 話速 | +0%(全体統一。ユーザーが明示的に要求した場合のみ変更可能。内容の密度に応じて部分ごとに変速してはいけない) |
| 字幕 | 白文字 + 黒色外部発光(blur 0.8)、透明背景、下部中央揃え |
| 画面サイズ | 1920×1080(16:9) |
| 発音修正 | 「老子」→ TTSで「ラオズー」(lǎo zǐ 文語読み第三声)と発音、字幕表示は「老子」のまま |
| 抖音カバー | 横版16:9 + 縦版9:16;期名4文字の大文字;AI生成一式(アンカーチェーン)、動画フレームは使用しない |
作業ディレクトリの規約
ワークスペース直下に 動画作業ディレクトリ/ を作成。各動画はテーマ名のサブディレクトリに格納:
動画作業ディレクトリ/{期名}/
├── {BASE} ナレーション原稿.json # 単一データソース:タイトル/音声/発音修正/各ページナレーション原稿(+ページ文言)
├── {BASE} ナレーション原稿_編集可能.txt # export_txt.py で出力、ユーザーがメモ帳で確認する用
├── 01_deck/ # deck.html(アニメーションプレビュー表示可能) + deck.json(タイムラインリスト)
├── 01_html_frames/ # f_XXXXX.png フレーム毎 + frames_manifest.json(HTMLルート)
├── 01_frames/ # frame_01.png ...(静的PPTフォールバックルート)
├── 02_audio/ # slide_01.mp3 ... slide_NN.mp3(ページごとの音声)
├── 音声試聴/ # 複数音声色試聴mp3 + 音声試聴.html
└── 03_output/ # 完成品 {BASE}(字幕付き).mp4
BASE = 期名(「ナレーション原稿」の文字が含まれている場合は自動除去)。ナレーション原稿JSONはPythonの json.dump でプログラム的に生成。中国語引用符を含むJSONを手書きしてはいけません(エスケープエラーの原因)。
カバーキャンバス {期名}-抖音カバー.miora はワークスペースルートに配置、2サイズのPNGはその _assets/ ディレクトリ内に配置。
フェーズ別ワークフロー(4つの確認ゲートあり。各ゲートでユーザーの回答を得てから次に進む)
作業開始前(初回または環境に異常がある場合)は先に環境診断を実行:
python scripts/doctor.py、MISSINGがあれば補ってから開始。 ペース配分の基準、ゲートリスト、BGMと改版範囲テーブルはreferences/pacing-and-gates.md参照。 (liyupi/ai-promo-video-maker の方法論を統合:ペースの厳格基準 / データ検証 / 二重ゲート / 改版ルール)。
フェーズ ① コンテンツ企画(ゲート1:開始時の5つの質問)
5つの質問に基づき計画を決定。短い企画パッケージ(文案構成 / ビジュアル案 / 音声案)を作成し、ユーザー承認を得てから②へ進む。
フェーズ ② ページ編集(HTMLアニメーションルート = デフォルト)
- もうPPTは作成しない:直接プログラム的に
{BASE} ナレーション原稿.jsonを生成、ページごとにナレーション原稿textを記述。 各ページでオプションとしてtitle(ページタイトル)、points(画面に表示する項目の配列)、layout(title/bullets/quote/end)、cues(強調ポイント、下記参照)を指定可能。省略時はナレーション原稿から自動推論(ルールは references/html-animation.md 参照)。 ただし本制作では明示的に指定する方が品質が安定する。 - ページ数は内容の深さに応じて決定(詳細解説で約8ページ)。テーブル/データは静的PPTフォールバックルートを推奨。
フェーズ ②′ PPT制作(静的フォールバックルート)
- workbuddy-pptx(SlideDSL)を使用してスライドを作成。ページ数は内容の深さに応じて決定(詳細解説で約8ページ)。
- 発表者ノート = ページごとのナレーション原稿:一度書き込めば複数箇所で再利用(動画音声 / DOCXタイムライン / 剪映インポート)。
- フォントは英語名(SimSun / Microsoft YaHei)を使用。中国語名はレンダリングされない。
- 配色と要素はスタイル設定に従う。テーブル/データページはネイティブPPT要素を優先。
フェーズ ③ ナレーション原稿確定(ゲート2:ナレーション原稿審査)
-
PPTノートからナレーション原稿を抽出、プログラム的に
{BASE} ナレーション原稿.jsonを生成(構造は下記参照)。 -
編集可能なテキストを書き出して審査に供する:
python scripts/export_txt.py "{BASE} ナレーション原稿.json" -
ユーザーにメモ帳でtxtファイルを開き、ページごとに確認するよう明確に伝える。ユーザーが修正して返してきたらJSONに同期:
python scripts/import_txt.py "{BASE} ナレーション原稿.json" "{BASE} ナレーション原稿_編集可能.txt"ユーザーが「文案はOK」とだけ返し、修正がない場合は同期をスキップ。
フェーズ ④ 音声合成(ゲート3:音声色試聴、ハードゲート voice_confirmed)
-
試聴ページを生成し、ユーザーに音声色を選んでもらう:
python scripts/preview_voices.py 音声試聴 -
ユーザーが選択した後、JSONに書き込み
voice_confirmed=trueをセット(これがないとTTSと合成は実行を拒否):python -c "import json;p='{BASE} ナレーション原稿.json';d=json.load(open(p,encoding='utf-8'));d['voice']='zh-CN-YunjianNeural';d['rate']='+0%';d['voice_confirmed']=True;json.dump(d,open(p,'w',encoding='utf-8'),ensure_ascii=False,indent=2)"話速はデフォルト
+0%のまま変更しない。ユーザーが明示的に変速を要求した場合のみ変更し、かつ全体統一。
フェーズ ⑤ 動画合成(ゲート4:合成前にユーザーに開始確認)
順序:音声合成 → アニメーションページ生成 → フレームレンダリング → 動画合成(HTMLルート)。または フレームレンダリング → 音声 → 動画(静的ルート)。
HTMLアニメーションルート(デフォルト):
-
ページごとの音声を合成(最初に必ず行う — ページの長さは実際の音声の長さから取得):
python scripts/tts_synth.py --narration "{BASE} ナレーション原稿.json" --out 02_audio -
アニメーションデモページを生成(deck.html はブラウザ
#previewでアニメーションプレビュー可能):python scripts/gen_html_deck.py --narration "{BASE} ナレーション原稿.json" --audio 02_audio --out 01_deck -
フレームレンダリング(アニメーションウィンドウのみをレンダリング、数分で完了):
node scripts/render_html_frames.mjs --deck 01_deck --out 01_html_frames -
動画合成(フレームシーケンス + 文単位の字幕。白文字黒光デフォルトスタイル):
python scripts/compose_html_video.py --deck 01_deck --frames 01_html_frames --audio 02_audio --narration "{BASE} ナレーション原稿.json" --out 03_outputデフォルト出力は
{BASE}(字幕付き).mp4。--also-plainで字幕なし版を追加出力。--bgm <ファイル>で背景音楽を追加(自動ダッキング、ナレーション中は音量を下げる。楽曲はMixkitの無料商用利用可能なもの。ユーザー試聴後に決定)。
静的PPTフォールバックルート:
-
画面フレームをレンダリング(PowerPoint COMが第一選択。ローカルにPowerPointのインストールが必要):
powershell -ExecutionPolicy Bypass -File scripts/export_frames.ps1 -Pptx "{BASE}.pptx" -OutDir 01_framesPDFが既にある場合はpymupdfパスを使用可能:
python scripts/pdf_to_frames.py "{BASE}.pdf" 01_frames 1920。 レンダリング後、3ページ(表紙 / 内容の濃いページ / テーブルページ)を抜き打ちチェックし、フォント異常がないことを確認。 -
ページごとの音声を合成:同上 tts_synth.py。
-
動画合成(静的ページ + xfade + 文単位の字幕):
python scripts/compose_video.py --frames 01_frames --audio 02_audio --narration "{BASE} ナレーション原稿.json" --out 03_output -
納品検証:場面転換点のフレームをサンプリングし、アニメーションが正常で黒フラッシュがないことを確認。ページ中間のフレームをサンプリングし、字幕を確認。 完成動画ゲート実行:
python scripts/verify_output.py --video "03_output/{BASE}(字幕付き).mp4" --deck 01_deck(仕様/再生時間/ラウドネス/黒フレーム/無音のすべてをパスしてから納品)。present_filesで納品。
フェーズ ⑥ 抖音カバー(毎回標準装備:横版16:9 + 縦版9:16)
完成動画の納品時にカバーも一緒に提供し、抖音へ直接アップロードできるようにする。動画フレームは使用しない — 今回のテーマに基づいてAIが一式を生成。.miora キャンバス + 2サイズのPNGで納品。
プロンプトテンプレート / イメージ対照表 / 品質チェックリストは references/douyin-covers.md 参照。ユーザーがカバー不要と明言した場合はスキップ。
- 文案:期名4文字を画面上の唯一の大きな文字として使用(例:「有無相生」)。サブタイトルの小さな文字は追加しない(必ずつぶれる)。メイン文案以外は画面に文字ゼロ。
- アンカーチェーン一式(ハードルール):横版アンカー(純テキスト画像生成 1920×1080)→ ユーザー確認 → 縦版をアンカー画像を参照画像として派生(1080×1920、縦3段構成)。スタイルトークンは原文をそのまま再利用。2枚を同時に無作為生成してはいけない。
- ビジュアル:完成動画と同じスタイル(半紙アイボリー + 墨黒 + あい色 + 朱砂、水墨にじみ、すっきりした余白)。イメージは今回のテーマから取得(例:「有無相生」→ 満月 + 水面の月の反射)。
- サイズは実寸で報告:モデルの丸め処理で1920×1072 / 1072×1920になる可能性あり(8px差)。そのまま報告。ユーザーが正確なサイズを要求した場合のみ、標準値に余白を追加。
- 納品:ワークスペースルート
{期名}-抖音カバー.miora+ 2サイズの画像カード。カバー文案とサイズは要件確認.mdに記録。
(文字を100%制御したい場合、または複数回にわたってテンプレートを再利用する場合は、編集可能なデザインデータのレイアウト書き出しルートに変更。デフォルトはAI生成。)
フェーズ ⑦ 微調整と反復
- 毎回のディレクトリに
要件確認.mdを保持:5つの質問への回答 + 各回の修正記録(ユーザーの発言をそのまま記録)。フィードバックを受け取ったらまず記録してから修正。必要な手順のみをやり直す(変更範囲→やり直し手順の対応表はreferences/pacing-and-gates.md参照)。 - 字幕スタイル/色の調整 →
references/subtitle-style.md参照(ASSカラーはBBGGRR反転順、必読)。 - 発音問題 →
tts_replacementsのみを変更してTTSと合成を再実行。字幕は変更しない。 - 字幕同期 → composeは
02_audio/timing_XX.jsonを優先して読み込む(TTSの文レベルのリアルタイムタイムライン。tts_synthが自動生成)。 - 画面/アニメーション問題(HTMLルート)→ ナレーション原稿JSONのtitle/points/visual/cues、または
gen_html_deck.pyの編集を変更 → deckの生成、レンダリング、合成を再実行(音声は再利用。ナレーション原稿も変更された場合を除く)。 - 画面問題(静的ルート)→ PPTを変更してフレームを再書き出し。音声は再利用。
- カバー修正 → 文案/イメージが間違っている場合は該当するデータのみを再作成。スタイル全体が間違っている場合はアンカーを再作成してから派生(
references/douyin-covers.md参照)。
フェーズ ⑧ 納品検収(セルフチェックリスト)
- 画面:フォント/配色に異常なし。テーブルページ(ある場合)のレンダリングが正しい。
- アニメーション:タイトル/項目の入場が自然、ページ間の遷移が滑らか、cue強調がナレーションと一致している(HTMLルート)。
- 音声:聞き取りやすい、音が飛ばない、話速が全編で統一されている。
- 発音:文語読みが正しい(例:「老子」= lǎo zǐ)。
- 字幕:音声と文単位で同期、スタイル統一、はみ出しや切り取りなし。
- トランジション:クロスフェードが滑らか、黒フラッシュなし、空白フレームなし。
- 再生時間:目標時間に近い(±10秒)。
- フォーマット:1920×1080 / H.264 / AAC / .mp4。
- カバー:横縦2バージョンの4文字が欠けや誤字なし、スタイルが一貫、サイズは実寸(チェックリストは
references/douyin-covers.md参照)。
ナレーション原稿JSON構造(単一データソース)
{
"title": "老子今読-上善若水",
"voice": "zh-CN-YunjianNeural",
"rate": "+0%",
"voice_confirmed": true,
"tts_replacements": { "老子": "老紫" },
"slides": [
{ "idx": 1, "text": "最初のページのナレーション原稿……" },
{ "idx": 2, "text": "2ページ目のナレーション原稿……",
"title": "水の三つの品格", "points": ["利他、万物を育む", "争わず、低い位置に甘んじる"],
"cues": [ { "t": 4.5, "dur": 0.9, "target": 0 } ] }
]
}
idxは1から連番。frame_XX.png(静的ルート)/slide_XX.mp3と厳密に対応。- HTMLアニメーションルートの各ページで指定可能なフィールド:
title(ページタイトル)、points(画面表示項目の配列)、layout(title/bullets/quote/end)、cues(強調ポイント:t=ページ内相対秒、target=項目番号0始まり、dur=強調時間、action=pulse)。図文連携(v2.1):visual(水墨シーン water/ripples/mountain/ bamboo/moon/fish、省略時はナレーション原稿のキーワードから自動マッチング)、icons(項目アイコン droplet/wave/mountain/moon/leaf)、image(外部画像リンク、右欄に埋め込み)。省略時はナレーション原稿から自動推論。本制作では明示的な指定を推奨。 tts_replacements:発音修正テーブル。TTS入力にのみ作用。字幕と編集可能テキストは元の文字を維持。汎用シリーズでは空{}とする。voice_confirmedはデフォルトfalse。ゲート③でtrueに設定。そうでなければスクリプトは合成を拒否。
よくある失敗とクイック対処表
| 症状 | 原因 | 対処法 |
|---|---|---|
| 字幕の外枠の色が期待と異なる | ASSカラーはBBGGRR反転順 | 赤=&H000000FF 青=&H00FF0000 黒=&H00000000 |
| 文語読みの単語が口語読みされる(例:老子 lǎo zi) | TTSがデフォルトで口語読みを選択 | tts_replacements に追加してTTSを再実行 |
| PPTのフォントがレンダリングされない | 中国語名が認識されない | SimSun / Microsoft YaHei を使用 |
| ワンステップ合成で白画面/フィルターチェーンが壊れる | xfadeの後にoverlayを重ねている | 2ステップに分割:先にベースを作成してから重ね合わせ。カンマは \, でエスケープ |
| フレームが「生成された」のに見つからない | pymupdfが無言で失敗 | スクリプトは既にabspath + 書き込み後検証を実施。または export_frames.ps1 を使用 |
--rate -10% で expected one argument エラー | argparseがオプションを誤認識 | --rate=-10% を使用、またはJSONのrateのみ変更 |
| 合成が「音声未確認」とエラー | ゲート③をスキップ | voice_confirmed=true を設定して再実行 |
| 中国語引用符をJSONに書くとエラー | 手書きエスケープエラー | Pythonのjson.dumpでプログラム的に生成 |
| deck生成が「音声不足」とエラー | HTMLルートではまずTTSが必要 | 先に tts_synth.py を実行し、その後 gen_html_deck.py |
| レンダリングが「Chromiumが見つからない」とエラー | ブラウザのパスが変更された | --browser で chrome.exe / msedge.exe を指定 |
| タイトルページが中央揃えにならない | CSSクラスセレクターの記述方法 | .inner.layout-title(同種要素)を使用。子孫セレクターは使わない |
| 項目がバラバラになる(番号付きの短文が独立した項目に) | 番号付き短文が結合されていない | gen_html_deck.py は既に内部結合を実装。カスタムpointsで完全回避可能 |
| 完成動画の最終フレームの再生時間が合わない | concatの最終ファイルの癖 | compose_html_video.py は既に最終ファイルの繰り返しを内部実装済み。削除しないこと |
| cue強調が出現しない | cueがページの再生時間を超えている | slides[].cues の t が該当ページの音声再生時間より短いか確認 |
| カバーの大きな文字に欠け/誤字 | AIが中国語の長文を安定してレンダリングできない | 文案を4文字以内に抑えて再作成。アンカーの文字が間違っている場合はまずアンカーを再作成してから派生 |
| カバーの短辺が1072≠1080 | モデルの丸め処理 | 実寸のまま納品(比率はほぼ16:9/9:16)。正確なサイズが必要な場合は1920×1080 / 1080×1920に余白を追加 |
| 2枚のカバーがセットに見えない | 2枚とも純テキスト画像生成で個別にブレ | 必ずアンカーチェーンを使用:縦版は横版アンカーを参照画像として派生 |
完全なトラブルシューティングとアーキテクチャの知見は references/pitfalls.md を参照。HTMLアニメーションルートの詳細は references/html-animation.md を参照。
リソース
scripts/doctor.py— 環境診断(毎回作業開始時に実行、MISSINGがあれば補ってから開始)scripts/verify_output.py— 完成動画ゲート(仕様/再生時間/ラウドネス/黒フレーム/無音、すべてパスしてから納品)scripts/gen_html_deck.py— ナレーション原稿 → 図文連携アニメーションHTMLプレゼンページ + deck.jsonリスト(HTMLルートのエントリポイント)scripts/render_html_frames.mjs— Playwrightによる確定論的フレームレンダリング(アニメーションウィンドウのみをレンダリング、静止部分は最終フレームを再利用)scripts/compose_html_video.py— フレームシーケンス + 音声 + リアルタイムタイムライン字幕 + BGMダッキング合成(HTMLルート)scripts/tts_synth.py— edge-tts バッチ合成(発音修正 + 文レベルのリアルタイムタイムライン + voice_confirmed ゲート)scripts/compose_video.py— 静的ページ+xfade+文単位字幕合成(静的フォールバックルート)scripts/export_txt.py/scripts/import_txt.py— ナレーション原稿と編集可能txtの双方向同期scripts/preview_voices.py— 5音声色試聴比較ページ(オフライン再生可)scripts/export_frames.ps1— PowerPoint COMによる1920×1080画面フレーム書き出し(静的ルートの第一選択)scripts/pdf_to_frames.py— pymupdfによるPDFフレームレンダリング(静的ルートの代替)references/douyin-covers.md— 抖音カバー全工程:文案ルール / プロンプトテンプレート / アンカーチェーン / 品質チェックリスト(毎回標準装備の横縦2サイズ)references/html-animation.md— HTMLアニメーションルート:実現可能性の結論 / 編集ルール / トラブルシューティング(必読)references/pacing-and-gates.md— ペース配分基準 / データ検証 / 二重ゲート / BGM / 改版範囲テーブル(必読)references/playbook.md— 全工程マニュアル:確認項目表 / 技術スタック / 最適化ルートreferences/pitfalls.md— トラブルシューティングリストとアーキテクチャの知見references/subtitle-style.md— ASS字幕スタイルマニュアル(カラー反転順 / 発光効果 / スタイルプリセット)assets/narration-template.json— ナレーション原稿JSONテンプレート
依存関係:playwright-core(スキルルートディレクトリの node_modules、既にインストール済み)。Chromium検出順序:
ms-playwright キャッシュ → システムEdge。両方ともない場合は --browser で指定。