高度な使い方と内部構造

このセクションでは、差分ビルドシステム、ステータスファイルの直接操作、トラブルシューティングなど、パワーユーザー向けの機能を解説します。

差分ビルドシステム

動画生成には時間がかかり、TTS API のコストもかかります。そのため、slidemovie差分ビルド(インクリメンタルビルド) を行うように設計されています。

仕組み

ツールはソースディレクトリに status.json というファイルを保持します。このファイルには以下が記録されています:

  • 各スライドの Markdown コンテンツ(原稿)のハッシュ値
  • PowerPoint ファイルのハッシュ値
  • 生成された音声・動画ファイルのハッシュ値
  • 使用された設定(解像度、FPS)

ロジック

slidemovie -v を実行したとき:

  1. PPTX の確認: PPTX ファイルが前回実行時から変更されていなければ、画像の再変換をスキップします。
  2. 音声の確認: 各スライドについて、現在の ::: notes のテキストと記録されたハッシュを比較します。
    • 一致: 既存の WAV ファイルを再利用します。
    • 不一致: そのスライドについてのみ、AI API を呼び出して音声を再生成します。
  3. 動画の確認: 画像と音声に変更がなければ、そのスライドの MP4 生成をスキップします。

これにより、例えばスライド #10 の誤字を修正して再ビルドする場合でも、スライド #1〜#9 の TTS コストを払うことなく、数秒で動画全体を再生成できます。

状態ファイル (status.json) の管理

status.json は単なるキャッシュではなく、生成挙動を細かく制御するために編集することも可能です。

スライドごとのカスタムプロンプト

config.jsonprompt は TTS エンジン全体へのシステム指示を設定しますが、status.json を編集することで、特定のスライドだけに個別の追加指示を与えることができます。

  1. ツールを一度実行して、初期の status.json を生成させます。
  2. status.json を開き、"slides" オブジェクトの中から対象のスライドを探します。
  3. "audio" セクション内の "additional_prompt" フィールドを見つけます。
  4. 追加したい指示を文字列として入力します。

status.json の記述例:

"myproject-05": {
  "title": "導入",
  "audio": {
    "status": "generated",
    "wav_file": "myproject-05.wav",
    "additional_prompt": "この文は興奮した口調で話してください。"
  }
}
  • 効果: このスライドの音声を再生成する際、TTS エンジンには 全体プロンプト + 追加プロンプト + prompt_separator + スライドの原稿 が送信されます。
  • 再生成のトリガー: additional_prompt を編集した後、再生成をトリガーする必要があります。最も簡単な方法は、status.json 内の "status" の値を "generated" から別の値(例: "missing""update")に変更することです。

プロンプトと原稿の区切り (prompt_separator)

prompt が長くなると、「どこまでが指示で、どこからが読み上げ原稿か」の境界を明示したくなります。このとき、区切り文字を prompt の末尾に書いてはいけません。スライドごとの additional_promptprompt の後ろに挿入されるため、prompt 末尾に区切りを置くと additional_prompt が原稿側に押し出されてしまいます。

代わりに prompt_separatorconfig.json または --prompt-separator)を設定します。これは指示部分と読み上げ本文の間に挿入されるため、エンジンが受け取る並びは常に次のようになります。

{prompt}{additional_prompt}{prompt_separator}{読み上げ本文}

promptadditional_prompt は常に区切りの上(指示側)に残ります。ナレーションの言語に合わせて自然な文字列を指定してください。

{
  "prompt": "あなたはプロのナレーターです。落ち着いた声で、聞き取りやすい速度で読んでください。",
  "prompt_separator": "\n\n## 原稿\n"
}

デフォルトは ""(無効)なので、既存プロジェクトには影響しません。prompt_separator は記録される TTS 設定の一部であり、変更すると「TTS config change detected」の確認が表示されます(長文ナレーション → 注意点 を参照)。

長文ナレーションの自動チャンク分割

スライドのナレーション(::: notes)が長い場合、プロバイダのリクエスト長制限を超えたり、一部の Gemini モデルのように長文で品質が劣化したりすることがあります。slidemovie は、長いナレーションを小さなチャンクに自動分割し、それぞれを合成して音声を結合できます。

この機能は デフォルトでは無効chunk_size: null)で、明示的に有効化しない限り従来どおりの動作です。

有効化の方法

