Skip to content

TTS合成をNeural2に切り替え、nameIpa削除、バリデーション強化#5598

Merged
TinyKitten merged 1 commit intodevfrom
feature/tts-neural2-cleanup
Mar 15, 2026
Merged

TTS合成をNeural2に切り替え、nameIpa削除、バリデーション強化#5598
TinyKitten merged 1 commit intodevfrom
feature/tts-neural2-cleanup

Conversation

@TinyKitten
Copy link
Member

@TinyKitten TinyKitten commented Mar 14, 2026

Summary

  • TTS合成をGemini TTSからCloud Text-to-Speech Neural2に切り替え
  • プロンプト機能を全面削除(Cloud Function、クライアント双方)
  • ボイス名のデフォルト値をJA/EN個別に定数化(JA: ja-JP-Neural2-B、EN: en-US-Neural2-F
  • Cloud Function側でボイス名・テキストのバリデーション(空白トリム、バイト長制限、SSMLタグ除去後の空テキスト拒否)を追加
  • getTtsConfig にエラー時キャッシュフォールバックを導入
  • wrapPhoneme にXMLエスケープを追加しSSMLインジェクションを防止
  • #5594で追加したTrainType/TrainTypeNestedのnameIpaクエリを削除(GraphQLスキーマ未実装のため)
  • trainType未設定時のLocalフォールバックが効くようnull合体演算子を論理ORに修正

Test plan

  • npm run typecheck パス
  • npm run lint パス
  • npm test 全137 suites / 1281 tests パス
  • Neural2ボイスでTTS再生が正常に動作することを確認
  • TrainTypeにnameIpaを参照していた箇所でクラッシュしないことを確認

🤖 Generated with Claude Code

Summary by CodeRabbit

リリースノート

  • 新機能

    • IPA音声記号対応により、駅名・路線名の発音がより正確になりました。
  • 変更

    • TTS音声エンジンをGeiminiからNeural2に切り替えました。
    • 設定画面のTTS音声選択とプロンプトカスタマイズ機能を削除しました。
    • デフォルトTTS音声を日本語・英語別に更新しました。

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 14, 2026

📝 Walkthrough

Walkthrough

TTS(テキスト音声合成)バックエンドを Gemini から Neural2 に移行し、プロンプト機能を削除。GraphQL 型に IPA表記フィールドを追加し、言語別の音声設定を導入。TTS テンプレートに音素ラッピング機能を実装。

Changes

コホート / ファイル 要約
TTS バックエンド統合
functions/src/funcs/tts.ts
Gemini TTS から Neural2 TTS へ移行。プロンプトパラメータを削除し、ssml ペイロード利用に統一。言語別デフォルトボイス定数に対応。キャッシュキーのバージョン番号を 10 から 11 へ更新。
TTS 定数と設定
src/constants/tts.ts, src/store/atoms/tuning.ts
DEFAULT_TTS_VOICE_NAMEDEFAULT_JA_TTS_VOICE_NAMEDEFAULT_EN_TTS_VOICE_NAME に分割。TuningState から ttsJaPromptttsEnPrompt を削除。
GraphQL 型定義拡張
src/@types/graphql.d.ts, src/lib/graphql/queries.ts
LineLineNestedStationStationNested 型と複数のフラグメントに nameIpa フィールドを追加。関連するクエリで IPA フィールドをリクエスト。
TTS フック更新
src/hooks/useTTS.ts, src/hooks/useTTSText.ts, src/utils/ttsSpeechFetcher.ts
プロンプト処理を削除し、ボイス名ベースの処理に統一。useTTSText に音素ラッピング(wrapPhoneme)を導入して station/line 名の IPA 対応。キャッシュキー生成からプロンプト削除。
UI コンポーネント簡略化
src/components/TuningSettings.tsx, src/constants/asyncStorage.ts
TTS 音声選択・プロンプト編集 UI を削除。AsyncStorage キー TTS_JA_PROMPTTTS_EN_PROMPT を廃止。
音素ユーティリティ
src/utils/phoneme.ts
新規作成。XML エスケープ関数と wrapPhoneme 関数を実装。IPA 表記がある場合は SSML 音素タグを生成。
テストフィクスチャー更新
src/__fixtures__/line.ts, src/hooks/useGetStationsWithTermination.test.tsx, src/hooks/useRefreshStation.test.tsx, src/utils/__fixtures__/search.ts, src/utils/test/factories.ts, src/hooks/useTransferLinesFromStation.test.tsx
Line および Station フィクスチャーに nameIpa: null を追加。テスト用ファクトリーも同様に更新。
JR 線オブジェクト更新
src/utils/jr.ts
JR 線情報に nameIpa: null フィールドを追加。既存の nameKatakananameRomannameShort フィールドを明示的に指定。

Sequence Diagram

sequenceDiagram
    actor User
    participant React as React Component<br/>(useTTSText)
    participant Hook as TTS Hook<br/>(useTTS)
    participant Cache as Cache &<br/>Fetcher
    participant Function as Cloud Function<br/>(functions/tts)
    participant API as Text-to-Speech API<br/>(Neural2)

    User->>React: Trigger announcement
    React->>React: Generate TTS text<br/>with wrapPhoneme(nameRoman, nameIpa)
    React->>Hook: Fetch speech audio<br/>(voiceName, ssml only)
    Hook->>Cache: Check cache key<br/>(voice, ssml, version)
    alt Cache Hit
        Cache-->>Hook: Cached audio
    else Cache Miss
        Hook->>Function: POST with ssml payload<br/>(no prompts)
        Function->>Function: Validate text byte limit<br/>per language
        Function->>Function: Build ssml with<br/>phoneme tags
        Function->>API: synthesizeWithNeural2<br/>(ssml, voiceName)
        API-->>Function: Audio bytes
        Function-->>Hook: Audio response
        Hook->>Cache: Store in cache<br/>(version: 11)
    end
    Cache-->>React: Audio stream
    React-->>User: Play announcement
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

react, functions

Poem

🐰 Neural2 へ優雅に移ろい
プロンプトは消え、IPA が歌う
音素でラップされた駅名よ
キャッシュは軽く、キーは短く
ウサギの耳も音の美しさに
ぴょんぴょんと喜ぶ

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed タイトルは、Neural2への切り替え、nameIpaの削除、バリデーション強化という3つの主要な変更を簡潔に要約しており、プルリクエストの主要な変更内容を明確に反映しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/tts-neural2-cleanup
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@TinyKitten TinyKitten self-assigned this Mar 14, 2026
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@functions/src/funcs/tts.ts`:
- Line 139: The code currently passes client-provided raw SSML (input.ssml /
ssml: text) directly to the TTS synth without sanitization; update the TTS
path(s) (references: input.ssml, variable text and the call sites around the
noted ranges 139, 245-258, 338-339) to validate and enforce a strict SSML
policy: parse the SSML server-side (XML/HTML parser), enforce a tag/attribute
allowlist, strip or reject any disallowed tags/attributes, and enforce a
byte-length limit (and overall visible-text non-empty check) before forwarding
to the synth; for trusted flows consider building canonical SSML server-side
instead of trusting raw input and return a clear validation error for rejects.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4010b522-83b1-41b4-bd51-5492c03ccc96

📥 Commits

Reviewing files that changed from the base of the PR and between e02c6f7 and 4e373a1.

📒 Files selected for processing (18)
  • functions/src/funcs/tts.ts
  • src/@types/graphql.d.ts
  • src/__fixtures__/line.ts
  • src/components/TuningSettings.tsx
  • src/constants/asyncStorage.ts
  • src/constants/tts.ts
  • src/hooks/useGetStationsWithTermination.test.tsx
  • src/hooks/useRefreshStation.test.tsx
  • src/hooks/useTTS.ts
  • src/hooks/useTTSText.ts
  • src/hooks/useTransferLinesFromStation.test.tsx
  • src/lib/graphql/queries.ts
  • src/store/atoms/tuning.ts
  • src/utils/__fixtures__/search.ts
  • src/utils/jr.ts
  • src/utils/phoneme.ts
  • src/utils/test/factories.ts
  • src/utils/ttsSpeechFetcher.ts
💤 Files with no reviewable changes (1)
  • src/constants/asyncStorage.ts

@TinyKitten TinyKitten merged commit b13c7a4 into dev Mar 15, 2026
7 checks passed
@TinyKitten TinyKitten deleted the feature/tts-neural2-cleanup branch March 15, 2026 00:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant