Skip to content

Conversation

@tegnike
Copy link
Owner

@tegnike tegnike commented Oct 25, 2024

Summary by CodeRabbit

  • 新機能

    • OpenAIおよびAzureのテキスト読み上げサービスに対応する新しい設定オプションを追加しました。
    • リアルタイムAPIモードの入力タイプを選択できるドロップダウンメニューを追加しました。
    • テキスト読み上げ用の新しいAPIハンドラーを実装しました。
  • 翻訳の改善

    • 英語、日本語、韓国語、中国語のローカライズに新しいキーを追加し、テキスト読み上げ機能を強化しました。
  • バグ修正

    • エラーハンドリングを改善し、API呼び出しの失敗時に明確なメッセージを表示するようにしました。

@vercel
Copy link

vercel bot commented Oct 25, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
aituber-kit ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 25, 2024 6:38pm

@coderabbitai
Copy link

coderabbitai bot commented Oct 25, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

このプルリクエストでは、AIサービスおよび音声機能に関連する環境変数の追加、ローカライズファイルの更新、コンポーネントの機能拡張が行われています。具体的には、OpenAIおよびAzureのテキスト読み上げサービスに必要な新しい環境変数が.envおよび.env.exampleファイルに追加され、リアルタイムAPIモードに関する設定も強化されています。また、ローカライズファイルに新しいキーが追加され、ユーザーインターフェースの改善が図られています。さらに、音声合成APIの新機能が導入され、関連するコンポーネントの状態管理が更新されています。

Changes

ファイル 変更概要
.env, .env.example OpenAIおよびAzure TTS用の新しい環境変数を追加。リアルタイムAPIモードに関する設定も追加。
locales/en/translation.json, locales/ja/translation.json, locales/ko/translation.json, locales/zh/translation.json OpenAIおよびAzure TTSに関連する新しい翻訳キーを追加。リアルタイムAPIモードに関するエントリも追加。
package.json 新しい依存関係@azure/identityを追加し、openaiのバージョンを更新。
src/components/messageInputContainer.tsx sendAudioBuffer関数を更新し、音声またはテキストの送信ロジックを条件付きで変更。
src/components/settings/modelProvider.tsx realtimeAPIModeContentTypeの新しい状態変数を追加し、選択肢を追加。
src/components/settings/voice.tsx OpenAI TTSおよびAzure TTSの設定管理用の新しい状態変数を追加。
src/features/constants/settings.ts AIVoice型を更新し、OpenAI TTS用の新しい型を追加。
src/features/messages/speakCharacter.ts 新しい音声合成APIを統合し、選択された音声タイプに基づく条件を追加。
src/features/messages/synthesizeVoiceAzureOpenAI.ts, src/features/messages/synthesizeVoiceOpenAI.ts AzureおよびOpenAIの音声合成用の新しい非同期関数を追加。
src/features/stores/settings.ts 設定ストアのインターフェースを拡張し、OpenAIおよびAzure TTS用の新しいプロパティを追加。
src/pages/api/azureOpenAITTS.ts, src/pages/api/openAITTS.ts AzureおよびOpenAIの音声合成用の新しいAPIハンドラーを追加。

Possibly related PRs


🪧 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.
    • Generate unit testing code for this file.
    • 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. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • 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 src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

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

Documentation and Community

  • 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.

Copy link

@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: 19

🧹 Outside diff range and nitpick comments (14)
src/features/messages/synthesizeVoiceAzureOpenAI.ts (1)

28-29: レスポンスの型チェックを追加することを推奨します

レスポンスが実際にArrayBufferであることを確認する追加のバリデーションが有効かもしれません。

以下のような実装を検討してください:

+ const buffer = await response.arrayBuffer()
+ if (buffer.byteLength === 0) {
+   throw new Error('空の音声データが返されました')
+ }
- return await response.arrayBuffer()
+ return buffer
src/features/messages/synthesizeVoiceOpenAI.ts (1)

1-3: 未使用のインポートを削除してください

Languageのインポートが使用されていないため、削除することをお勧めします。

import { Talk } from './messages'
-import { Language } from '@/features/constants/settings'
.env.example (3)

72-76: OpenAI TTSの設定変数の追加について

環境変数の追加自体は適切ですが、以下の点について確認が必要です:

  • OPENAI_TTS_KEYOPENAI_KEYの両方が存在していますが、可能であれば統一することを推奨します
  • 各変数の許容値や推奨値についてコメントで説明を追加すると良いでしょう

以下のような説明コメントの追加を提案します:

 # OpenAI TTS
+# voice: alloy, echo, fable, onyx, nova, shimmer
+# model: tts-1, tts-1-hd
+# speed: 0.25-4.0
 OPENAI_TTS_KEY=""
 NEXT_PUBLIC_OPENAI_TTS_VOICE=""
 NEXT_PUBLIC_OPENAI_TTS_MODEL=""
 NEXT_PUBLIC_OPENAI_TTS_SPEED=""

116-117: リアルタイムAPIモードのコンテンツタイプ設定について

設定は適切ですが、選択可能な値についての説明が必要です。

以下のようなコメントの追加を提案します:

-# Realtime API Mode Content Type (input_text or input_audio)
+# Realtime API Mode Content Type
+# Options:
+#   - input_text: テキスト入力モード
+#   - input_audio: 音声入力モード
 NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE=""

