## speak.py: 統合TTS CLIツール

### 1) プログラムの動作

`speak.py` は、テキストデータ（クリップボードまたはファイル）を様々なTTS (Text-to-Speech) エンジン（`pyttsx3`, `AquesTalkPlayer`, `OpenAI TTS`）で音声に変換し、リアルタイムで再生するか、音声ファイルとして出力するコマンドラインツールです。

**主な機能:**
-   **複数のTTSエンジンをサポート**:
    -   `pyttsx3`: ローカルOSにインストールされているTTSエンジン（WindowsのSAPI5, macOSのNSSpeechSynthesizer, LinuxのeSpeakなど）を利用します。
    -   `AquesTalkPlayer` (Windows専用): 高品質な合成音声を提供する外部プログラムを利用します。
    -   `OpenAI TTS`: OpenAIのTTS APIを利用します（APIキーが必要）。
-   **入力ソースの選択**: クリップボード (`--infile clip`) または指定されたテキストファイル (`--infile <ファイルパス>`) からテキストを読み込みます。
-   **テキスト形式の自動判別**: ファイル入力の場合、`chardet` を使用してファイルエンコーディングを自動判別し、適切にデコードします。
-   **対話形式の読み上げ**: `話者名,セリフ` の形式で書かれたテキストに対応し、話者ごとに異なるボイスやプリセットを割り当てて読み上げることができます。
-   **独話形式の読み上げ**: `--monologue 1` オプションを使用すると、カンマ区切りのない一般的なテキストを単一話者で読み上げます。
-   **ボイス/プリセットのカスタマイズ**: `VOICE_MAPS` で定義されたデフォルトマッピングに加え、`--voices "話者1=ボイス名1;話者2=ボイス名2"` オプションでカスタムのボイス/プリセットを割り当てることができます。
-   **文字列置換**: `--replace "元文字列=置換文字列"` オプションで、読み上げ前にテキスト内の特定の文字列を置換できます。
-   **音声ファイル出力**: `--outfile <ファイルパス>` オプションを指定すると、生成された音声を指定されたファイルに保存します。指定しない場合はリアルタイムで再生されます。
-   **利用可能ボイスの表示**: `--list` オプションで、選択したTTSエンジンで利用可能なボイスの一覧を表示できます。

**動作フローの概要:**
1.  **初期設定**: 必要なPythonライブラリのチェックと、コマンドライン引数の解析を行います。
2.  **テキスト取得**: `infile` オプションに従い、クリップボードまたはテキストファイルから読み上げテキストを取得します。ファイルの場合は `chardet` でエンコーディングを判別します。
3.  **テキスト解析**: 取得したテキストを行ごとに解析し、対話形式 (話者とセリフ) または独話形式に変換します。
4.  **設定適用**: 検出された話者に基づき、選択されたTTSエンジンのデフォルトボイスマップを初期化し、`--voices` 引数で指定されたカスタムマッピングや `--replace` 引数で指定された文字列置換ルールを適用します。
5.  **音声生成と出力**: 準備されたテキストデータと設定を `tktts.speak_dialogue` 関数に渡し、各セリフに対応するTTSエンジンとボイスで音声を生成します。生成された音声はリアルタイムで再生されるか、`--outfile` で指定されたファイルに結合されて保存されます。
6.  **終了**: 処理が完了すると、オプションで入力待ちを行った後、プログラムを終了します。

### 2) 必要な非標準ライブラリとインストールコマンドとインストール方法

**Pythonライブラリ:**

以下のライブラリは `pip` を使用してインストールできます。
```bash
pip install chardet pyttsx3 openai pydub pyperclip
```
*補足: `tktts` は通常、`speak.py` と同じディレクトリに配置されるカスタムモジュールであると想定されます。このモジュール自体は `pyttsx3`, `openai`, `pydub` 等に依存しています。もし `tktts` がPyPIで公開されている場合は `pip install tktts` でインストール可能です。*

**外部依存:**

-   **`ffmpeg.exe`**
    -   **説明**: `pydub` ライブラリがオーディオファイルの操作（結合、形式変換など）を行うために必要です。
    -   **インストール方法**: ffmpegの公式サイト（<https://ffmpeg.org/download.html>）から適切なバイナリをダウンロードし、`ffmpeg.exe` をシステムの環境変数 `PATH` に追加してください。これにより、`pydub` が `ffmpeg` を自動的に検出できるようになります。
-   **`AquesTalkPlayer.exe`** (Windowsでのみ使用可能)
    -   **説明**: `AquesTalkPlayer` エンジンを選択した場合に必要となる、合成音声生成のための外部プログラムです。
    -   **インストール方法**: AquesTalkPlayerを開発元から入手し、PCにインストールしてください。`speak.py` 実行時に `--aquestalk_path` 引数でこの実行ファイルのフルパスを指定する必要があります。
-   **OpenAI API Key**
    -   **説明**: `OpenAI` エンジンを選択した場合に必要となる、OpenAIのTTS APIを利用するための認証キーです。
    -   **設定方法**: 環境変数 `OPENAI_API_KEY` にAPIキーを設定してください。
        -   Windows (コマンドプロンプト): `set OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx`
        -   Linux/macOS (Bash/Zsh): `export OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxx`
        -   永続的に設定するには、OSの環境変数設定を使用してください。

### 3) 必要な入力ファイル

-   **テキスト入力元:**
    -   **クリップボード**: `--infile clip` または `--infile` オプションを省略した場合、プログラムはクリップボードの内容を読み込みます。実行前に、読み上げたいテキストをクリップボードにコピーしておく必要があります。
    -   **テキストファイル**: `--infile <ファイルパス>` で指定する任意のテキストファイル。
        -   **ファイル形式**:
            -   **対話形式 (デフォルト)**: 各行が `話者名,セリフ` の形式である必要があります。カンマで区切られていない行や `#` で始まるコメント行は無視されます。
                例: `dialogue.txt`
                ```
                れいむ,こんにちは、ゆっくりしていってね。
                まりさ,魔理沙も元気そうだな。
                # これはコメントです。
                ```
            -   **独話形式 (`--monologue 1` オプション使用時)**: 各行が独立した一つのセリフとして扱われます。
                例: `monologue.txt`
                ```
                これは最初の文です。
                そして、これが二番目の文。
                ```

-   **外部プログラムファイル:**
    -   `AquesTalkPlayer.exe`: `AquesTalkPlayer` エンジンを使用する場合に、`--aquestalk_path` で指定されたパスに存在する必要があります。
    -   `ffmpeg.exe`: `pydub` がオーディオ処理を行うために、システムの `PATH` 上、または検出可能な場所に存在する必要があります。

### 4) 実行後に生成される出力ファイル

-   **出力音声ファイル**:
    -   `--outfile <ファイルパス>` オプションが指定された場合に生成されます。
    -   ファイル形式は、指定されたファイルパスの拡張子によって決定されます（例: `output.wav`, `output.mp3`, `output.flac` など）。対応する形式は `pydub` がサポートしている形式に依存します。
    -   `--outfile` オプションが指定されない場合、音声はリアルタイムで再生されるため、ファイルは生成されません。

-   **一時ファイル**:
    -   `AquesTalkPlayer` または `OpenAI` エンジンを使用する場合、特に複数のセリフがある場合や `outfile` が指定されている場合、`--temp_dir` オプションで指定されたディレクトリ（デフォルトは `tts_temp_wavs`）に一時的なWAVファイルが生成される可能性があります。
    -   これらのファイルは、通常、処理完了後に自動的に削除されますが、プログラムの異常終了時には残る場合があります。

### 5) コマンドラインでの使用例 (Usage)

```bash
# ヘルプメッセージの表示
python speak.py --help

# クリップボードのテキストをpyttsx3でリアルタイム再生 (デフォルト設定)
# (例: クリップボードに「こんにちは、世界！」とコピーしてから実行)
python speak.py

# クリップボードのテキストをpyttsx3で、"Zira"ボイスを使用してリアルタイム再生
python speak.py -i clip -t pyttsx3 --voices "れいむ=Zira"

# テキストファイル "dialogue.txt" (対話形式) をpyttsx3で読み上げ、"output.wav" に保存
# dialogue.txt の内容例:
#   れいむ,こんにちは
#   まりさ,どうも
python speak.py -i dialogue.txt -o output.wav -t pyttsx3 --voices "れいむ=Zira;まりさ=David"

# テキストファイル "monologue.txt" (独話形式) をpyttsx3で読み上げ
# monologue.txt の内容例:
#   これは独り言です。
#   長い文章を読み上げます。
python speak.py -i monologue.txt -m 1 -t pyttsx3

# AquesTalkPlayerを使用して、クリップボードのテキストをリアルタイム再生
# (AquesTalkPlayer.exe が "C:\Program Files\AquesTalkPlayer\AquesTalkPlayer.exe" にある場合)
python speak.py -i clip -t aquestalkplayer --aquestalk_path "C:\Program Files\AquesTalkPlayer\AquesTalkPlayer.exe" --voices "れいむ=れいむ"

# OpenAI TTSを使用して、テキストファイル "story.txt" を読み上げ、"story.mp3" に保存
# (環境変数 OPENAI_API_KEY が設定されている必要があります。)
# 話者「四国めたん」に"nova"ボイスを割り当て、「ずんだもん」に"shimmer"を割り当てる例
python speak.py -i story.txt -o story.mp3 -t openai --voices "四国めたん=nova;ずんだもん=shimmer"

# OpenAI TTSで、クリップボードのテキストをリアルタイム再生し、
# 読み上げ前に「っす」を「です」に置換する
python speak.py -i clip -t openai --replace "っす=です"

# pyttsx3で利用可能なボイスをリスト表示
python speak.py --list -t pyttsx3

# AquesTalkPlayerで利用可能なプリセット（VOICE_MAPSの設定に基づく）をリスト表示
python speak.py --list -t aquestalkplayer

# OpenAIで利用可能なボイス（VOICE_MAPSの設定に基づく）をリスト表示
python speak.py --list -t openai
```