为什么 AudioBufferSourceNode 会在播放时堆叠?
Why AudioBufferSourceNodes stacks on play?
基本上,我正在尝试从来自 WS 套接字的字节构建和播放音频数据。
详细:
我有一个用 Django-Channels 编写的简单 WS 服务器,在连接时 returns 我将音频文件拆分为 blob 对象,每个块有 6144 字节。接下来,我想解码这个 blob 数据并将其转换为声音:
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
var play = document.querySelector('#play');
var audioQueue = []
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ 'audio-stream-test'
+ '/'
);
chatSocket.onmessage = function(e) {
e.data.arrayBuffer().then(buffer => {
audioCtx.decodeAudioData(buffer, (x)=>{
source = audioCtx.createBufferSource();
source.buffer = x;
source.connect(audioCtx.destination);
source.loop = false;
audioQueue.push(source)
})
})
}
WS发送完所有数据后,在服务器端关闭。最后一件事是播放来自 audioQueue
数组的排队缓冲区:
play.onclick = function() {
var playOffset;
for (let [bufferCount, buffer] of audioQueue.entries()) {
if (bufferCount == 0) {
playOffset = 0
} else {
playOffset = audioQueue[bufferCount-1].buffer.duration
}
buffer.start(when=playOffset)
}
}
想澄清这一行:playOffset = audioQueue[bufferCount-1].buffer.duration
。我想,我写对了,因为我想在旧的(已经播放过的)缓冲区的末尾播放新的缓冲区。
对我来说,作为 服务器端 开发人员,它似乎应该可以正常工作。
但是,主要问题是:audioQueue
数组中的所有缓冲区都一次 播放。 IDK我做错了什么。希望得到您的帮助:)
您需要启动与 AudioContext
的 currentTime
相关的每个 AudioBufferSourceNode
。
play.onclick = function() {
audioQueue.reduce((startTime, audioBufferSourceNode) => {
audioBufferSourceNode.start(startTime);
return startTime + audioBufferSourceNode.buffer.duration;
}, audioContext.currentTime);
};
上面的代码将遍历 audioQueue
中的所有节点。它通过根据 AudioContext
.
的 currentTime
累积先前节点的持续时间来计算每个 AudioBufferSourceNode
的 startTime
基本上,我正在尝试从来自 WS 套接字的字节构建和播放音频数据。
详细:
我有一个用 Django-Channels 编写的简单 WS 服务器,在连接时 returns 我将音频文件拆分为 blob 对象,每个块有 6144 字节。接下来,我想解码这个 blob 数据并将其转换为声音:
var audioCtx = new (window.AudioContext || window.webkitAudioContext)();
var source;
var play = document.querySelector('#play');
var audioQueue = []
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ 'audio-stream-test'
+ '/'
);
chatSocket.onmessage = function(e) {
e.data.arrayBuffer().then(buffer => {
audioCtx.decodeAudioData(buffer, (x)=>{
source = audioCtx.createBufferSource();
source.buffer = x;
source.connect(audioCtx.destination);
source.loop = false;
audioQueue.push(source)
})
})
}
WS发送完所有数据后,在服务器端关闭。最后一件事是播放来自 audioQueue
数组的排队缓冲区:
play.onclick = function() {
var playOffset;
for (let [bufferCount, buffer] of audioQueue.entries()) {
if (bufferCount == 0) {
playOffset = 0
} else {
playOffset = audioQueue[bufferCount-1].buffer.duration
}
buffer.start(when=playOffset)
}
}
想澄清这一行:playOffset = audioQueue[bufferCount-1].buffer.duration
。我想,我写对了,因为我想在旧的(已经播放过的)缓冲区的末尾播放新的缓冲区。
对我来说,作为 服务器端 开发人员,它似乎应该可以正常工作。
但是,主要问题是:audioQueue
数组中的所有缓冲区都一次 播放。 IDK我做错了什么。希望得到您的帮助:)
您需要启动与 AudioContext
的 currentTime
相关的每个 AudioBufferSourceNode
。
play.onclick = function() {
audioQueue.reduce((startTime, audioBufferSourceNode) => {
audioBufferSourceNode.start(startTime);
return startTime + audioBufferSourceNode.buffer.duration;
}, audioContext.currentTime);
};
上面的代码将遍历 audioQueue
中的所有节点。它通过根据 AudioContext
.
currentTime
累积先前节点的持续时间来计算每个 AudioBufferSourceNode
的 startTime