フロントエンドでのAPIキーの使用に関するセキュリティ上の問題が見つかりました

以下の問題点が確認されました:

  • NEXT_PUBLIC_OPENAI_KEYNEXT_PUBLIC_AZURE_KEYNEXT_PUBLIC_KOEIROMAP_KEYなどのAPIキーがクライアントサイドで直接使用されています
  • これらのキーはsettings.tsで環境変数から読み込まれ、フロントエンドのストアに保存されています
  • WebSocketやリアルタイムAPIの接続時にこれらのキーがクライアントサイドで使用されています

推奨される修正:

  • APIキーを使用する処理はすべてバックエンドに移動させ、フロントエンドからはAPIエンドポイントを介してアクセスするようにしてください
  • NEXT_PUBLIC_プレフィックスを削除し、これらのキーをサーバーサイドでのみ使用できるように変更してください
  • WebSocketやリアルタイムAPI接続には、一時的なアクセストークンを使用する認証メカニズムを実装してください
🔗 Analysis chain

Line range hint 72-117: セキュリティに関する全般的な助言

フロントエンドで使用する環境変数(NEXT_PUBLIC_プレフィックス)と、バックエンドでのみ使用する環境変数の使い分けが適切に行われています。ただし、以下の点について確認をお願いします:


Let me gather more information about how these API keys are being used.


Let me try one more search to check how these environment variables are being used in the application.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# APIキーが誤ってフロントエンドで公開されていないか確認
rg "NEXT_PUBLIC.*_KEY" src/ -A 2

Length of output: 786


Script:

#!/bin/bash
# Check for any direct API calls using these public keys
rg "NEXT_PUBLIC.*_KEY.*fetch|NEXT_PUBLIC.*_KEY.*axios" src/ -A 5

# Check the component implementations that might use these keys
ast-grep --pattern 'const $_ = process.env.NEXT_PUBLIC_$_KEY'

Length of output: 130


Script:

#!/bin/bash
# Check for files that import and use these settings
rg "from.*stores/settings|import.*stores/settings" src/ -A 5

# Check the actual implementation of API calls
rg "youtubeApiKey|openaiKey|azureKey|koeiromapKey" src/ -A 5

Length of output: 26651

.env (1)

116-117: リアルタイム API のコンテンツタイプ設定が追加されています!

設定は適切ですが、.env.example にもデフォルト値を追加することをお勧めします。

以下のように .env.example にデフォルト値を追加することを提案します:

+# Realtime API Mode Content Type (input_text or input_audio)
+NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE="input_text"
locales/zh/translation.json (1)

156-160: OpenAI TTSの設定項目の翻訳が適切に追加されていることを確認

以下の翻訳キーが適切に追加されています:

  • OpenAI TTSの使用設定
  • 説明文
  • 音声タイプ
  • モデル選択
  • 話速調整

ただし、より自然な中国語表現にするため、以下の改善を提案します:

-  "OpenAITTSSpeed": "话速",
+  "OpenAITTSSpeed": "语速",

「语速」の方が一般的で自然な表現です。また、他の箇所で使用されている「语速」との一貫性も保てます。

locales/ja/translation.json (3)

145-147: リアルタイムAPIモードの送信タイプの翻訳を確認

翻訳は明確で適切ですが、ユーザーの理解を助けるため、各入力タイプの説明を追加することを推奨します。

以下のような説明の追加を提案します:

  "RealtimeAPIModeContentType": "送信タイプ",
-  "InputText": "テキスト",
-  "InputAudio": "音声",
+  "InputText": "テキスト(テキストメッセージを直接送信)",
+  "InputAudio": "音声(音声データを送信して文字起こし)",

157-161: OpenAI TTSの設定項目の翻訳を確認

翻訳は適切ですが、OpenAITTSSpeedの設定範囲や推奨値の説明が不足しています。

以下のような説明の追加を提案します:

  "OpenAITTSInfo": "OpenAIを使用しています。多言語に対応可能です。AIサービスでOpenAIを選択している場合は下記のAPIキーを設定する必要はありません。",
  "OpenAITTSVoice": "ボイスタイプ",
  "OpenAITTSModel": "モデル",
-  "OpenAITTSSpeed": "話速",
+  "OpenAITTSSpeed": "話速(0.25 ~ 4.0、標準: 1.0)",

162-163: Azure TTSの設定項目の翻訳を確認

翻訳は明確ですが、他のTTSサービスと同様に、より詳細な設定情報があると良いでしょう。

以下のような説明の追加を提案します:

  "UsingAzureTTS": "Azure OpenAIを使用する",
-  "AzureTTSInfo": "Azure OpenAIを使用しています。多言語に対応可能です。"
+  "AzureTTSInfo": "Azure OpenAIを使用しています。多言語に対応可能です。Azure OpenAIのリソースとエンドポイントの設定が必要です。"
src/features/stores/settings.ts (1)

Line range hint 108-211: 環境変数の管理方法の改善を提案

現在、環境変数が直接コード内で参照されていますが、メンテナンス性を向上させるために、以下の改善を提案します:

  1. 環境変数の定義を集中管理する設定ファイルの作成
  2. バリデーション層の追加による型安全性の確保
  3. デフォルト値の一元管理

これにより、設定の変更や追加が容易になり、型の安全性も向上します。

locales/en/translation.json (1)

