在 Node.js 上从 Web Audio API 播放 PCM 流
Posted
技术标签:
【中文标题】在 Node.js 上从 Web Audio API 播放 PCM 流【英文标题】:Playing PCM stream from Web Audio API on Node.js 【发布时间】:2014-01-19 11:59:43 【问题描述】:我正在使用网络音频 api 从浏览器流式传输录制的 PCM 音频。
我正在使用binaryJS (websocket connection) 将其流式传输到 nodejs 服务器,并且我正在尝试使用扬声器 npm 模块在服务器上播放该流。
这是我的客户。 The audio buffers are at first non-interleaved IEEE 32-bit linear PCM with a nominal range between -1 and +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 for speaker 和docs for the AudioBuffer
这几天我一直在纠结这个问题。有人可以找出问题所在或提供不同的方法吗?
更新解决方案
首先,我错误地使用了 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);
【问题讨论】:
为了消除或识别扬声器作为错误源,如果您以与客户端相同的方式将接收端的缓冲区写入 wav,它是否正确播放(扬声器有问题)还是尖锐的声音(流有问题)?或者,您是否可以通过扬声器播放正常工作的 AudioBuffer? 嗨,我可以在 github 上的某个地方找到你的代码吗? 【参考方案1】:看起来您正在通过 meta
对象发送流。
根据文档,BinaryClient.send
按顺序采用 data
对象(流)和 meta
对象。 stream
事件的回调在第一个参数中接收流(作为BinaryStream
对象,而不是Buffer
),在第二个参数中接收meta
对象。
您将send()
字符串'channel'
作为流传递,并将getChannelData()
中的Float32Array
作为元对象传递。也许如果您要交换这两个参数(或只使用client.send(leftChannel)
),然后将服务器代码更改为将stream
传递给speaker.write
而不是leftchannel
(可能应该重命名为meta
,或丢弃如果您不需要它),它可能会起作用。
请注意,由于Float32Array
不是流或缓冲区对象,BinaryJS 可能会try to send it in one chunk。您可能想改为发送leftChannel.buffer
(the ArrayBuffer
behind that object)。
让我知道这是否适合您;我现在无法测试您的确切设置。
【讨论】:
我确实对 websocket API 有问题。我用正确的用法更新了我的答案。这是错误的一部分,我发现了与音频缓冲区有关的另一部分。既然你帮助解决了部分问题,我会奖励你。以上是关于在 Node.js 上从 Web Audio API 播放 PCM 流的主要内容,如果未能解决你的问题,请参考以下文章
在 python 服务器上从 Fabric.js JSON 构造图像
将音频从 Node.js 服务器流式传输到 HTML5 <audio> 标签