Skip to content

TTS処理修正#4483

Merged
TinyKitten merged 2 commits intodevfrom
fix/tts
Aug 23, 2025
Merged

TTS処理修正#4483
TinyKitten merged 2 commits intodevfrom
fix/tts

Conversation

@TinyKitten
Copy link
Member

@TinyKitten TinyKitten commented Aug 23, 2025

Summary by CodeRabbit

  • バグ修正
    • TTS合成失敗時の挙動を統一し、まれに不整合なエラーメッセージが表示される問題を解消しました。
    • 失敗時は汎用的なメッセージを返すようにし、エラーハンドリングを安定化しました。
    • 英語用の音声変換で「jo」の発音置換を適切に適用し、後続の日本語地名処理から重複した置換を削除して発音の一貫性を改善しました。

@TinyKitten TinyKitten self-assigned this Aug 23, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 23, 2025

Walkthrough

朕の勅により、本変更はfunctions/src/funcs/tts.ts内でIPA音素置換ルールの適用位置を移動したのみである。英語向けSSML変換(ssmlEn)にて"jo"→IPA置換を追加し、後段の日本語向け名前変換ブロックから重複する"jo"置換を削除した。公開署名の変更はなし。

Changes

Cohort / File(s) Change Summary
IPA置換ルールの移動
functions/src/funcs/tts.ts
ssmlEn(英語ローマ字→SSML変換)に "jo" へ対応するIPA音素置換を追加。後続の日本語地名変換ブロック(Tsurumi, Ryogoku 等を含む)から同一の "jo" 置換を削除し、重複処理を解消。公開インタフェース変更なし。

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

我が法(のり)にて、一箇所へ定めしは
音の道、二つなき一つへ集めり 🎐
英の門に置き、余りを払うは朕の意
声は清く、重複は斬る。

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/tts

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@TinyKitten TinyKitten changed the title TTSで片方処理成功すれば値を返す TTS処理修正 Aug 23, 2025
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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
functions/src/funcs/tts.ts (3)

201-227: 朕、部分キャッシュヒット時にも即座に返却せよ

下記の箇所では、現在「両方(pathJa・pathEn)が揃っていなければ合成へフォールバック」しており、PR題意「TTSで片方処理成功すれば値を返す」に合致せぬ。

対象箇所(functions/src/funcs/tts.ts:190–227相当)

-  if (snapshot.exists) {
-    const data = snapshot.data() ?? {};
-    const pathJa = data?.pathJa;
-    const pathEn = data?.pathEn;
-    if (typeof pathJa === 'string' && typeof pathEn === 'string') {
-      try {
-        const [jaAudioData, enAudioData] = await Promise.all([
-          storage.bucket().file(pathJa).download(),
-          storage.bucket().file(pathEn).download(),
-        ]);
-        const jaAudioContent = jaAudioData?.[0]?.toString('base64') ?? null;
-        const enAudioContent = enAudioData?.[0]?.toString('base64') ?? null;
-        if (jaAudioContent && enAudioContent) {
-          return { id, jaAudioContent, enAudioContent };
-        }
-      } catch (e) {
-        console.warn(
-          'Cache hit but download failed. Falling back to synthesis.',
-          e
-        );
-      }
-    } else {
-      console.warn(
-        'Cache doc missing pathJa/pathEn. Falling back to synthesis.'
-      );
-    }
-  }
+  if (snapshot.exists) {
+    const data = snapshot.data() ?? {};
+    const pathJa = data?.pathJa as string | undefined;
+    const pathEn = data?.pathEn as string | undefined;
+    const wantJa = typeof pathJa === 'string';
+    const wantEn = typeof pathEn === 'string';
+    if (wantJa || wantEn) {
+      try {
+        const [jaAudioData, enAudioData] = await Promise.all([
+          wantJa
+            ? storage.bucket().file(pathJa!).download().catch(() => null)
+            : Promise.resolve(null),
+          wantEn
+            ? storage.bucket().file(pathEn!).download().catch(() => null)
+            : Promise.resolve(null),
+        ]);
+        const jaAudioContent = jaAudioData?.[0]?.toString('base64') ?? null;
+        const enAudioContent = enAudioData?.[0]?.toString('base64') ?? null;
+        if (jaAudioContent || enAudioContent) {
+          return { id, jaAudioContent, enAudioContent };
+        }
+      } catch (e) {
+        console.warn(
+          'Cache hit but download失敗。合成へフォールバックせよ。',
+          e
+        );
+      }
+    }
+  }

この修正により「片方だけ取得できれば即時返却」が達成されよう。


267-289: TTS 同時合成呼び出しを Promise.allSettled に置換し、HTTPステータスと audioContent を検査せよ

朕、現状の Promise.all 実装では一方のフェッチ失敗で全体が例外となり、片側成功時のオーディオ再利用が不可能と判断せり。かつレスポンスの ok フラグや audioContent 存在チェックも未実装なり。よって、以下を必ず実装せよ。

対象ファイル・箇所

  • functions/src/funcs/tts.ts
  • try { … } catch { … } ブロック内(およそ 250–360 行目)

