我有一个 React Next Web 应用程序,它使用 Web 音频 api 播放歌曲。我注意到浏览大量歌曲后,有时我的应用程序将无法加载新歌曲。
在 Chrome 中我收到此错误: 无法在“BaseAudioContext”上执行“decodeAudioData”:无法解码音频数据, 并且只有刷新页面后(有时需要刷新2-3次),我才能再次加载歌曲。 在 Chrome 开发工具的“内存”选项卡中查看“JS 堆总大小”并不表明存在内存泄漏。
在 Safari 中,它只是自动刷新页面。
为了确保它不在我的代码中,我用一个最小的示例创建了一个新的网络应用程序,并且我可以重现该问题。我在大约 250 次后收到解码错误。
export const test = async () => {
const audioContext = new AudioContext();
const blob = (
await axios.get("./url-to-some-song.wav", {
responseType: "blob",
})
).data;
for (let i = 0; i < 300; i++) {
const arrayBuffer = await blob.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
}
};
我尝试在每次迭代后添加延迟 - 但这没有帮助。 看起来浏览器可能有一些限制,但我找不到任何相关文档。 可能是什么?
我可以在 Chrome v122 中重现该问题。使用
structuredClone()
时似乎已修复。但我没有很好的解释为什么会这样。我猜这是 Chrome 中的一个错误。
export const test = async () => {
const audioContext = new AudioContext();
const blob = (
await axios.get("./url-to-some-song.wav", {
responseType: "blob",
})
).data;
for (let i = 0; i < 300; i++) {
const arrayBuffer = await blob.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(
structuredClone(arrayBuffer)
);
}
};
您还可以通过直接获取数据作为
'arrayBuffer'
来避免额外的步骤。
export const test = async () => {
const audioContext = new AudioContext();
const arrayBuffer = (
await axios.get("./url-to-some-song.wav", {
responseType: "arrayBuffer",
})
).data;
for (let i = 0; i < 300; i++) {
const audioBuffer = await audioContext.decodeAudioData(
structuredClone(arrayBuffer)
);
}
};