Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center">
<img style="max-width: 100%;" src="./docs/logo.png">
</h1>
# AITuberKit

<img style="max-width: 100%;" src="./docs/logo.png">

**お知らせ: 本プロジェクトはバージョン v2.0.0 以降、カスタムライセンスを採用しています。商用目的でご利用の場合は、[利用規約](#利用規約) セクションをご確認ください。**

Expand Down Expand Up @@ -275,6 +275,9 @@ npm run dev
<a href="https://github.com/terisuke" title="terisuke">
<img src="https://github.com/terisuke.png" width="40" height="40" alt="terisuke">
</a>
<a href="https://github.com/konpeita" title="konpeita">
<img src="https://github.com/konpeita.png" width="40" height="40" alt="konpeita">
</a>
</p>

他、プライベートスポンサー 複数名
Expand Down
9 changes: 6 additions & 3 deletions docs/README_en.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center">
<img style="max-width: 100%;" src="./logo.png">
</h1>
# AITuberKit

<img style="max-width: 100%;" src="./logo.png">

**Notice: From version v2.0.0, this project adopts a custom license. If you plan to use it for commercial purposes, please check the [Usage Agreement](#usage-agreement) section.**

Expand Down Expand Up @@ -276,6 +276,9 @@ Your support will greatly contribute to the development and improvement of the A
<a href="https://github.com/terisuke" title="terisuke">
<img src="https://github.com/terisuke.png" width="40" height="40" alt="terisuke">
</a>
<a href="https://github.com/konpeita" title="konpeita">
<img src="https://github.com/konpeita.png" width="40" height="40" alt="konpeita">
</a>
</p>

Plus multiple private sponsors
Expand Down
9 changes: 6 additions & 3 deletions docs/README_ko.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center">
<img style="max-width: 100%;" src="./logo.png">
</h1>
# AITuberKit

<img style="max-width: 100%;" src="./logo.png">

**공지사항: 버전 v2.0.0부터 이 프로젝트는 커스텀 라이선스를 채택하고 있습니다. 상업적 목적으로 사용하실 경우 [이용 약관](#이용-약관) 섹션을 확인해 주시기 바랍니다.**

Expand Down Expand Up @@ -272,6 +272,9 @@ npm run dev
<a href="https://github.com/terisuke" title="terisuke">
<img src="https://github.com/terisuke.png" width="40" height="40" alt="terisuke">
</a>
<a href="https://github.com/konpeita" title="konpeita">
<img src="https://github.com/konpeita.png" width="40" height="40" alt="konpeita">
</a>
</p>

그 외, 다수의 비공개 스폰서
Expand Down
9 changes: 6 additions & 3 deletions docs/README_zh.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h1 align="center">
<img style="max-width: 100%;" src="./logo.png">
</h1>
# AITuberKit

<img style="max-width: 100%;" src="./logo.png">
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

画像のアクセシビリティを改善してください

スクリーンリーダーのユーザーのために、画像にalt属性を追加することを推奨します。

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

-<img style="max-width: 100%;" src="./logo.png">
+<img style="max-width: 100%;" src="./logo.png" alt="AITuberKitのロゴ">
📝 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
<img style="max-width: 100%;" src="./logo.png">
<img style="max-width: 100%;" src="./logo.png" alt="AITuberKitのロゴ">
🧰 Tools
🪛 Markdownlint

3-3: null
Images should have alternate text (alt text)

(MD045, no-alt-text)


**通知:从版本v2.0.0开始,本项目采用自定义许可方式。如果您计划将其用于商业目的,请查看[使用协议](#使用协议)部分。**

Expand Down Expand Up @@ -271,6 +271,9 @@ npm run dev
<a href="https://github.com/terisuke" title="terisuke">
<img src="https://github.com/terisuke.png" width="40" height="40" alt="terisuke">
</a>
<a href="https://github.com/konpeita" title="konpeita">
<img src="https://github.com/konpeita.png" width="40" height="40" alt="konpeita">
</a>
</p>

以及多位匿名贊助者
Expand Down
1 change: 1 addition & 0 deletions locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"AivisSpeechSpeed": "Speed",
"AivisSpeechPitch": "Pitch",
"AivisSpeechIntonation": "Intonation",
"UpdateSpeakerList": "Update Speaker List",
"UsingGoogleTTS": "Google TTS",
"UsingStyleBertVITS2": "Style-Bert-VITS2",
"StyleBertVITS2Info": "Using Style-Bert-VITS2. It supports only Japanese, English, and Chinese. If using a local API, you need to download and launch the app that suits your environment from the site below. Please also set up an API key if necessary.",
Expand Down
3 changes: 2 additions & 1 deletion locales/ja/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@
"VoicevoxIntonation": "抑揚",
"UsingAivisSpeech": "AivisSpeechを使用する",
"AivisSpeechInfo": "AivisSpeechを使用しています。日本語のみに対応しています。ローカルAPIを使用するので下記のサイトから環境にあったアプリをダウンロードし、起動しておく必要があります。",
"AivisSpeechSpeaker": "ボイスタイプ",
"AivisSpeechSpeaker": "話者",
"AivisSpeechSpeed": "話速",
"AivisSpeechPitch": "音高",
"AivisSpeechIntonation": "抑揚",
"UpdateSpeakerList": "話者リストを更新",
"UsingGoogleTTS": "Google TTSを使用する",
"UsingStyleBertVITS2": "Style-Bert-VITS2を使用する",
"StyleBertVITS2Info": "Style-Bert-VITS2を使用しています。日・英・中のみに対応しています。ローカルAPIを使用する場合は、下記のサイトから環境にあったアプリをダウンロードし起動しておく必要があります。必要な場合はAPIキーも設定してください。",
Expand Down
1 change: 1 addition & 0 deletions locales/ko/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"AivisSpeechSpeed": "말 속도",
"AivisSpeechPitch": "음높이",
"AivisSpeechIntonation": "억양",
"UpdateSpeakerList": "보이스 타입 업데이트",
"UsingGoogleTTS": "Google TTS 사용",
"UsingStyleBertVITS2": "Style-Bert-VITS2 사용",
"StyleBertVITS2Info": "Style-Bert-VITS2를 사용하고 있습니다. 일본어, 영어, 중국어만 지원됩니다. 로컬 API를 사용하는 경우 아래 사이트에서 환경에 맞는 앱을 다운로드하고 실행해야 합니다. 필요한 경우 API 키도 설정해 주세요.",
Expand Down
105 changes: 53 additions & 52 deletions locales/zh/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"YoutubeLiveID": "YouTube 直播 ID",
"ConversationContinuityMode": "會話持續模式(測試版)",
"ConversationContinuityModeInfo": "這是一個在沒有評論時,AI會自行嘗試繼續會話的模式。目前僅支援 OpenAI, Anthropic Claude, Google Gemini。",
"ConversationContinuityModeInfo2": "由於一次回答可能多次調用 LLM,因此 API 使用費用可能會增加,請注意。",
"ConversationContinuityModeInfo3": "在 gpt-4o、gpt-4-turbo、claude-3-opus、claude-3.5-sonnet 上能夠比較穩定地運行。",
"ConversationContinuityModeInfo2": "由於一次回答可能多次呼叫 LLM,因此 API 使用費用可能會增加,請注意。",
"ConversationContinuityModeInfo3": "在 gpt-4o、gpt-4-turbo、claude-3-opus、claude-3.5-sonnet 上能夠比較穩定地執行。",
"StatusOn": "狀態:開",
"StatusOff": "狀態:關",
"Select": "選擇",
Expand All @@ -33,13 +33,13 @@
"GroqAPIKeyLabel": "Groq API 金鑰",
"DifyAPIKeyLabel": "Dify API 金鑰",
"APIKeyInstruction": "您可以在下方獲取 API 金鑰。請將獲得的 API 金鑰輸入到表單中。",
"LocalLLMInfo": "Local LLM 伺服器必須正在運行。",
"LocalLLMInfo": "Local LLM 伺服器必須正在執行。",
"LocalLLMInfo2": "Local LLM 伺服器URL 和 模型名 必須正確填寫。",
"GroqInfo": "Groq API 直接從瀏覽器存取。",
"DifyInfo": "Dify 只支援聊天機器人和代理型態。",
"DifyInfo2": "会話履歴的長度取決於Dify聊天機器人的規格。",
"DifyInfo2": "會話履歴的長度取決於Dify聊天機器人的規格。",
"DifyInfo3": "例:http://localhost:80/v1/chat-messages",
"DifyInstruction": "如果您正在使用 Dify,則此系統提示將不會被使用。請將 Dify 聊天機器人設定為系統提示。",
"DifyInstruction": "如果您正在使用 Dify,則此係統提示將不會被使用。請將 Dify 聊天機器人設定為系統提示。",
"EnterURL": "輸入 URL",
"CharacterModelLabel": "角色模型",
"OpenVRM": "開啟 VRM",
Expand All @@ -63,6 +63,7 @@
"AivisSpeechSpeed": "語速",
"AivisSpeechPitch": "音調",
"AivisSpeechIntonation": "語調",
"UpdateSpeakerList": "更新語音角色",
"UsingGoogleTTS": "使用 Google TTS",
"UsingStyleBertVITS2": "使用 Style-Bert-VITS2",
"StyleBertVITS2Info": "使用 Style-Bert-VITS2。僅支援日語、英語和中文。如果使用本地 API,您需要從以下網站下載並啟動適合您環境的應用程式。如有需要,請也設定 API 金鑰。",
Expand All @@ -80,13 +81,13 @@
"ConversationHistory": "聊天記錄",
"ConversationHistoryInfo": "最新的 10 個對話內容會被儲存為記憶。",
"ConversationHistoryReset": "重設聊天記錄",
"NotConnectedToExternalAssistant": "未連接外部助理。",
"NotConnectedToExternalAssistant": "未連線外部助理。",
"APIKeyNotEntered": "尚未輸入 API 金鑰。",
"ChatLog": "聊天記錄",
"EnterYourQuestion": "在此輸入您的問題",
"AnswerGenerating": "正在生成回答",
"AboutThisApplication": "關於這個應用程式",
"AboutThisApplicationDescription": "只需使用網頁瀏覽器,即可通過麥克風或文字輸入、語音合成與 3D 角色對話。你可以更換角色(VRM)、設定性格和調整語音。<br />設定可以從左上角的選單按鈕進行更改。",
"AboutThisApplicationDescription": "只需使用網頁瀏覽器,即可透過麥克風或文字輸入、語音合成與 3D 角色對話。你可以更換角色(VRM)、設定性格和調整語音。<br />設定可以從左上角的選單按鈕進行更改。",
"TechnologyIntroduction": "技術介紹",
"TechnologyIntroductionDescription1": "這個應用程式是基於 pixiv 公司的 <b>ChatVRM</b> 改造而成。原始程式碼請參考",
"TechnologyIntroductionLink1": "這裡",
Expand All @@ -97,9 +98,9 @@
"TechnologyIntroductionDescription6": "等各種 TTS。詳細內容請參閱此",
"TechnologyIntroductionLink2": "解說文章",
"TechnologyIntroductionDescription7": "。",
"SourceCodeDescription1": "這個應用程式的源代碼在 GitHub 上公開,歡迎自由修改和改進。",
"SourceCodeDescription1": "這個應用程式的原始碼在 GitHub 上公開,歡迎自由修改和改進。",
"RepositoryURL": "儲存庫 URL:",
"DontShowIntroductionNextTime": "下次不再顯示此對話框",
"DontShowIntroductionNextTime": "下次不再顯示此對話方塊",
"Close": "關閉",
"Language": "語言設定",
"UsingGSVITTS": "使用 GSVI TTS",
Expand All @@ -109,66 +110,66 @@
"GSVITTSBatchSize": "GSVI TTS 批次大小 (1 ~ 100 數值越大推理速度越快,太大可能會用完記憶體)",
"GSVITTSSpeechRate": "語速 (0.5 ~ 2.0 數字越大越快)",
"UsingElevenLabs": "使用 ElevenLabs",
"ElevenLabsInfo": "使用 ElevenLabs API。支持多种语言。请从下面的URL获取API密钥。",
"ElevenLabsApiKey": "ElevenLabs API密钥",
"ElevenLabsVoiceId": "ElevenLabs 语音ID",
"ElevenLabsVoiceIdInfo": "请从下面的URL选择语音ID。",
"ElevenLabsInfo": "使用 ElevenLabs API。支援多種語言。請從下面的URL獲取API金鑰。",
"ElevenLabsApiKey": "ElevenLabs API金鑰",
"ElevenLabsVoiceId": "ElevenLabs 語音ID",
"ElevenLabsVoiceIdInfo": "請從下面的URL選擇語音ID。",
"CharacterName": "角色名字",
"ShowAssistantText": "顯示回答框",
"ShowCharacterName": "在回答框中显示角色名称",
"AdvancedSettings": "高级设置",
"ShowControlPanel": "显示设置按钮",
"ShowControlPanelInfo": "可以通过按 Cmd + . (Mac) / Ctrl + . (Windows) 来显示设置界面。",
"ShowCharacterName": "在回答框中顯示角色名稱",
"AdvancedSettings": "高階設定",
"ShowControlPanel": "顯示設定按鈕",
"ShowControlPanelInfo": "可以透過按 Cmd + . (Mac) / Ctrl + . (Windows) 來顯示設定介面。",
"SlideMode": "投影片模式",
"SelectedSlideDocs": "使用的投影片",
"SlideModeDescription": "這是一個 AI 自動展示投影片的模式。僅在選擇的 AI 服務為 OpenAI、Anthropic Claude或 Google Gemini 時有效。",
"PdfConvertLabel": "PDF 投影片轉換",
"PdfConvertDescription": "將 PDF 轉換為投影片模式數據。僅在選擇的 AI 服務為 OpenAI、Anthropic Claude或 Google Gemini 時可用。",
"PdfConvertFileUpload": "選擇 PDF 文件",
"PdfConvertFolderName": "保存文件夹名称",
"PdfConvertModelSelect": "选择模型",
"PdfConvertButton": "将PDF转换为幻灯片",
"PdfConvertLoading": "转换中...",
"PdfConvertSuccess": "转换完成",
"PdfConvertError": "转换失败",
"PdfConvertSubmitError": "请确保已设置PDF文件、文件夹名称和API密钥。",
"PdfConvertDescription": "將 PDF 轉換為投影片模式資料。僅在選擇的 AI 服務為 OpenAI、Anthropic Claude或 Google Gemini 時可用。",
"PdfConvertFileUpload": "選擇 PDF 檔案",
"PdfConvertFolderName": "儲存資料夾名稱",
"PdfConvertModelSelect": "選擇模型",
"PdfConvertButton": "將PDF轉換為幻燈片",
"PdfConvertLoading": "轉換中...",
"PdfConvertSuccess": "轉換完成",
"PdfConvertError": "轉換失敗",
"PdfConvertSubmitError": "請確保已設定PDF檔案、資料夾名稱和API金鑰。",
"LocalStorageReset": "重設設定(頁面會重新載入)",
"Errors": {
"EmptyAPIKey": "API 密钥未设置",
"AIInvalidProperty": "AI 服务设置值不正确",
"AIAPIError": "AI API 执行时发生错误",
"InvalidAIService": "选择的 AI 服务不正确",
"MethodNotAllowed": "请求不适当",
"TTSServiceError": "{{serviceName}} TTS服务发生错误:{{message}}",
"UnexpectedError": "发生了意外错误"
"EmptyAPIKey": "API 金鑰未設定",
"AIInvalidProperty": "AI 服務設定值不正確",
"AIAPIError": "AI API 執行時發生錯誤",
"InvalidAIService": "選擇的 AI 服務不正確",
"MethodNotAllowed": "請求不適當",
"TTSServiceError": "{{serviceName}} TTS服務發生錯誤:{{message}}",
"UnexpectedError": "發生了意外錯誤"
},
"MessageReceiver": "接收外部指示",
"MessageReceiverDescription": "你可以使用 API 来指示 AI 角色从外部说话。",
"MessageReceiverDescription": "你可以使用 API 來指示 AI 角色從外部說話。",
"ClientID": "Client ID",
"OpenSendMessagePage": "開啟發送訊息頁面",
"OpenSendMessagePage": "開啟傳送訊息頁面",
"RealtimeAPIMode": "實時API模式",
"RealtimeAPIModeContentType": "送信類型",
"RealtimeAPIModeVoice": "語音類型",
"AudioMode": "音頻模式(Beta)",
"InputText": "文本",
"InputAudio": "音頻",
"RealtimeAPIModeContentType": "送信型別",
"RealtimeAPIModeVoice": "語音型別",
"AudioMode": "音訊模式(Beta)",
"InputText": "文字",
"InputAudio": "音訊",
"UpdateRealtimeAPISettings": "更新實時API設定",
"UpdateRealtimeAPISettingsInfo": "當更新 API 密鑰、Azure Endpoint、語音類型或系統提示時,請按更新按鈕以開始新的 WebSocket 會話。",
"UpdateRealtimeAPISettingsInfo": "當更新 API 金鑰、Azure Endpoint、語音型別或系統提示時,請按更新按鈕以開始新的 WebSocket 會話。",
"AzureEndpoint": "Azure Endpoint",
"Toasts": {
"WebSocketConnectionError": "WebSocket连接发生错误",
"WebSocketConnectionClosed": "WebSocket连接已关闭",
"WebSocketConnectionAttempt": "正在尝试WebSocket连接...",
"WebSocketConnectionSuccess": "WebSocket连接成功",
"FunctionExecuting": "正在执行{{funcName}}",
"FunctionExecutionFailed": "{{funcName}}执行失败",
"FirefoxNotSupported": "Firefox不支持此功能"
"WebSocketConnectionError": "WebSocket連線發生錯誤",
"WebSocketConnectionClosed": "WebSocket連線已關閉",
"WebSocketConnectionAttempt": "正在嘗試WebSocket連線...",
"WebSocketConnectionSuccess": "WebSocket連線成功",
"FunctionExecuting": "正在執行{{funcName}}",
"FunctionExecutionFailed": "{{funcName}}執行失敗",
"FirefoxNotSupported": "Firefox不支援此功能"
},
"UsingOpenAITTS": "使用 OpenAI",
"OpenAITTSInfo": "使用 OpenAI。它支持多种语言。如果您选择 OpenAI 作为 AI 服务,则不需要设置下面的 API 密钥。",
"OpenAITTSVoice": "语音类型",
"OpenAITTSInfo": "使用 OpenAI。它支援多種語言。如果您選擇 OpenAI 作為 AI 服務,則不需要設定下面的 API 金鑰。",
"OpenAITTSVoice": "語音型別",
"OpenAITTSModel": "模型",
"OpenAITTSSpeed": "话速",
"OpenAITTSSpeed": "話速",
"UsingAzureTTS": "使用 Azure OpenAI",
"AzureTTSInfo": "使用 Azure OpenAI。它支持多种语言。"
"AzureTTSInfo": "使用 Azure OpenAI。它支援多種語言。"
}
2 changes: 1 addition & 1 deletion src/components/settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const Main = () => {
const Footer = () => {
return (
<footer className="absolute py-4 bg-[#413D43] text-center text-white font-Montserrat bottom-0 w-full">
powered by ChatVRM from Pixiv. version 2.8.1
powered by ChatVRM from Pixiv. version 2.10.0
</footer>
)
}
4 changes: 2 additions & 2 deletions src/components/settings/modelProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,10 @@ const ModelProvider = () => {
}
}}
>
<option value="gpt-4o-mini">gpt-4o-mini</option>
<option value="chatgpt-4o-latest">chatgpt-4o-latest</option>
<option value="gpt-4o-mini">gpt-4o-mini</option>
<option value="gpt-4o-2024-08-06">gpt-4o-2024-08-06</option>
<option value="gpt-4o">gpt-4o(2024-05-13)</option>
<option value="gpt-4o-2024-11-20">gpt-4o-2024-11-20</option>
<option value="gpt-4-turbo">gpt-4-turbo</option>
</select>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/settings/slideConvert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,10 @@ const SlideConvert: React.FC<SlideConvertProps> = ({ onFolderUpdate }) => {
>
{aiService === 'openai' && (
<>
<option value="gpt-4o-mini">gpt-4o-mini</option>
<option value="chatgpt-4o-latest">chatgpt-4o-latest</option>
<option value="gpt-4o-mini">gpt-4o-mini</option>
<option value="gpt-4o-2024-08-06">gpt-4o-2024-08-06</option>
<option value="gpt-4o">gpt-4o(2024-05-13)</option>
<option value="gpt-4o-2024-11-20">gpt-4o-2024-11-20</option>
<option value="gpt-4-turbo">gpt-4-turbo</option>
</>
)}
Expand Down
24 changes: 23 additions & 1 deletion src/components/settings/voice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ const Voice = () => {
label="https://aivis-project.com/"
/>
</div>
<div className="mt-16 font-bold">{t('SpeakerSelection')}</div>
<div className="mt-16 font-bold">{t('AivisSpeechSpeaker')}</div>
<div className="flex items-center">
<select
value={aivisSpeechSpeaker}
Expand All @@ -463,6 +463,28 @@ const Voice = () => {
>
{t('TestVoice')}
</TextButton>
<TextButton
onClick={async () => {
const response = await fetch('/api/update-aivis-speakers')
if (response.ok) {
// 話者リストを再読み込み
const updatedSpeakersResponse = await fetch(
'/speakers_aivis.json'
)
const updatedSpeakers =
await updatedSpeakersResponse.json()
// speakers_aivisを更新
speakers_aivis.splice(
0,
speakers_aivis.length,
...updatedSpeakers
)
}
}}
className="ml-16"
>
{t('UpdateSpeakerList')}
</TextButton>
Comment on lines +466 to +487
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

話者リストの更新機能に改善の余地があります

以下の点について改善を提案します:

  1. エラーハンドリングの強化
  2. 状態管理の改善
  3. ユーザーフィードバックの追加

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

 <TextButton
   onClick={async () => {
+    try {
+      settingsStore.setState({ isUpdatingSpeakers: true });
       const response = await fetch('/api/update-aivis-speakers')
-      if (response.ok) {
-        // 話者リストを再読み込み
-        const updatedSpeakersResponse = await fetch(
-          '/speakers_aivis.json'
-        )
-        const updatedSpeakers =
-          await updatedSpeakersResponse.json()
-        // speakers_aivisを更新
-        speakers_aivis.splice(
-          0,
-          speakers_aivis.length,
-          ...updatedSpeakers
-        )
+      if (!response.ok) {
+        throw new Error('更新に失敗しました');
       }
+      const updatedSpeakersResponse = await fetch('/speakers_aivis.json');
+      const updatedSpeakers = await updatedSpeakersResponse.json();
+      settingsStore.setState({ speakers_aivis: updatedSpeakers });
+      alert('話者リストを更新しました');
+    } catch (error) {
+      console.error('話者リスト更新エラー:', error);
+      alert('話者リストの更新に失敗しました');
+    } finally {
+      settingsStore.setState({ isUpdatingSpeakers: false });
+    }
   }}
   className="ml-16"
+  disabled={settingsStore((s) => s.isUpdatingSpeakers)}
 >
-  {t('UpdateSpeakerList')}
+  {settingsStore((s) => s.isUpdatingSpeakers) 
+    ? t('Updating') 
+    : t('UpdateSpeakerList')
+  }
 </TextButton>

Committable suggestion skipped: line range outside the PR's diff.

</div>
<div className="my-24 font-bold">
<div className="select-none">
Expand Down
30 changes: 24 additions & 6 deletions src/components/speakers_aivis.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,26 @@
[
{ "speaker": "Anneli/ノーマル", "id": 888753760 },
{ "speaker": "Anneli/通常", "id": 888753761 },
{ "speaker": "Anneli/テンション高め", "id": 888753762 },
{ "speaker": "Anneli/落ち着き", "id": 888753763 },
{ "speaker": "Anneli/上機嫌", "id": 888753764 },
{ "speaker": "Anneli/怒り・悲しみ", "id": 888753765 }
{
"speaker": "Anneli/ノーマル",
"id": 888753760
},
{
"speaker": "Anneli/通常",
"id": 888753761
},
{
"speaker": "Anneli/テンション高め",
"id": 888753762
},
{
"speaker": "Anneli/落ち着き",
"id": 888753763
},
{
"speaker": "Anneli/上機嫌",
"id": 888753764
},
{
"speaker": "Anneli/怒り・悲しみ",
"id": 888753765
}
]
Loading
Loading