AudioNode.disconnect()后跟.connect()在Safari中不起作用

问题描述 投票:0回答:1

我已经建立了一个语音助理的演示,该演示会获取麦克风数据,将其传递到分析器,然后使用.getByteFrequencyData()显示视觉效果。它的工作方式如下:

  1. 按麦克风按钮连接到麦克风输入
  2. 释放麦克风按钮断开麦克风流,并播放响应的MP3。
  3. 当MP3结束时:返回待机状态,并等待按下新按钮再次开始步骤1。

此处为实时版本:https://dyadstudios.com/playground/daysi/

我实现这一目标的方法如下:

var audioContext = (window.AudioContext) ? new AudioContext() : new window["webkitAudioContext"]();
var analyser = audioContext.createAnalyser();
analyser.fftSize = Math.pow(2, 9);  // 512
var sourceMic = undefined;  // Microphone stream source
var sourceMp3 = undefined;  // MP3 buffer source

// Browser requests mic access
window.navigator.mediaDevices.getUserMedia({audio: true}).then((stream) => {
    sourceMic = audioContext.createMediaStreamSource(stream)
})

// 1. Mic button pressed, start listening
listen() {
    audioContext.resume();

    // Connect mic to analyser
    if (sourceMic) {
        sourceMic.connect(analyser);
    }
}

// 2. Disconnect mic, play mp3
answer(mp3AudioBuffer) {
    if (sourceMic) {
        // Disconnect mic to prevent audio feedback
        sourceMic.disconnect();
    }

    // Play mp3
    sourceMp3 = audioContext.createBufferSource();
    sourceMp3.onended = mp3StreamEnded;
    sourceMp3.buffer = mp3AudioBuffer;
    sourceMp3.connect(analyser);
    sourceMp3.start(0);

    // Connect to speakers to hear MP3
    analyser.connect(audioContext.destination);
}

// 3. MP3 has ended
mp3StreamEnded() {
    sourceMp3.disconnect();

    // Disconnect speakers (prevents mic feedback)
    analyser.disconnect();
}

它在Firefox和Chrome上运行良好,但是OSX Safari 12.1仅在我第一次按下按钮时获得麦克风数据。每当我第二次按下麦克风按钮时,分析​​仪就不再获取麦克风数据,但MP3数据仍然有效。似乎将麦克风的AudioNode连接,断开连接并将其重新连接到分析仪似乎会以某种方式破坏它。我检查了一下,Safari浏览器同时支持AudioNode.connect()AudioNode.connect()。我知道Safari的WebAudio实现有些过时,是否有解决此问题的解决方法?

javascript safari html5-audio web-audio-api microphone
1个回答
0
投票

Safari中确实存在一个错误,如果MediaStreamAudioSourceNode断开连接一段时间,它会导致信号丢失。您可以通过不断开连接来避免这种情况,只要您可能再次需要它即可。您可以改用GainNode来使信号静音。

您可以通过引入新的变量来控制音量来做到这一点。

AudioNode.disconnect()

然后,您需要在实例化AudioNode.disconnect()时立即连接所有内容。

const sourceMicVolume = audioContext.createGain();

sourceMicVolume.gain.value = 0;

然后在事件处理程序内部,您将只设置增益的大小,而不是(断开)连接节点。在sourceMic函数内部,如下所示:

sourceMic = audioContext.createMediaStreamSource(stream);

sourceMic.connect(sourceMicVolume);
sourceMicVolume.connect(analyser);

listen()函数内部,看起来像这样:

if (sourceMic) {
    sourceMicVolume.gain.value = 1;
}
© www.soinside.com 2019 - 2024. All rights reserved.