統合TTS GUI (Qt非同期)

プログラムの動作

speak_qt_async.py は、PySide6 (Qt) を使用して構築されたグラフィカルユーザーインターフェース (GUI) ベースのテキスト読み上げ (TTS) アプリケーションです。このプログラムは、複数のTTSエンジン (pyttsx3, WinRT, Voicevox, Qwen3, Irodori, OpenAI, ElevenLabs, AquesTalkPlayer, Gemini) を統合し、ユーザーが直感的にテキスト音声変換と再生を行えるように設計されています。

主な機能は以下の通りです。

  • テキスト入力とスライド管理: Markdown形式のテキストファイル(またはプレーンテキストファイル)を読み込み、# Slide または *N (例: *1) で区切られたスライドページとして内容を分割・表示します。

  • 正規表現置換: 指定されたINIファイルに基づいて正規表現置換ルールを適用し、読み上げに適した形にテキストを変換します。

  • 複数のTTSエンジンサポート: 様々なTTSエンジンを選択でき、それぞれのエンジンに応じたボイス、速度、ピッチ、その他詳細な設定(Qwen3-TTSやIrodori-TTSのモデル、デバイス、キャプションなど)をGUIから調整できます。

  • 非同期音声生成と再生: 音声生成処理はバックグラウンドスレッドで非同期に実行されるため、GUIがフリーズすることなくスムーズな操作が可能です。生成された音声はアプリケーション内で直接再生できます。

  • 設定の永続化: ウィンドウの配置、各種パス、TTS設定は speak_qt_async.ini ファイルに自動的に保存され、次回起動時に復元されます。

  • 一時ファイルのクリーンアップ: 未指定で生成された一時音声ファイルは、アプリケーション終了時に自動的に削除されます。

このプログラムは、プレゼンテーション資料やスクリプトなどのテキストを、多様な合成音声で手軽に確認・出力したいユーザーに役立ちます。

原理