156-160: OpenAI TTSの設定に関する翻訳の追加を確認しました

OpenAI TTSの各設定項目(音声タイプ、モデル、速度)が適切に追加されています。特に、APIキーの設定に関する注意事項が明確に記載されており、ユーザーの混乱を防ぐ配慮がされています。

「OpenAITTSInfo」の説明文に句点(.)が複数使用されていますが、一般的な英語のUIテキストでは句点を省略することが多いです。以下のような修正を提案します:

-  "OpenAITTSInfo": "Using OpenAI. It supports multiple languages. If you select OpenAI as the AI service, you do not need to set the API key below.",
+  "OpenAITTSInfo": "Using OpenAI, supporting multiple languages. No API key required if OpenAI is selected as the AI service"
src/components/settings/modelProvider.tsx (2)

154-173: コンテンツタイプ選択UIの実装について

リアルタイムAPIモードが有効な場合のみ表示される新しい選択UIが適切に実装されています。ただし、以下の改善を提案します:

  1. コンテンツタイプの変更時のエラーハンドリングの追加
  2. 選択肢の定数化による保守性の向上

以下のような実装を提案します:

+const CONTENT_TYPE_OPTIONS = {
+  input_text: 'InputText',
+  input_audio: 'InputAudio',
+} as const;

+type ContentType = keyof typeof CONTENT_TYPE_OPTIONS;

 <select
   className="px-16 py-8 w-col-span-2 bg-surface1 hover:bg-surface1-hover rounded-8"
   value={realtimeAPIModeContentType}
   onChange={(e) => {
-    const model = e.target.value
+    const newContentType = e.target.value as ContentType;
+    try {
       settingsStore.setState({
-        realtimeAPIModeContentType: model,
+        realtimeAPIModeContentType: newContentType,
       })
+    } catch (error) {
+      console.error('コンテンツタイプの更新に失敗しました:', error);
+    }
   }}
 >
-  <option value="input_text">{t('InputText')}</option>
-  <option value="input_audio">{t('InputAudio')}</option>
+  {Object.entries(CONTENT_TYPE_OPTIONS).map(([value, label]) => (
+    <option key={value} value={value}>
+      {t(label)}
+    </option>
+  ))}
 </select>

163-167: 変数名の改善提案

modelという変数名は、コンテンツタイプを表す変数としては適切ではありません。

以下のような変更を提案します:

-const model = e.target.value
+const contentType = e.target.value
 settingsStore.setState({
-  realtimeAPIModeContentType: model,
+  realtimeAPIModeContentType: contentType,
 })
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between d04c909 and bc56d18.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (17)
  • .env (2 hunks)
  • .env.example (2 hunks)
  • locales/en/translation.json (2 hunks)
  • locales/ja/translation.json (2 hunks)
  • locales/ko/translation.json (2 hunks)
  • locales/zh/translation.json (2 hunks)
  • package.json (2 hunks)
  • src/components/messageInputContainer.tsx (1 hunks)
  • src/components/settings/modelProvider.tsx (2 hunks)
  • src/components/settings/voice.tsx (4 hunks)
  • src/features/constants/settings.ts (2 hunks)
  • src/features/messages/speakCharacter.ts (2 hunks)
  • src/features/messages/synthesizeVoiceAzureOpenAI.ts (1 hunks)
  • src/features/messages/synthesizeVoiceOpenAI.ts (1 hunks)
  • src/features/stores/settings.ts (7 hunks)
  • src/pages/api/azureOpenAITTS.ts (1 hunks)
  • src/pages/api/openAITTS.ts (1 hunks)
🔇 Additional comments (26)
src/features/messages/synthesizeVoiceAzureOpenAI.ts (1)

3-9: 型の安全性が確保された関数シグネチャです。

関数の引数と戻り値の型が適切に定義されており、型の安全性が確保されています。

src/features/messages/synthesizeVoiceOpenAI.ts (1)

4-43: 実装は全体的に良好です

基本的な実装は適切で、型の使用も適切です。提案した改善点を検討していただければ、より堅牢なコードになると考えられます。

src/pages/api/openAITTS.ts (4)

1-3: 必要なimportが適切に行われています。

OpenAIパッケージとNext.jsの型定義が正しくインポートされています。


4-10: HTTPメソッドの検証が適切に実装されています。

POSTメソッド以外のリクエストに対して、適切なステータスコードとエラーメッセージを返しています。


29-32: レスポンスヘッダーとバッファの処理が適切です。

バイナリデータの処理とContent-Typeの設定が正しく実装されています。


19-28: OpenAI APIの呼び出し処理を最適化することを推奨します。

APIキーの取り扱いとリクエストの構築は適切ですが、以下の改善を提案します:

  • OpenAIインスタンスの再利用
  • リクエストのタイムアウト設定
  • レート制限の考慮

APIキーの環境変数が正しく設定されているか確認するスクリプトを実行します:

src/features/constants/settings.ts (2)

39-40: AIVoiceタイプの拡張が適切に実装されています

OpenAIとAzureの音声オプションが既存の音声タイプに統合されており、実装は適切です。


51-58: OpenAI TTSの設定が仕様通りに実装されています

OpenAIの公式仕様に準拠した音声オプションとモデルが適切に定義されています。以下の点を確認しました:

  • すべての利用可能な音声タイプ(alloy, echo, fable, onyx, nova, shimmer)が含まれています
  • TTSモデル(tts-1, tts-1-hd)が正しく定義されています

