diff --git a/frontend/src/composables/useVoiceRecorder.ts b/frontend/src/composables/useVoiceRecorder.ts index 2b55a57..7ac1de1 100644 --- a/frontend/src/composables/useVoiceRecorder.ts +++ b/frontend/src/composables/useVoiceRecorder.ts @@ -1,4 +1,4 @@ -import { ref, readonly } from 'vue' +import { ref, readonly, type Ref } from 'vue' /** * Push-to-talk recorder wrapping the browser MediaRecorder API. @@ -15,7 +15,7 @@ export function useVoiceRecorder() { let mediaRecorder: MediaRecorder | null = null let chunks: Blob[] = [] - let stream: MediaStream | null = null + const streamRef = ref(null) let resolveStop: ((blob: Blob) => void) | null = null let rejectStop: ((err: Error) => void) | null = null @@ -28,7 +28,7 @@ export function useVoiceRecorder() { if (recording.value) return try { - stream = await navigator.mediaDevices.getUserMedia({ audio: true }) + streamRef.value = await navigator.mediaDevices.getUserMedia({ audio: true }) } catch (e) { error.value = 'Microphone access denied' return @@ -41,7 +41,7 @@ export function useVoiceRecorder() { ? 'audio/webm' : '' - mediaRecorder = mimeType ? new MediaRecorder(stream, { mimeType }) : new MediaRecorder(stream) + mediaRecorder = mimeType ? new MediaRecorder(streamRef.value!, { mimeType }) : new MediaRecorder(streamRef.value!) mediaRecorder.ondataavailable = (e) => { if (e.data.size > 0) chunks.push(e.data) @@ -50,8 +50,8 @@ export function useVoiceRecorder() { mediaRecorder.onstop = () => { const blob = new Blob(chunks, { type: mediaRecorder?.mimeType ?? 'audio/webm' }) chunks = [] - stream?.getTracks().forEach((t) => t.stop()) - stream = null + streamRef.value?.getTracks().forEach((t) => t.stop()) + streamRef.value = null recording.value = false resolveStop?.(blob) resolveStop = null @@ -88,5 +88,6 @@ export function useVoiceRecorder() { isSupported, startRecording, stopRecording, + stream: readonly(streamRef) as Readonly>, } }