UNPKG

@picovoice/picovoice-react

Version:

React component for Picovoice SDK for Web

193 lines (175 loc) 5.23 kB
/* Copyright 2022-2023 Picovoice Inc. You may not use this file except in compliance with the license. A copy of the license is located in the "LICENSE" file accompanying this source. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ import { useCallback, useEffect, useRef, useState } from 'react'; import { WebVoiceProcessor } from '@picovoice/web-voice-processor'; import { PicovoiceOptions, PicovoiceWorker, PorcupineDetection, PorcupineKeyword, PorcupineModel, RhinoContext, RhinoInference, RhinoModel, } from '@picovoice/picovoice-web'; export function usePicovoice(): { wakeWordDetection: PorcupineDetection | null; inference: RhinoInference | null; contextInfo: string | null; isLoaded: boolean; isListening: boolean; error: Error | null; init: ( accessKey: string, keyword: PorcupineKeyword, porcupineModel: PorcupineModel, context: RhinoContext, rhinoModel: RhinoModel, options?: PicovoiceOptions ) => Promise<void>; start: () => Promise<void>; stop: () => Promise<void>; release: () => Promise<void>; } { const picovoiceRef = useRef<PicovoiceWorker | null>(null); const [wakeWordDetection, setWakeWordDetection] = useState<PorcupineDetection | null>(null); const [inference, setInference] = useState<RhinoInference | null>(null); const [contextInfo, setContextInfo] = useState<string | null>(null); const [isLoaded, setIsLoaded] = useState(false); const [isListening, setIsListening] = useState(false); const [error, setError] = useState<Error | null>(null); const wakeWordCallback = useCallback( (newDetection: PorcupineDetection): void => { if (newDetection) { setWakeWordDetection(newDetection); setInference(null); } }, [] ); const inferenceCallback = useCallback( (newInference: RhinoInference): void => { if (newInference) { setInference(newInference); setWakeWordDetection(null); } }, [] ); const errorCallback = useCallback((newError: Error): void => { if (newError) { setError(newError); } }, []); const init = useCallback( async ( accessKey: string, keyword: PorcupineKeyword, porcupineModel: PorcupineModel, context: RhinoContext, rhinoModel: RhinoModel, options: PicovoiceOptions = {} ): Promise<void> => { try { if (!picovoiceRef.current) { if (options.processErrorCallback) { // eslint-disable-next-line no-console console.warn( 'processErrorCallback is only supported in the Picovoice Web SDK. ' + "Use the 'error' state to monitor for errors in the React SDK." ); } PicovoiceWorker.setSdk('react'); picovoiceRef.current = await PicovoiceWorker.create( accessKey, keyword, wakeWordCallback, porcupineModel, context, inferenceCallback, rhinoModel, { ...options, processErrorCallback: errorCallback } ); setContextInfo(picovoiceRef.current.contextInfo); setIsLoaded(true); setError(null); } } catch (e: any) { setError(e); } }, [wakeWordCallback, inferenceCallback, errorCallback] ); const start = useCallback(async (): Promise<void> => { try { if (!picovoiceRef.current) { setError(new Error('Picovoice has not been initialized or has been released')); return; } if (!isListening) { await WebVoiceProcessor.subscribe(picovoiceRef.current); setIsListening(true); setError(null); } } catch (e: any) { setError(e); } }, [isListening]); const stop = useCallback(async (): Promise<void> => { try { if (!picovoiceRef.current) { setError(new Error('Picovoice has not been initialized or has been released')); return; } if (isListening) { await WebVoiceProcessor.unsubscribe(picovoiceRef.current); picovoiceRef.current.reset(); setIsListening(false); setError(null); } } catch (e: any) { setError(e); } }, [isListening]); const release = useCallback(async (): Promise<void> => { try { if (picovoiceRef.current) { await stop(); picovoiceRef.current.terminate(); picovoiceRef.current = null; setIsLoaded(false); } } catch (e: any) { setError(e); } }, [stop]); useEffect( () => (): void => { if (picovoiceRef.current) { WebVoiceProcessor.unsubscribe(picovoiceRef.current); picovoiceRef.current.terminate(); picovoiceRef.current = null; } }, [] ); return { wakeWordDetection, inference, contextInfo, isLoaded, isListening, error, init, start, stop, release, }; }