Skip to content

Conversation

@tegnike
Copy link
Owner

@tegnike tegnike commented Oct 25, 2024

Summary by CodeRabbit

  • 新機能

    • OpenAIおよびAzureのテキスト読み上げ(TTS)サービスをサポートするための新しい環境変数が追加されました。
    • リアルタイムAPIモードのためのコンテンツタイプ選択機能が追加されました。
    • READMEおよび各言語のドキュメントに、リアルタイムAPIモードや新しいAIキャラクターとのインタラクションに関する情報が追加されました。
  • バグ修正

    • エラーメッセージの明確化とJSON解析エラーの処理が改善されました。
  • ドキュメント

    • ライセンス情報が更新され、商業利用に関する詳細が追加されました。
    • 各種設定や機能に関するドキュメントが強化されました。

@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 9:48pm

@coderabbitai
Copy link

coderabbitai bot commented Oct 25, 2024

Walkthrough

このプルリクエストでは、AIサービスおよびリアルタイムAPIの機能を強化するために、複数の新しい環境変数が.envおよび.env.exampleファイルに追加されました。具体的には、OpenAI TTSおよびAzure TTSに関連する変数が含まれ、リアルタイムAPIモードのコンテンツタイプを指定するための変数も導入されています。また、READMEファイルや各種翻訳ファイルにおいて、これらの新機能に関するドキュメントが更新され、ユーザーが新しい設定や機能を理解しやすくなっています。

Changes

ファイル 変更概要
.env, .env.example 新しい環境変数が追加されました: OPENAI_TTS_KEY, NEXT_PUBLIC_OPENAI_TTS_VOICE, NEXT_PUBLIC_OPENAI_TTS_MODEL, NEXT_PUBLIC_OPENAI_TTS_SPEED, AZURE_TTS_KEY, AZURE_TTS_ENDPOINT, NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE
README.md, docs/README_en.md, docs/README_ko.md, docs/README_zh.md 新機能や設定に関する説明が追加・更新され、リアルタイムAPIモードやライセンス情報が強化されました。
docs/license-faq.md, docs/license-faq_en.md 商業ライセンスに関するFAQが拡充され、詳細な価格設定と使用条件が追加されました。
locales/en/translation.json, locales/ja/translation.json, locales/ko/translation.json, locales/zh/translation.json OpenAIおよびAzure TTSに関連する新しい翻訳キーが追加され、多言語対応が強化されました。
package.json 新しい依存関係@azure/identityが追加され、openaiのバージョンが更新されました。
src/components/messageInputContainer.tsx sendAudioBuffer関数が修正され、送信するコンテンツタイプに基づいてデータ形式が動的に変更されるようになりました。
src/components/settings/modelProvider.tsx リアルタイムAPIモードのコンテンツタイプを管理するための新しい状態変数が追加されました。
src/components/settings/voice.tsx OpenAIおよびAzureの音声エンジンをサポートするための新しい設定変数が追加されました。
src/features/constants/settings.ts AIサービスおよび音声に関連するタイプが拡張され、新しい音声オプションが追加されました。
src/features/messages/synthesizeVoiceAzureOpenAI.ts, src/features/messages/synthesizeVoiceOpenAI.ts 新しい音声合成関数が追加され、AzureおよびOpenAIの音声合成機能が強化されました。
src/pages/api/azureOpenAITTS.ts, src/pages/api/openAITTS.ts 新しいAPIハンドラーが追加され、AzureおよびOpenAIの音声合成リクエストを処理する機能が実装されました。

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: 25

🧹 Outside diff range and nitpick comments (32)
src/components/settings/websocket.tsx (1)

Line range hint 14-19: モード間の相互排他性についてコメントの追加を推奨

コードの保守性を向上させるため、これらのモードが互いに排他的である理由を説明するコメントの追加を提案します。

    if (newMode) {
+     // WebSocketモード有効時は会話の連続性モードとリアルタイムAPIモードを無効化
+     // これらのモードは互いに競合する可能性があるため、同時に有効にはできない
      settingsStore.setState({
        conversationContinuityMode: false,
        realtimeAPIMode: false,
      })
    }
src/features/messages/synthesizeVoiceOpenAI.ts (2)

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

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

import { Talk } from './messages'
-import { Language } from '@/features/constants/settings'

4-10: 関数のドキュメントを追加することを推奨します

パラメータの目的と戻り値の型を明確にするために、JSDocドキュメントの追加を提案します。

+/**
+ * OpenAI TTSを使用して音声を合成します
+ * @param talk - 音声合成するテキストとメタデータ
+ * @param apiKey - OpenAI APIキー
+ * @param voice - 使用する音声モデル名
+ * @param model - 使用するTTSモデル名
+ * @param speed - 音声の速度(0.25-4.0)
+ * @returns 音声データのArrayBuffer
+ */
export async function synthesizeVoiceOpenAIApi(
src/pages/api/openAITTS.ts (2)

1-3: OpenAIパッケージのバージョン指定を推奨

package.jsonでOpenAIパッケージのバージョンを明示的に指定することを推奨します。これにより、予期せぬ破壊的変更を防ぎ、アプリケーションの安定性を確保できます。


1-37: セキュリティとパフォーマンスの改善が必要

以下の重要な改善点を検討してください:

  1. リクエストサイズの制限
  2. キャッシュの実装
  3. Content Security Policyヘッダーの追加

これらの実装について詳細な提案が必要な場合は、お申し付けください。

.env.example (3)

78-80: Azure TTS の設定値にコメントを追加することを推奨します

本番環境での設定をスムーズにするため、以下の情報をコメントとして追記することを推奨します:

  1. エンドポイントのフォーマット例
  2. リージョン情報の注意点

以下の修正を提案します:

 # Azure TTS
 AZURE_TTS_KEY=""
-AZURE_TTS_ENDPOINT=""
+AZURE_TTS_ENDPOINT=""  # 例: https://{region}.tts.speech.microsoft.com/

116-117: Realtime API のコンテンツタイプに関する説明の追加が必要です

設定可能な値と各値の意味について、明確な説明をコメントとして追加することを推奨します。

以下の修正を提案します:

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

環境変数の設定に関する重要な改善点が見つかりました

以下の点について対応が必要です:

  1. API関連の必須環境変数の検証が不十分です:

    • src/pages/api/openAITTS.tssrc/pages/api/azureOpenAITTS.tsでは基本的な検証が実装されていますが、アプリケーション起動時の検証が欠けています。
    • フロントエンド側(src/features/stores/settings.ts)では、環境変数が存在しない場合のフォールバック値の設定のみで、妥当性の検証が行われていません。
  2. セキュリティ上の懸念事項:

    • 多くの機密性の高いAPIキーがNEXT_PUBLIC_プレフィックス付きで定義されており、クライアントサイドに露出する可能性があります。
    • 特にNEXT_PUBLIC_OPENAI_KEYNEXT_PUBLIC_AZURE_KEYなどは、サーバーサイドでのみ使用すべきです。
  3. 設定値の型安全性:

    • 数値型の環境変数(速度、ピッチなど)のパース処理は実装されていますが、不正な値に対するエラーハンドリングが不足しています。
🔗 Analysis chain

Line range hint 1-117: 本番リリースに向けた全体的な確認事項

本番環境へのデプロイに向けて、以下の点を確認してください:

  1. 必須の環境変数が明確になっていない
  2. 各設定値の検証ロジックの実装状況
  3. セキュリティ上の考慮事項(特にNEXT_PUBLIC_プレフィックスの使用)

環境変数の使用状況を確認するスクリプトを実行します:


Let me gather more information about the environment variable validation and usage:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 必須の環境変数の使用箇所を確認
rg -l "process\.env\.(OPENAI_TTS|AZURE_TTS|NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE)"

# 環境変数の検証ロジックの有無を確認
ast-grep --pattern 'if (!process.env.$_) { throw new Error($_) }'

Length of output: 248


Script:

#!/bin/bash
# Check environment variable validation in the files that use these variables
rg -A 5 "process\.env\.(OPENAI_TTS|AZURE_TTS|NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPE)" src/

# Check for any environment variable validation patterns
rg -A 5 "process\.env" src/features/stores/settings.ts

# Look for any config validation or initialization code
fd -e ts -e js config

Length of output: 5752

docs/license-faq.md (2)

Line range hint 48-53: エンタープライズライセンスの制限事項を追加してください

「無制限の再配布が可能」という条件について、以下の制限事項の追加を検討してください:

  • 再配布時のブランディング要件
  • サポート責任の所在
  • セキュリティ更新の配布方法

109-125: 商用利用の具体例をより詳細に記述してください

現在の例示に以下の情報を追加することを推奨します:

  • 各ケースでの具体的な利用規模
  • 予想される年間コスト
  • 必要なライセンス数の計算方法
src/components/useWebSocket.tsx (1)

45-57: useEffectでのメッセージ処理に関する提案

メッセージの処理ロジックについて、以下の点を考慮することを推奨します:

  1. 大量のメッセージが届いた場合のパフォーマンス最適化
  2. バッチ処理の検討

また、roleの変更ロジックをより明確な形で分離することを推奨します:

+const normalizeRole = (role: string): string => {
+  if (['output', 'executing', 'console'].includes(role)) {
+    return 'code';
+  }
+  return role;
+}

 useEffect(() => {
   if (receivedMessages.length > 0) {
     const message = receivedMessages[0];
-    if (
-      message.role === 'output' ||
-      message.role === 'executing' ||
-      message.role === 'console'
-    ) {
-      message.role = 'code'
-    }
+    message.role = normalizeRole(message.role);
     setReceivedMessages((prev) => prev.slice(1))
     processMessage(message)
   }
 }, [receivedMessages, processMessage])
locales/zh/translation.json (2)

144-146: 送信タイプの説明を強化することを推奨します

現在の翻訳は簡潔ですが、各送信タイプの使用例や具体的な説明をツールチップとして追加することで、ユーザーの理解を深めることができます。

以下のようなヘルプテキストの追加を提案します:

  "RealtimeAPIModeContentType": "送信類型",
+ "RealtimeAPIModeContentTypeHelp": "リアルタイムAPIモードで使用する送信タイプを選択してください",
  "InputText": "文本",
+ "InputTextHelp": "テキストメッセージとして送信されます",
  "InputAudio": "音頻",
+ "InputAudioHelp": "音声メッセージとして送信されます"

156-162: TTSサービスの説明文のフォーマットを統一することを推奨します

翻訳の内容は正確ですが、説明文のフォーマットを他のTTSサービス(VoiceVox、Google TTS等)と統一することで、ドキュメントの一貫性が向上します。

以下のような形式に統一することを提案します:

  "UsingOpenAITTS": "使用 OpenAI",
- "OpenAITTSInfo": "使用 OpenAI。它支持多种语言。如果您选择 OpenAI 作为 AI 服务,则不需要设置下面的 API 密钥。",
+ "OpenAITTSInfo": "使用 OpenAI TTS。支持多种语言。注意:如果您选择 OpenAI 作为 AI 服务,则不需要设置下面的 API 密钥。",
  "UsingAzureTTS": "使用 Azure OpenAI",
- "AzureTTSInfo": "使用 Azure OpenAI。它支持多种语言。"
+ "AzureTTSInfo": "使用 Azure OpenAI TTS。支持多种语言。"
locales/ja/translation.json (1)

157-163: TTSの設定項目の翻訳は適切ですが、話速の設定についての補足が推奨されます

現在の実装は明確で分かりやすいですが、以下の改善を提案させていただきます:

-  "OpenAITTSSpeed": "話速",
+  "OpenAITTSSpeed": "話速(0.5~2.0)",

この変更により、ユーザーは適切な入力範囲を即座に理解できるようになります。

src/features/youtube/conversationContinuityFunctions.ts (1)

Line range hint 332-337: エラーログの改善を提案

エラーハンドリングをより堅牢にするため、以下の改善を提案します:

  • エラー発生時に、受信したレスポンスの内容もログに含める
  • エラーの種類(構文エラー、型エラーなど)を識別して記録する
  } catch (error) {
-   console.error('JSON.parseエラーが発生しました。', error)
+   console.error('JSON.parseエラーが発生しました。', {
+     error,
+     receivedResponse: response.text,
+     errorType: error instanceof SyntaxError ? 'SyntaxError' : error.name
+   })
    answer = 'false'
  }
locales/en/translation.json (2)

156-160: OpenAI TTSの設定に関する説明の改善を提案

設定項目は網羅的ですが、以下の点について説明を追加することを推奨します:

  • 各音声タイプの特徴や用途
  • モデルの選択基準
  • 速度設定の推奨範囲

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

-  "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. It supports multiple languages. If you select OpenAI as the AI service, you do not need to set the API key below. Each voice type has unique characteristics suitable for different use cases. The speed can be adjusted between 0.25 and 4.0.",

161-162: Azure TTSの設定に関する説明の拡充を提案

現在の説明は基本的な情報のみです。以下の情報を追加することで、ユーザーの理解を深めることができます:

  • サポートされている音声タイプ
  • 必要な設定手順
  • 推奨される使用シナリオ

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

-  "AzureTTSInfo": "Using Azure OpenAI. It supports multiple languages."
+  "AzureTTSInfo": "Using Azure OpenAI. It supports multiple languages. Azure TTS offers neural voices with different speaking styles and emotions. Please ensure you have set up the Azure OpenAI service and have the necessary credentials."
docs/README_ko.md (1)

158-172: 新機能:Realtime APIモードの追加!

OpenAIのRealtime APIを使用した低遅延対話機能が追加されました。関数実行の定義方法も明確に説明されています。

ただし、以下の点について追記を検討してください:

  • 必要なAPIキーや設定
  • 具体的なユースケース
README.md (5)

91-98: 新しいLLMサービスの追加について

新しく追加されたLLMサービス(Azure OpenAI、Groq、Cohere、Mistral AI、Perplexity、Fireworks、ローカルLLM、Dify)の説明が簡潔すぎます。各サービスの特徴や利用上の注意点を追記することを推奨します。

以下のような追記を提案します:

   - Azure OpenAI
+  - Azure OpenAI: OpenAIと同等の機能をAzure上で利用可能
   - Groq
+  - Groq: 高速な推論が特徴のLLMサービス
   - Cohere
+  - Cohere: 多言語対応に優れたLLMサービス

102-109: 音声合成エンジンの説明を改善

音声合成エンジンの説明が追加されていますが、より具体的な情報が必要です。

以下のような修正を提案します:

-  - VOICEVOX: 複数の選択肢から話者を選ぶことができます。予めVOICEVOXアプリを起動しておく必要があります。
+  - VOICEVOX: 無料で利用可能な音声合成エンジン。複数の話者から選択可能。利用前にVOICEVOXアプリの起動が必要。
-  - OpenAI: APIキーの入力が必要です。
+  - OpenAI: 自然な音声合成が特徴。APIキーの入力が必要。対応言語:英語、日本語など。
🧰 Tools
🪛 LanguageTool

[uncategorized] ~102-~102: 「ことができる」という表現は冗長な可能性があります。
Context: ...4. 音声合成エンジンを選択し、必要に応じて声の設定を行います。 - VOICEVOX: 複数の選択肢から話者を選ぶことができます。予めVOICEVOXアプリを起動...

(DOUSI_KOTOGADEKIRU)


130-131: 外部連携モードの説明を簡潔化

冗長な表現を改善し、より直接的な説明に修正します。

- WebSocketでサーバーアプリにリクエストを送信して、レスポンスを取得することができます。
+ WebSocketでサーバーアプリと双方向通信が可能です。
🧰 Tools
🪛 LanguageTool

[uncategorized] ~130-~130: 「ことができる」という表現は冗長な可能性があります。
Context: ... WebSocketでサーバーアプリにリクエストを送信して、レスポンスを取得することができます。 - 別途サーバーアプリを用意する必要があります。 #### 使用方法 ...

(DOUSI_KOTOGADEKIRU)


161-176: Realtime APIモードの説明を充実化

新機能の説明としては情報が不足しています。具体的な利点や使用例を追加することを推奨します。

以下のような追記を提案します:

### Realtime APIモード

- OpenAIのRealtime APIを使用して、低遅延でキャラと対話できるモードです。
- 関数実行を定義することができます。
+ OpenAIのRealtime APIを使用した低遅延対話モードです。
+ - 通常モードと比べて応答が最大50%高速化
+ - リアルタイムな音声認識による自然な会話が可能
+ - カスタム関数による外部システムとの連携機能
+ - 音声・テキストのストリーミング処理対応

#### 関数実行
+ - 天気情報取得やスケジュール管理など、外部APIとの連携が可能
+ - 関数のレスポンスをリアルタイムに会話に組み込み
🧰 Tools
🪛 LanguageTool

[uncategorized] ~164-~164: 「ことができる」という表現は冗長な可能性があります。
Context: ...e APIを使用して、低遅延でキャラと対話できるモードです。 - 関数実行を定義することができます。 #### 使用方法 1. AIサービスでOpenAIまたはAzu...

(DOUSI_KOTOGADEKIRU)


196-196: その他セクションの表現を改善

冗長な表現を簡潔にします。

- 設定情報・会話履歴は設定画面でリセットすることができます。
+ 設定画面で設定情報・会話履歴をリセットできます。
🧰 Tools
🪛 LanguageTool

[uncategorized] ~196-~196: 「ことができる」という表現は冗長な可能性があります。
Context: ...リックで送信 ### その他 - 設定情報・会話履歴は設定画面でリセットすることができます。 - 各種設定項目はブラウザにローカルストレージとして保存されます。 - ...

(DOUSI_KOTOGADEKIRU)

docs/README_en.md (3)

161-175: リアルタイムAPIモードの新機能について

OpenAIのリアルタイムAPIを使用した低遅延対話機能が追加され、適切に文書化されています。機能実行の定義方法も具体的に説明されています。

ただし、以下の点について追記を検討してください:

  • リアルタイムAPIモードの利点や使用シナリオ
  • 必要なAPIキーや設定項目の詳細

200-208: 関連記事セクションについて

新機能に関する詳細な解説記事が適切に追加されています。特に、リアルタイムAPIモードに関する記事は、新機能の理解を深めるのに役立ちます。

ただし、記事タイトルの「!!!!」の使用は控えめにすることを推奨します。

-[AI Does Slide Presentations Now!!!!]
+[AI Does Slide Presentations Now!]
🧰 Tools
🪛 LanguageTool

[style] ~204-~204: Using many exclamation marks might seem excessive (in this case: 12 exclamation marks for a text that’s 7429 characters long)
Context: ...af3f) - [AI Does Slide Presentations Now!!!!](https://note.com/nike_cha_n/n/n867081a...

(EN_EXCESSIVE_EXCLAMATION)


106-107: 重複した表現について

「A local API server needs to be running」という表現が連続して使用されています。表現を変更して文章の多様性を高めることを推奨します。

-Style-Bert-VITS2: A local API server needs to be running.
-GSVI TTS: A local API server needs to be running.
+Style-Bert-VITS2: Requires a running local API server.
+GSVI TTS: Local API server must be active.
🧰 Tools
🪛 LanguageTool

[style] ~107-~107: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ning. - GSVI TTS: A local API server needs to be running. - ElevenLabs: Various la...

(REP_NEED_TO_VB)

src/features/chat/handlers.ts (2)

Line range hint 378-392: WebSocketの処理が改善されました!

WebSocketモードの判定がシンプルになり、メッセージの送信タイミングも適切です。

エラーハンドリングをより堅牢にするため、以下の改善を提案します:

 if (hs.ws?.readyState === WebSocket.OPEN) {
   // ユーザーの発言を追加して表示
   const updateLog: Message[] = [
     ...hs.chatLog,
     { role: 'user', content: newMessage },
   ]
   homeStore.setState({
     chatLog: updateLog,
   })

   // WebSocket送信
-  hs.ws.send(JSON.stringify({ content: newMessage, type: 'chat' }))
+  try {
+    hs.ws.send(JSON.stringify({ content: newMessage, type: 'chat' }))
+  } catch (error) {
+    console.error('WebSocketメッセージの送信に失敗しました:', error)
+    homeStore.setState({
+      assistantMessage: 'メッセージの送信に失敗しました。再度お試しください。',
+      chatProcessing: false,
+    })
+  }

Line range hint 495-537: 感情パラメータの追加により、より豊かな応答が可能になりました!

感情パラメータの追加は素晴らしい改善ですが、型安全性をさらに高めることができます。

以下の改善を提案します:

+// 許可された感情の型定義
+type Emotion = 'neutral' | 'happy' | 'sad' | 'angry' | 'surprised'
+
 export const handleReceiveTextFromWsFn =
   () =>
   async (
     text: string,
     role?: string,
-    emotion: string = 'neutral',
+    emotion: Emotion = 'neutral',
     state?: string
   ) => {

また、感情値のバリデーションも追加することをお勧めします:

     if (role === 'assistant' && text !== '') {
+      // 感情値の検証
+      const validEmotions: Emotion[] = ['neutral', 'happy', 'sad', 'angry', 'surprised']
+      const validatedEmotion = validEmotions.includes(emotion as Emotion) ? emotion : 'neutral'
-      let aiText = `[${emotion}] ${text}`
+      let aiText = `[${validatedEmotion}] ${text}`
       try {
         const aiTalks = textsToScreenplay([aiText], ss.koeiroParam)
src/components/settings/modelProvider.tsx (2)

154-173: UIの条件付きレンダリングとユーザー体験について

リアルタイムAPIモードがアクティブな場合のみコンテンツタイプ選択UIを表示する実装は適切ですが、以下の改善を検討してください:

  1. 選択肢の変更時にユーザーに確認を求めることを推奨します(特にアクティブなセッション中の変更時)
  2. 各オプションの説明ツールチップの追加を検討してください

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

 <select
   className="px-16 py-8 w-col-span-2 bg-surface1 hover:bg-surface1-hover rounded-8"
   value={realtimeAPIModeContentType}
   onChange={(e) => {
+    if (confirm(t('ContentTypeChangeConfirmation'))) {
       const model = e.target.value
       settingsStore.setState({
         realtimeAPIModeContentType: model,
       })
+    }
   }}
 >
-  <option value="input_text">{t('InputText')}</option>
-  <option value="input_audio">{t('InputAudio')}</option>
+  <option value="input_text" title={t('InputTextDescription')}>{t('InputText')}</option>
+  <option value="input_audio" title={t('InputAudioDescription')}>{t('InputAudio')}</option>
 </select>

Line range hint 4-6: テストの追加が必要です

TODOコメントで指摘されているように、テストの実装が必要です。特に新しいrealtimeAPIModeContentTypeの機能に関するテストを含めることを推奨します。

テストコードの実装をお手伝いしましょうか?以下のようなテストケースを提案できます:

  1. コンテンツタイプの切り替え
  2. 無効な値のバリデーション
  3. ステート更新の確認
src/features/messages/speakQueue.ts (2)

33-41: エラーログの出力方法を簡素化しましょう

現在、エラー発生時に2つのconsole.errorを使用していますが、これらを1つにまとめてエラー情報を包括的にログ出力できます。

以下の差分を適用してください:

-          console.error(
-            'An error occurred while processing the speech synthesis task:',
-            error
-          )
-          if (error instanceof Error) {
-            console.error('Error details:', error.message)
-          }
+          console.error('An error occurred while processing the speech synthesis task:', error)

57-57: console.log('play neutral')は不要かもしれません

デバッグ目的でなければ、このログ出力は削除を検討してください。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

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

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (29)
  • .env (2 hunks)
  • .env.example (2 hunks)
  • README.md (7 hunks)
  • docs/README_en.md (8 hunks)
  • docs/README_ko.md (7 hunks)
  • docs/README_zh.md (8 hunks)
  • docs/license-faq.md (3 hunks)
  • docs/license-faq_en.md (3 hunks)
  • locales/en/translation.json (2 hunks)
  • locales/ja/translation.json (2 hunks)
  • locales/ko/translation.json (5 hunks)
  • locales/zh/translation.json (4 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/components/settings/websocket.tsx (1 hunks)
  • src/components/useWebSocket.tsx (3 hunks)
  • src/features/chat/handlers.ts (4 hunks)
  • src/features/constants/settings.ts (2 hunks)
  • src/features/messages/speakCharacter.ts (3 hunks)
  • src/features/messages/speakQueue.ts (1 hunks)
  • src/features/messages/synthesizeVoiceAzureOpenAI.ts (1 hunks)
  • src/features/messages/synthesizeVoiceOpenAI.ts (1 hunks)
  • src/features/stores/settings.ts (7 hunks)
  • src/features/vrmViewer/model.ts (2 hunks)
  • src/features/youtube/conversationContinuityFunctions.ts (1 hunks)
  • src/pages/api/azureOpenAITTS.ts (1 hunks)
  • src/pages/api/openAITTS.ts (1 hunks)
🧰 Additional context used
🪛 LanguageTool
README.md

[uncategorized] ~102-~102: 「ことができる」という表現は冗長な可能性があります。
Context: ...4. 音声合成エンジンを選択し、必要に応じて声の設定を行います。 - VOICEVOX: 複数の選択肢から話者を選ぶことができます。予めVOICEVOXアプリを起動...

(DOUSI_KOTOGADEKIRU)


[uncategorized] ~130-~130: 「ことができる」という表現は冗長な可能性があります。
Context: ... WebSocketでサーバーアプリにリクエストを送信して、レスポンスを取得することができます。 - 別途サーバーアプリを用意する必要があります。 #### 使用方法 ...

(DOUSI_KOTOGADEKIRU)


[uncategorized] ~164-~164: 「ことができる」という表現は冗長な可能性があります。
Context: ...e APIを使用して、低遅延でキャラと対話できるモードです。 - 関数実行を定義することができます。 #### 使用方法 1. AIサービスでOpenAIまたはAzu...

(DOUSI_KOTOGADEKIRU)


[uncategorized] ~196-~196: 「ことができる」という表現は冗長な可能性があります。
Context: ...リックで送信 ### その他 - 設定情報・会話履歴は設定画面でリセットすることができます。 - 各種設定項目はブラウザにローカルストレージとして保存されます。 - ...

(DOUSI_KOTOGADEKIRU)

docs/README_en.md

[style] ~107-~107: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...ning. - GSVI TTS: A local API server needs to be running. - ElevenLabs: Various la...

(REP_NEED_TO_VB)


[style] ~204-~204: Using many exclamation marks might seem excessive (in this case: 12 exclamation marks for a text that’s 7429 characters long)
Context: ...af3f) - [AI Does Slide Presentations Now!!!!](https://note.com/nike_cha_n/n/n867081a...

(EN_EXCESSIVE_EXCLAMATION)

🔇 Additional comments (63)
src/features/messages/synthesizeVoiceAzureOpenAI.ts (1)

1-9: 関数のシグネチャは適切に実装されています

型の定義が明確で、必要なパラメータが適切に定義されています。非同期関数として正しく実装されており、音声データを返すためのArrayBufferの使用も適切です。

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

18-18: 実装の論理的な分離を確認しました

WebSocketモードが有効な場合にrealtimeAPIModeを無効にする実装は適切です。これにより、互いに競合する可能性のある機能を明確に分離できています。

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

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

OpenAIとAzureの音声サービスが追加され、既存の音声タイプと整合性が取れています。


50-50: コードの区切りが適切に追加されています

タイプ定義間の視認性が向上しています。


51-58: OpenAI TTSの型定義を確認してください

新しく追加されたOpenAI TTSの音声タイプとモデルタイプの実装は適切ですが、以下の点を確認することを推奨します:

  1. 定義された音声オプションが最新のOpenAI TTSの仕様と一致していること
  2. 環境変数(NEXT_PUBLIC_OPENAI_TTS_VOICENEXT_PUBLIC_OPENAI_TTS_MODEL)との整合性
✅ Verification successful

Let me verify the usage of these types in the voice component to ensure complete validation.


OpenAI TTSの型定義は適切に実装されています

コードベースの検証結果から、以下が確認できました:

  • 定義された音声タイプとモデルタイプは、コンポーネントとストアで正しく使用されています
  • 環境変数との整合性も取れています
  • 実装は音声設定UIと音声生成機能の両方で適切に統合されています
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 環境変数の定義と型定義の整合性を確認

# .envファイルでの音声設定を確認
echo "Checking voice settings in .env files:"
rg "NEXT_PUBLIC_OPENAI_TTS_" .env*

# 音声関連のコンポーネントでの使用箇所を確認
echo "Checking usage in voice components:"
rg "OpenAITTSVoice|OpenAITTSModel" "src/components/"

Length of output: 1385


Script:

#!/bin/bash
# Check the implementation details of the voice component
echo "Checking voice component implementation:"
cat src/components/settings/voice.tsx

# Check for any other potential usage of these types
echo "Checking other potential usage:"
rg "openaiTTSVoice|openaiTTSModel" src/

Length of output: 28750

package.json (2)

25-25: Azure認証パッケージの追加を確認

Azure TTSサービスの統合に必要な@azure/identityパッケージが適切に追加されています。バージョン4.5.0は安定版であり、本番環境での使用に適しています。


45-45: OpenAIパッケージのアップデートを確認

openaiパッケージのバージョンアップデート(4.38.5から4.68.4)により、新しいTTS機能のサポートが追加されています。メジャーバージョンは4のままで、後方互換性が維持されています。

以下のスクリプトで、依存関係の互換性を確認します:

✅ Verification successful

OpenAIパッケージのアップデートは安全に実施可能です

新しいバージョン(4.68.4)で追加されたTTS機能が適切に実装されており、APIの使用方法も最新の仕様に準拠しています。以下の点から互換性の問題はないと判断できます:

  • TTSの実装(openAITTS.ts)が新しいバージョンのAPIに従って正しく実装されています
  • OpenAIクラスの初期化とメソッドの使用方法が適切です
  • 既存の機能に影響を与える破壊的な変更は含まれていません
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: パッケージの互換性とインストール履歴を確認

# package-lock.jsonが存在するか確認
if [ -f "package-lock.json" ]; then
  # openaiパッケージの依存関係を確認
  echo "OpenAIパッケージの依存関係:"
  jq '.packages["node_modules/openai"].requires' package-lock.json
fi

Length of output: 258


Script:

#!/bin/bash
# openaiパッケージの使用状況を確認
echo "OpenAIパッケージの使用箇所を検索:"
rg "openai" -l

# APIの使用パターンを確認
echo -e "\nOpenAI APIの使用パターンを確認:"
rg "new OpenAI" -A 2

# importステートメントを確認
echo -e "\nOpenAIのインポート方法を確認:"
rg "import.*openai" --type js --type ts

Length of output: 1363


Script:

#!/bin/bash
# TTSの実装詳細を確認
echo "OpenAI TTSの実装を確認:"
cat src/pages/api/openAITTS.ts

# 以前のバージョンでの実装との比較のため、git履歴を確認
echo -e "\nOpenAI TTSファイルの変更履歴:"
git log -p src/pages/api/openAITTS.ts

Length of output: 2537

.env.example (1)

72-76: ⚠️ Potential issue

OpenAI TTS の設定値の検証が必要です

本番リリースに向けて、以下の点を確認してください:

  1. OPENAI_TTS_KEYOPENAI_TTS_KEYが重複して定義されています。セキュリティ上のリスクを避けるため、一つに統合することを推奨します。
  2. NEXT_PUBLIC_OPENAI_TTS_VOICEMODELSPEEDの有効な値の範囲をコメントとして追記することで、設定ミスを防ぐことができます。

以下の修正を提案します:

 # OpenAI TTS
-OPENAI_TTS_KEY=""
 NEXT_PUBLIC_OPENAI_TTS_VOICE=""  # alloy, echo, fable, onyx, nova, or shimmer
 NEXT_PUBLIC_OPENAI_TTS_MODEL=""  # tts-1 or tts-1-hd
-NEXT_PUBLIC_OPENAI_TTS_SPEED=""  # 0.25 to 4.0
+NEXT_PUBLIC_OPENAI_TTS_SPEED=""  # 0.25から4.0の範囲で指定

Likely invalid or redundant comment.

.env (2)

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

NEXT_PUBLIC_REALTIME_API_MODE_CONTENT_TYPEの有効な値はinput_textまたはinput_audioのみとのことですが、バリデーションの追加を推奨します。

#!/bin/bash
# リアルタイムAPIモードの設定に関する説明がREADMEに記載されているか確認
rg "REALTIME_API_MODE_CONTENT_TYPE" README.md

.env.exampleに以下のようなコメントの追加を推奨します:

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

72-76: OpenAI TTSの設定変数の追加について確認事項があります

セキュリティと設定の観点から以下の点を確認してください:

  1. OPENAI_TTS_KEYは既存のOPENAI_KEYと異なる認証情報が必要なのでしょうか?
  2. NEXT_PUBLIC_プレフィックスが付いている変数はクライアントサイドで公開されますが、想定通りでしょうか?
✅ Verification successful

OpenAI TTSの設定について確認が完了しました

コードベースの分析から以下のことが確認できました:

  1. OPENAI_TTS_KEYOPENAI_KEYとは別の認証情報として使用されており、TTSサービス専用のキーとして適切に実装されています。ユーザーがAIサービスとしてOpenAIを選択している場合は、既存のOPENAI_KEYが自動的に使用される仕組みになっています。

  2. NEXT_PUBLIC_プレフィックスが付いている変数は以下の用途で適切に使用されています:

    • NEXT_PUBLIC_OPENAI_TTS_VOICE: 音声タイプの初期値設定
    • NEXT_PUBLIC_OPENAI_TTS_MODEL: TTSモデルの初期値設定
    • NEXT_PUBLIC_OPENAI_TTS_SPEED: 音声速度の初期値設定

これらの設定は適切に実装されており、セキュリティ上の問題はありません。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# OpenAI TTSの設定に関する説明がREADMEに記載されているか確認
rg -i "openai.*tts" README.md

Length of output: 45


Script:

#!/bin/bash
# Check for OpenAI TTS usage in the codebase
rg -i "openai.*tts" -A 3

# Check if OPENAI_KEY is used separately
rg "OPENAI_KEY" -A 3

# Look for TTS related configuration or documentation
rg -i "text.?to.?speech|tts" -A 3

Length of output: 69267

src/features/vrmViewer/model.ts (1)

2-7: インポートの追加が適切です

VRMExpressionPresetNameのインポートは、新しい感情表現機能の実装に必要であり、関連するVRMインポートと共に適切にグループ化されています。

docs/license-faq.md (2)

41-47: デベロッパーライセンスの価格設定の根拠を確認してください

スタンダードライセンス(1社)とデベロッパーライセンス(5社)の価格差が大きいように見えます。以下の検討が必要かもしれません:

  • 中間的な価格帯のプラン(例:3社まで)の追加
  • 価格設定の根拠の明確化

33-40: スタンダードライセンスの再配布条件の明確化が必要です

「再配布・再販は1社まで可能」という条件について、以下の点を明確にすることを推奨します:

  • 再配布先での使用期間の制限の有無
  • 再配布先でのユーザー数制限の有無
  • 再配布時の通知義務の有無
src/components/useWebSocket.tsx (3)

Line range hint 8-13: インターフェース名の改善とプロパティの追加について

TmpMessageからReceivedMessageへの名前変更は、インターフェースの目的をより明確に表現しており、適切な変更です。また、emotionプロパティの追加により、感情コンテキストの処理が可能になりました。


28-30: 状態管理の命名改善について

tmpMessagesからreceivedMessagesへの変更は、状態の目的をより明確に表現しており、コードの可読性が向上しています。


Line range hint 16-22: handleReceiveTextFromWsの引数追加について確認が必要

emotionパラメータが追加されましたが、このパラメータの使用方法と影響範囲について確認が必要です。

✅ Verification successful

emotionパラメータの実装は適切に行われています

emotionパラメータの追加は以下の理由で問題ありません:

  • handleReceiveTextFromWsFn内でデフォルト値'neutral'が設定されており、後方互換性が保たれています
  • 感情パラメータは['neutral', 'happy', 'angry', 'sad', 'relaxed']の定義された値を使用
  • メッセージ処理時に[${emotion}] ${text}の形式で適切に組み込まれ、音声合成時の感情表現に活用されています
  • WebSocketインターフェースとRealtimeAPIインターフェースの両方で一貫して実装されています
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# handleReceiveTextFromWsの実装を確認
ast-grep --pattern 'handleReceiveTextFromWs($$$)'

Length of output: 397


Script:

#!/bin/bash
# handleReceiveTextFromWsの呼び出し元を確認
rg "handleReceiveTextFromWs" -A 3

# WebSocketから受信したメッセージの型定義を確認
ast-grep --pattern 'interface $_ {
  text: $_
  role?: $_
  emotion?: $_
  state?: $_
}'

Length of output: 2052


Script:

#!/bin/bash
# handleReceiveTextFromWsFnの実装を確認
rg -A 10 "handleReceiveTextFromWsFn =" 

# emotionパラメータを使用している箇所を確認
rg "emotion" -A 3

Length of output: 7272

locales/zh/translation.json (2)

83-83: 説明文の更新が適切です!

アプリケーションの主要機能が簡潔かつ正確に説明されており、他の言語ファイルとの一貫性も保たれています。


103-103: バッチサイズの説明が分かりやすいです!

パフォーマンスとメモリ使用量のトレードオフが明確に説明されており、ユーザーが適切な設定を選択できる情報が提供されています。

docs/license-faq_en.md (2)

33-37: ライセンス価格体系の明確化について

各ライセンスの価格設定と利用範囲が明確に定義されていますが、以下の点について確認・検討が必要です:

  • 再配布可能な企業数の制限(1社、5社、無制限)の根拠
  • 税込価格の表示方法の一貫性
  • 為替変動を考慮した国際価格設定の方針

Also applies to: 41-45, 48-52


146-147: フォークプロジェクトのライセンスに関する補足

フォークプロジェクトのライセンスについての説明が追加されていますが、以下の点について明確化が必要です:

  • オープンソースコントリビューションとの関係
  • フォーク元のバージョンアップ時の対応
  • コミュニティ開発における取り扱い

より詳細な説明を追加するためのドキュメント案を作成いたしましょうか?

locales/ja/translation.json (1)

145-147: リアルタイムAPIモードの翻訳が適切に実装されています!

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

locales/ko/translation.json (3)

57-57: 音声速度の翻訳が統一されました!

「말하는 속도」から「말 속도」への変更により、より簡潔で一貫性のある表現になっています。この変更は以下の箇所で統一的に適用されています:

  • VoiceVox
  • StyleBertVITS2
  • GSVI TTS

Also applies to: 73-73, 104-104


144-146: リアルタイムAPIモードのコンテンツタイプが追加されました

入力タイプの区別(テキストと音声)が明確に翻訳されており、ユーザーにとって分かりやすい表現になっています。


156-162: OpenAIとAzure TTSの翻訳が追加されました

新しく追加されたTTS機能の翻訳が適切に実装されています。以下の点が評価できます:

  • 多言語対応に関する説明が明確
  • OpenAI APIキーに関する補足情報が丁寧
  • 設定項目(ボイスタイプ、モデル、速度など)が分かりやすく翻訳されている
✅ Verification successful

OpenAIとAzure TTSの翻訳が全言語で適切に実装されていることを確認しました

検証の結果、以下の点が確認できました:

  • 英語(en)、日本語(ja)、中国語(zh)、韓国語(ko)の全ての言語ファイルで必要な翻訳キーが実装されています
  • 各言語で一貫性のある翻訳内容が提供されており、特に以下の要素が適切に反映されています:
    • OpenAIとAzure OpenAIの機能説明
    • 多言語対応に関する説明
    • APIキーに関する補足情報
    • 設定項目(ボイスタイプ、モデル、速度)の表記
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 他の言語ファイルでも同じキーが実装されているか確認
for lang in en ja zh; do
  echo "Checking $lang translation..."
  rg "OpenAITTS|AzureTTS" "locales/$lang/translation.json"
done

Length of output: 1391

src/features/youtube/conversationContinuityFunctions.ts (2)

237-237: システムメッセージの改善を承認します

レスポンスフォーマットの要件が明確になり、メンテナンス性が向上しています。


Line range hint 326-327: 非同期シグネチャの変更の影響を確認

checkIfResponseContinuationIsRequired関数の戻り値の型がPromise<boolean>に変更されています。この変更による影響を確認する必要があります。

✅ Verification successful

Let me analyze the results. I can see that checkIfResponseContinuationIsRequired is properly called with await in src/features/youtube/youtubeComments.ts. Let me verify if there are any other usages of this function that might have been missed.


非同期シグネチャの変更は適切に処理されています

checkIfResponseContinuationIsRequired関数の非同期シグネチャの変更は、すべての呼び出し箇所でawaitキーワードを使用して適切に処理されていることを確認しました。コードベース内で唯一の使用箇所(src/features/youtube/youtubeComments.ts)で正しく実装されています。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 関数の呼び出し箇所を確認し、awaitが適切に使用されているか確認します
rg -l "checkIfResponseContinuationIsRequired" | xargs rg "checkIfResponseContinuationIsRequired" -B 2 -A 2

Length of output: 2391


Script:

#!/bin/bash
# Check for any other potential usages of the function using ast-grep
ast-grep --pattern 'checkIfResponseContinuationIsRequired($$$)'

Length of output: 175

docs/README_zh.md (8)

81-81: LLM APIリストの更新が適切に行われています。

新しいLLMプロバイダー(Azure OpenAI、Groq、Cohere、Mistral AI、Perplexity、Fireworks、DifyなどのLocal LLM)が追加され、ユーザーにより多くの選択肢が提供されています。

Also applies to: 91-98


102-109: 音声合成エンジンのオプションが適切に更新されています。

VOICEVOXやKoeiromap以外にも、以下の新しいTTSオプションが追加されています:

  • Google TTS
  • Style-Bert-VITS2
  • GSVI TTS
  • ElevenLabs
  • OpenAI
  • Azure OpenAI

各オプションの要件も明確に記載されています。


130-131: 外部統合モードの説明が改善されています。

WebSocketを介したリクエスト送信に関する説明が明確になり、メンテナンス中の注記が削除されています。


157-171: Realtime APIモードの説明が適切に追加されています。

新機能の説明が以下の点で明確です:

  • OpenAIのRealtime APIを使用した低遅延対話
  • 関数実行の定義方法
  • セットアップ手順

185-189: マイク入力方法の説明が分かりやすく追加されています。

2つの入力モードが明確に説明されています:

  1. Altキー(またはoption)を押しながらの入力
  2. マイクボタンのクリックによる入力

192-195: その他の機能説明が適切に更新されています。

設定情報や会話履歴のリセット、ブラウザでの設定保存、コードブロックのTTS処理に関する説明が追加されています。


196-204: 関連記事セクションが有用な情報とともに追加されています。

開発者向けの記事やチュートリアルへのリンクが適切に提供されており、ユーザーが詳細な情報を得られるようになっています。


270-272: スポンサーリストが適切に更新されています。

新しいスポンサー「terisuke」が追加され、適切なGitHubプロフィールリンクとアバター画像が含まれています。

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

6-12: 新しい定数のインポートが追加されました

OpenAI TTSの音声とモデルの定数が適切にインポートされています。これらは新しいTTS機能をサポートするために必要な変更です。


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

realtimeAPIModeContentTypeが追加されていますが、以下の点について確認が必要です:

  1. 許可される値の型定義
  2. バリデーション処理

有効な値を型として定義することを推奨します:

type ContentType = 'input_text' | 'chat_message' | 'system_prompt';

Also applies to: 209-210


267-272: 永続化設定の更新について

新しいTTS関連の設定がpartialize関数に適切に追加されています。セキュリティの観点から、以下の確認をお願いします:

  1. APIキーの保存方法の見直し
  2. センシティブデータの暗号化
locales/en/translation.json (1)

144-146: リアルタイムAPIモードの入力タイプの追加について承認

テキストと音声の入力タイプが明確に区別されており、ユーザーにとって分かりやすい実装になっています。

docs/README_ko.md (7)

82-99: LLMの選択肢が大幅に拡充されました!

新しく追加されたLLMオプション(Azure OpenAI、Groq、Cohere、Mistral AI、Perplexity、Fireworks、ローカルLLM、Dify)により、ユーザーの選択肢が広がりました。


103-110: 音声合成エンジンのオプションが充実しました!

VOICEVOXやKoeiromap以外にも、以下の選択肢が追加されています:

  • Google TTS
  • Style-Bert-VITS2
  • GSVI TTS
  • ElevenLabs
  • OpenAI
  • Azure OpenAI

各エンジンの要件(APIキーやローカルサーバーの必要性)が明確に記載されています。


131-132: 外部連携モードの要件が明確になりました!

WebSocketを介したサーバーアプリケーションとの連携に関する説明が改善されています。


186-189: マイク入力方法が明確になりました!

2つの入力パターンが分かりやすく説明されています:

  1. Altキー押下中の入力
  2. マイクボタンによる入力開始/終了

197-206: 関連記事セクションの追加は非常に有用です!

ユーザーが必要な情報を見つけやすくなり、プロジェクトの理解を深めるのに役立ちます。


271-273: 新しいスポンサーの追加を確認しました!

スポンサーセクションが適切に更新されています。


285-285: ライセンスの無償利用に関する説明が明確になりました!

非営利目的での利用に関する説明が分かりやすく追記されています。

src/components/messageInputContainer.tsx (2)

122-124: 設定の取得とWebSocket接続の確認が適切に実装されています

WebSocketの状態チェックと設定の取得が適切に実装されており、安全な通信処理が確保されています。


125-143: 条件分岐による入力タイプの処理が実装されています

realtimeAPIModeContentTypeに基づいて、音声入力とテキスト入力を適切に処理する実装になっています。しかし、以下の点について確認が必要です:

  1. 音声データが空の場合のエラーハンドリング
  2. テキストが空の場合の処理

また、デバッグ用のconsole.logが本番環境に残っているため、削除を検討してください。

-          console.log('Sending buffer. Length:', audioBufferRef.current.length)
-          console.log('Sending text. userMessage:', currentText)
✅ Verification successful

Let me search for error handling implementations around this code.


空の入力に対する適切なエラーハンドリングが実装されています

コードの確認結果:

  • 音声データについては、audioBufferRef.current && audioBufferRef.current.length > 0 による空チェックが実装されています
  • テキストデータは transcriptRef.current.trim() で空白を除去した後に処理されています

なお、デバッグ用の console.log ステートメントの削除については、別途対応をお願いします。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# エラーハンドリングの実装を確認
rg -A 5 "realtimeAPIModeContentType.*input_audio" .

Length of output: 563


Script:

#!/bin/bash
# Check error handling for empty audio buffer
ast-grep --pattern 'audioBufferRef.current.length'

# Check error handling for empty text
ast-grep --pattern 'transcriptRef.current.trim()'

# Check the broader context of the send function
rg -B 10 -A 10 "sendContent = \[" src/components/messageInputContainer.tsx

Length of output: 1703

docs/README_en.md (4)

92-99: 新しいLLMサービスの追加について

以下のLLMサービスが追加されており、ユーザーの選択肢が大幅に拡大されています:

  • Azure OpenAI
  • Groq
  • Cohere
  • Mistral AI
  • Perplexity
  • Fireworks
  • Local LLM
  • Dify

これらの追加は適切に文書化されています。


109-110: 音声合成エンジンの拡張について

OpenAIとAzure OpenAIのTTSサービスが追加され、適切に文書化されています。APIキーが必要である旨も明確に記載されています。


131-132: 外部統合モードの説明について

WebSocketを介したサーバーアプリとの連携について、より具体的な説明が追加されています。別途サーバーアプリが必要である旨も明確に記載されています。


189-192: マイク入力方法の説明について

2つのマイク入力パターンが明確に説明されています:

  1. Altキー(またはoptionキー)を押しながら録音
  2. マイクボタンのクリックによる録音開始/終了

ユーザーにとって分かりやすい説明になっています。

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

15-17: ステート管理の実装が適切です

settingsStoreからrealtimeAPIModeContentTypeを取得する実装は、既存のステート管理パターンに従っており、適切です。

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

4-9: SpeakTask型の定義は適切です

SpeakTask型の定義は明確で、必要なプロパティが適切に含まれています。


16-19: addTaskメソッドのキュー処理は正しく機能します

タスクをキューに追加し、processQueueを適切に呼び出しています。

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

12-13: OpenAIとAzureの音声合成APIのインポートを確認しました

新しい音声合成機能の追加に伴い、適切なインポートが行われています。


16-16: SpeakQueueのインポートを確認しました

音声再生処理のキュー管理を行うためのSpeakQueueがインポートされています。


24-25: SpeakQueueのインスタンス化を確認しました

音声再生タスクの管理に必要なSpeakQueueのインスタンスが正しく作成されています。


102-109: OpenAIの音声合成機能の追加を確認しました

ss.selectVoice'openai'の場合に、synthesizeVoiceOpenAIApiが正しく呼び出されています。パラメータも適切に渡されています。


129-138: 音声再生処理をキューに追加する実装を確認しました

音声再生処理がfetchPromiseの完了後にspeakQueueにタスクとして追加されるようになり、非同期処理が適切に管理されています。

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

9-13: インポート文が正しく追加されています

必要なコンポーネントが適切にインポートされています。


44-49: 新しい設定項目が正しく追加されています

OpenAI TTSとAzure TTSの設定が適切に追加されています。


537-607: OpenAI TTSの設定が正しく追加されています

OpenAI TTSの設定セクションが適切に実装されています。


73-74: 新しい音声エンジンの選択肢が正しく追加されています

{t('UsingOpenAITTS')}{t('UsingAzureTTS')}の翻訳キーがローカライズファイルに正しく定義されていることを確認してください。

以下のスクリプトで翻訳キーが正しく定義されているか確認できます。

✅ Verification successful

翻訳キーが全ての言語ファイルで正しく定義されていることを確認しました

すべての言語ファイル(en, ja, ko, zh)において、UsingOpenAITTSUsingAzureTTSの翻訳キーが適切に定義されており、それぞれの言語に対応した適切な翻訳が設定されています。

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 説明: 翻訳キー 'UsingOpenAITTS' と 'UsingAzureTTS' がローカライズファイルに存在するか確認します。

# テスト: 翻訳キーを検索します。期待結果: 翻訳キーが各言語のファイルに存在する。
rg -e '"UsingOpenAITTS"' -e '"UsingAzureTTS"' src/locales/

Length of output: 113


Script:

#!/bin/bash
# 翻訳ファイルの場所を特定
fd -t f ".*\.(json|js|ts)" -E "*.test.*" -E "*.spec.*" | rg -i "translation|locale|lang"

# 翻訳キーの検索(ファイルが見つかった後で実行)
rg -e "UsingOpenAITTS" -e "UsingAzureTTS" .

Length of output: 1024

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.

⚠️ Potential issue

APIキーの取り扱いに関するセキュリティ上の懸念

APIキーをリクエストボディに含めて送信していますが、これはクライアントサイドでAPIキーが露出するリスクがあります。サーバーサイドでAPIキーを管理し、クライアントには必要最小限の情報のみを送信することを推奨します。

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

-  body: JSON.stringify({
-    message: talk.message,
-    voice,
-    speed,
-    apiKey,
-    azureTTSEndpoint,
-  }),
+  body: JSON.stringify({
+    message: talk.message,
+    voice,
+    speed,
+  }),

サーバーサイドで環境変数としてapiKeyazureTTSEndpointを管理することを推奨します。

📝 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 response = await fetch('/api/azureOpenAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: talk.message,
voice,
speed,
apiKey,
azureTTSEndpoint,
}),
})
const response = await fetch('/api/azureOpenAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: talk.message,
voice,
speed,
}),
})

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

return await response.arrayBuffer()
}
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 timeout = 30000; // 30 seconds
+  const controller = new AbortController();
+  const timeoutId = setTimeout(() => controller.abort(), timeout);
+
   const response = await fetch('/api/azureOpenAITTS', {
     method: 'POST',
     headers: {
       'Content-Type': 'application/json',
     },
     body: JSON.stringify({
       message: talk.message,
       voice,
       speed,
-      apiKey,
-      azureTTSEndpoint,
     }),
+    signal: controller.signal,
   })
+  clearTimeout(timeoutId);

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

Committable suggestion was skipped due to low confidence.

Comment on lines +20 to +26
const res = await fetch('/api/openAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})
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リクエストにタイムアウトの追加を推奨します

長時間のリクエストを防ぐため、タイムアウトの設定を追加することをお勧めします。

    const res = await fetch('/api/openAITTS', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(body),
+     signal: AbortSignal.timeout(30000), // 30秒でタイムアウト
    })
📝 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 res = await fetch('/api/openAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
})
const res = await fetch('/api/openAITTS', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
signal: AbortSignal.timeout(30000), // 30秒でタイムアウト
})

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.

⚠️ Potential issue

セキュリティとバリデーションの改善が必要です

  1. APIキーをリクエストボディに含めることはセキュリティリスクとなる可能性があります。サーバーサイドで管理することを検討してください。

  2. speedパラメータの値(0.25-4.0)のバリデーションを追加することを推奨します。

  try {
+   if (speed < 0.25 || speed > 4.0) {
+     throw new Error('速度は0.25から4.0の間で指定してください')
+   }
    const body = {
      message: talk.message,
      voice: voice,
      model: model,
      speed: speed,
-     apiKey: apiKey,
    }

Committable suggestion was skipped due to low confidence.

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

const buffer = await res.arrayBuffer()
return buffer
} 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

エラーハンドリングの改善を推奨します

HTTPステータスコードに応じた具体的なエラーメッセージを提供することで、デバッグがより容易になります。

    if (!res.ok) {
+     let errorMessage = 'OpenAI APIからの応答が異常です。'
+     switch (res.status) {
+       case 401:
+         errorMessage += 'APIキーが無効です。'
+         break
+       case 429:
+         errorMessage += 'レート制限を超過しました。'
+         break
+       default:
+         errorMessage += `ステータスコード: ${res.status}`
+     }
-     throw new Error(
-       `OpenAI APIからの応答が異常です。ステータスコード: ${res.status}`
-     )
+     throw new Error(errorMessage)
    }
📝 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 (!res.ok) {
throw new Error(
`OpenAI APIからの応答が異常です。ステータスコード: ${res.status}`
)
}
const buffer = await res.arrayBuffer()
return buffer
} catch (error) {
if (error instanceof Error) {
throw new Error(`OpenAI TTSでエラーが発生しました: ${error.message}`)
} else {
throw new Error('OpenAI TTSで不明なエラーが発生しました')
}
}
if (!res.ok) {
let errorMessage = 'OpenAI APIからの応答が異常です。'
switch (res.status) {
case 401:
errorMessage += 'APIキーが無効です。'
break
case 429:
errorMessage += 'レート制限を超過しました。'
break
default:
errorMessage += `ステータスコード: ${res.status}`
}
throw new Error(errorMessage)
}
const buffer = await res.arrayBuffer()
return buffer
} catch (error) {
if (error instanceof Error) {
throw new Error(`OpenAI TTSでエラーが発生しました: ${error.message}`)
} else {
throw new Error('OpenAI TTSで不明なエラーが発生しました')
}
}

Comment on lines +36 to +38
openaiTTSKey: string
azureTTSKey: string
azureTTSEndpoint: string
Copy link

Choose a reason for hiding this comment

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

💡 Codebase verification

TTSサービスのAPIキー管理に関する重要な問題点

コードベースの分析結果から、以下のセキュリティ上の懸念点が確認されました:

  1. APIキーがクライアントサイドのステート(settingsStore)で平文で保存されています
  2. 暗号化メカニズムが実装されていません
  3. APIキーがブラウザのメモリに保持されており、セッション管理による保護がありません

改善が必要な箇所:

  • src/features/stores/settings.ts: APIキーの保存方法の見直し
  • src/components/settings/voice.tsx: クライアントサイドでのキー入力処理
  • src/pages/api/: サーバーサイドでの適切なキー管理の実装
🔗 Analysis chain

APIキーインターフェースの拡張について

新しいTTSサービス用のAPIキーとエンドポイントが追加されています。セキュリティの観点から、これらの値の取り扱いについて以下の確認が必要です:

  1. 環境変数からの読み込み
  2. 値の暗号化
  3. セッション管理での扱い

以下のスクリプトで環境変数の設定を確認できます:


Let me gather more information about how these API keys are handled in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# 環境変数の存在確認
rg "NEXT_PUBLIC_(OPENAI_TTS|AZURE_TTS)" .env*

Length of output: 305


Script:

#!/bin/bash
# Check for API key handling patterns
rg -A 3 "(openaiTTSKey|azureTTSKey|azureTTSEndpoint)" --type ts

# Check for encryption or secure storage patterns
ast-grep --pattern 'encrypt($_)'

# Check for session management related to these keys
rg -A 3 "session.*TTS" --type ts

Length of output: 6638

Comment on lines 144 to +150
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.

🛠️ Refactor suggestion

WebSocketメッセージ構造の更新について

メッセージ構造が適切に更新され、新しいcontent形式に対応していますが、以下の改善を提案します:

  1. 型の安全性を高めるため、メッセージ構造の型定義を追加
  2. WebSocketエラー時のリトライロジックの実装
type WebSocketMessage = {
  type: 'conversation.item.create' | 'response.create';
  item?: {
    type: 'message';
    role: 'user';
    content: Array<{
      type: 'input_audio' | 'input_text';
      text?: string;
      audio?: string;
    }>;
  };
};

Comment on lines +110 to +117
} else if (ss.selectVoice == 'azure') {
buffer = await synthesizeVoiceAzureOpenAIApi(
screenplay.talk,
ss.azureTTSKey || ss.azureKey,
ss.azureTTSEndpoint || ss.azureEndpoint,
ss.openaiTTSVoice,
ss.openaiTTSSpeed
)
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の音声合成でOpenAIの設定値が使用されています

Azureの音声合成関数synthesizeVoiceAzureOpenAIApiに渡されるパラメータで、ss.openaiTTSVoicess.openaiTTSSpeedが使用されています。これはOpenAIの設定であり、Azure用のss.azureTTSVoicess.azureTTSSpeedを使用する必要があります。

以下の修正を適用してください:

             } else if (ss.selectVoice == 'azure') {
               buffer = await synthesizeVoiceAzureOpenAIApi(
                 screenplay.talk,
                 ss.azureTTSKey || ss.azureKey,
                 ss.azureTTSEndpoint || ss.azureEndpoint,
-                ss.openaiTTSVoice,
-                ss.openaiTTSSpeed
+                ss.azureTTSVoice,
+                ss.azureTTSSpeed
               )
             }
📝 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
} else if (ss.selectVoice == 'azure') {
buffer = await synthesizeVoiceAzureOpenAIApi(
screenplay.talk,
ss.azureTTSKey || ss.azureKey,
ss.azureTTSEndpoint || ss.azureEndpoint,
ss.openaiTTSVoice,
ss.openaiTTSSpeed
)
} else if (ss.selectVoice == 'azure') {
buffer = await synthesizeVoiceAzureOpenAIApi(
screenplay.talk,
ss.azureTTSKey || ss.azureKey,
ss.azureTTSEndpoint || ss.azureEndpoint,
ss.azureTTSVoice,
ss.azureTTSSpeed
)

Comment on lines +537 to +676
} else if (selectVoice === 'openai') {
return (
<>
<div>{t('OpenAITTSInfo')}</div>
<div className="mt-16 font-bold">{t('OpenAIAPIKeyLabel')}</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={openaiTTSKey}
onChange={(e) =>
settingsStore.setState({
openaiTTSKey: 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-8">
<select
value={openaiTTSModel}
onChange={(e) =>
settingsStore.setState({
openaiTTSModel: e.target.value as OpenAITTSModel,
})
}
className="px-16 py-8 bg-surface1 hover:bg-surface1-hover rounded-8"
>
<option value="tts-1">tts-1</option>
<option value="tts-1-hd">tts-1-hd</option>
</select>
</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),
})
}}
/>
</>
)
} else if (selectVoice === 'azure') {
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.

🛠️ Refactor suggestion

OpenAI TTSとAzure TTSの共通コードをリファクタリングできます

OpenAI TTSとAzure TTSの設定セクションで、音声選択や速度調整のコードが重複しています。これらを共通のコンポーネントまたは関数として抽出し、コードの再利用性と保守性を向上させることができます。

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用の変数やラベルが誤って使用されています。これにより、Azure TTSの設定が正しく機能しない可能性があります。

以下の修正を提案します:

- {t('OpenAITTSVoice')}
+ {t('AzureTTSVoice')}

- value={openaiTTSVoice}
+ value={azureTTSVoice}

- settingsStore.setState({
-   openaiTTSVoice: e.target.value as OpenAITTSVoice,
+ settingsStore.setState({
+   azureTTSVoice: e.target.value as AzureTTSVoice,

...

- {t('OpenAITTSSpeed')}: {openaiTTSSpeed}
+ {t('AzureTTSSpeed')}: {azureTTSSpeed}

- value={openaiTTSSpeed}
+ value={azureTTSSpeed}

- openaiTTSSpeed: Number(e.target.value),
+ azureTTSSpeed: Number(e.target.value),

...

Azure 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
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),
})
}}
/>
</>
)
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('AzureTTSVoice')}</div>
<div className="mt-8">
<select
value={azureTTSVoice}
onChange={(e) =>
settingsStore.setState({
azureTTSVoice: e.target.value as AzureTTSVoice,
})
}
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('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),
})
}}
/>
</>
)

@tegnike tegnike merged commit 6c0182d into main Oct 25, 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