diff --git a/app/context/Deepgram.tsx b/app/context/Deepgram.tsx index 0e8213a7..f46f4a9c 100644 --- a/app/context/Deepgram.tsx +++ b/app/context/Deepgram.tsx @@ -20,9 +20,9 @@ import { useToast } from "./Toast"; import { useLocalStorage } from "../lib/hooks/useLocalStorage"; type DeepgramContext = { - ttsOptions: SpeakSchema; + ttsOptions: SpeakSchema | undefined; setTtsOptions: (value: SpeakSchema) => void; - sttOptions: LiveSchema; + sttOptions: LiveSchema | undefined; setSttOptions: (value: LiveSchema) => void; connection: LiveClient | undefined; connectionReady: boolean; @@ -36,7 +36,20 @@ const DeepgramContext = createContext({} as DeepgramContext); const DEFAULT_TTS_MODEL = 'aura-asteria-en'; const DEFAULT_STT_MODEL = 'nova-2'; -; + +const defaultTtsOptions = { + model: DEFAULT_TTS_MODEL +} + +const defaultSttsOptions = { + model: DEFAULT_STT_MODEL, + interim_results: true, + smart_format: true, + endpointing: 550, + utterance_end_ms: 1500, + filler_words: true, +} + /** * TTS Voice Options */ @@ -136,44 +149,55 @@ const getApiKey = async (): Promise => { const DeepgramContextProvider = ({ children }: DeepgramContextInterface) => { const { toast } = useToast(); - const [ttsOptions, setTtsOptions] = useLocalStorage('ttsModel', { - model: DEFAULT_TTS_MODEL - }); - const [sttOptions, setSttOptions] = useLocalStorage('sttModel', { - model: DEFAULT_STT_MODEL, - interim_results: true, - smart_format: true, - endpointing: 350, - utterance_end_ms: 1000, - filler_words: true, - }); + const [ttsOptions, setTtsOptions] = useLocalStorage('ttsModel'); + const [sttOptions, setSttOptions] = useLocalStorage('sttModel'); const [connection, setConnection] = useState(); const [connecting, setConnecting] = useState(false); const [connectionReady, setConnectionReady] = useState(false); - const connect = useCallback(async () => { - if (!connection && !connecting) { - setConnecting(true); + const connect = useCallback( + async (defaultSttsOptions: SpeakSchema) => { + if (!connection && !connecting) { + setConnecting(true); - const connection = new LiveClient( - await getApiKey(), - {}, - sttOptions - ); + const connection = new LiveClient( + await getApiKey(), + {}, + defaultSttsOptions + ); - setConnection(connection); - setConnecting(false); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [connecting, connection]); + setConnection(connection); + setConnecting(false); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, + [connecting, connection] + ); useEffect(() => { // it must be the first open of the page, let's set up the defaults + // Why this is needed?, the requestTtsAudio of Conversation is wrapped in useCallback + // which has a dependency of ttsOptions model + // but the player inside the Nowplaying provider is set on mount, means + // the when the startAudio is called the player is undefined. + + // This can be fixed in 3 ways: + // 1. set player as a dependency inside the useCallback of requestTtsAudio + // 2. change the code of react-nowplaying to use the ref mechanism + // 3. follow the old code to avoid any risk i.e., first ttsOptions is undefined + // and later when it gets set, it also update the requestTtsAudio callback. + if (ttsOptions === undefined) { + setTtsOptions(defaultTtsOptions); + } + + if (!sttOptions === undefined) { + setSttOptions(defaultSttsOptions); + } if (connection === undefined) { - connect(); + connect(defaultSttsOptions); } - }, [connect, connection, sttOptions, ttsOptions]); + }, [connect, connection, setSttOptions, setTtsOptions, sttOptions, ttsOptions]); useEffect(() => { if (connection && connection?.getReadyState() !== undefined) { diff --git a/app/lib/hooks/useLocalStorage.ts b/app/lib/hooks/useLocalStorage.ts index b8eff6c3..aa308192 100644 --- a/app/lib/hooks/useLocalStorage.ts +++ b/app/lib/hooks/useLocalStorage.ts @@ -2,8 +2,8 @@ import { useEffect, useState } from 'react' export const useLocalStorage = ( key: string, - initialValue: T -): [T, (value: T) => void] => { + initialValue?: T +): [T | undefined, (value: T) => void] => { const [storedValue, setStoredValue] = useState(initialValue) useEffect(() => {