音声エージェントにおけるカスタム発音の改善
Posted by Sandeep Kumar Nayak, AI Engineer of Gaudiy Inc.
この記事は #GauDev Advent Calendar 2025 の13日目の記事です。
はじめに
Text-to-Speech(TTS:音声合成)を使用したアプリケーションを開発する際、必ず直面する問題があります。それは「固有名詞の発音問題」です。
例えば、英語のTTSがアニメ『【推しの子】』のキャラクター名である「アイ(AI)」(「あ・い」と発音)を読み上げる際、2つの文字として「A-I(エー・アイ)」と綴るのではなく、「A.I.(人工知能)」のように発音してしまうことがあります。ユーザー向けの音声体験において、これは没入感を損ない、ユーザーを混乱させる重大な問題となります。
この記事では、以下の内容について包括的なガイドを提供します。
- TTSの発音問題の本質 — なぜ発生するのか、その影響について
- 利用可能な解決策 — さまざまなアプローチの比較
- 私たちの実装 — Cartesia TTS向けのカスタム発音辞書
- ベストプラクティス — 本番環境での運用から得られた教訓
音声アシスタント、オーディオブックのナレーター、あるいは音声対応アプリケーションを構築している方にとって、このガイドが発音の課題に取り組む助けになれば幸いです。
背景:TTSの仕組み
問題に入る前に、現代のTTSシステムがどのように機能するかを理解しておきましょう。
TTSパイプライン
現代のニューラルTTSシステムは、一般的に以下のようなパイプラインをたどります。
発音にとって重要なコンポーネントは、Grapheme-to-Phoneme(G2P:書記素から音素への変換)です。ここでシステムは、各単語をどう発音するかを決定します。G2Pモデルは、辞書やテキストコーパスでトレーニングされているため、「一般的」な発音は学習していますが、以下のようなケースで苦戦します。
- 未知の単語(Out-of-vocabulary words): トレーニングデータに含まれない名前、ブランド名、造語
- 同綴異義語(Heteronyms): 文脈によって発音が異なる、同じ綴りの単語
- ドメイン固有の用語: 技術専門用語、頭字語、略語
なぜニューラルTTSではこれがより困難なのか
皮肉なことに、現代のニューラルTTSシステムは、古い連結合成システムよりも発音問題を悪化させることがあります。
その理由は以下の通りです。
- End-to-End学習: ニューラルモデルは発音を暗黙的に学習するため、特定の単語を上書きすることが難しくなります。
- 文脈依存: モデルは周囲の単語を考慮するため、予期せぬ発音の変化が起こることがあります。
- ブラックボックスな挙動: 特定の入力に対してモデルがどう発音するかを予測するのが困難です。
これが、明示的な発音制御メカニズムが不可欠である理由です。
発音問題の性質
なぜTTSは固有名詞を誤読するのか
TTSエンジンは膨大なテキストデータセットでトレーニングされていますが、固有名詞の発音にはいくつかの課題があります。
同形異義語(Homographs)
- 例: AI(人名)
- 期待される発音: A-I(エー・アイではなく、アイと発音)
- 実際の発音: “eye”(アイ)または “Aa-ee”(エイ・イー)
頭字語の曖昧さ(Acronym ambiguity)
- 例: GUI
- 期待される発音: G-U-I(ジー・ユー・アイ)
- 実際の発音: “gooey”(グーイー)
ドメイン固有の用語
- 例: NFT
- 期待される発音: N-F-T(エヌ・エフ・ティー)
- 実際の発音: “nft”(ナフトのように一語で発音)
キャラクター名
- 例: Naruto
- 期待される発音: “Nah-roo-toh”(ナルト)
- 実際の発音: “Nah-roo-toe”(ナルトゥ)
最も厄介なケースは、文脈に基づいて発音を変える必要がある単語です。
現実世界への影響
不適切な発音は重大な結果をもたらします。
- ユーザーの混乱: ユーザーは何が言われているのか理解できない可能性があります。
- ブランドの毀損: 自社製品の名前を誤読することはプロフェッショナルに見えません。
- アクセシビリティの問題: アクセシビリティのためにTTSを利用しているユーザーが最も影響を受けます。
- 没入感の喪失: エンターテインメントアプリケーションにおいて、誤った発音は体験を台無しにします。
具体例:「AI」の発音問題
「AI」の問題を詳しく見てみましょう。文字列「AI」は文脈に応じて異なる発音を必要とします。
文脈1: 人工知能(Artificial Intelligence)
Input: "AI is transforming the world"
Expected: "A.I. is transforming the world" (pronounced as initialism)文脈2: 日本人の名前(「あい」)
Input: "AI hoshino is a famous idol"
Expected: "Ai(Ah-ee) Hoshino" is a famous idol" (pronounced as name)文脈3: 私たちのアプリケーション
Input: "AI hoshino is a famous idol"
Problem: TTS says "eye hoshino" or "A.I. hoshino"
We need: "Ai(Ah-ee) Hoshino " (letters spelled out, proper capitalization)課題は、「AI」がトレーニングデータ内で圧倒的に「人工知能(artificial intelligence)」として登場するため、TTSがデフォルトでその発音をしてしまうことです。私たちの特定のユースケース(人名)のために、この挙動を上書きする必要があります。
部分一致(Substring)の問題
もう一つの重要な問題は、部分一致の競合です。以下の辞書エントリを考えてみましょう。
{
"AI": "<<a|i>>",
"AI hoshino": "<<a|i>> Hoshino"
}注意しないと、「AI」が先にマッチしてしまい、「AI hoshino」が「<<a|i>> hoshino」(hが小文字のまま)になってしまう可能性があります。これがパターンの順序が重要である理由です。
解決策:カスタム発音辞書
1. 発音記号(IPA)
国際音声記号(IPA)は正確な発音を提供します。
AI hoshino → /eɪ aɪ hoʊˈʃiːnoʊ/
Get Gaudiy Lab’s stories in your inbox
Join Medium for free to get updates from this writer.
メリット:
- 言語学的に正確
- 言語に依存しない
デメリット:
- 専門知識が必要
- すべてのTTSシステムがIPA入力をサポートしているわけではない
- 言語学者以外にとってメンテナンスが難しい
テキスト前処理(私たちのアプローチ)
TTSに送信する前に、問題のあるテキストを置換します。
text = "AI hoshino is a famous idol"
text = apply_pronunciation_rules(text)
# Result: "<<a|i>> Hoshino is a famous idol"メリット:
- TTS非依存(プロバイダーを変更可能)
- 実装とメンテナンスが簡単
- 再起動なしで動的に更新可能
- 置換ロジックを完全に制御可能
デメリット:
- 複雑なケースにはTTS固有の表記法が必要
- パターンの競合を慎重に扱う必要がある
私たちは、柔軟性、保守性、制御性のバランスが最も良いことから、TTS固有の表記法を用いたテキスト前処理を選択しました。
Cartesiaの音声表記法の理解
Cartesia TTSは、発音を制御するためのいくつかのメカニズムを提供しています。
1. << >> による音の分割
最も便利な機能は、単語を別々の音に分割することです。
"AI" → pronounced as one sound ("eye")
"<<a|i>>" → pronounced as separate letters ("A" then "I")| の文字は異なる音声単位を区切ります。これは頭字語やイニシャリズムに最適です。
2. 強調とペーシング(間)
Cartesiaは句読点を解釈してペーシングを行います。
"Hello, world" → カンマの後で自然な間
"Hello... world" → 三点リーダーで長めの間
"Hello! World!" → 強調した発音3. 特殊文字の処理
いくつかの文字は問題を引き起こすため、削除する必要があります。
DISALLOWED_CHARACTERS = "「」『』()[]{}()"これらの括弧類はTTSモデルを混乱させ、予期せぬ間や発音の変化を引き起こす可能性があります。
実装の詳細
では、実装に入りましょう。完全な発音上書きシステムを構築します。
システムアーキテクチャ
発音辞書のデータ構造
発音辞書は、言語ごとに整理された階層的なJSON構造を使用します。
{
"ja": {
"御社": "おんしゃ",
"弊社": "へいしゃ",
"漢字": "かんじ",
"Gaudiy": "ゴーディ"
},
"en": {
"AI hoshino": "<<a|i>> Hoshino",
"Gaudiy": "Gaudy",
"NFT": "<<n|f|t>>",
"GUI": "<<g|u|i>>",
"API": "<<a|p|i>>"
},
"fr": {
"AI": "a i",
"Gaudiy": "Godi"
},
"es": {
"AI": "a i"
},
"de": {
"AI": "a i"
}
}設計上の決定事項:
- 言語をトップレベルのキーにする: 言語固有の発音を可能にする
- 単純な文字列マッピング: 理解しやすくメンテナンスが容易
- 拡張性: 新しい言語の追加にコードの変更が不要
- 言語ごとのフラットな構造: パターンマッチングを簡素化
重要なルール:長い一致を優先する
これは発音辞書の実装において最も重要な概念です。
問題点
重複するパターンがある場合、適用の順序が結果を決定します。
# Dictionary entries
{
"AI": "<<a|i>>",
"AI hoshino": "<<a|i>> Hoshino"
}シナリオA:短いパターンを先に適用(誤り)
Input: "AI hoshino is a famous idol"
Step 1: Match "AI" → "<<a|i>> hoshino is a famous idol"
Step 2: Match "AI hoshino" → NO MATCH (already replaced!)
Result: "<<a|i>> hoshino is a famous idol" ❌
└── (小文字の "hoshino" になってしまい誤り!)シナリオB:長いパターンを先に適用(正解)
Input: "AI hoshino is a famous idol"
Step 1: Match "AI hoshino" → "<<a|i>> Hoshino is a famous idol"
Step 2: Match "AI" → no remaining matches
Result: "<<a|i>> Hoshino is a famous idol" ✅
└── (適切な大文字化が保持される!)解決策
適用する前に、常にパターンを長さ(降順)でソートします。
sorted_items = sorted(
replacements.items(),
key=lambda x: len(x[0]),
reverse=True # Longest first
)これにより、「AI hoshino」(11文字)が常に「AI」(2文字)よりも先にチェックされることが保証されます。
今後の改善点
計画中の機能強化
- 文脈認識型の発音: NLPを使用して、周囲の単語に基づいて発音を決定する
- ユーザーフィードバックの統合: ユーザーが発音の問題を直接報告できるようにする
- A/Bテスト: ユーザーの一部で発音の変更をテストする
- 辞書の自動提案: ユーザークエリに基づいて新しいエントリを提案するMLモデル
- リアルタイム更新: WebSocketベースで再起動なしに辞書を更新する
今後のアーキテクチャの展望
結論
TTSの発音問題は、ユーザー体験に大きな影響を与えうる共通の課題です。この記事では以下を取り上げました。
重要なポイント
- 問題を理解する: TTSモデルは、あなたのドメインに合わないかもしれない「一般的」な発音を学習しています。
- 適切なアプローチを選ぶ: TTS固有の表記法を用いたテキスト前処理は、柔軟性と保守性の最良のバランスを提供します。
- 正しく実装する: 「長い一致を優先する」ルールは、部分一致の競合を避けるために重要です。
結果
このシステムを実装した後:
- 既知の発音問題に対する精度が100%に
- 前処理のオーバーヘッドは1ミリ秒未満
- GCS(Google Cloud Storage)経由でのダウンタイムゼロの辞書更新
- 言語固有のルールによる多言語サポート
カスタム発音辞書は、私たちのTTSパイプラインの不可欠なコンポーネントとなり、固有名詞やドメイン固有の用語が常に正しく発音されることを保証しています。
この包括的なガイドが、あなた自身のアプリケーションにおけるTTSの発音課題に取り組む助けになることを願っています。質問がある場合や、独自のソリューションを共有したい場合は、お気軽にご連絡ください!
読んでいただきありがとうございました!









