add_notes_voice_pptx2.py の技術ドキュメント

プログラムの動作

add_notes_voice_pptx2.py は、PowerPointプレゼンテーション(PPTXファイル)のノートセクションに記述されたテキストから、様々なText-to-Speech (TTS) エンジンを使用して音声ファイルを生成し、その音声ファイルを元のPPTXまたは新しく作成されたPPTXのスライドに自動再生リンクとして追加するPythonスクリプトです。

主な機能:

  • PPTXノートからのテキスト抽出: 各スライドのノートからナレーションテキストを抽出します。

  • 独話・対話形式のサポート:

    • 独話形式: ノート全文、または ((...)) で囲まれた部分を単一のナレーションとして扱います。

    • 対話形式: ((話者名,本文)) の形式で記述されたノートを解析し、話者ごとに音声を生成します。

  • 複数のTTSエンジンをサポート: pyttsx3, VOICEVOX, Qwen3-TTS, Irodori-TTS, AquesTalkPlayer, OpenAI, Geminiなど、複数のTTSエンジンを選択できます。

  • 音声のカスタマイズ: 読み上げ速度、声の高さ(VOICEVOX)、話者ごとのボイス割り当てなど、TTSエンジンの特性に応じた詳細な設定が可能です。

  • 自動再生リンク設定: 生成された音声ファイルをPPTXスライドに埋め込み(厳密にはリンク)、スライド表示時に自動的に再生されるように設定します。

  • ボイスリスト表示モード: 利用可能なTTSボイスの一覧を表示するモードを提供します。

解決する課題: PowerPointプレゼンテーションにナレーションを手動で追加する手間を削減し、スライドノートから一括で高品質なナレーション音声を生成・リンクすることで、プレゼンテーション作成の効率化と品質向上を支援します。特に、対話形式のコンテンツにおいて、複数の話者の音声を自動で割り当てて生成できる点が強みです。

原理

このプログラムは、Windows環境にインストールされたPowerPointアプリケーションのCOM (Component Object Model) オブジェクトを利用してPPTXファイルを操作します。TTS音声の生成には、外部ライブラリ tktts (おそらくカスタムまたは補助ライブラリ) を介して、様々なTTSエンジンと連携します。

  1. PowerPointアプリケーションの起動とファイルアクセス:

    • win32com.client.Dispatch("PowerPoint.Application") を使用してPowerPointアプリケーションのインスタンスを生成します。

    • ppt.Presentations.Open() メソッドで入力PPTXファイルを開きます。

  2. ノートテキストの抽出:

    • 各スライド(pres.Slides(idx))の NotesPage オブジェクトにアクセスします。

    • NotesPage.Shapes コレクションを反復処理し、ノートのテキストを含む特定のシェイプ (shp.Type == 14 と shp.PlaceholderFormat.Type == 2) からテキスト (shp.TextFrame.TextRange.Text) を取得します。

    • 取得されたノートテキストは extract_narration_text 関数で解析されます。この関数は、ナレーションが ((...)) で囲まれている場合にその内容を抽出し、それ以外の場合はノート全文を使用します。

  3. 対話テキストの解析 (対話モード時):

    • --monologue 0 オプションが指定された場合、抽出されたナレーションテキストは parse_dialogue_lines 関数によって対話形式として解析されます。

    • 「話者名,本文」の形式で記述された各行を話者と本文に分割します。

    • カンマを含まない行は、直前の話者の発言に連結することで、複数行にわたる発言をサポートします。

    • 発音できる文字(英数字、日本語など)が含まれない行はスキップされ、テキストが再構築されます。

  4. 話者とボイスのマッピング:

    • VOICE_MAPS 辞書には、各TTSエンジンで使用可能な話者名とボイス名の初期マッピングが定義されています。

    • コマンドライン引数 --voices ("話者名=ボイス;話者名=ボイス" または "ボイス1;ボイス2;...") を使用して、このマッピングを上書き・カスタマイズできます。

    • 対話モードの場合、プログラムはノートから検出されたすべての一意な話者名を収集し、それらにボイスを割り当てます。

  5. TTSエンジンによる音声生成:

    • 抽出・解析されたテキストと、決定された話者マッピングに基づき、tkTTS クラスのインスタンス (tktts) を使用して音声ファイルを生成します。

    • tktts.speak_dialogue() メソッドが呼び出され、選択されたTTSエンジン(例: pyttsx3, VOICEVOXなど)のAPIを通じてテキストが音声に変換され、指定された出力ディレクトリに .wav ファイルとして保存されます。

    • 各スライドにつき1つの音声ファイルが生成されます。

  6. PowerPointスライドへの音声リンク設定:

    • 生成された音声ファイルは link_audio_autoplay 関数によって、出力PPTXファイルの対応するスライドにリンクされます。

    • slide.Shapes.AddMediaObject2() メソッドを使用して音声ファイルがメディアオブジェクトとして追加されます。LinkToFile=True はファイルを埋め込むのではなくリンクすることを意味します。

    • slide.TimeLine.MainSequence.AddEffect(shape, 83, 0, 2, 1) は、追加されたメディアオブジェクトに対して、スライド表示時に自動的に再生されるようにアニメーション効果を設定します。83 は msoAnimEffectMediaPlay を指し、2 は msoAnimateOnPageClick (クリック時)ではなく、msoAnimateAfterPrevious (直前のイベント後) の開始トリガーを示唆していますが、コード内の値は ppEffectMediaPlay と ppAnimateAfterPrevious に対応し、これによりスライド表示と同時に自動再生される効果が得られます。

    • tktts_narration_slide_X という命名規則で既存のメディアオブジェクトを識別し、置き換えることで、複数回実行時の更新に対応しています。