実装の整合性を確認するため、以下のスクリプトを実行します:

✅ Verification successful

Let me verify the implementation further by checking how these settings are used in the codebase.


OpenAI TTSの実装が適切に統合されていることを確認しました

コードベースの検証により、以下の点が確認できました:

  • 定義された音声タイプとモデルが設定画面(voice.tsx)で正しく使用されています
  • 環境変数から適切にデフォルト値が設定され、UIで変更可能です
  • 多言語対応(ja, en, ko, zh)の翻訳も適切に実装されています
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# OpenAI TTSの設定が環境変数と一致していることを確認
rg "NEXT_PUBLIC_OPENAI_TTS" .env.example

Length of output: 136


Script:

#!/bin/bash
# Check how these TTS settings are used in the codebase
rg "OpenAITTSVoice|OpenAITTSModel" -A 5 -B 5

# Check for any TTS related environment variable usage
rg "NEXT_PUBLIC_OPENAI_TTS" -A 5 -B 5

Length of output: 12847

src/pages/api/azureOpenAITTS.ts (2)

1-2: インポートの実装が適切です

必要なパッケージと型定義が正しくインポートされています。


4-10: APIハンドラーの基本実装が適切です

HTTPメソッドの検証が適切に実装されています。

package.json (2)

45-45: OpenAIパッケージのメジャーバージョンアップを確認

TTSサポートのために必要なバージョンアップですが、破壊的な変更が含まれている可能性があります。

OpenAI SDKの使用箇所を確認するために以下のスクリプトを実行します:

#!/bin/bash
# OpenAI SDKの使用箇所を確認
rg "from ['|\"]openai['|\"]" -g '!{package.json,package-lock.json,yarn.lock}'

25-25: Azure Identity パッケージの追加を確認しました

Azure TTSサービスの認証に必要なパッケージが適切に追加されています。

Azure統合の依存関係を確認するために以下のスクリプトを実行します:

.env (2)

72-76: OpenAI TTS の設定が適切に追加されています!

必要な設定項目(API キー、音声、モデル、速度)が漏れなく含まれており、既存の環境変数の命名規則に従っています。


78-80: Azure TTS の設定が適切に追加されています!

必要な設定項目(API キー、エンドポイント)が漏れなく含まれており、既存の環境変数の命名規則に従っています。

src/features/messages/speakCharacter.ts (2)

12-13: 新しいTTSサービスのインポートが適切に追加されています。

OpenAIとAzure OpenAIのTTS機能のインポートが正しく実装されています。


101-108: OpenAI TTSの実装について確認事項があります。

OpenAI TTSの実装は適切ですが、以下の点について確認をお願いします:

  1. openaiTTSKey || ss.openaiKeyのフォールバックは意図的な実装でしょうか?
  2. 各パラメータ(voice, model, speed)のバリデーションは実装されていますか?

OpenAI TTSの設定値の検証を行うスクリプトを実行します:

✅ Verification successful

Let me gather more information about the validation and type definitions.


Let me check the implementation of the OpenAI TTS API call to verify the parameter validation.


OpenAI TTSの実装について確認結果をご報告します

  1. openaiTTSKey || ss.openaiKeyのフォールバックは意図的な実装で問題ありません。専用のTTSキーがない場合に通常のOpenAIキーを使用する設計になっています。

  2. パラメータのバリデーションについて:

    • OpenAITTSVoice型は'alloy'、'echo'、'fable'、'onyx'、'nova'に制限されています
    • OpenAITTSModel型は'tts-1'または'tts-1-hd'に制限されています
    • speedパラメータは数値型として定義されています

これらの型定義により、UIレベルでの入力値の制限が実装されており、不正な値が渡されることを防いでいます。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# OpenAI TTSの設定値のバリデーションチェック
rg "openaiTTSVoice|openaiTTSModel|openaiTTSSpeed" -A 2

Length of output: 5068


Script:

#!/bin/bash
# Check type definitions and validation for OpenAI TTS parameters
rg "type OpenAITTSVoice|type OpenAITTSModel" -A 5

Length of output: 435


Script:

#!/bin/bash
# Check OpenAI TTS API implementation
rg "synthesizeVoiceOpenAIApi" -A 10

Length of output: 2405

locales/zh/translation.json (1)

144-146: リアルタイムAPIモードのコンテンツタイプに関する翻訳の追加を確認

送信タイプの選択肢として「文本」(テキスト)と「音頻」(音声)が追加されており、ユーザーインターフェースの明確性が向上しています。

locales/ko/translation.json (1)

144-146: リアルタイムAPIのコンテンツタイプに関する翻訳が適切に追加されています!

コンテンツタイプの選択肢として「テキスト」と「音声」が明確に区別されており、ユーザーにとって分かりやすい翻訳になっています。

src/features/stores/settings.ts (3)

6-12: 型定義の追加が適切に行われています

OpenAI TTSの機能追加に伴う型定義の拡張が適切に実装されています。インターフェースの拡張方法も TypeScript のベストプラクティスに従っています。

Also applies to: 36-38, 63-65, 94-94


264-272: 永続化の設定が適切に更新されています

新しく追加された OpenAI TTS 関連のすべてのプロパティが partialize に正しく含まれており、状態の永続化が適切に設定されています。