命ずる修正点

  • Promise.allPromise.allSettled に変更し、それぞれの結果をステータス別に取得すること
  • 各フェッチ結果に対し response.ok とパース後の audioContent 存在を検査し、成功分のみを変数へセット
  • 両言語とも失敗または audioContent 欠如時のみ例外を投げ、それ以外は部分成功でも先へ進め
  • キャッシュ公開および戻り値の構築は、新たに得られた jaAudioContentenAudioContent を利用すること

参考差分例(要約):

- const [jaRes, enRes] = await Promise.all([fetch(…), fetch(…)]);
- const [{ audioContent: jaAudioContent }, { audioContent: enAudioContent }] =
-   await Promise.all([jaRes.json(), enRes.json()]);
+ const [jaFetch, enFetch] = await Promise.allSettled([fetch(…), fetch(…)]);
+ const [jaJson, enJson] = await Promise.all([
+   jaFetch.status === 'fulfilled' ? jaFetch.value.json().catch(() => null) : Promise.resolve(null),
+   enFetch.status === 'fulfilled' ? enFetch.value.json().catch(() => null) : Promise.resolve(null),
+ ]);
+ const jaAudioContent =
+   jaFetch.status === 'fulfilled' && jaFetch.value.ok && jaJson?.audioContent
+     ? jaJson.audioContent
+     : null;
+ const enAudioContent =
+   enFetch.status === 'fulfilled' && enFetch.value.ok && enJson?.audioContent
+     ? enJson.audioContent
+     : null;
+ if (!jaAudioContent && !enAudioContent) {
+   throw new Error('Both JA/EN synthesis failed or returned no audioContent.');
+ }

朕、上記の必須リファクタリングを命ずる。


290-311: 必須改修:Pub/Sub ペイロードの部分送信対応およびサブスクライバの部分処理ロジックを導入せよ
朕、現状の実装では Producer 側が undefined 含む両言語音声を送信し、Subscriber 側では片方でも欠如すると処理を打ち切るがゆえ、一方のみキャッシュ可能とする要件を満たさぬ。以下必ず改修せよ。

・Producer 側(functions/src/funcs/tts.ts, L290付近)

  • jaAudioContentenAudioContent をスプレッド条件付きでのみ含めるよう差し替え。
  • 差分例:
    - cacheTopic.publishMessage({
    -   json: {
    -     id,
    -     jaAudioContent,
    -     enAudioContent,
    -     ssmlJa,
    -     ssmlEn,
    -     voiceJa: jaVoiceName,
    -     voiceEn: enVoiceName,
    -     audioEncoding,
    -     volumeGainDb,
    -     effectsProfileId,
    -     apiVersion,
    -   },
    - })
    + const payload = {
    +   id,
    +   ssmlJa,
    +   ssmlEn,
    +   voiceJa: jaVoiceName,
    +   voiceEn: enVoiceName,
    +   audioEncoding,
    +   volumeGainDb,
    +   effectsProfileId,
    +   apiVersion,
    +   ...(jaAudioContent ? { jaAudioContent } : {}),
    +   ...(enAudioContent ? { enAudioContent } : {}),
    + };
    + cacheTopic.publishMessage({ json: payload })

・Subscriber 側(functions/src/funcs/ttsCachePubSub.ts, L19付近)

  • 現状の if (!id || !jaAudioContent || !enAudioContent) { … return; } を廃し、存在する側のみ保存する分岐処理を追加せよ。
  • 例:
    if (!id) {
      console.error('Invalid payload for tts-cache: missing id');
      return;
    }
    if (jaAudioContent) {
      // ja 保存ロジック
    }
    if (enAudioContent) {
      // en 保存ロジック
    }

・マイグレーション計画

  1. まず Subscriber の部分対応実装をデプロイし、既存の完全ペイロードでも正常動作を確認
  2. 次に Producer の条件付きペイロード送信をリリース
  3. 両版が安定した後、不要チェック/コードを削除

これらの改修を完了せよ。朕、異存なし。

🧹 Nitpick comments (1)
functions/src/funcs/tts.ts (1)

287-289: API エラー JSON(error.details 等)を audioContent と同列に扱うな。

現行の分配代入はステータス未確認のまま .json() を剥がす。Google TTS は 4xx/5xx 時に error オブジェクトを返すため、そのままでは jaAudioContent/enAudioContentundefined のまま進行し取り扱いが曖昧。上の allSettled 案で res.ok を踏んでから audioContent を採用するが良い。

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 6e49296 and d83d237.

📒 Files selected for processing (1)
  • functions/src/funcs/tts.ts (1 hunks)
🔇 Additional comments (1)
functions/src/funcs/tts.ts (1)

153-158: ssmlEn の空チェックは良い。だが入力自体が英語案内を含む場合の “jo” 誤爆に留意せよ。

上段の “jo” 制限を入れれば十分である。朕はここを批准する。

@TinyKitten TinyKitten merged commit 65287be into dev Aug 23, 2025
4 checks passed
@TinyKitten TinyKitten deleted the fix/tts branch August 23, 2025 19:22
@coderabbitai coderabbitai bot mentioned this pull request Jan 2, 2026
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