Воспроизведение потока PCM из API веб-аудио на Node.js
Я транслирую записанный звук PCM из браузера с помощью веб-аудио api.
Я передаю его с помощью binaryJS (соединение с веб-сайтами) на сервер nodejs, и я пытаюсь воспроизвести этот поток на сервере с помощью модуля динамиков npm.
Это мой клиент. Звуковые буферы - это первый неперемещенный 32-разрядный линейный ИКМ IEEE с номинальным диапазоном от -1 до +1. Я беру один из двух каналов PCM, чтобы начать и потопить его ниже.
var client = new BinaryClient('ws://localhost:9000');
var Stream = client.send();
recorder.onaudioprocess = function(AudioBuffer){
var leftChannel = AudioBuffer.inputBuffer.getChannelData (0);
Stream.write(leftChannel);
}
Теперь я получаю данные в виде буфера и пытаюсь записать его в объект динамика из пакета npm.
var Speaker = require('speaker');
var speaker = new Speaker({
channels: 1, // 1 channel
bitDepth: 32, // 32-bit samples
sampleRate: 48000, // 48,000 Hz sample rate
signed:true
});
server.on('connection', function(client){
client.on('stream', function(stream, meta){
stream.on('data', function(data){
speaker.write(leftchannel);
});
});
});
В результате получается высокий визг на моем ноутбуке, который явно не является тем, что записывается. Это тоже не обратная связь. Я могу подтвердить, что буферы записи на клиенте действительны, так как я пытался записать их в WAV файл, и он отлично воспроизводится.
docs для динамиков и docs для AudioBuffer, о которых идет речь
Я был в тупике в течение нескольких дней. Может ли кто-то выяснить, что не так, или, возможно, предложить другой подход?
Обновление с помощью решения
Во-первых, я неправильно использовал API-интерфейс websocket. Я обновил выше, чтобы использовать его правильно.
Мне нужно было преобразовать звуковые буферы в буфер массива целых чисел. Я предпочитаю использовать Int16Array. Так как данный звуковой буфер имеет диапазон между 1 и -1, это было так же просто, как умножение на диапазон нового ArrayBuffer (32767 по -32768).
recorder.onaudioprocess = function(AudioBuffer){
var left = AudioBuffer.inputBuffer.getChannelData (0);
var l = left.length;
var buf = new Int16Array(l)
while (l--) {
buf[l] = left[l]*0xFFFF; //convert to 16 bit
}
Stream.write(buf.buffer);
}
Ответы
Ответ 1
Похоже, вы отправляете свой поток как объект meta
.
В соответствии с документами BinaryClient.send
берет объект data
(поток) и объект meta
в указанном порядке, Обратный вызов для события stream
принимает поток (как объект BinaryStream
, а не Buffer
) в первом параметре, а meta
объект во втором.
Вы передаете send()
строку 'channel'
как поток и Float32Array
из getChannelData()
в качестве метаобъекта. Возможно, если бы вы обменяли эти два параметра (или просто использовали client.send(leftChannel)
), а затем изменили код сервера, чтобы передать stream
в speaker.write
вместо leftchannel
(который, вероятно, должен быть переименован в meta
или удален если вам это не нужно), это может сработать.
Обратите внимание, что поскольку Float32Array
не является потоковым или буферным объектом, BinaryJS может попытаться отправить его в один фрагмент. Вместо этого вы можете отправить leftChannel.buffer
(ArrayBuffer
за этот объект).
Сообщите мне, если это сработает для вас; Я не могу проверить вашу точную настройку прямо сейчас.