Как исправить "треск" звука при использовании Audio Worklets?
Я пытаюсь понять как AudioWorklet
работает и сделал несколько тестов.
Пока что у меня огромная проблема "взламывания", когда я позволяю браузеру воспроизводить звук в фоновом режиме и делать что-то еще (например, открывать загруженное ЦП приложение, такое как Photoshop или VSCode, и перемещать окно).
Сначала я подумал, что это проблема с оборудованием. Я обновился до Catalina, удалил все системные звуковые расширения, которые нашел, но то же самое на Android и компьютерах некоторых других друзей (Mac, ПК).
Я использую версию 1.0.1 Chromium: 78.0.3904.108 (официальная сборка) (64-разрядная версия).
Это видео на YouTube демонстрирует проблему с треском звука.
Я сделал две демонстрации CodePen, которые вы можете протестировать здесь:
Взломы веб-аудио (Vanila + no Worklet):
const ctx = new(window.AudioContext || window.webkitAudioContext)();
const request = new XMLHttpRequest();
const gainNode = ctx.createGain();
const sourceNode = ctx.createBufferSource();
request.open('GET', 'https://poppublic.s3.amazonaws.com/other/2.mp3', true);
request.responseType = 'arraybuffer';
request.onload = () => {
ctx.decodeAudioData(request.response, buffer => {
sourceNode.buffer = buffer;
console.log(sourceNode.buffer.sampleRate);
});
};
request.onerror = function(e) {
console.log('HTTP error', e);
};
request.send();
play = () => {
sourceNode.connect(gainNode);
gainNode.connect(ctx.destination);
sourceNode.start(0);
}
stop = () => {
sourceNode.stop(0);
}
<button onClick="play()">Play</button>
<button onClick="stop()">Stop</button>
Взломы веб-аудио (Vanila + Worklet):
const ctx = new(window.AudioContext || window.webkitAudioContext)();
const request = new XMLHttpRequest();
let gainNode = null;
let sourceNode = null;
let buffer = null;
let worklet = null;
try {
const script = 'https://poppublic.s3.amazonaws.com/other/worklet/processor.js';
ctx.audioWorklet.addModule(script).then(() => {
worklet = new AudioWorkletNode(ctx, 'popscord-processor')
request.open('GET', 'https://poppublic.s3.amazonaws.com/other/2.mp3', true);
request.responseType = 'arraybuffer';
request.onload = () => {
ctx.decodeAudioData(request.response, buff => {
buffer = buff;
console.log(buff.sampleRate);
});
};
request.onerror = function(e) {
console.log('HTTP error', e);
};
request.send();
});
} catch (e) {
this.setState({
moduleLoaded: false
});
console.log('Failed to load module', e);
}
play = () => {
stop();
gainNode = ctx.createGain();
sourceNode = ctx.createBufferSource();
sourceNode.buffer = buffer;
sourceNode.connect(gainNode);
gainNode.connect(ctx.destination);
sourceNode.start(0);
}
stop = () => {
try {
sourceNode.disconnect();
gainNode.disconnect();
sourceNode.stop(0);
} catch (e) {
console.log(e.message)
}
}
<button onClick="play()">Play</button>
<button onClick="stop()">Stop</button>
Фортепианный MP3, который вы услышите, представляет собой звук 48000 Гц / 32 бита / 320 КБ, записанный в студии.
Перед тем как сообщать об ошибках, мне нужно убедиться, что мой код верен. Может, я не связываю вещи так, как должно.
1 ответ
При использовании рабочего пакета приоритет аудиопотока по умолчанию является нормальным. Это не очень хорошо для звука, как вы видели, запустив webaudio и затем перемещая окно.
Что вы можете сделать, так это перейти к chrome://flags, найти рабочийлет и включить флаг с именем "Использовать поток с приоритетом реального времени для звукового рабочего пакета". Это должно помочь на Mac и Windows. Не знаю, повлияет ли это на Android.
Если вы слышите трещины с помощью WebAudio без рабочего пакета, как в первом примере кода, то это неожиданно, и вам действительно следует сообщить об этом.