gpt4 book ai didi

javascript - 如何使用来自网络套接字的网络音频 API 流式传输音频 block ?

转载 作者:搜寻专家 更新时间:2023-10-31 22:54:16 25 4
gpt4 key购买 nike

我正在通过来自服务器的 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)
});
});

客户端

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);
});
}
}

但是第二次设置buffer soundSource.buffer = soundBuffer;会报错

Uncaught DOMException: Failed to set the 'buffer' property on 'AudioBufferSourceNode': Cannot set buffer after it has been already been set

对于如何使用新音频数据更新 Web Audio API 播放的最佳建议或见解,我们将不胜感激。

最佳答案

一旦设置了 AudioBufferSourceNode,您就无法重置缓冲区。这就像一劳永逸。每次要播放不同的缓冲区时,都必须创建一个新的 AudioBufferSourceNode 才能继续播放。这些都是非常轻量级的 Node ,因此即使创建大量 Node 也不必担心性能。

为了解决这个问题,您可以修改 createSoundSource 函数,为循环体中的每个 block 简单地创建一个 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);
});
}
}

我试图让代码风格尽可能接近原始风格,但现在是 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);
})
);
}

如果你想在新数据到达时立即停止旧 Node (看起来你希望通过重置 .buffer 但我不确定),你必须存储他们并在适当的时候对所有这些人调用 disconnect

关于javascript - 如何使用来自网络套接字的网络音频 API 流式传输音频 block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41346699/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com