必要な非標準ライブラリとインストール方法

このプログラムは、主に以下の非標準ライブラリに依存します。

  • pywin32: PowerPointのCOMオブジェクトをPythonから操作するために必要です。

    pip install pywin32
    
  • tktts: プログラムのソースコードと同じディレクトリに tktts.py ファイルが存在する必要があります。これは、様々なTTSエンジンを抽象化し、一貫したインターフェースで利用するための補助的なPythonスクリプトです。tktts.py 自体は、内部で利用するTTSエンジン(例: pyttsx3, requests for VOICEVOX, transformers for Qwen/Irodori, etc.)に応じて、追加のライブラリ依存関係を持つ場合があります。tktts.py の要件については、そのドキュメントを参照してください。

必要な入力ファイル

  • PowerPointプレゼンテーションファイル (.pptx):

    • コマンドライン引数 --input_path または -i で指定します。

    • 各スライドの「ノート」セクションに、ナレーションとして読み上げたいテキストが記述されている必要があります。

    • テキスト形式:

      • 独話形式 (デフォルト): ノート全体が1つのナレーションとして読み上げられます。または、特定のナレーション部分を ((...)) で囲むことで、その部分のみを読み上げることができます。 例:

        スライドのノートに記述された本文です。
        ((この部分だけがナレーションとして読み上げられます。))
        残りのテキストは無視されます。
        
      • 対話形式 (--monologue 0 を指定): ((...)) で囲まれた部分が対話テキストとして解析されます。各発言は「話者名,本文」の形式で記述し、改行区切りで複数発言を記述します。 例:

        ((
        四国めたん,こんにちは、四国めたんです。
        ずんだもん,やっほー、ずんだもんなのだ!
        四国めたん,今日はプレゼンのナレーションについて説明します。
        この行は前の四国めたんの発言に連結されます。
        ))
        
        • 「話者名,本文」の形式でない行や、カンマのない継続行は、直前の話者の発言に連結されます。

        • 空行や記号のみの行は、発音可能なテキストがないと判断されスキップされます。

生成される出力ファイル

  • 出力PowerPointプレゼンテーションファイル (.pptx):

    • コマンドライン引数 --output_path または -o で指定されたパスに保存されます。

    • 入力PPTXファイルがコピーされ、そのコピーの各スライドに生成された音声ファイルへのリンクが追加されます。

    • リンクされた音声ファイルは、スライドが表示されたときに自動的に再生されるように設定されます。

  • 音声ファイル (.wav):

    • コマンドライン引数 --audio_dir または -a で指定されたディレクトリに保存されます(デフォルトは audio_output)。

    • 各スライドのナレーションに対応して、slide{スライド番号}.wav の形式でファイルが生成されます(例: slide1.wav, slide2.wav)。

コマンドラインでの使用例 (Usage)

add_notes_voice_pptx2.py の基本的な使用法は以下の通りです。

usage: add_notes_voice_pptx2.py [-h] [--mode {list,conv}] [--monologue {0,1}] [--tts {pyttsx3,voicevox,qwen3,qwen,irodori,irodori-tts,aquestalkplayer,atp,openai,gemini}] [--input_path INPUT_PATH] [--audio_dir AUDIO_DIR] [--output_path OUTPUT_PATH] [--voices VOICES] [--temp_dir TEMP_DIR] [--speak_rate SPEAK_RATE] [--tinterval TINTERVAL] [--endpoint ENDPOINT] [--fspeak_rate FSPEAK_RATE] [--fspeak_pitch FSPEAK_PITCH] [--aquestalk_path AQUESTALK_PATH] [--instruction INSTRUCTION] [--qwen3_language QWEN3_LANGUAGE] [--qwen3_model_id QWEN3_MODEL_ID] [--qwen3_device QWEN3_DEVICE] [--qwen3_dtype {auto,bfloat16,bf16,float16,fp16,float32,fp32}] [--qwen3_instruct QWEN3_INSTRUCT] [--irodori_caption IRODORI_CAPTION] [--irodori_ref_wav IRODORI_REF_WAV] [--irodori_ref_wavs IRODORI_REF_WAVS] [--irodori_model_id IRODORI_MODEL_ID] [--irodori_device IRODORI_DEVICE] [--irodori_precision {auto,bf16,bfloat16,fp32,float32}] [--irodori_codec_device IRODORI_CODEC_DEVICE] [--irodori_codec_precision IRODORI_CODEC_PRECISION] [--irodori_num_steps IRODORI_NUM_STEPS] [--irodori_cfg_scale_text IRODORI_CFG_SCALE_TEXT] [--irodori_cfg_scale_caption IRODORI_CFG_SCALE_CAPTION] [--irodori_cfg_scale_speaker IRODORI_CFG_SCALE_SPEAKER] [--irodori_duration_scale IRODORI_DURATION_SCALE] [--irodori_seed IRODORI_SEED] [--irodori_lora_adapter IRODORI_LORA_ADAPTER] [--pause {0,1}]

PPTXノートから音声ファイルを生成し、自動再生リンクを設定するプログラム (Windows/PowerPoint, tktts使用)

options:
  -h, --help            show this help message and exit
  --mode {list,conv}    実行モード:
                        list: 利用可能な音声名を表示
                        conv: PPTXノートから音声を生成しPPTXにリンク
  --monologue {0,1}     1: 独話形式、0: '話者名,本文' の対話形式 (default: 1)
  --tts {pyttsx3,voicevox,qwen3,qwen,irodori,irodori-tts,aquestalkplayer,atp,openai,gemini}
                        TTSエンジンを選択
  --input_path -i INPUT_PATH
                        [convモード] ノート設定済みPPTXファイルパス
  --audio_dir -a AUDIO_DIR
                        [convモード] 生成された音声ファイルを保存するディレクトリ
  --output_path -o OUTPUT_PATH
                        [convモード] 音声リンクが追加された出力PPTXファイルパス
  --voices -v VOICES    [tktts] voice_map の上書き (話者名=ボイス;話者名=ボイス)
  --temp_dir TEMP_DIR   一時ファイルを作成するディレクトリ名
  --speak_rate SPEAK_RATE
                        [pyttsx3] 読み上げ速度 (WPM) / [AQT] 速度比
  --tinterval TINTERVAL
                        [AQT/OpenAI/VOICEVOX] 音声ファイル間に挿入する無音区間の長さ(秒)
  --endpoint ENDPOINT   [VOICEVOX] Engineのendpoint
  --fspeak_rate FSPEAK_RATE
                        [VOICEVOX] 読み上げ速度比 (標準: 1.0)
  --fspeak_pitch FSPEAK_PITCH
                        [VOICEVOX] 声の高さ比 (標準: 0.0)
  --aquestalk_path AQUESTALK_PATH
                        [AQT] AquesTalkPlayer.exe の実行パス
  --instruction INSTRUCTION
                        [OpenAI/Gemini] TTS APIへの追加指示
  --qwen3_language QWEN3_LANGUAGE
                        [Qwen3-TTS] language
  --qwen3_model_id QWEN3_MODEL_ID
                        [Qwen3-TTS] model ID
  --qwen3_device QWEN3_DEVICE
                        [Qwen3-TTS] auto/cuda:0/cpu
  --qwen3_dtype {auto,bfloat16,bf16,float16,fp16,float32,fp32}
                        [Qwen3-TTS] dtype
  --qwen3_instruct QWEN3_INSTRUCT
                        [Qwen3-TTS] CustomVoice instruction
  --irodori_caption IRODORI_CAPTION
                        [Irodori-TTS] voice/style caption
  --irodori_ref_wav IRODORI_REF_WAV
                        [Irodori-TTS] reference WAV
  --irodori_ref_wavs IRODORI_REF_WAVS
                        [Irodori-TTS] reference WAVs (;区切り)
  --irodori_model_id IRODORI_MODEL_ID
                        [Irodori-TTS] model ID
  --irodori_device IRODORI_DEVICE
                        [Irodori-TTS] auto/cuda/cuda:0/cpu
  --irodori_precision {auto,bf16,bfloat16,fp32,float32}
                        [Irodori-TTS] precision
  --irodori_codec_device IRODORI_CODEC_DEVICE
                        [Irodori-TTS] codec device
  --irodori_codec_precision IRODORI_CODEC_PRECISION
                        [Irodori-TTS] codec precision
  --irodori_num_steps IRODORI_NUM_STEPS
                        [Irodori-TTS] sampling steps
  --irodori_cfg_scale_text IRODORI_CFG_SCALE_TEXT
  --irodori_cfg_scale_caption IRODORI_CFG_SCALE_CAPTION
  --irodori_cfg_scale_speaker IRODORI_CFG_SCALE_SPEAKER
  --irodori_duration_scale IRODORI_DURATION_SCALE
  --irodori_seed IRODORI_SEED
                        [Irodori-TTS] seed; random/noneも可
  --irodori_lora_adapter IRODORI_LORA_ADAPTER
                        [Irodori-TTS] LoRA adapter
  --pause {0,1}         プログラム終了時にENTER入力を要求するか [0|1]

コマンドラインでの具体的な使用例

1. 利用可能な音声の一覧を表示する (pyttsx3エンジン)

コマンド:

python add_notes_voice_pptx2.py --mode list --tts pyttsx3

説明: --mode list を指定することで、プログラムはTTS処理を実行せず、指定されたTTSエンジン (--tts pyttsx3) で利用可能な音声(ボイス)の一覧をコンソールに表示します。これにより、どのボイスが利用可能かを確認できます。

2. PowerPointノートから独話形式で音声を生成し、PPTXにリンクする (pyttsx3エンジン)

入力PPTXファイル input.pptx のノートに独話形式 (((ナレーション本文))) でテキストが記述されていると仮定します。

コマンド:

python add_notes_voice_pptx2.py --mode conv -i input.pptx -o output.pptx -a audio_output --tts pyttsx3 --speak_rate 180 --pause 0

説明:

  • --mode conv: 変換モードを指定します。

  • -i input.pptx: ノートが記述された入力PowerPointファイルを指定します。

  • -o output.pptx: 音声リンクが追加された新しいPowerPointファイルの出力パスを指定します。

  • -a audio_output: 生成された音声ファイル(.wav)を保存するディレクトリを指定します。

  • --tts pyttsx3: TTSエンジンとして pyttsx3 を選択します。

  • --speak_rate 180: 読み上げ速度を1分あたり180単語に設定します。

  • --pause 0: プログラム終了時にEnterキーの入力を求めないようにします。

実行結果: input.pptx の各スライドノートからテキストが抽出され、pyttsx3 を使って audio_output/slideX.wav の形式で音声ファイルが生成されます。その後、これらの音声ファイルが output.pptx の対応するスライドに、自動再生設定でリンクされます。

3. PowerPointノートから対話形式で音声を生成し、PPTXにリンクする (VOICEVOXエンジン)

入力PPTXファイル input_dialogue.pptx のノートに、以下のような対話形式 (((話者名,本文))) のテキストが記述されていると仮定します。 (例: ノートの内容が ((四国めたん,こんにちは。;ずんだもん,なのだ!)) の場合)

コマンド:

python add_notes_voice_pptx2.py --mode conv -i input_dialogue.pptx -o output_dialogue.pptx --monologue 0 --tts voicevox --endpoint "http://127.0.0.1:50021" -v "四国めたん=1;ずんだもん=3"

説明:

  • --monologue 0: 対話形式での解析を有効にします。

  • --tts voicevox: TTSエンジンとして VOICEVOX を選択します。VOICEVOXエンジンがローカルで起動しており、デフォルトのエンドポイント http://127.0.0.1:50021 で利用可能である必要があります。

  • -v "四国めたん=1;ずんだもん=3": 話者「四国めたん」にVOICEVOXのボイスID 1 を、話者「ずんだもん」にボイスID 3 を割り当てます。これはセミコロン区切りで複数の話者マッピングを指定できます。

実行結果: input_dialogue.pptx のノートから対話形式のテキストが解析され、VOICEVOX を使って各話者に対応するボイスで音声が生成されます。生成された音声ファイルは audio_output ディレクトリに保存され、output_dialogue.pptx の対応するスライドに自動再生設定でリンクされます。