speak_qt_async.py は以下の技術的原理に基づいています。

  1. GUIフレームワーク: PySide6 (Qt) ライブラリを使用しており、ウィジェットベースのデスクトップアプリケーションを構築します。UIイベント (ボタンクリック、スライダー操作など) はシグナルとスロット機構を通じて処理されます。

  2. 非同期処理: 重い処理である音声生成は、メインGUIスレッドをブロックしないように QThread を継承した MyTTSWorker クラスで実行されます。

    • MyTTSWorker は Signal を使ってGUIスレッドに進行状況 (progress) や完了 (finished)、エラー (error) を通知します。

    • GUIスレッドの MyTTSApp クラスは、これらのシグナルを Slot で受け取り、プログレスバーの更新、ステータス表示、音声再生開始などの処理を行います。

  3. 音声再生: 生成された音声ファイルは PySide6.QtMultimedia モジュールの QMediaPlayer と QAudioOutput を使用して再生されます。これにより、再生・一時停止・停止・シーク(再生位置の移動)といった操作がGUIから可能になります。

  4. TTSエンジン統合 (tktts ライブラリ):

    • このプログラムは、tktts というライブラリの統一インターフェースを利用して、多様なTTSエンジンを呼び出します。

    • MyTTSWorker 内では、ArgsStub クラスが tktts ライブラリが期待するコマンドライン引数のような形式のオブジェクトをエミュレートし、各種設定値(エンジン、速度、ピッチ、ボイスなど)を tktts の speak_dialogue 関数に渡します。

    • tktts.get_available_voices 関数により、選択されたTTSエンジンで利用可能なボイスリストを取得し、GUIのコンボボックスに表示します。

  5. テキスト処理と正規表現置換:

    • エンコーディング検出: chardet ライブラリを用いて、入力テキストファイルの文字エンコーディングを自動的に判定し、適切なエンコーディングでファイルを読み込みます。

    • スライド解析: 入力テキストは、正規表現 ^\s*(#\s*Slide.*|\*\d+)\s*$ (例: # Slide 1, *2) を使用してスライドごとに分割されます。

    • 置換ルール: load_replace_dict 関数はINIファイルから置換ルールを読み込みます。このINIファイルは # で始まるコメント行と、key=value 形式の行で構成され、key は正規表現パターン、value は置換文字列として扱われます。

    • キャッシュ機構: _GLOBAL_REPLACE_DICT_CACHE と _GLOBAL_TIMESTAMP_CACHE を使用して、INIファイルのタイムスタンプを監視し、変更がない場合はキャッシュされた置換ルールを再利用してパフォーマンスを向上させます。

    • 置換適用: apply_replacements 関数が re.sub を使用し、INIファイルで定義された正規表現パターンをテキストに適用します。置換後、スライド区切りマーカーや余分な空行がクリーンアップされます。

  6. 設定管理:

    • アプリケーションのウィンドウ位置とサイズ、各種パス、TTS設定は、アプリケーション終了時に os.path.splitext(__file__)[0] + ".ini" (通常 speak_qt_async.ini) というファイルに保存されます。

    • 保存形式はセクション [window], [tts_paths], [qwen3], [irodori] を持つ単純なINIファイル形式です。

    • 次回起動時にこのファイルが読み込まれ、設定が復元されます。

  7. 一時ファイル管理:

    • GUIで出力ファイルパスが指定されなかった場合、生成された音声ファイルは DEFAULT_TEMP_DIR (tts_temp_wavs) 内に _tktts_tmp_ で始まる一時ファイルとして保存されます。

    • アプリケーション終了時 (QApplication.aboutToQuit シグナル) に、これらのファイルおよび指定された一時ディレクトリ内の関連ファイルが自動的に削除され、ディスクスペースを節約します。

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

このプログラムを実行するには、以下の非標準Pythonライブラリが必要です。

pip を使用してインストールできます。

pip install PySide6 chardet tktts pydub
  • PySide6: QtフレームワークのPythonバインディング。GUI構築に使用されます。

  • chardet: ファイルの文字エンコーディングを検出するために使用されます。

  • tktts: 複数のテキスト読み上げ (TTS) エンジンを統一的に扱うためのライブラリ。様々なTTSエンジンへのインターフェースを提供します。

  • pydub: 音声ファイルを操作するためのライブラリ。tktts の内部で音声ファイルの結合などに使用される可能性があります。

補足:TTSエンジンの要件

  • Voicevox: Voicevoxエンジンを利用する場合、ローカルでVoicevox Engineが動作している必要があります。通常 http://127.0.0.1:50021 にてサービスが提供されます。

  • AquesTalkPlayer: AquesTalkPlayerエンジンを利用する場合、AquesTalkPlayer.exe のパスを指定する必要があります。

  • OpenAI / ElevenLabs / Gemini: これらのクラウドベースのTTSサービスを利用する場合、APIキーを環境変数として設定する必要がある場合があります(例: ELEVENLABS_API_KEY)。

必要な入力ファイル

このプログラムは、以下の種類の入力ファイルを扱います。

  1. 入力テキストファイル (.txt, .md):

    • Main タブの「Input File」で指定します。

    • プレーンテキストまたはMarkdown形式のファイルです。

    • プログラムは、以下の正規表現パターンで始まる行を「スライド区切り」として認識し、テキストを分割してGUIの「Slide Page」プルダウンに表示します。

      • # Slide (例: # Slide Introduction)

      • *N (例: *1, *2)

    • デフォルトのファイル名は input.md が設定としてロードされます。

    • 文字エンコーディングは chardet によって自動検出されます。

  2. 置換ルールINIファイル (.ini):

    • Main タブの「Replace INI (Default)」と「Replace INI (User)」でそれぞれ指定します。

    • TOML風の簡易INI形式で、正規表現による置換ルールを記述します。

    • 各行は パターン=置換文字列 の形式で記述します。

    • # で始まる行はコメントとして無視されます。

    • 例:

      # 敬称の統一
      "氏"=さん
      "様"=さん
      # 特定の略語を展開
      "AI"=エーアイ
      
    • デフォルトのファイル名はそれぞれ replace.ini と user_replace.ini が設定としてロードされます。

  3. AquesTalkPlayer実行ファイル (AquesTalkPlayer.exe):

    • Config タブの「AquesTalk Path」で指定します。

    • AquesTalkPlayer TTSエンジンを使用する場合に必要です。

  4. Irodori-TTS 参照WAVファイル (.wav):

    • Config タブの「Irodori-TTS Reference WAV」で指定します。

    • Irodori-TTSエンジンを使用する際に、声のスタイルを模倣するための参照音声として利用されます。

生成される出力ファイル

speak_qt_async.py は、以下の種類のファイルを出力または生成します。

  1. 出力音声ファイル (.wav, .mp3):

    • Main タブの「出力ファイル (wav/mp3)」でパスを指定した場合に生成されます。

    • 指定されたパスの拡張子に基づいて、WAVまたはMP3形式で音声ファイルが保存されます。

    • 拡張子が指定されていない場合、使用中のTTSエンジンに応じて自動的に .wav または .mp3 (OpenAI, ElevenLabsなどの場合) が付与されます。

  2. 一時音声ファイル (.wav):

    • 出力ファイルパスをGUIで指定しなかった場合、またはプレビュー再生のために、一時ファイルが生成されます。

    • これらのファイルは通常、プログラム実行ディレクトリ内の tts_temp_wavs ディレクトリに、_tktts_tmp_ プレフィックスとランダムな文字列を含むファイル名 (例: _tktts_tmp_87a3b4c1_merged.wav) で保存されます。

    • 一時ファイルは、アプリケーション終了時に自動的にクリーンアップ(削除)されます。

  3. 設定ファイル (speak_qt_async.ini):

    • プログラムが終了する際に、現在のウィンドウのサイズと位置、各種パス、TTSエンジンの設定(選択中のエンジン、ボイス、速度、ピッチ、Qwen3/Irodoriの詳細設定など)が自動的に保存されます。

    • ファイルは speak_qt_async.py と同じディレクトリに speak_qt_async.ini という名前で保存されます。

    • 次回プログラムを起動する際に、このファイルから設定が読み込まれ、GUIの状態が復元されます。

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

speak_qt_async.py はGUIアプリケーションであるため、通常コマンドライン引数は受け付けません。Pythonインタープリタを使用して直接実行します。

python speak_qt_async.py

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

上記の使用法でプログラムを起動すると、GUIウィンドウが表示されます。以下に一般的な使用シナリオとその操作手順を示します。

  1. プログラムの起動:

    python speak_qt_async.py
    

    これにより、統合TTS GUI (コンパクト・リサイズ可能) というタイトルのウィンドウが起動します。

  2. 入力ファイルの読み込み:

    • Main タブの「Input File」の横にある「Path」ボタンをクリックします。

    • ファイル選択ダイアログが表示されるので、読み上げたいテキストファイル(例: presentation.md)を選択します。

    • ファイルが読み込まれると、「Slide Page」プルダウンに「0. (All Document)」が表示され、ファイル内容によっては「1. Slide 1」などのスライドページがリストされます。

    • 「読み上げテキスト (Original)」エリアに選択されたスライドのテキストが表示されます。

  3. 置換ルールの適用:

    • 必要に応じて、「Replace INI (Default)」や「Replace INI (User)」の「Path」ボタンをクリックし、置換ルールを定義したINIファイルを選択します。

    • 「⚙️ Convert (Apply Rules)」ボタンをクリックします。

    • 「読み上げテキスト (Converted)」エリアに、置換ルールが適用され、スライドマーカーが削除されたテキストが表示されます。Status バーに「Conversion complete. Ready to Play.」と表示されます。

  4. TTSエンジンの設定:

    • Config タブに切り替えます。

    • 「Engine」プルダウンから使用したいTTSエンジン(例: Voicevox)を選択します。

    • エンジンに応じて、「Voice」プルダウンに利用可能なボイスのリストが表示されるので、好みのボイスを選択します。

    • 「Speed (fspeak_rate)」や「Pitch (ピッチ)」の値を調整します。

    • Qwen3-TTS や Irodori-TTS を選択した場合は、それぞれの専用設定(モデルID、デバイス、キャプション、参照WAVなど)を調整できます。

    • Voicevox を選択した場合は、「Voicevox Endpoint」が適切に設定されていることを確認してください。

  5. 音声の生成と再生:

    • Main タブに戻ります。

    • 「▶ Play/Generate」ボタンをクリックします。

    • プログラムは「読み上げテキスト (Converted)」の内容に基づき、設定されたTTSエンジンで音声ファイルを生成します。この間、「Prog/Pos」バーに進行状況が表示され、Status バーに「音声生成を開始しました... (非同期実行中)」と表示されます。

    • 音声生成が完了すると、自動的にその音声が再生されます。「Prog/Pos」スライダーで再生位置を調整できます。

    • 同じテキストと設定で再度再生したい場合は、is_converted_text_dirty フラグが False のため、再生成なしで既存の音声が再生されます。設定を変更した場合や、強制的に再生成したい場合は「⚡ Generate (Force)」ボタンを使用します。

  6. 再生コントロール:

    • 再生中に「⏸ Pause」ボタンで一時停止、再度「▶ Play/Generate」ボタンで再開できます。

    • 「■ Stop」ボタンで再生を停止し、スライダーが先頭に戻ります。

  7. アプリケーションの終了:

    • ウィンドウを閉じるか、メニューから終了を選択します。

    • 設定は自動的に speak_qt_async.ini に保存され、一時ファイルがクリーンアップされます。