|
|
@@ -7,6 +7,7 @@
|
|
|
>
|
|
|
<div class="waveform-container" v-if="isRecording">
|
|
|
<LiveWaveform
|
|
|
+ style="min-width: 50px;"
|
|
|
:active="isRecording"
|
|
|
:processing="false"
|
|
|
:height="25"
|
|
|
@@ -53,6 +54,7 @@ const recognition = ref(null) // 语音识别实例
|
|
|
const countdown = ref(0) // 倒计时剩余秒数
|
|
|
const countdownTimer = ref(null) // 倒计时定时器
|
|
|
const isBrowserSupported = ref(true) // 浏览器是否支持语音识别
|
|
|
+const mediaStream = ref(null) // 媒体流引用,用于释放资源
|
|
|
|
|
|
// 检测浏览器是否支持语音识别
|
|
|
const checkBrowserSupport = () => {
|
|
|
@@ -100,6 +102,11 @@ const initSpeechRecognition = () => {
|
|
|
isRecording.value = false
|
|
|
countdown.value = 0
|
|
|
emit('recordingStatusChanged', false)
|
|
|
+ // 释放媒体流资源
|
|
|
+ if (mediaStream.value) {
|
|
|
+ mediaStream.value.getTracks().forEach(track => track.stop())
|
|
|
+ mediaStream.value = null
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
instance.onerror = (event) => {
|
|
|
@@ -109,6 +116,11 @@ const initSpeechRecognition = () => {
|
|
|
emit('recordingStatusChanged', false)
|
|
|
ElMessage.error('语音输入失败,请重试!', true)
|
|
|
countdown.value = 0
|
|
|
+ // 释放媒体流资源
|
|
|
+ if (mediaStream.value) {
|
|
|
+ mediaStream.value.getTracks().forEach(track => track.stop())
|
|
|
+ mediaStream.value = null
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return instance
|
|
|
@@ -173,7 +185,9 @@ const toggleSpeechInput = () => {
|
|
|
}
|
|
|
|
|
|
navigator.mediaDevices.getUserMedia({ audio: true })
|
|
|
- .then(() => {
|
|
|
+ .then((stream) => {
|
|
|
+ // 存储媒体流,以便后续释放
|
|
|
+ mediaStream.value = stream
|
|
|
// 先设置UI状态,让用户知道系统正在准备
|
|
|
isRecording.value = true
|
|
|
emit('recordingStatusChanged', true)
|
|
|
@@ -195,6 +209,11 @@ const toggleSpeechInput = () => {
|
|
|
onUnmounted(() => {
|
|
|
clearInterval(countdownTimer.value)
|
|
|
recognition.value?.stop()
|
|
|
+ // 释放媒体流资源
|
|
|
+ if (mediaStream.value) {
|
|
|
+ mediaStream.value.getTracks().forEach(track => track.stop())
|
|
|
+ mediaStream.value = null
|
|
|
+ }
|
|
|
})
|
|
|
</script>
|
|
|
|