You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebRTC音频录制问题:停止流媒体后无法恢复录制求助

问题分析与解决方案

核心问题

  • mediaRecorder.stop()仅终止录制过程,但底层音频流(MediaStream)仍处于活跃状态,所以浏览器的红色录制标识不会消失。
  • 直接调用stream.getTracks().forEach(track => track.stop())会彻底销毁音频流,导致已初始化的mediaRecorder失效,无法再次触发录制。

修复方案

  1. 录制结束后销毁音频流并重置MediaRecorder:在mediaRecorder.onstop回调中停止音频轨道,同时将mediaRecorder置为null,确保下次录制能重新初始化。
  2. 修正按钮点击逻辑顺序:先初始化MediaRecorder,再启动录制,避免第一次点击时因mediaRecorder未创建导致录制不启动。

修改后的完整代码

let mediaRecorder;
let recordedChunks = [];
let isRecording = false;

// 启动录制
function startRecording() {
  if (mediaRecorder && mediaRecorder.state === 'inactive') {
    mediaRecorder.start();
    isRecording = true;
  }
}

// 停止录制
function stopRecording() {
  if (mediaRecorder && mediaRecorder.state === 'recording') {
    mediaRecorder.stop();
    isRecording = false;
  }
}

// 初始化MediaRecorder
function initializeMediaRecorder() {
  // 重置之前的mediaRecorder(如果存在)
  if (mediaRecorder) {
    mediaRecorder = null;
  }
  navigator.mediaDevices
    .getUserMedia({ audio: true })
    .then((stream) => {
      mediaRecorder = new MediaRecorder(stream);

      mediaRecorder.ondataavailable = (e) => {
        if (e.data.size > 0) {
          recordedChunks.push(e.data);
        }
      };

      mediaRecorder.onstop = () => {
        const audioBlob = new Blob(recordedChunks, { type: 'audio/wav' });
        const audioSize = audioBlob.size;
        recordedChunks = [];

        // 渲染录制消息
        const messageItem = document.createElement('li');
        messageItem.classList.add('message', 'sent');
        messageItem.innerHTML = `
          <div class="message-text">
            <div class="message-sender">
              <b>You</b>
            </div>
            <div class="message-content">
              Audio size: ${audioSize}. Recording state: ${mediaRecorder.state}
            </div>
          </div>`;
        messagesList.appendChild(messageItem);

        // 停止音频流,消除红色录制标识
        stream.getTracks().forEach(track => track.stop());
        // 重置mediaRecorder,为下次录制做准备
        mediaRecorder = null;
      };

      // 初始化完成后立即启动录制
      startRecording();
    })
    .catch((error) => {
      console.error('Error accessing audio:', error);
      isRecording = false;
    });
}

// 录制按钮点击事件
const recordButton = document.querySelector('.btn-record');
recordButton.addEventListener('click', () => {
  if (!isRecording) {
    initializeMediaRecorder();
  } else {
    stopRecording();
  }
});

关键修改点

  • 移除initializeMediaRecorder中的if (!mediaRecorder)判断,改为每次录制前重置mediaRecorder,确保每次录制都使用新的音频流。
  • 在mediaRecorder.onstop中添加mediaRecorder = null,保证下次录制能重新创建MediaRecorder实例。
  • 调整按钮点击逻辑:点击开始录制时直接调用initializeMediaRecorder,并在初始化完成后自动启动录制,解决原逻辑中先调用startRecording但mediaRecorder未就绪的问题。

内容的提问来源于stack exchange,提问作者Enzo Ferrari

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:17:07