UNPKG

@charisma-ai/react

Version:
229 lines (228 loc) 9.13 kB
import React, { createContext, useContext, useEffect, useRef, useState, useCallback, useMemo } from "react"; import { AudioManager } from "@charisma-ai/sdk"; import { AudioManagerConnectionError, AudioManagerInitialisationError, AudioPlaybackError } from "./errors/AudioManagerErrors.js"; const AudioManagerContext = /*#__PURE__*/ createContext(undefined); export const AudioManagerProvider = ({ children, options })=>{ const audioManagerRef = useRef(null); const [isListening, setIsListening] = useState(false); const [isBrowserSupported, setIsBrowserSupported] = useState(false); const [transcript, setTranscript] = useState(""); const [interimTranscript, setInterimTranscript] = useState(""); const [confirmedTranscripts, setConfirmedTranscripts] = useState(""); const [recordingStatus, setRecordingStatus] = useState("OFF"); const [, forceUpdate] = useState(0); useEffect(()=>{ try { const customHandleTranscript = (transcriptText)=>{ if (transcriptText.trim().length > 0) { queueMicrotask(()=>{ setTranscript(transcriptText); setInterimTranscript(""); setConfirmedTranscripts((existing)=>`${existing} ${transcriptText}`.trim()); }); } }; const customHandleInterimTranscript = (transcriptText)=>{ if (transcriptText.trim().length > 0) { queueMicrotask(()=>setInterimTranscript(transcriptText)); } }; const customHandleStartSTT = ()=>{ setRecordingStatus("RECORDING"); }; const customHandleStopSTT = ()=>{ setRecordingStatus("OFF"); }; const modifiedOptions = { ...options, handleTranscript: customHandleTranscript, handleInterimTranscript: customHandleInterimTranscript, handleStartSTT: customHandleStartSTT, handleStopSTT: customHandleStopSTT }; const audioManager = new AudioManager(modifiedOptions); audioManagerRef.current = audioManager; setIsBrowserSupported(audioManager.browserIsSupported()); } catch (error) { // eslint-disable-next-line no-console console.error("Failed to initialise AudioManager:", error); } return ()=>{ audioManagerRef.current?.stopListening(); audioManagerRef.current?.mediaAudioStopAll(); audioManagerRef.current = null; }; }, [ options ]); const initialise = useCallback(()=>{ audioManagerRef.current?.initialise(); }, []); const clearTranscript = useCallback(()=>{ setTranscript(""); setInterimTranscript(""); setConfirmedTranscripts(""); }, []); const startListening = useCallback((timeout)=>{ try { if (!audioManagerRef.current) { throw new AudioManagerInitialisationError("AudioManager is not initialised"); } setRecordingStatus("STARTING"); audioManagerRef.current.startListening(timeout); setIsListening(true); } catch (error) { // eslint-disable-next-line no-console console.error("Failed to start listening:", error); setRecordingStatus("OFF"); } }, []); const stopListening = useCallback(()=>{ try { if (!audioManagerRef.current) { throw new AudioManagerInitialisationError("AudioManager is not initialised"); } audioManagerRef.current?.stopListening(); setIsListening(false); } catch (error) { // eslint-disable-next-line no-console console.error("Failed to stop listening:", error); } }, []); const connect = useCallback((token, playerSessionId)=>{ try { if (!audioManagerRef.current) { throw new AudioManagerInitialisationError("AudioManager is not initialised"); } audioManagerRef.current.connect(token, playerSessionId); } catch (error) { throw new AudioManagerConnectionError("Failed to connect to AudioManager"); } }, []); const disconnect = useCallback(()=>{ // eslint-disable-next-line @typescript-eslint/no-unsafe-call audioManagerRef.current?.disconnect(); }, []); const resetTimeout = useCallback((timeout)=>{ audioManagerRef.current?.resetTimeout(timeout); }, []); const playCharacterSpeech = useCallback(async (audio, playOptions)=>{ try { if (!audioManagerRef.current) { throw new AudioManagerInitialisationError("AudioManager is not initialised"); } return await audioManagerRef.current.playCharacterSpeech(audio, playOptions); } catch (error) { throw new AudioPlaybackError("Failed to play output"); } }, []); const characterSpeechVolume = audioManagerRef.current ? audioManagerRef.current.characterSpeechVolume : 1; const setCharacterSpeechVolume = useCallback((volume)=>{ if (!audioManagerRef.current) { console.warn("setMediaAudioMuted called but AudioManager is not initialised"); return; } audioManagerRef.current.characterSpeechVolume = volume; forceUpdate((x)=>x + 1); }, []); const characterSpeechIsMuted = audioManagerRef.current ? audioManagerRef.current.characterSpeechIsMuted : false; const setCharacterSpeechMuted = useCallback((mute)=>{ if (!audioManagerRef.current) { console.warn("setMediaAudioMuted called but AudioManager is not initialised"); return; } audioManagerRef.current.characterSpeechIsMuted = mute; forceUpdate((x)=>x + 1); }, []); const playMediaAudio = useCallback((audioTracks)=>{ audioManagerRef.current?.mediaAudioPlay(audioTracks); }, []); const mediaAudioVolume = audioManagerRef.current ? audioManagerRef.current.mediaAudioVolume : 1; const setMediaAudioVolume = useCallback((volume)=>{ if (!audioManagerRef.current) { console.warn("setMediaAudioMuted called but AudioManager is not initialised"); return; } audioManagerRef.current.mediaAudioVolume = volume; forceUpdate((x)=>x + 1); }, []); const mediaAudioIsMuted = audioManagerRef.current ? audioManagerRef.current.mediaAudioIsMuted : false; const setMediaAudioMuted = useCallback((mute)=>{ if (!audioManagerRef.current) { console.warn("setMediaAudioMuted called but AudioManager is not initialised"); return; } audioManagerRef.current.mediaAudioIsMuted = mute; forceUpdate((x)=>x + 1); }, []); const stopAllMedia = useCallback(()=>{ audioManagerRef.current?.mediaAudioStopAll(); }, []); const getCharacterSpeechAnalyserNode = useCallback(()=>{ return audioManagerRef.current?.getCharacterSpeechAnalyserNode(); }, []); const liveTranscript = `${confirmedTranscripts} ${interimTranscript}`.trim(); const value = useMemo(()=>({ isListening, isBrowserSupported, initialise, transcript, interimTranscript, liveTranscript, clearTranscript, recordingStatus, startListening, stopListening, connect, disconnect, resetTimeout, playCharacterSpeech, getCharacterSpeechAnalyserNode, characterSpeechVolume, setCharacterSpeechVolume, characterSpeechIsMuted, setCharacterSpeechMuted, playMediaAudio, mediaAudioVolume, setMediaAudioVolume, mediaAudioIsMuted, setMediaAudioMuted, stopAllMedia }), [ isListening, isBrowserSupported, initialise, transcript, interimTranscript, liveTranscript, clearTranscript, recordingStatus, startListening, stopListening, connect, disconnect, resetTimeout, playCharacterSpeech, getCharacterSpeechAnalyserNode, characterSpeechVolume, setCharacterSpeechVolume, characterSpeechIsMuted, setCharacterSpeechMuted, playMediaAudio, mediaAudioVolume, setMediaAudioVolume, mediaAudioIsMuted, setMediaAudioMuted, stopAllMedia ]); return /*#__PURE__*/ React.createElement(AudioManagerContext.Provider, { value: value }, children); }; export const useAudioManager = ()=>{ const context = useContext(AudioManagerContext); if (!context) { throw new Error("useAudioManager must be used within an AudioManagerProvider"); } return context; };