From 6359c9f50dd71cc3ba39f6ae3552460d532d0f25 Mon Sep 17 00:00:00 2001 From: Cogent Apps Date: Mon, 20 Mar 2023 21:03:12 +0000 Subject: [PATCH] fallback to whisper when speechrecognition is not available --- app/src/components/input.tsx | 25 +++++++++++++------ app/src/components/settings/user.tsx | 5 ++-- ...types.d.ts => speech-recognition-types.ts} | 13 +++++++--- 3 files changed, 29 insertions(+), 14 deletions(-) rename app/src/{speech-recognition-types.d.ts => speech-recognition-types.ts} (92%) diff --git a/app/src/components/input.tsx b/app/src/components/input.tsx index e41dd775..1ac7dd7d 100644 --- a/app/src/components/input.tsx +++ b/app/src/components/input.tsx @@ -8,8 +8,8 @@ import { useAppContext } from '../context'; import { useAppDispatch, useAppSelector } from '../store'; import { selectMessage, setMessage } from '../store/message'; import { selectTemperature } from '../store/parameters'; -import { openSystemPromptPanel, openTemperaturePanel } from '../store/settings-ui'; -import { speechRecognition } from '../speech-recognition-types.d' +import { openOpenAIApiKeyPanel, openSystemPromptPanel, openTemperaturePanel } from '../store/settings-ui'; +import { speechRecognition, supportsSpeechRecognition } from '../speech-recognition-types' import MicRecorder from 'mic-recorder-to-mp3'; import { selectUseOpenAIWhisper, selectOpenAIApiKey } from '../store/api-keys'; import { Mp3Encoder } from 'lamejs'; @@ -109,7 +109,7 @@ export default function MessageInput(props: MessageInputProps) { console.error('speech recognition error', e); try { - speechRecognition.stop(); + speechRecognition?.stop(); } catch (e) { } @@ -122,14 +122,19 @@ export default function MessageInput(props: MessageInputProps) { }, [recorder]); const onSpeechStart = useCallback(() => { + if (!openAIApiKey) { + dispatch(openOpenAIApiKeyPanel()); + return false; + } + try { if (!recording) { setRecording(true); // if we are using whisper, the we will just record with the browser and send the api when done - if (useOpenAIWhisper) { + if (useOpenAIWhisper || !supportsSpeechRecognition) { recorder.start().catch(onSpeechError); - } else { + } else if (speechRecognition) { const initialMessage = message; speechRecognition.continuous = true; @@ -146,10 +151,12 @@ export default function MessageInput(props: MessageInputProps) { }; speechRecognition.start(); + } else { + onSpeechError(new Error('not supported')); } } else { setRecording(false); - if (useOpenAIWhisper) { + if (useOpenAIWhisper || !supportsSpeechRecognition) { setTranscribing(true); const mp3 = recorder.stop().getMp3(); @@ -185,14 +192,16 @@ export default function MessageInput(props: MessageInputProps) { } }).catch(onSpeechError); - } else { + } else if (speechRecognition) { speechRecognition.stop(); + } else { + onSpeechError(new Error('not supported')); } } } catch (e) { onSpeechError(e); } - }, [recording, message, dispatch]); + }, [recording, message, dispatch, onSpeechError, openAIApiKey]); const onKeyDown = useCallback((e: React.KeyboardEvent) => { diff --git a/app/src/components/settings/user.tsx b/app/src/components/settings/user.tsx index 6b6d1303..474e3be1 100644 --- a/app/src/components/settings/user.tsx +++ b/app/src/components/settings/user.tsx @@ -6,6 +6,7 @@ import { useAppDispatch, useAppSelector } from "../../store"; import { selectOpenAIApiKey, setOpenAIApiKeyFromEvent, selectUseOpenAIWhisper, setUseOpenAIWhisperFromEvent } from "../../store/api-keys"; import { selectSettingsOption } from "../../store/settings-ui"; import { FormattedMessage, useIntl } from "react-intl"; +import { supportsSpeechRecognition } from "../../speech-recognition-types"; export default function UserOptionsTab(props: any) { const option = useAppSelector(selectSettingsOption); @@ -31,11 +32,11 @@ export default function UserOptionsTab(props: any) {

- + />}

diff --git a/app/src/speech-recognition-types.d.ts b/app/src/speech-recognition-types.ts similarity index 92% rename from app/src/speech-recognition-types.d.ts rename to app/src/speech-recognition-types.ts index 8e205a5b..89eee651 100644 --- a/app/src/speech-recognition-types.d.ts +++ b/app/src/speech-recognition-types.ts @@ -122,12 +122,17 @@ declare global { } } -let speechRecognition: SpeechRecognition +let speechRecognition: SpeechRecognition | null = null; if (window.SpeechRecognition) { speechRecognition = new SpeechRecognition() -} else { - speechRecognition = new webkitSpeechRecognition() +} else if ((window as any).webkitSpeechRecognition) { + speechRecognition = new (window as any).webkitSpeechRecognition() as SpeechRecognition; } -export { speechRecognition } \ No newline at end of file +const supportsSpeechRecognition = speechRecognition !== null; + +export { + speechRecognition, + supportsSpeechRecognition, +} \ No newline at end of file