-
-
Notifications
You must be signed in to change notification settings - Fork 143
にじボイスをTTSの選択肢に追加 #258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
にじボイスをTTSの選択肢に追加 #258
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Walkthroughこのプルリクエストでは、NijiVoiceサービスに関連する新しい環境変数とローカリゼーションエントリが追加されました。具体的には、 Changes
Possibly related PRs
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Outside diff range and nitpick comments (6)
src/pages/api/get-nijivoice-actors.ts (1)
14-24: パフォーマンスとエラーハンドリングの改善が必要です
- レスポンスのキャッシュ
- タイムアウトの設定
- より詳細なエラーメッセージ
以下の修正を提案します:
try { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), 5000); + const response = await fetch( 'https://api.nijivoice.com/api/platform/v1/voice-actors', { headers: { 'x-api-key': nijivoiceApiKey as string, + 'Cache-Control': 'public, max-age=300', }, + signal: controller.signal, } ) + clearTimeout(timeoutId); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } const data = await response.json() return res.status(200).json(data)src/features/messages/synthesizeVoiceNijivoice.ts (1)
9-36: エラーハンドリングの改善が必要です
- 再試行メカニズムの追加
- より具体的なエラーメッセージ
- i18n対応
以下の修正を提案します:
+const MAX_RETRIES = 3; +const RETRY_DELAY = 1000; + +async function delay(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + export async function synthesizeVoiceNijivoiceApi( talk: Talk, apiKey: string, voiceActorId: string, speed: number ) { + let attempts = 0; try { - const res = await fetch('/api/tts-nijivoice', { - method: 'POST', + while (attempts < MAX_RETRIES) { + try { + const res = await fetch('/api/tts-nijivoice', { + method: 'POST', ... + return await res.arrayBuffer(); + } catch (error) { + attempts++; + if (attempts === MAX_RETRIES) throw error; + await delay(RETRY_DELAY * attempts); + } + } - return await res.arrayBuffer() } catch (error) { if (error instanceof Error) { - throw new Error(`Nijivoiceでエラーが発生しました: ${error.message}`) + throw new Error(`音声合成中にエラーが発生しました: ${error.message}`) } else { - throw new Error('Nijivoiceで不明なエラーが発生しました') + throw new Error('音声合成中に予期せぬエラーが発生しました') } } }.env.example (1)
88-92: 環境変数の追加についてドキュメント改善の提案NijiVoice関連の環境変数が適切に追加されていますが、以下の改善を提案します:
- 各変数の期待される値や形式について説明を追加
NEXT_PUBLIC_NIJIVOICE_SPEEDの有効な範囲を明記以下のような形でコメントを追加することを提案します:
# NijiVoice -NIJIVOICE_API_KEY= +# APIキー(必須) +NIJIVOICE_API_KEY="" -NEXT_PUBLIC_NIJIVOICE_ACTOR_ID= +# アクターID(必須) +NEXT_PUBLIC_NIJIVOICE_ACTOR_ID="" -NEXT_PUBLIC_NIJIVOICE_SPEED= +# 音声の速度(オプション、デフォルト: 1.0、範囲: 0.5-2.0) +NEXT_PUBLIC_NIJIVOICE_SPEED=""src/features/stores/settings.ts (1)
257-262: 速度パラメータの検証を追加することを推奨します。現在の実装では、
nijivoiceSpeedのパース失敗時のフォールバック処理は実装されていますが、有効な範囲の検証が行われていません。以下のような検証ロジックの追加を提案します:
nijivoiceSpeed: - parseFloat(process.env.NEXT_PUBLIC_NIJIVOICE_SPEED || '1.0') || 1.0, + (() => { + const speed = parseFloat(process.env.NEXT_PUBLIC_NIJIVOICE_SPEED || '1.0') || 1.0; + return Math.max(0.5, Math.min(2.0, speed)); // 一般的なTTS速度の範囲に制限 + })(),src/components/settings/voice.tsx (2)
854-859: 話者データの型安全性が必要です
any型の使用を避け、話者データの型を明示的に定義することを推奨します。以下の実装を提案します:
interface NijiVoiceActor { id: string; name: string; } const [nijivoiceSpeakers, setNijivoiceSpeakers] = useState<NijiVoiceActor[]>([]); // マッピング部分の修正 {nijivoiceSpeakers.map((actor: NijiVoiceActor) => ( <option key={actor.id} value={actor.id}> {actor.name} </option> ))}
825-879: UIのエラー状態とローディング状態の表示が必要ですユーザー体験を向上させるため、話者一覧の取得状態をUIに反映することを推奨します。
以下のような条件付きレンダリングの追加を提案します:
<div className="mt-8"> + {isLoading && ( + <div className="text-warning">読み込み中...</div> + )} + {error && ( + <div className="text-error">{error}</div> + )} <select value={nijivoiceActorId} onChange={(e) => { settingsStore.setState({ nijivoiceActorId: e.target.value, }) }} className="px-16 py-8 bg-surface1 hover:bg-surface1-hover rounded-8" + disabled={isLoading} >
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (14)
.env(1 hunks).env.example(1 hunks)locales/en/translation.json(1 hunks)locales/ja/translation.json(1 hunks)locales/ko/translation.json(1 hunks)locales/zh/translation.json(1 hunks)src/components/settings/based.tsx(1 hunks)src/components/settings/voice.tsx(4 hunks)src/features/constants/settings.ts(1 hunks)src/features/messages/speakCharacter.ts(2 hunks)src/features/messages/synthesizeVoiceNijivoice.ts(1 hunks)src/features/stores/settings.ts(3 hunks)src/pages/api/get-nijivoice-actors.ts(1 hunks)src/pages/api/tts-nijivoice.ts(1 hunks)
🔇 Additional comments (9)
src/features/constants/settings.ts (1)
38-38: AIVoiceタイプへのnijivoiceの追加を承認します
変更は適切に実装されていますが、以下の点を確認することをお勧めします。
✅ Verification successful
nijivoiceの実装が適切に行われていることを確認しました
voice.tsxコンポーネントにnijivoiceのオプションが正しく実装され、必要な設定項目(APIキー、話者ID、速度など)も適切に組み込まれています。また、関連するAPI実装やストア設定も整っています。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: voice選択UIコンポーネントでnijivoiceが適切に処理されているか確認
# Test: Check if nijivoice is properly handled in voice selection components
rg -l "AIVoice.*nijivoice" src/components/
Length of output: 44
Script:
#!/bin/bash
# Search for voice selection related components and their usage of AIVoice
rg -A 5 "AIVoice" src/components/ src/features/
Length of output: 2448
Script:
#!/bin/bash
# Search for any nijivoice related implementations
rg "nijivoice" src/
Length of output: 3533
Script:
#!/bin/bash
# Find voice selection related components
fd "voice" src/components/
Length of output: 60
.env (1)
88-92: 環境変数の追加が.env.exampleと一致していることを確認
.env.exampleファイルと同様の変更が適切に実装されています。変数の配置と形式が一貫しており、問題ありません。
src/components/settings/based.tsx (1)
66-67: 実装は適切です!
日本語専用のTTSサービスとしてNijiVoiceを他の日本語TTSサービス(voicevox、koeiromap、aivis_speech)と同様に扱う実装になっています。非日本語が選択された場合、適切にGoogleTTSに切り替わります。
src/features/messages/speakCharacter.ts (1)
18-18: 実装は論理的で一貫性があります!
NijiVoice TTSの実装が他のTTSサービスと同様のパターンで実装されており、以下の点で適切です:
- 必要なパラメータ(apiKey、actorId、speed)が正しく渡されている
- 既存のエラーハンドリング機構を活用している
- コードの構造が他のTTSサービスと統一されている
Also applies to: 125-131
locales/zh/translation.json (2)
67-71: 翻訳の追加は適切です!
NijiVoice関連の翻訳が以下の点で適切に実装されています:
- 他のTTSサービスと同様の翻訳キー構造を維持
- 必要なUI要素(APIキー、話者ID、速度)の翻訳を網羅
- 既存の翻訳スタイルとフォーマットに準拠
67-71: 他の言語ファイルでの翻訳の存在を確認してください
全ての言語ファイルで同じNijiVoice関連の翻訳キーが実装されていることを確認します。
✅ Verification successful
NijiVoice関連の翻訳キーは全ての言語ファイルで正しく実装されています
検証の結果、以下のNijiVoice関連の翻訳キーが全ての言語ファイル(en, ja, ko, zh)で適切に実装されていることを確認しました:
- UsingNijiVoice
- NijiVoiceInfo
- NijiVoiceApiKey
- NijiVoiceActorId
- NijiVoiceSpeed
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 全言語ファイルでNijiVoice関連の翻訳キーの存在を確認
echo "Checking NijiVoice translations in all language files..."
for key in "UsingNijiVoice" "NijiVoiceInfo" "NijiVoiceApiKey" "NijiVoiceActorId" "NijiVoiceSpeed"; do
echo "\nChecking key: $key"
rg "\"$key\":" locales/
done
Length of output: 2663
locales/ja/translation.json (1)
67-71: にじボイス関連の翻訳が適切に追加されています!
翻訳の内容が明確で、他のTTSサービスの翻訳と一貫性が保たれています。
locales/ko/translation.json (1)
67-71: 韓国語の翻訳が適切に実装されています!
日本語版と同じ構造を保ちながら、適切に韓国語に翻訳されています。
src/features/stores/settings.ts (1)
74-76: ModelProviderインターフェースの拡張が適切に実装されています!
にじボイスの設定に必要な型定義が他のTTSサービスと同様のパターンで追加されています。
| const { apiKey } = req.query | ||
|
|
||
| const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY | ||
| if (!nijivoiceApiKey) { | ||
| return res.status(400).json({ error: 'API key is required' }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
API キーの検証を強化する必要があります
API キーのフォーマット検証を追加することで、不正なリクエストを早期に検出できます。
以下の修正を提案します:
const { apiKey } = req.query
const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY
if (!nijivoiceApiKey) {
return res.status(400).json({ error: 'API key is required' })
}
+if (typeof nijivoiceApiKey !== 'string' || !nijivoiceApiKey.match(/^[A-Za-z0-9-_]+$/)) {
+ return res.status(400).json({ error: 'Invalid API key format' })
+}📝 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.
| const { apiKey } = req.query | |
| const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY | |
| if (!nijivoiceApiKey) { | |
| return res.status(400).json({ error: 'API key is required' }) | |
| } | |
| const { apiKey } = req.query | |
| const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY | |
| if (!nijivoiceApiKey) { | |
| return res.status(400).json({ error: 'API key is required' }) | |
| } | |
| if (typeof nijivoiceApiKey !== 'string' || !nijivoiceApiKey.match(/^[A-Za-z0-9-_]+$/)) { | |
| return res.status(400).json({ error: 'Invalid API key format' }) | |
| } |
| export async function synthesizeVoiceNijivoiceApi( | ||
| talk: Talk, | ||
| apiKey: string, | ||
| voiceActorId: string, | ||
| speed: number | ||
| ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
入力パラメータの検証が必要です
パラメータの型と値の検証を追加することで、より堅牢な実装になります。
以下の修正を提案します:
export async function synthesizeVoiceNijivoiceApi(
talk: Talk,
apiKey: string,
voiceActorId: string,
speed: number
) {
+ if (!talk?.message) {
+ throw new Error('メッセージが必要です');
+ }
+ if (speed < 0.5 || speed > 2.0) {
+ throw new Error('速度は0.5から2.0の間で指定してください');
+ }📝 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.
| export async function synthesizeVoiceNijivoiceApi( | |
| talk: Talk, | |
| apiKey: string, | |
| voiceActorId: string, | |
| speed: number | |
| ) { | |
| export async function synthesizeVoiceNijivoiceApi( | |
| talk: Talk, | |
| apiKey: string, | |
| voiceActorId: string, | |
| speed: number | |
| ) { | |
| if (!talk?.message) { | |
| throw new Error('メッセージが必要です'); | |
| } | |
| if (speed < 0.5 || speed > 2.0) { | |
| throw new Error('速度は0.5から2.0の間で指定してください'); | |
| } |
| const audioResponse = await axios.get(audioUrl, { | ||
| responseType: 'stream', | ||
| timeout: 30000, | ||
| }) | ||
|
|
||
| res.setHeader('Content-Type', 'audio/mpeg') | ||
| audioResponse.data.pipe(res) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ストリーミングの改善が必要です
- メモリリークの防止
- エラーハンドリングの追加
- Content-Length ヘッダーの設定
以下の修正を提案します:
- const audioResponse = await axios.get(audioUrl, {
- responseType: 'stream',
- timeout: 30000,
- })
-
- res.setHeader('Content-Type', 'audio/mpeg')
- audioResponse.data.pipe(res)
+ const audioResponse = await axios.get(audioUrl, {
+ responseType: 'arraybuffer',
+ timeout: 30000,
+ })
+
+ res.setHeader('Content-Type', 'audio/mpeg')
+ res.setHeader('Content-Length', audioResponse.data.length)
+ res.send(audioResponse.data)📝 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.
| const audioResponse = await axios.get(audioUrl, { | |
| responseType: 'stream', | |
| timeout: 30000, | |
| }) | |
| res.setHeader('Content-Type', 'audio/mpeg') | |
| audioResponse.data.pipe(res) | |
| const audioResponse = await axios.get(audioUrl, { | |
| responseType: 'arraybuffer', | |
| timeout: 30000, | |
| }) | |
| res.setHeader('Content-Type', 'audio/mpeg') | |
| res.setHeader('Content-Length', audioResponse.data.length) | |
| res.send(audioResponse.data) |
| const { script, speed, voiceActorId, apiKey } = req.body | ||
|
|
||
| const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY | ||
| if (!nijivoiceApiKey) { | ||
| return res.status(400).json({ error: 'API key is required' }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
リクエストボディの検証が必要です
入力パラメータの存在チェックと型チェックを追加することで、より安全な実装になります。
以下の修正を提案します:
- const { script, speed, voiceActorId, apiKey } = req.body
+ const { script, speed, voiceActorId, apiKey } = req.body
+
+ if (!script || typeof script !== 'string') {
+ return res.status(400).json({ error: 'スクリプトが必要です' })
+ }
+ if (!voiceActorId || typeof voiceActorId !== 'string') {
+ return res.status(400).json({ error: 'ボイスアクターIDが必要です' })
+ }
+ if (typeof speed !== 'number' || speed < 0.5 || speed > 2.0) {
+ return res.status(400).json({ error: '速度は0.5から2.0の間で指定してください' })
+ }📝 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.
| const { script, speed, voiceActorId, apiKey } = req.body | |
| const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY | |
| if (!nijivoiceApiKey) { | |
| return res.status(400).json({ error: 'API key is required' }) | |
| } | |
| const { script, speed, voiceActorId, apiKey } = req.body | |
| if (!script || typeof script !== 'string') { | |
| return res.status(400).json({ error: 'スクリプトが必要です' }) | |
| } | |
| if (!voiceActorId || typeof voiceActorId !== 'string') { | |
| return res.status(400).json({ error: 'ボイスアクターIDが必要です' }) | |
| } | |
| if (typeof speed !== 'number' || speed < 0.5 || speed > 2.0) { | |
| return res.status(400).json({ error: '速度は0.5から2.0の間で指定してください' }) | |
| } | |
| const nijivoiceApiKey = apiKey || process.env.NIJIVOICE_API_KEY | |
| if (!nijivoiceApiKey) { | |
| return res.status(400).json({ error: 'API key is required' }) | |
| } |
| } catch (error) { | ||
| console.error('Error in Nijivoice TTS:', error) | ||
| res.status(500).json({ error: 'Internal Server Error' }) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
エラーハンドリングの標準化が必要です
エラーレスポンスの形式を統一し、より詳細な情報を提供することで、デバッグが容易になります。
以下の修正を提案します:
} catch (error) {
- console.error('Error in Nijivoice TTS:', error)
- res.status(500).json({ error: 'Internal Server Error' })
+ console.error('NijivoiceのTTSでエラーが発生:', error)
+ if (axios.isAxiosError(error)) {
+ const status = error.response?.status || 500
+ const message = error.response?.data?.message || 'サーバーエラーが発生しました'
+ return res.status(status).json({
+ error: message,
+ code: error.code,
+ details: process.env.NODE_ENV === 'development' ? error.message : undefined
+ })
+ }
+ res.status(500).json({
+ error: '予期せぬエラーが発生しました',
+ details: process.env.NODE_ENV === 'development' ? String(error) : undefined
+ })
}📝 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.
| } catch (error) { | |
| console.error('Error in Nijivoice TTS:', error) | |
| res.status(500).json({ error: 'Internal Server Error' }) | |
| } | |
| } catch (error) { | |
| console.error('NijivoiceのTTSでエラーが発生:', error) | |
| if (axios.isAxiosError(error)) { | |
| const status = error.response?.status || 500 | |
| const message = error.response?.data?.message || 'サーバーエラーが発生しました' | |
| return res.status(status).json({ | |
| error: message, | |
| code: error.code, | |
| details: process.env.NODE_ENV === 'development' ? error.message : undefined | |
| }) | |
| } | |
| res.status(500).json({ | |
| error: '予期せぬエラーが発生しました', | |
| details: process.env.NODE_ENV === 'development' ? String(error) : undefined | |
| }) | |
| } |
| "UsingNijiVoice": "NijiVoice", | ||
| "NijiVoiceInfo": "NijiVoice API is used. It supports only Japanese. API key can be obtained from the URL below.", | ||
| "NijiVoiceApiKey": "NijiVoice API Key", | ||
| "NijiVoiceActorId": "NijiVoice Actor ID", | ||
| "NijiVoiceSpeed": "NijiVoice Speed", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
にじボイスのAPIキー取得URLの追加が必要です
NijiVoiceInfoの翻訳文で「下記のURL」と記載されていますが、実際のURLが定義されていません。ElevenLabsなど他の音声サービスと同様に、APIキー取得用の具体的なURLを追加する必要があります。以下の2点の対応をお願いします:
NijiVoiceInfoの文言から「下記のURL」という記述を削除するか、- APIキー取得用のURLを示す新しいキーを追加する
🔗 Analysis chain
APIキー取得用URLの追加が必要です
NijiVoiceInfoの翻訳文に「URL below」という記述がありますが、実際のURLが提供されていません。他の音声サービスと同様に、APIキーを取得するための具体的なURLを追加することを推奨します。
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# 他の音声サービスのURL参照パターンを確認
rg -A 1 "url=\"http" locales/
Length of output: 30
Script:
#!/bin/bash
# Search for URL patterns in translation files
rg -i "url" locales/
# Also check for any existing voice service related URLs
rg -i "voice.*url|url.*voice" locales/
Length of output: 4129
Script:
#!/bin/bash
# Search for any URL key-value pairs in the translation files
rg -i "\".*url\".*:.*\"http" locales/
# Also check for any URL references in the codebase related to NijiVoice
rg -i "nijivoice.*url|url.*nijivoice" .
Length of output: 546
| const [nijivoiceSpeakers, setNijivoiceSpeakers] = useState<Array<any>>([]) | ||
|
|
||
| // にじボイスの話者一覧を取得する関数 | ||
| const fetchNijivoiceSpeakers = async () => { | ||
| try { | ||
| const response = await fetch( | ||
| `/api/get-nijivoice-actors?apiKey=${nijivoiceApiKey}` | ||
| ) | ||
| const data = await response.json() | ||
| if (data.voiceActors) { | ||
| const sortedActors = data.voiceActors.sort( | ||
| (a: any, b: any) => a.id - b.id | ||
| ) | ||
| setNijivoiceSpeakers(sortedActors) | ||
| } | ||
| } catch (error) { | ||
| console.error('Failed to fetch nijivoice speakers:', error) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
ローディング状態とエラー状態の管理が必要です
話者一覧の取得中やエラー発生時のユーザー体験を改善するため、ローディング状態とエラー状態の管理を追加することを推奨します。
以下の実装を提案します:
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const fetchNijivoiceSpeakers = async () => {
setIsLoading(true);
setError(null);
try {
const response = await fetch('/api/get-nijivoice-actors', {
headers: {
'Authorization': `Bearer ${nijivoiceApiKey}`
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
if (data.voiceActors) {
const sortedActors = data.voiceActors.sort(
(a: any, b: any) => a.id - b.id
);
setNijivoiceSpeakers(sortedActors);
}
} catch (error) {
console.error('Failed to fetch nijivoice speakers:', error);
setError(t('Errors.TTSServiceError', {
serviceName: 'NijiVoice',
message: error instanceof Error ? error.message : String(error)
}));
} finally {
setIsLoading(false);
}
};| const response = await fetch( | ||
| `/api/get-nijivoice-actors?apiKey=${nijivoiceApiKey}` | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
APIキーをURLパラメータとして送信することは安全ではありません
APIキーをURLパラメータとして送信すると、サーバーログやブラウザ履歴に記録される可能性があります。代わりにAuthorizationヘッダーを使用することを推奨します。
以下の修正を提案します:
- const response = await fetch(
- `/api/get-nijivoice-actors?apiKey=${nijivoiceApiKey}`
- )
+ const response = await fetch('/api/get-nijivoice-actors', {
+ headers: {
+ 'Authorization': `Bearer ${nijivoiceApiKey}`
+ }
+ })📝 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.
| const response = await fetch( | |
| `/api/get-nijivoice-actors?apiKey=${nijivoiceApiKey}` | |
| ) | |
| const response = await fetch('/api/get-nijivoice-actors', { | |
| headers: { | |
| 'Authorization': `Bearer ${nijivoiceApiKey}` | |
| } | |
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Outside diff range and nitpick comments (2)
src/components/settings/voice.tsx (2)
859-863: 型安全性を向上させる必要があります
nijivoiceSpeakersの型がArray<any>として定義されています。これは型安全性を損なう可能性があります。以下のような型定義を追加することを推奨します:
interface NijiVoiceActor { id: string; name: string; } const [nijivoiceSpeakers, setNijivoiceSpeakers] = useState<NijiVoiceActor[]>([]);
870-874: スピード調整の粒度が粗すぎる可能性があります現在のスピード調整のステップ値が0.1と大きく、細かい調整が難しい可能性があります。より細かい調整を可能にすることを検討してください。
以下の修正を提案します:
<input type="range" min={0.4} max={3.0} - step={0.1} + step={0.01} value={nijivoiceSpeed} // ... rest of the code />
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (1)
src/components/settings/voice.tsx(4 hunks)
🔇 Additional comments (2)
src/components/settings/voice.tsx (2)
67-69:
APIキーをURLパラメータとして送信することはセキュリティ上のリスクがあります
APIキーをURLパラメータとして送信すると、サーバーログやブラウザ履歴に記録される可能性があります。代わりにAuthorizationヘッダーを使用することを推奨します。
以下の修正を提案します:
- const response = await fetch(
- `/api/get-nijivoice-actors?apiKey=${nijivoiceApiKey}`
- )
+ const response = await fetch('/api/get-nijivoice-actors', {
+ headers: {
+ 'Authorization': `Bearer ${nijivoiceApiKey}`
+ }
+ })Likely invalid or redundant comment.
77-79: 🛠️ Refactor suggestion
エラーハンドリングを改善する必要があります
現在のエラーハンドリングではコンソールにログを出力するだけです。ユーザーにエラーを通知し、適切なフォールバック処理を実装することを推奨します。
以下の実装を提案します:
+ const [error, setError] = useState<string | null>(null);
const fetchNijivoiceSpeakers = async () => {
+ setError(null);
try {
// ... existing code ...
} catch (error) {
console.error('Failed to fetch nijivoice speakers:', error);
+ setError(t('Errors.TTSServiceError', {
+ serviceName: 'NijiVoice',
+ message: error instanceof Error ? error.message : String(error)
+ }));
}
}Likely invalid or redundant comment.
にじボイスをTTSの選択肢に追加
Summary by CodeRabbit
新機能
バグ修正
ドキュメント
チョア