Как исправить "треск" звука при использовании 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 без рабочего пакета, как в первом примере кода, то это неожиданно, и вам действительно следует сообщить об этом.

Другие вопросы по тегам