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

如何在JavaScript中安全启停音频流并支持后续重复启动?

问题根源
  • 回调持续触发的原因:你只停止了媒体流的音轨,但是AudioContext实例仍在运行,ScriptProcessor节点也保持和音频上下文的连接状态,onaudioprocess事件回调也没有解绑,浏览器会按照设定的缓冲区大小持续触发该回调,哪怕没有音频输入也会执行,导致CPU空转。
  • 无法重启的原因:你把audioCtx、source、processor、stream这些核心实例都声明在handleAudioStream的局部作用域里,停止音频时无法访问这些实例做资源清理,每次重启都会重复创建新的音频上下文和媒体流,旧的资源持续占用浏览器的媒体通道和内存,多次调用getUserMedia会因为资源抢占触发无响应,部分浏览器还会对高频媒体权限请求做限流。
修复思路
  1. 将音频相关的核心实例提升到全局作用域,方便停止时统一清理
  2. 停止音频时执行完整的资源释放流程,而非仅停止音轨:
    • 停止所有活跃的音轨
    • 断开音频节点之间的连接
    • 解绑onaudioprocess事件回调
    • 关闭AudioContext实例释放底层资源
    • 清空所有实例引用方便垃圾回收
  3. 每次启动前先检查是否有残留资源,先清理再初始化,避免重复创建
修正后代码
// 全局存储音频相关实例
let running = false;
let audioCtx = null;
let source = null;
let processor = null;
let stream = null;

function handleAudioStream(mediaStream) {
    stream = mediaStream;
    audioCtx = new AudioContext();
    source = audioCtx.createMediaStreamSource(stream);
    processor = audioCtx.createScriptProcessor(1024, 1, 1);

    source.connect(processor);
    processor.connect(audioCtx.destination);

    processor.onaudioprocess = function(event) {
        if (!running) return;
        const audioData = event.inputBuffer.getChannelData(0);
        do_stuff(audioData);
    };
}

function start_audio() {
    // 启动前先清理残留资源
    stop_audio();
    running = true;
    navigator.mediaDevices.getUserMedia({
        audio: true,
        video: false
    }).then(handleAudioStream);
}

function stop_audio() {
    running = false;
    // 按顺序清理资源
    if (stream) {
        stream.getTracks().forEach(track => {
            if (track.readyState === 'live' && track.kind === 'audio') {
                track.stop();
            }
        });
        stream = null;
    }
    if (processor) {
        processor.disconnect();
        processor.onaudioprocess = null;
        processor = null;
    }
    if (source) {
        source.disconnect();
        source = null;
    }
    if (audioCtx) {
        audioCtx.close().then(() => {
            audioCtx = null;
        });
    }
}

补充说明:ScriptProcessor 已经被Web Audio API标准废弃,现代浏览器推荐使用性能更好、运行在音频渲染线程的AudioWorklet替代,如果是新业务开发建议切换到AudioWorklet实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 04:06:04