diff --git a/src/frontend/src/customization/hooks/use-custom-start-recording.ts b/src/frontend/src/customization/hooks/use-custom-start-recording.ts index 9af82b9d7ec0..f9d43409964a 100644 --- a/src/frontend/src/customization/hooks/use-custom-start-recording.ts +++ b/src/frontend/src/customization/hooks/use-custom-start-recording.ts @@ -6,6 +6,7 @@ export const customUseStartRecording = ( microphoneRef: MutableRefObject, analyserRef: React.MutableRefObject, wsRef: React.MutableRefObject, + mediaStreamRef: MutableRefObject, setIsRecording: (isRecording: boolean) => void, playNextAudioChunk: () => void, isPlayingRef: React.MutableRefObject, @@ -19,6 +20,7 @@ export const customUseStartRecording = ( microphoneRef, analyserRef, wsRef, + mediaStreamRef, setIsRecording, playNextAudioChunk, isPlayingRef, diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-start-recording.ts b/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-start-recording.ts index 204d5a335055..ae96cf9d3b66 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-start-recording.ts +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-start-recording.ts @@ -5,6 +5,7 @@ export const useStartRecording = async ( microphoneRef: MutableRefObject, analyserRef: MutableRefObject, wsRef: MutableRefObject, + mediaStreamRef: MutableRefObject, setIsRecording: (isRecording: boolean) => void, playNextAudioChunk: () => void, isPlayingRef: MutableRefObject, @@ -31,6 +32,9 @@ export const useStartRecording = async ( }); if (!audioContextRef.current) return; + // Store the MediaStream reference so we can stop it later + mediaStreamRef.current = stream; + microphoneRef.current = audioContextRef?.current?.createMediaStreamSource(stream); analyserRef.current = audioContextRef?.current?.createAnalyser(); diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-stop-recording.ts b/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-stop-recording.ts index 7e35f51f8732..b5448988e649 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-stop-recording.ts +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/hooks/use-stop-recording.ts @@ -3,8 +3,17 @@ export const useStopRecording = ( processorRef: React.MutableRefObject, analyserRef: React.MutableRefObject, wsRef: React.MutableRefObject, + mediaStreamRef: React.MutableRefObject, setIsRecording: (isRecording: boolean) => void, ) => { + // Stop all media stream tracks to release the microphone + if (mediaStreamRef.current) { + mediaStreamRef.current.getTracks().forEach((track) => { + track.stop(); + }); + mediaStreamRef.current = null; + } + if (microphoneRef.current) { microphoneRef.current.disconnect(); microphoneRef.current = null; diff --git a/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/voice-assistant.tsx b/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/voice-assistant.tsx index 0d0df54224a5..acef3d0b24b9 100644 --- a/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/voice-assistant.tsx +++ b/src/frontend/src/modals/IOModal/components/chatView/chatInput/components/voice-assistant/voice-assistant.tsx @@ -59,6 +59,7 @@ export function VoiceAssistant({ const isPlayingRef = useRef(false); const microphoneRef = useRef(null); const analyserRef = useRef(null); + const mediaStreamRef = useRef(null); const soundDetected = useVoiceStore((state) => state.soundDetected); const _setIsVoiceAssistantActive = useVoiceStore( @@ -139,6 +140,7 @@ export function VoiceAssistant({ microphoneRef, analyserRef, wsRef, + mediaStreamRef, setIsRecording, playNextAudioChunk, isPlayingRef, @@ -155,6 +157,7 @@ export function VoiceAssistant({ processorRef, analyserRef, wsRef, + mediaStreamRef, setIsRecording, ); };