Safari下,AudioNode节点disconnect后,再次connect无效的问题
在修复项目issue时,在手机端的safari下发现了个录音暂停后,再次录音无效的问题。
问题
去除掉冗余代码,直接看代码:
<body>
<button id="start">开始</button>
<button id="pause">暂停</button>
<button id="resume">恢复</button>
<button id="stop">结束</button>
</body>
<script>
let context = null;
let createScript = null;
let recorder = null;
let audioInput = null;
let stream = null;
document.getElementById('start').addEventListener('click', start)
document.getElementById('pause').addEventListener('click', pause)
document.getElementById('resume').addEventListener('click', resume)
document.getElementById('stop').addEventListener('click', stop)
function start() {
context = new (window.AudioContext || window.webkitAudioContext)();
createScript = context.createScriptProcessor || context.createJavaScriptNode;
recorder = createScript.apply(context, [4096, 1, 1]);
navigator.mediaDevices.getUserMedia({
audio: true
}).then(stream => {
audioInput = context.createMediaStreamSource(stream);
stream = stream;
}).then(() => {
audioInput.connect(recorder);
recorder.connect(context.destination);
});
recorder.onaudioprocess = e => {
let lData = e.inputBuffer.getChannelData(0);
console.log('回调获取数据', lData);
}
}
function pause() {
audioInput.disconnect();
recorder.disconnect();
}
function resume() {
audioInput.connect(recorder);
recorder.connect(context.destination);
}
function stop() {
context.close();
if (stream && stream.getTracks) {
stream.getTracks().forEach(track => track.stop());
stream = null;
}
}
</script>
开启录音后,先暂停录音,再恢复录音,在safari下,回调中获取的都是0,
而在chrome或firefox都可以获取到正常的音频数据。
注:如果safari也能获取到数据,可以暂停久一点。
解决方案
在stackoverflow上也找到了类似的问题:AudioNode.disconnect() followed by .connect() not working in Safari。
也就确认了这是safari下的bug。
所以我们此处就需要抛弃disconnect,毕竟他会导致最后数据搜集错误的问题。
let isPause = false;
function start() {
// ....
recorder.onaudioprocess = e => {
if (isPause) {
return;
}
let lData = e.inputBuffer.getChannelData(0);
console.log('回调获取数据', lData);
}
// ...
}
function pause() {
isPause = true;
}
function resume() {
isPause = false;
}
代码其他地方不变,新增isPause
表示是否暂停,而onaudioprocess
回调仅对不暂停时的数据进行处理,这样就可以达到兼容了。
详细代码见:github。