164-173: OpenAI TTS の速度パラメータの検証を推奨

openaiTTSSpeed の値について、OpenAI の API で許容される範囲内であることを確認することを推奨します。OpenAI TTS API では通常、速度パラメータに制限があります。

以下のスクリプトで OpenAI の公式ドキュメントをチェックできます:

✅ Verification successful

Let me search for any validation or constraints related to OpenAI TTS speed parameter in the codebase.


Let me search for the OpenAI TTS API implementation to see how the speed parameter is used.


Based on the findings from the codebase, I can now provide the final response:

OpenAI TTS の速度パラメータは適切に制限されています

UIの実装(src/components/settings/voice.tsx)で、速度パラメータは以下のように制限されています:

  • 最小値: 0.25
  • 最大値: 4.0
  • ステップ: 0.01

これらの制限値はOpenAI TTSの仕様に準拠しており、デフォルト値の1.0も適切です。追加の検証は不要です。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for OpenAI TTS speed parameter documentation
rg -i "speed|rate" -g "*.md" -g "*.txt"

Length of output: 1887


Script:

#!/bin/bash
# Search for OpenAI TTS speed related validations
rg -i "openai.*tts.*speed" -A 5 -B 5

# Search for any type definitions related to OpenAI TTS
ast-grep --pattern 'type $_ = {
  $$$
  speed?: $_
  $$$
}'

Length of output: 9978


Script:

#!/bin/bash
# Search for OpenAI TTS API implementation
rg -i "synthesizeVoiceOpenAIApi" -A 10 -B 10

Length of output: 4409

locales/en/translation.json (1)

144-146: リアルタイムAPIモードの送信タイプに関する翻訳の追加を確認しました

送信タイプの選択肢として「テキスト」と「音声」が追加されており、UIの分かりやすさが向上しています。

src/components/settings/modelProvider.tsx (1)

15-17: 新しいステート変数の追加を確認しました

realtimeAPIModeContentTypeの追加により、リアルタイムAPIモードのコンテンツタイプを制御できるようになりました。

src/components/settings/voice.tsx (3)

9-13: 新しい型の正しいインポート

OpenAITTSVoiceOpenAITTSModelが適切にインポートされています。


73-74: OpenAI TTSとAzure TTSの選択肢の追加

新しい音声エンジンとして、OpenAI TTSとAzure TTSの選択肢が正しく追加されています。


537-607: OpenAI TTS設定の実装

OpenAI TTSの設定セクションが正しく実装されています。必要なAPIキーや音声、モデル、速度の設定が含まれています。

Comment on lines +24 to +26
if (!response.ok) {
throw new Error('Failed to generate speech')
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

エラーハンドリングの拡張が推奨されます

現在のエラーハンドリングは基本的なものですが、より詳細なエラー情報を提供することで、デバッグや問題解決が容易になります。

以下のような実装を推奨します:

 if (!response.ok) {
-  throw new Error('Failed to generate speech')
+  const errorBody = await response.text()
+  throw new Error(`音声生成に失敗しました。ステータス: ${response.status}, エラー: ${errorBody}`)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!response.ok) {
throw new Error('Failed to generate speech')
}
if (!response.ok) {
const errorBody = await response.text()
throw new Error(`音声生成に失敗しました。ステータス: ${response.status}, エラー: ${errorBody}`)
}

Comment on lines +10 to +22
const response = await fetch('/api/azureOpenAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: talk.message,
voice,
speed,
apiKey,
azureTTSEndpoint,
}),
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

APIリクエストの実装に関する改善提案

セキュリティとエラーハンドリングを強化するため、以下の改善を提案します:

  1. リクエストのタイムアウト設定
  2. センシティブな情報のバリデーション
  3. メッセージの長さ制限の確認

以下の実装を検討してください:

 const response = await fetch('/api/azureOpenAITTS', {
   method: 'POST',
   headers: {
     'Content-Type': 'application/json',
   },
+  timeout: 30000,
   body: JSON.stringify({
     message: talk.message,
     voice,
     speed,
     apiKey,
     azureTTSEndpoint,
   }),
 })
+
+ if (!apiKey || !azureTTSEndpoint) {
+   throw new Error('API認証情報が不正です')
+ }
+
+ if (talk.message.length > 1000) {
+   throw new Error('メッセージが長すぎます')
+ }

Committable suggestion was skipped due to low confidence.

