TECH NOTE / 005
WindowsでIrodori-TTSの声を作り、Codexの返答を自動読み上げさせた備忘録
VoiceDesignで作った声を、CodexのStopフックと非同期ワーカー経由でローカル再生するまでの構成、観測、調整をまとめます。
/ Hræsa
01 / OVERVIEW
声を作り、返答の要点だけを読む
これはCodexの標準機能ではなく、ローカルで組み合わせた独自連携です。2026-08-19に記録した構成と観測をもとにしており、Codexのフック、画面、同梱CLIの配置や操作はバージョンで変わり得ます。
- TTS要約返答末尾へ短い要約を付ける
- Stopフック最後のタグを抽出し、対象と重複を確認する
- 非同期ワーカージョブを受け、ローカルAPIへ渡す
- 生成と再生WAVを処理して音量を調整し、再生する
時間のかかるモデル推論をStopフック内で待たず、ジョブ登録後は別プロセスへ任せる構成にしました。
02 / IRODORI-TTS
VoiceDesignをループバックで動かす
記録時はWindows、NVIDIA GPU / CUDA 12.8、uv、Irodori-TTS v4系(revision 8224daf)、Aratako/Irodori-TTS-v4.1-Small、gradio_app_voicedesign.pyを使い、127.0.0.1:7861でVoiceDesign UIを起動しました。
| 記録時の項目 | 値 |
|---|---|
| GPUバックエンド | NVIDIA CUDA 12.8向け環境 |
| パッケージ管理 | uv |
| checkpoint | Aratako/Irodori-TTS-v4.1-Small |
| UI / URL | gradio_app_voicedesign.py / 127.0.0.1:7861 |
uv sync --extra cu128
uv run --no-sync python gradio_app_voicedesign.py --server-name 127.0.0.1 --server-port 7861uv sync --extra cu128は当時のGPUバックエンド向けの例で、すべての環境に共通するコマンドではありません。外部公開ではなくループバックへ限定する意図で127.0.0.1を使いました。Irodori-TTS公式READMEは2026-09-11に、v4.1-Small、VoiceDesign UI、uvのバックエンド別extraを確認しています。
03 / VOICE DESIGN
説明文と三つの評価文で声を選ぶ
落ち着いた成人女性の声。やや低めで澄んだ音色。知的だが冷たくなく、自然体。親しい相手に少し近い距離感で話す。感情は控えめだが好奇心がにじむ。幼すぎる声、甲高い声、芝居がかった演技は避ける。
今確認できているのはここまで。まだ推測の部分もあるから、次は実際の動作を見て判断しよう。
それ、ちょっと面白いね。どういう条件で変わるのか、もう少し中を見てみたい。
いや待って。それを直すために機能を三つ増やすのは違う。各文章から選んだWAVを一本ずつ、合計三本を参照音声にしました。採用時のseedと評価文の対応を保存していなかったため、同一候補の再現性には限界が残ります。実際のWAVや固有のファイル名は掲載しません。
| 設定 | 採用値 |
|---|---|
| Num Steps / candidates | 40 / 1 |
| seed / seconds / duration | random / auto / 1.0 |
| schedule / guidance | linear / independent |
| CFG | text 3.0 / caption 4.0 / speaker 5.0 |
| model / codec | cuda fp32 / cuda fp32 |
04 / SIBILANCE
歯擦音は狭い帯域だけで比較した
約13kHz付近の電子的な歯擦音が気になったため、常時EQではなく、対象帯域が強い瞬間だけを抑える処理を比較しました。
| 試行 | 対象帯域 | 最大減衰 | 観測 |
|---|---|---|---|
| Mild | 11.5–15.2 kHz | 4 dB | 変化が小さかった |
| Strong | 11.5–15.2 kHz | 8 dB | 問題がまだ残った |
| Focused | 12.3–14.5 kHz | 16 dB | 改善した |
| Focused | 12.3–14.5 kHz | 24 dB | この声では採用した |
{
"max_reduction_db": 24.0,
"low_hz": 12300.0,
"high_hz": 14500.0,
"threshold_percentile": 82.0,
"knee_db": 8.0,
"detector_ms": 8.0,
"attack_ms": 0.8,
"release_ms": 30.0
}これはこの環境、この生成音声に対する局所的な調整結果です。別の声へそのまま適用する一般的な推奨ではありません。
05 / TTS TAG
詳細な本文と、短い読み上げ要約を分ける
<TTS>重要な結論と次の行動だけを、短い自然な文章で書く。</TTS>- 一つだけ置く
返答末尾に一つだけ置き、閉じタグより後ろへ文字を書かない。
- 音声向けに短くする
Markdown、コード、URL、引用や出典表記を含めず、自然な話し言葉にする。
- 運用例として扱う
これは記録時の
AGENTS.md運用例であり、Codexの将来仕様を断定するものではない。
06 / HOOK & WORKER
Stopフックは登録だけを行い、生成は非同期へ渡す
{
"hooks": {
"Stop": [{
"hooks": [{
"type": "command",
"command": "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"<TTS_PROJECT>\\tools\\codex_tts_hook.ps1\"",
"timeout": 10,
"async": true
}]
}]
}
}- 読み上げが有効か、
cwdが許可リスト内か確認する。 - 最後の
<TTS>だけを抽出し、空なら終了する。 - 内容からSHA-256のジョブIDを作り、同じジョブを重複実行しない。
- ローカルのジョブJSONを作り、非表示のPowerShellワーカーを起動する。
- 失敗はローカルログへ残し、Codexの停止処理を妨げない。
{"continue":true}ワーカーはhttp://127.0.0.1:7861/gradio_api/infoで起動確認を行い、VoiceDesign呼び出し、生成WAVの保存、歯擦音処理、gain調整、成果物・レポート保存、winsound再生を行います。ジョブはファイルロックで直列化しました。
{
"scope": {
"allowed_project_roots": [
"<PROJECT_ROOT_A>",
"<PROJECT_ROOT_B>"
]
}
}グローバルフックでローカルの全Codex作業を無条件に読まないよう、明示的に許可したプロジェクトだけを対象にします。
07 / OBSERVATIONS
実際に詰まった点
- CLIの配置
codexが見つからず、当時はCodex Desktop同梱の実行ファイルを使いました。記録時の版は0.148.0-alpha.15で、将来の配置は保証されません。 - フックの信頼
/hooksで内容を確認してから信頼しました。当時の画面で観測した信頼操作のキーTも、将来の操作として断定しません。 - 二重実行
ユーザー設定とプロジェクト設定へ同じStopフックを置くと二重実行されたため、プロジェクト側の重複を外しました。
- プロセス寿命
Codexの子プロセスとして起動すると終了時にWeb UIも止まったため、独立したCMDランチャーへ分けました。
08 / GAIN
再生音量は会話で比較して決める
| ゲイン | 振幅比 | 試聴結果 |
|---|---|---|
| -6 dB | 約0.50 | まだ大きかった |
| -12 dB | 約0.25 | まだ大きかった |
| -20 dB | 0.10 | この環境で採用した |
amplitude_ratio = 10^(gain_db / 20)-20 dBはこの環境で採用した値であり、一般的な推奨ではありません。振幅比と人間が感じる音量も同じ尺度ではありません。
09 / STRUCTURE & SAFETY
構成を分け、安全境界を明示する
<TTS_PROJECT>/
├─ AGENTS.md
├─ tools/
│ ├─ start-irodori-tts.cmd
│ ├─ codex_tts_hook.ps1
│ ├─ codex_tts_worker.ps1
│ ├─ codex_tts_worker.py
│ └─ process_irodori_sibilance.py
└─ voice/
├─ AUTOMATION.md
├─ automation.json
├─ generated/YYYY-MM-DD/
├─ runtime/jobs/ and logs/
└─ voice-profile-v1/
├─ profile.json
├─ postprocess.json
└─ reference/selected-reference-wavs...| 症状 | 今回の原因・確認点 |
|---|---|
| Web UIのCMDを開くとエラーになる | Irodori-TTS、uv、起動対象スクリプトのパスと、ランチャーの用途を確認する。 |
| 返答後に音が出ない | Web UI、TTSタグ、対象プロジェクトが許可リスト内かを確認する。 |
| Codex再起動後に音が出ない | Codex終了時にWeb UIまで停止していないか確認し、Web UIを独立起動する。 |
codexコマンドが見つからない | スタンドアロンCLIのPATHまたはDesktop同梱CLIの有無を確認する。 |
| Hooks need review | /hooksでソースとコマンドを確認し、納得したものだけ信頼する。 |
| Stopフックが複数表示される | ユーザー設定とプロジェクト設定の重複を確認する。複数の一致フックはすべて動く。 |
| 初回の読み上げが遅い | モデルとcodecの初回ロードを通常時と分けて評価する。 |
| さ行に電子的な音が乗る | 問題帯域を測り、狭い帯域の動的処理を比較する。 |
| 処理後のさ行が弱すぎる | 最大抑制量、帯域、閾値を弱め、通常文章で再評価する。 |
| 読み上げ音量が大きい | 再生前に負のゲインを適用し、デシベルと振幅比を混同しない。 |
| 別プロジェクトで読まない | そのプロジェクトのAGENTS.mdとフック側の許可リストを確認する。 |
| 設定変更が既存チャットへ反映されない | 新しいセッションで開始するか、AGENTS.mdを読み直す。 |
- TTSサーバーはループバックだけへbindする。
- スクリプトやフックへ認証情報を書かない。
<TTS>へ個人情報や秘密情報を入れない。- WAV、ジョブJSON、ログは公開ディレクトリへ置かない。
- フックは内容を確認してから信頼し、声や参照音声の権利・同意を確認する。
- 公開例ではユーザー名、パス、プロジェクト名、音声名、ハッシュを一般化する。
記録時の最終設定
| 項目 | 採用値 |
|---|---|
| TTSモデル | Aratako/Irodori-TTS-v4.1-Small |
| 参照音声 | 選定した生成WAV三本 |
| VoiceDesign caption | 落ち着いた成人女性、やや低め、自然体、近い距離感 |
| 歯擦音処理 | 12.3–14.5 kHzを検出時に最大24 dB抑制 |
| 全体再生ゲイン | -20 dB、振幅比0.10 |
| Web UI | 127.0.0.1:7861で独立起動 |
| Codex連携 | Stopフックから非同期ジョブ登録 |
| 読み上げ対象 | 回答末尾の最後のTTSタグだけ |
| プロジェクト範囲 | 明示的な許可リスト |
| 保存 | 元WAV、処理後WAV、ジョブ状態、ログ |
10 / FINAL CHECK
導入時の確認項目
これは閲覧用のチェックリストです。サイト上で操作する項目ではありません。
- Irodori-TTSの現在のREADMEと対応バックエンドを確認する
- uv環境を適切なGPUまたはCPU extraで同期する
- Web UIを127.0.0.1で起動する
- caption、モデル、全生成設定を保存する
- 各候補の文章、seed、採用理由を保存する
- 参照WAVは未加工のまま保持する
- 問題音は印象だけでなく、発生箇所と帯域も確認する
- 後処理は弱い版から比較し、通常文章でも評価する
- AGENTS.mdへTTS要約の書式を追加する
- Stopフックは一か所だけへ登録する
- /hooksでフック内容を確認して信頼する
- Web UIをCodexとは独立して起動する
- 許可プロジェクト以外ではフックが何もしないことを試す
- 同一ジョブの重複防止を確認する
- 初回ロードと通常時の待ち時間を分けて評価する
- 再生音量を実際の会話で調整する
- ログや公開用記事に個人情報・秘密情報がないか確認する
11 / REFERENCES
まとめと参考リンク
声づくりだけでなく、短い要約の形式、Stopフックからの非同期化、Web UIの寿命、重複設定、局所的な後処理、音量、プロジェクト範囲の制御を分けて扱うことで、問題を個別に観測して直せる構成になりました。
公式情報は利用時点で再確認してください。