我正在流式录制的PCM音频从一个浏览器与web音频API。
我正在用binaryJS(websocket连接)将它流到一个nodejs服务器上,并尝试使用speaker npm模块在服务器上播放该流。
这是我的当事人。音频缓冲器首先是非交错的IEEE 32位线性PCM,标称范围在-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包写入speaker对象。
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文件,并且它很好地回放了。
扬声器的文档和音频缓冲区的文档
我被这事难住好几天了。有人能找出问题所在或者提供一个不同的方法吗?
首先,我错误地使用了websocket API。我更新了上面,以正确使用它。
我需要将音频缓冲区转换为整数数组缓冲区。我选择使用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);
}
看起来像是作为meta
对象发送流。
根据这些文档,binaryclient.send
按此顺序接受一个data
对象(流)和一个meta
对象。stream
事件的回调在第一个参数中接收流(作为BinaryStream
对象,而不是Buffer
),在第二个参数中接收Meta
对象。
您将send()
字符串'channel'
作为流传递,并将GetChannelData()
中的Float32Array
作为元对象传递。如果您交换这两个参数(或者只使用client.send(leftChannel)
),然后更改服务器代码,将stream
传递给speaker.write
而不是leftChannel
(可能应该将其重命名为meta
,或者在不需要时将其删除),可能会起作用。
注意,由于float32array
不是流或缓冲区对象,所以BinaryJS可能尝试在一个块中发送它。您可能希望发送leftchannel.buffer
(该对象后面的arraybuffer
)。
让我知道这对你有用吗;我现在无法测试你的精确设置。