Мы работали над клиентом аудиочата на основе JavaScript, который запускается в браузере и отправляет образцы аудио на сервер через WebSocket. Ранее мы пытались использовать ScriptProcessorNode API веб-аудио для получения образцов значений. Это хорошо работало на наших настольных компьютерах и ноутбуках, но мы столкнулись с плохим качеством звука при передаче с портативной платформы, которую мы должны поддерживать. Мы связываем это с задокументированными проблемами производительности процессора сценариев (https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API). На КПК с размером буфера процессора сценариев 2048 звук постоянно прерывался. На следующем интервале максимального размера (4096) звук был гладким (без разрывов), но была слишком большая задержка (около двух секунд).
Наши результаты от ScriptProcessorNode побудили поэкспериментировать с Audio Worklet. К сожалению, с нашей ворлетной реализацией качество звука хуже: и обрывы, и задержки, даже на наших ноутбуках. Мне интересно, есть ли способ настроить нашу реализацию ворклета, чтобы повысить производительность, или того, что мы испытываем, следует ожидать от (является «нормальным») текущего состояния аудио-ворклетов (проблемы Chromium 796330, 813825 и 836306 кажутся актуальными).
Вот немного подробнее о том, что делает код:
- Создайте MediaStreamStreamSourceNode с помощью MediaStream, полученного от getUserMedia.
- Соедините исходный узел с реализацией нашего рабочего узла (расширяет AudioWorkletNode).
- Наша реализация процессора worklet (расширяет AudioWorkletProcessor) буферизует блоки, поступающие в качестве «входного» аргумента для его метода обработки.
- Когда буфер заполнен, используйте MessagePort, чтобы отправить содержимое буфера на узел worklet.
- Узел Worklet передает содержимое буфера через соединение WebSocket.
Метод процесса ниже. Переменная "samples" представляет собой Float32Array, который инициализируется размером буфера и используется повторно. Я немного поэкспериментировал с размером буфера, но, похоже, это не повлияло. Этот подход основан на рекомендациях раздела 4.1 документа AudioWorklet: будущее веб-аудио, чтобы свести к минимуму выделение памяти.
if (micKeyed == true) {
if (inputs[0][0].length == framesPerBlock) {
samples.set(inputs[0][0], currentBlockIndex * framesPerBlock);
currentBlockIndex++;
if (currentBlockIndex == lastBlockIndex) {
// console.log('About to send buffer.');
this.port.postMessage(samples);
currentBlockIndex = 0;
}
} else {
console.error("Got a block of unexpected length!!!");
}
}
return true;
В настоящее время проводится тестирование на ПК с Chrome 72.0.3626.109 на CentOS 7. Наши портативные устройства — Panasonic FZ-N1 с Chrome 72.0.3626.105 на Android 6.0.1.
Спасибо за чтение и любые предложения, которые вы можете предоставить.
MediaSource
? См. также Потоковая передача аудио HTML5: точное измерение задержки?; Как использовать большой двоичный объект URL, MediaSource или другие методы для воспроизведения объединенных BLOB-объектов фрагментов мультимедиа? - person guest271314   schedule 20.02.2019