Ama*_*pta 5 javascript websocket node.js web-audio-api
我正在通过Web-Socket从服务器流式传输音频数据
ws.on('message', function incoming(message) {
var readStream = fs.createReadStream("angular/data/google.mp3",
{
'flags': 'r',
'highWaterMark': 128 * 1024
}
);
readStream.on('data', function(data) {
ws.send(data);
});
readStream.on('end', function() {
ws.send('end');
});
readStream.on('error', function(err) {
console.log(err)
});
});
Run Code Online (Sandbox Code Playgroud)
在客户端
var chunks = [];
var context = new AudioContext();
var soundSource;
var ws = new WebSocket(url);
ws.binaryType = "arraybuffer";
ws.onmessage = function(message) {
if (message.data instanceof ArrayBuffer) {
chunks.push(message.data)
} else {
createSoundSource(chunks);
}
};
function createSoundSource(audioData) {
soundSource = context.createBufferSource();
for (var i=0; i < audioData.length;i++) {
context.decodeAudioData(audioData[i], function(soundBuffer){
soundSource.buffer = soundBuffer;
soundSource.connect(context.destination);
soundSource.start(0);
});
}
}
Run Code Online (Sandbox Code Playgroud)
但是soundSource.buffer = soundBuffer;第二次设置缓冲区会导致错误
未捕获的DOMException:无法在'AudioBufferSourceNode'上设置'buffer'属性:已经设置后无法设置缓冲区
对于如何最好地update使用新的音频数据播放Web Audio API的任何建议或见解,将不胜感激。
缓冲区一旦AudioBufferSourceNode设置就无法重置。这就像“一劳永逸”。每次想要播放不同的缓冲区时,都必须创建一个新的缓冲区AudioBufferSourceNode才能继续播放。这些都是非常轻量级的节点,因此即使创建大量节点也不必担心性能。
为了解决这个问题,您可以修改函数以简单地为循环体内的每个块createSoundSource创建一个,如下所示:AudioBufferSourceNode
function createSoundSource(audioData) {
for (var i=0; i < audioData.length;i++) {
context.decodeAudioData(audioData[i], function(soundBuffer){
var soundSource = context.createBufferSource();
soundSource.buffer = soundBuffer;
soundSource.connect(context.destination);
soundSource.start(0);
});
}
}
Run Code Online (Sandbox Code Playgroud)
我试图让代码风格尽可能接近原始风格,但现在是 2020 年了,利用现代功能的函数实际上可能如下所示:
async function createSoundSource(audioData) {
await Promise.all(
audioData.map(async (chunk) => {
const soundBuffer = await context.decodeAudioData(chunk);
const soundSource = context.createBufferSource();
soundSource.buffer = soundBuffer;
soundSource.connect(context.destination);
soundSource.start(0);
})
);
}
Run Code Online (Sandbox Code Playgroud)
如果您想在新数据到达时立即停止旧节点(看起来您希望通过重置来实现这一点,.buffer但我不确定),您必须存储它们并disconnect在需要时调用所有节点。
| 归档时间: |
|
| 查看次数: |
1268 次 |
| 最近记录: |