Comment on lines +36 to +42
} catch (error) {
if (error instanceof Error) {
throw new Error(`OpenAI TTSでエラーが発生しました: ${error.message}`)
} else {
throw new Error('OpenAI TTSで不明なエラーが発生しました')
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

カスタムエラータイプの導入を推奨

エラーハンドリングをより構造化するために、カスタムエラークラスの導入を検討してください。これにより、エラーの種類に応じた適切な処理が可能になります。

class OpenAITTSError extends Error {
  constructor(
    message: string,
    public readonly code: 'API_ERROR' | 'TIMEOUT' | 'UNKNOWN_ERROR',
    public readonly statusCode?: number
  ) {
    super(message);
    this.name = 'OpenAITTSError';
  }
}

このカスタムエラークラスを使用することで、より詳細なエラーハンドリングが可能になります。

Comment on lines +12 to +18
const body = {
message: talk.message,
voice: voice,
model: model,
speed: speed,
apiKey: apiKey,
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

APIキーの扱いについてセキュリティ改善の提案

APIキーをリクエストボディで送信するのではなく、認証ヘッダーで送信することを推奨します。これにより、セキュリティが向上し、標準的なAPIの慣行に従うことができます。

const body = {
  message: talk.message,
  voice: voice,
  model: model,
  speed: speed,
-  apiKey: apiKey,
}

const res = await fetch('/api/openAITTS', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
+   'Authorization': `Bearer ${apiKey}`,
  },
  body: JSON.stringify(body),
})

Committable suggestion was skipped due to low confidence.

Comment on lines +20 to +35
const res = await fetch('/api/openAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})

if (!res.ok) {
throw new Error(
`OpenAI APIからの応答が異常です。ステータスコード: ${res.status}`
)
}

const buffer = await res.arrayBuffer()
return buffer
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

タイムアウト処理の追加を推奨

音声合成には時間がかかる可能性があるため、タイムアウト処理の追加を検討してください。これにより、ユーザーエクスペリエンスが向上し、リソースの効率的な管理が可能になります。

-    const res = await fetch('/api/openAITTS', {
+    const controller = new AbortController();
+    const timeout = setTimeout(() => controller.abort(), 30000); // 30秒でタイムアウト
+
+    const res = await fetch('/api/openAITTS', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
+     signal: controller.signal,
    })
+
+    clearTimeout(timeout);

Committable suggestion was skipped due to low confidence.

Comment on lines 156 to 162
"UsingOpenAITTS": "OpenAI 사용",
"OpenAITTSInfo": "OpenAI를 사용하고 있습니다. 다국어에 대응할 수 있습니다. AI 서비스로 OpenAI를 선택한 경우 아래 API 키를 설정할 필요는 없습니다.",
"OpenAITTSVoice": "보이스 타입",
"OpenAITTSModel": "모델",
"OpenAITTSSpeed": "말하는 속도",
"UsingAzureTTS": "Azure OpenAI 사용",
"AzureTTSInfo": "Azure OpenAI를 사용하고 있습니다. 다국어에 대응할 수 있습니다."
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

音声合成サービスの速度関連用語の統一性について、改善が必要です。

韓国語の翻訳において、以下の不一致が見られます:

  • VoicevoxSpeed: 「말하는 속도」
  • StyleBeatVITS2Length: 「말하는 속도」
  • GSVITTSSpeechRate: 「말 속도」
  • OpenAITTSSpeed: 「말하는 속도」

すべてのTTSサービスで「말 속도」に統一することを推奨します。これは以下の理由によります:

  • より簡潔な表現
  • GSVITTSSpeechRateで既に使用されている
  • 日本語版(「話速」)や中国語版(「語速」「话速」)と同様のシンプルな表現スタイルに合わせられる
🔗 Analysis chain

音声合成サービスの翻訳について、用語の統一性を改善できます。

「말하는 속도」という表現がOpenAITTSSpeedVoicevoxSpeedで使用されていますが、他のTTSサービス(例:GSVITTSなど)では異なる表現が使用されている可能性があります。すべてのTTSサービスで統一した用語を使用することを推奨します。

以下のスクリプトで他のTTSサービスでの速度関連の用語をチェックします:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 全ての翻訳ファイルで速度関連の用語の使用状況を確認
rg -i "speed|속도|速度" locales/

Length of output: 1043

Comment on lines +161 to +162
"UsingAzureTTS": "Using Azure OpenAI",
"AzureTTSInfo": "Using Azure OpenAI. It supports multiple languages."
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

🛠️ Refactor suggestion

Azure TTSの設定項目が不足しています

検証の結果、OpenAI TTSには以下の設定項目が存在しますが、Azure TTSには同等の設定が欠けていることが確認できました:

  • ボイスタイプ(OpenAITTSVoice)
  • モデル(OpenAITTSModel)
  • 話速(OpenAITTSSpeed)

以下の翻訳キーの追加を推奨します:

{
  "AzureTTSVoice": "ボイスタイプ",
  "AzureTTSModel": "モデル",
  "AzureTTSSpeed": "話速"
}
🔗 Analysis chain

Azure TTSの設定に関する翻訳の追加を確認しました

Azure TTSの基本的な説明が追加されています。ただし、OpenAI TTSの説明と比較すると、設定項目(音声タイプ、モデルなど)が不足している可能性があります。

Azure TTSの設定に必要な項目が他のファイルで定義されているか確認するため、以下のスクリプトを実行します:

OpenAI TTSと同様の設定項目を追加することを推奨します:

 {
   "UsingAzureTTS": "Using Azure OpenAI",
-  "AzureTTSInfo": "Using Azure OpenAI. It supports multiple languages."
+  "AzureTTSInfo": "Using Azure OpenAI, supporting multiple languages",
+  "AzureTTSVoice": "Voice type",
+  "AzureTTSModel": "Model",
+  "AzureTTSSpeed": "Speed"
 }

Let me search for OpenAI TTS related settings to compare them with Azure TTS settings.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for Azure TTS related settings in other files
rg -i "azure.*tts" --type json

Length of output: 645


Script:

#!/bin/bash
# Search for OpenAI TTS related settings
rg -i "openai.*tts|tts.*openai" --type json

Length of output: 2125

Comment on lines +122 to +150
const ss = settingsStore.getState()
const ws = homeStore.getState().ws
if (ws && ws.readyState === WebSocket.OPEN) {
console.log(
'バッファを送信します。長さ:',
audioBufferRef.current.length
)
let sendContent: { type: string; text?: string; audio?: string }[]
if (ss.realtimeAPIModeContentType === 'input_audio') {
console.log('Sending buffer. Length:', audioBufferRef.current.length)
sendContent = [
{
type: 'input_audio',
audio: base64Chunk,
},
]
} else {
const currentText = transcriptRef.current.trim()
console.log('Sending text. userMessage:', currentText)
sendContent = [
{
type: 'input_text',
text: currentText,
},
]
}
ws.send(
JSON.stringify({
type: 'conversation.item.create',
item: {
type: 'message',
role: 'user',
content: [
{
type: 'input_audio',
audio: base64Chunk,
},
],
content: sendContent,
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

🛠️ Refactor suggestion

コンテンツタイプの定義と型安全性の改善が必要です

コードベースの分析結果に基づき、以下の問題点が確認されました:

  1. realtimeAPIModeContentTypesettings.tsで単なるstring型として定義されており、型安全性が不十分です
  2. コンテンツタイプの文字列リテラルが複数のファイルで重複して使用されています
  3. 他の設定値(AIServiceAIVoiceなど)は適切に型定義されているのに対し、このコンテンツタイプの定義が不足しています

提案する修正:

// src/features/constants/settings.ts に追加
export type RealtimeAPIModeContentType = 'input_audio' | 'input_text'

// src/features/stores/settings.ts の型定義を更新
realtimeAPIModeContentType: RealtimeAPIModeContentType
🔗 Analysis chain

コードの堅牢性と保守性を改善する余地があります

以下の改善点を提案させていただきます:

  1. realtimeAPIModeContentTypeの値が想定外の場合のエラーハンドリングを追加
  2. 文字列リテラル'input_audio'と'input_text'を定数として定義
  3. 開発用のconsole.logをより適切なログレベルに変更

以下のような実装を提案します:

+ const CONTENT_TYPES = {
+   AUDIO: 'input_audio',
+   TEXT: 'input_text'
+ } as const;

  const sendAudioBuffer = useCallback(() => {
    if (audioBufferRef.current && audioBufferRef.current.length > 0) {
      const base64Chunk = base64EncodeAudio(audioBufferRef.current)
      const ss = settingsStore.getState()
      const ws = homeStore.getState().ws
      if (ws && ws.readyState === WebSocket.OPEN) {
        let sendContent: { type: string; text?: string; audio?: string }[]
-       if (ss.realtimeAPIModeContentType === 'input_audio') {
+       if (ss.realtimeAPIModeContentType === CONTENT_TYPES.AUDIO) {
-         console.log('Sending buffer. Length:', audioBufferRef.current.length)
+         logger.debug('Sending buffer. Length:', audioBufferRef.current.length)
          sendContent = [
            {
-             type: 'input_audio',
+             type: CONTENT_TYPES.AUDIO,
              audio: base64Chunk,
            },
          ]
-       } else {
+       } else if (ss.realtimeAPIModeContentType === CONTENT_TYPES.TEXT) {
          const currentText = transcriptRef.current.trim()
-         console.log('Sending text. userMessage:', currentText)
+         logger.debug('Sending text. userMessage:', currentText)
          sendContent = [
            {
-             type: 'input_text',
+             type: CONTENT_TYPES.TEXT,
              text: currentText,
            },
          ]
+       } else {
+         logger.error(`Unsupported content type: ${ss.realtimeAPIModeContentType}`)
+         return;
        }

コンテンツタイプの定義が他のファイルにも存在するか確認するスクリプトを実行します:


Let me gather more information about the content type usage and settings store implementation.


Let me try one more search to find any type definitions or constants related to these content types.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for content type definitions across the codebase
rg -g '*.{ts,tsx}' "('input_audio'|'input_text')" --type-add 'tsx:*.tsx'

Length of output: 453


Script:

#!/bin/bash
# Check the settings store implementation and type definitions
ast-grep --pattern 'type $_ = {
  $$$
  realtimeAPIModeContentType: $_
  $$$
}'

# Check for any enum or type definitions related to content types
rg -g '*.{ts,tsx}' "type.*ContentType|enum.*ContentType"

Length of output: 140


Script:

#!/bin/bash
# Search for any type definitions or constants related to input modes
rg -g '*.{ts,tsx}' -B 2 -A 2 "realtimeAPIModeContentType"

# Check for any type imports or exports
ast-grep --pattern 'export type $_ = $$$'

Length of output: 6677

Comment on lines +608 to +676
return (
<>
<div>{t('AzureTTSInfo')}</div>
<div className="mt-16 font-bold">{t('AzureAPIKeyLabel')}</div>
<div className="mt-8">
<input
className="text-ellipsis px-16 py-8 w-col-span-4 bg-surface1 hover:bg-surface1-hover rounded-8"
type="text"
placeholder="..."
value={azureTTSKey}
onChange={(e) =>
settingsStore.setState({
azureTTSKey: e.target.value,
})
}
/>
</div>
<div className="mt-16 font-bold">{t('AzureEndpoint')}</div>
<div className="mt-8">
<input
className="text-ellipsis px-16 py-8 w-col-span-4 bg-surface1 hover:bg-surface1-hover rounded-8"
type="text"
placeholder="..."
value={azureTTSEndpoint}
onChange={(e) =>
settingsStore.setState({
azureTTSEndpoint: e.target.value,
})
}
/>
</div>
<div className="mt-16 font-bold">{t('OpenAITTSVoice')}</div>
<div className="mt-8">
<select
value={openaiTTSVoice}
onChange={(e) =>
settingsStore.setState({
openaiTTSVoice: e.target.value as OpenAITTSVoice,
})
}
className="px-16 py-8 bg-surface1 hover:bg-surface1-hover rounded-8"
>
<option value="alloy">alloy</option>
<option value="echo">echo</option>
<option value="fable">fable</option>
<option value="onyx">onyx</option>
<option value="nova">nova</option>
<option value="shimmer">shimmer</option>
</select>
</div>
<div className="mt-16 font-bold">{t('OpenAITTSModel')}</div>
<div className="mt-16 font-bold">
{t('OpenAITTSSpeed')}: {openaiTTSSpeed}
</div>
<input
type="range"
min={0.25}
max={4.0}
step={0.01}
value={openaiTTSSpeed}
className="mt-8 mb-16 input-range"
onChange={(e) => {
settingsStore.setState({
openaiTTSSpeed: Number(e.target.value),
})
}}
/>
</>
)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

[バグ] Azure TTS設定でOpenAI TTSの変数とテキストが使用されています

Azure TTSの設定セクションで、OpenAI TTSに関連する変数やテキストが使用されています。これにより、ユーザーが混乱する可能性があります。

修正提案:

  1. テキストの修正

    表示されるテキストをAzure TTS用に変更します。

    - {t('OpenAITTSVoice')}
    + {t('AzureTTSVoice')}
  2. 状態変数の修正

    Azure TTS専用の状態変数を使用します。

    - value={openaiTTSVoice}
    + value={azureTTSVoice}
  3. 型の修正

    型アサーションをAzure TTS用にします。

    - openaiTTSVoice: e.target.value as OpenAITTSVoice,
    + azureTTSVoice: e.target.value as AzureTTSVoice,
  4. 速度設定の追加

    Azure TTS用の速度設定を追加し、状態変数を使用します。

    <div className="mt-16 font-bold">
      {t('AzureTTSSpeed')}: {azureTTSSpeed}
    </div>
    <input
      type="range"
      min={0.25}
      max={4.0}
      step={0.01}
      value={azureTTSSpeed}
      className="mt-8 mb-16 input-range"
      onChange={(e) => {
        settingsStore.setState({
          azureTTSSpeed: Number(e.target.value),
        })
      }}
    />
  5. 必要な型と状態変数の定義

    AzureTTSVoiceazureTTSSpeedなど、必要な型や状態変数を定義します。

Comment on lines +44 to +49
const openaiTTSKey = settingsStore((s) => s.openaiTTSKey)
const openaiTTSVoice = settingsStore((s) => s.openaiTTSVoice)
const openaiTTSModel = settingsStore((s) => s.openaiTTSModel)
const openaiTTSSpeed = settingsStore((s) => s.openaiTTSSpeed)
const azureTTSKey = settingsStore((s) => s.azureTTSKey)
const azureTTSEndpoint = settingsStore((s) => s.azureTTSEndpoint)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

[バグ] Azure TTSとOpenAI TTSの設定が混在しています

Azure TTS用の設定で、OpenAI TTSの状態変数が使用されています。これは誤りであり、Azure TTS専用の状態変数を使用する必要があります。

具体的な修正提案:

  1. 状態変数の追加と取得

    settingsStoreからAzure TTS用の状態変数を取得します。

    + const azureTTSVoice = settingsStore((s) => s.azureTTSVoice)
    + const azureTTSSpeed = settingsStore((s) => s.azureTTSSpeed)
  2. OpenAI TTSとAzure TTSの変数を明確に区別

    Azure TTSの設定で、OpenAI TTSの変数を使用しないようにします。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const openaiTTSKey = settingsStore((s) => s.openaiTTSKey)
const openaiTTSVoice = settingsStore((s) => s.openaiTTSVoice)
const openaiTTSModel = settingsStore((s) => s.openaiTTSModel)
const openaiTTSSpeed = settingsStore((s) => s.openaiTTSSpeed)
const azureTTSKey = settingsStore((s) => s.azureTTSKey)
const azureTTSEndpoint = settingsStore((s) => s.azureTTSEndpoint)
const openaiTTSKey = settingsStore((s) => s.openaiTTSKey)
const openaiTTSVoice = settingsStore((s) => s.openaiTTSVoice)
const openaiTTSModel = settingsStore((s) => s.openaiTTSModel)
const openaiTTSSpeed = settingsStore((s) => s.openaiTTSSpeed)
const azureTTSKey = settingsStore((s) => s.azureTTSKey)
const azureTTSEndpoint = settingsStore((s) => s.azureTTSEndpoint)
const azureTTSVoice = settingsStore((s) => s.azureTTSVoice)
const azureTTSSpeed = settingsStore((s) => s.azureTTSSpeed)

@tegnike tegnike merged commit 9649dec into develop Oct 25, 2024
@tegnike tegnike deleted the feature/add-openai-tts branch October 30, 2024 10:25
This was referenced Nov 19, 2024
This was referenced Dec 18, 2024
terisuke pushed a commit to terisuke/aituber-kit that referenced this pull request Dec 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants