From bcd50b89c860b33bb464a5e35e92ac43ad153721 Mon Sep 17 00:00:00 2001 From: dakai Date: Mon, 14 Oct 2024 03:25:44 +0800 Subject: [PATCH 1/4] feat: add voice audio preview button in tts-config option --- app/components/tts-config.tsx | 96 ++++++++++++++++++++++++++++------- 1 file changed, 79 insertions(+), 17 deletions(-) diff --git a/app/components/tts-config.tsx b/app/components/tts-config.tsx index 39ae85730c2..30c1424d698 100644 --- a/app/components/tts-config.tsx +++ b/app/components/tts-config.tsx @@ -1,19 +1,60 @@ import { TTSConfig, TTSConfigValidator } from "../store"; +import React, { useState } from "react"; import Locale from "../locales"; import { ListItem, Select } from "./ui-lib"; import { + ModelProvider, DEFAULT_TTS_ENGINE, DEFAULT_TTS_ENGINES, DEFAULT_TTS_MODELS, DEFAULT_TTS_VOICES, } from "../constant"; import { InputRange } from "./input-range"; +import { IconButton } from "./button"; +import SpeakIcon from "../icons/speak.svg"; +import SpeakStopIcon from "../icons/speak-stop.svg"; +import { createTTSPlayer } from "../utils/audio"; +import { useAppConfig } from "../store"; +import { ClientApi } from "../client/api"; +const ttsPlayer = createTTSPlayer(); export function TTSConfigList(props: { ttsConfig: TTSConfig; updateConfig: (updater: (config: TTSConfig) => void) => void; }) { + const [speechLoading, setSpeechLoading] = useState(false); + const [speechStatus, setSpeechStatus] = useState(false); + + async function openaiSpeech(text: string) { + if (speechStatus) { + ttsPlayer.stop(); + setSpeechStatus(false); + } else { + var api: ClientApi; + api = new ClientApi(ModelProvider.GPT); + const config = useAppConfig.getState(); + setSpeechLoading(true); + ttsPlayer.init(); + let audioBuffer: ArrayBuffer; + audioBuffer = await api.llm.speech({ + model: config.ttsConfig.model, + input: text, + voice: config.ttsConfig.voice, + speed: config.ttsConfig.speed, + }); + setSpeechStatus(true); + ttsPlayer + .play(audioBuffer, () => { + setSpeechStatus(false); + }) + .catch((e) => { + console.error("[OpenAI Speech]", e); + setSpeechStatus(false); + }) + .finally(() => setSpeechLoading(false)); + } + } return ( <> - +
+ : } + text={ + speechLoading + ? "Loading..." + : speechStatus + ? Locale.Chat.Actions.Stop + : Locale.Chat.Actions.Speech + } + onClick={() => { + speechStatus + ? (ttsPlayer.stop(), setSpeechStatus(false)) + : openaiSpeech( + "NextChat,Unleash your imagination, experience the future of AI conversation.", + ); + }} + /> + + +
Date: Mon, 14 Oct 2024 03:46:51 +0800 Subject: [PATCH 2/4] follow the rabbit to fix potential issues --- app/components/tts-config.tsx | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/app/components/tts-config.tsx b/app/components/tts-config.tsx index 30c1424d698..091f554452b 100644 --- a/app/components/tts-config.tsx +++ b/app/components/tts-config.tsx @@ -31,8 +31,7 @@ export function TTSConfigList(props: { ttsPlayer.stop(); setSpeechStatus(false); } else { - var api: ClientApi; - api = new ClientApi(ModelProvider.GPT); + const api = new ClientApi(ModelProvider.GPT); const config = useAppConfig.getState(); setSpeechLoading(true); ttsPlayer.init(); @@ -141,23 +140,25 @@ export function TTSConfigList(props: { : Locale.Chat.Actions.Speech } onClick={() => { - speechStatus - ? (ttsPlayer.stop(), setSpeechStatus(false)) - : openaiSpeech( - "NextChat,Unleash your imagination, experience the future of AI conversation.", - ); + if (speechStatus) { + ttsPlayer.stop(); + setSpeechStatus(false); + } else { + openaiSpeech( + "NextChat,Unleash your imagination, experience the future of AI conversation.", + ); + } }} />