config.jsonchunk_size を設定するか、コマンドラインで --chunk-size を指定します。

# ナレーションを最大 800 文字程度のチャンクに分割
slidemovie myproject -v --chunk-size 800
設定 CLI 説明
chunk_size --chunk-size N 1 チャンクあたりの最大文字数。設定したときのみ分割が有効になります。
split_chars --split-chars STR 分割を許可する文字(デフォルト: 。..!!?? と改行)。chunk_size 以内で見つかった最も右側の候補の直後で分割します。
chunk_overflow --chunk-overflow {extend,error} chunk_size 以内に候補が見つからない場合の挙動。extend(デフォルト)は次の候補(またはテキスト末尾)まで読み進めます。error は実行を停止します。

プロンプトとチャンク分割の関係

スタイルプロンプト(prompt とスライドごとの additional_prompt)は、読み上げ本文とは 分離して TTS エンジンに渡されます。その結果:

  • プロンプトは 各チャンクに再適用 されるため、ナレーション全体で声色・口調が一貫します。prompt_separator もスタイルプロンプトの一部として各チャンクに適用されます。
  • chunk_size読み上げ本文の長さのみ で評価され、プロンプト長(prompt_separator を含む)は含まれません。

注意点

  • チャンクの境界: 個別に合成したチャンクを結合するため、つなぎ目でピッチやテンポがわずかに変化することがあります。chunk_size を大きくするほどつなぎ目は減ります。
  • extendchunk_size を超え得る: chunk_size 以内に分割候補がない場合、extend は次の候補(またはテキスト末尾)まで読み進めるため、個々のチャンクが chunk_size を大きく超えることがあります。
  • API の文字数上限はユーザー責任: chunk_size はユーザーが指定する文字数であり、プロバイダの実際のリクエスト上限から自動算出されるものではありません。利用するプロバイダ/モデルの上限に収まる値を選んでください。
  • 再生成: chunk_size / split_chars / chunk_overflowstatus.json に記録される TTS 設定の一部です。これらを変更すると、声や モデルを変更したときと同様に「TTS config change detected」の確認プロンプトが表示されます。

サブプロジェクト(フォルダ管理)

シリーズ動画(例:オンラインコース)を作成する場合、--sub オプションを使うと便利です。

ディレクトリ構成:

MyCourse/               <-- 親プロジェクトルート
├── config.json         <-- 共通設定
├── Section01/          <-- サブプロジェクト 1
│   ├── Section01.md
│   └── Section01.pptx
└── Section02/          <-- サブプロジェクト 2
    ├── Section02.md
    └── Section02.pptx

コマンド:

# セクション 1 をビルド
slidemovie MyCourse --sub Section01 -v

# セクション 2 をビルド
slidemovie MyCourse --sub Section02 -v

出力ファイルは、出力ディレクトリ内で整理されて保存されます: movie/MyCourse/Section01/Section01.mp4

トラブルシューティング

“Movie class is not defined”

  • パッケージが正しくインストールされているか確認してください。
  • Python スクリプトから呼び出している場合、import slidemovie がされているか確認してください。

音ズレが発生する / 音声と映像が合わない

  • 原因: PowerPoint でスライドを削除したり、順番を入れ替えたりしていませんか?
  • 修正: slidemovie はスライドの「数」と「順番」が一致していることを前提としています。
    1. 生成された movie/{project}/slide_*.png ファイルを確認してください。
    2. Markdown のスライド数と、PPTX のスライド数が一致しているか確認してください。
    3. 同期が崩れてしまった場合、最も安全な方法は movie/{project} フォルダを削除して、再度 -v を実行して再ビルドすることです。

“build_config inconsistency detected”

  • 原因: プロジェクトを一度実行した後に、config.jsonscreen_sizevideo_fps を変更しました。
  • 修正: 一つのプロジェクト内で異なる解像度を混在させることはできません。
    1. ソースディレクトリ内の status.json を削除してください。
    2. 出力ディレクトリ movie/{project} を削除してください。
    3. 再ビルドを実行してください。

デバッグモード

ツールがクラッシュしたり、予期しない挙動をする場合は、--debug を付けて実行してください:

slidemovie myproject -v --debug

これにより、以下のような詳細情報が表示されます:

  • どのファイルがスキップされたか
  • FFmpeg コマンドの出力結果