我正在尝试通过node.js(express)服务器上的websocket将音频流式传输到Web浏览器。音频来自iOS设备,为16位单声道wav文件,采样速率为4k(每秒4000个样本)。
这是我的代码:
服务器代码:
webSocketServer.on('connection', function connection(client) {
client.on('message', function(message) {
webSocketServer.clients.forEach(function each(connection) {
connection.send(message, { binary: true }
);
});
});
客户代码:
webSocket = new WebSocket('ws://' + window.location.hostname + ':8080/');
webSocket.binaryType = 'arraybuffer'
webSocket.onmessage = function(message) {
var arrayBuffer = message.data // wav from server, as arraybuffer
var source = audioContext.createBufferSource();
audioContext.decodeAudioData(arrayBuffer, function(buffer){
source.buffer = buffer
source.connect(audioContext.destination)
source.start(time);
time += source.buffer.duration
}, function(){
console.log('error')
})
};
decodeAudioData()
似乎正在工作,但它返回的音频缓冲区长度是我预期的一半。 (例如4000个样本只会给我0.5秒的音频。我原本以为这是因为wav是16位而不是32,但是切换到32会导致decodeAudioData()
触发它的错误回调。
我认为这种解决方法可以添加到成功回调中:
source.playbackRate.value = 0.5 // play at half speed
time += source.buffer.duration * 2 // double duration
这样可以完美地完成,但是我遇到了一个问题:音频块之间有一个声音“点击”或“弹出”。在将块分隔一秒(time += (source.buffer.duration * 2) + 1
)后,我发现点击发生在每个块的最开始。
所以我的主要两个头脑是:
1)为什么解码后的音频播放速度是我预期的两倍?对于Web Audio API,我的采样率是否过低?为什么我不能解码32位wav?
2)我对数字音频工作站(能力,逻辑)有一些经验,我知道如果波从样本中“跳”回到零或反之亦然(即:开始/结束正弦),就会出现咔哒声在一个阶段中挥手)。那是怎么回事?有办法解决这个问题吗?交叉淡化每个单独的样本似乎很愚蠢。为什么不是最后一个停止的每个块拾取?
答案 0 :(得分:1)
1)我收到的音频实际上是错误的2k,但是wav标题仍然表示4k,因此双倍速度错误。
2)见Chris Wilsons answer here的最后一段:
最后 - 如果声音流与默认音频设备的采样率不匹配,这将无法正常工作;总会有点击,因为decodeAudioData将重新采样到设备速率,这将没有一个完美的持续时间。它会起作用,但可能会出现像块边界点击的工件。您需要一个尚未规范或实现的功能 - 可选择的AudioContext采样率 - 以便解决此问题。
Brion Vibbers AudioFeeder.js无需任何点击即可使用,但需要原始的32位pcm数据。同时要警惕upsampling artifacts!
答案 1 :(得分:-1)
另一种选择: 您可以使用MediaSource API来克服音频之间的这些故障。
如果您需要对此进行全面研究,请使用:MSE for Audio