如何让浏览器释放 OfflineAudioContext 使用的内存?
How to get browsers to release memory used by OfflineAudioContext?
我正在使用 OfflineAudioContext 将 WebAudio 信号呈现到缓冲区中,以便我可以分析结果。当我反复这样做时,似乎永远不会释放关联的内存,最终导致浏览器选项卡崩溃。
这是一个最小的复制:
// render 10 minutes of audio into a big buffer
var ctx = new OfflineAudioContext(1, 44100 * 600, 44100)
var osc = ctx.createOscillator()
osc.start()
ctx.startRendering().then(buffer => {
// attempt to clean up
osc.stop()
osc = null
buffer = null
ctx = null
})
运行 在 JS 控制台中将呈现一个永远不会释放的 ~100MB 缓冲区。 运行 它会反复消耗内存,直到选项卡最终崩溃(在 mac chrome/mozilla、windows chrome/mozilla/edge 中测试)。
如何让浏览器释放与 OfflineAudioContext
关联的内存?
这已 confirmed as a bug,没有解决方法。在修复之前,这似乎是生活中的事实。
这是一个令人头疼的问题,但我终于找到了一个解决方法:创建一个 iframe
,在其中 运行 音频渲染代码,return 结果到你的主要 window 使用 postMessage
,并在收到结果时立即从 DOM 中删除 iframe
。这将清除与其关联的所有资源,包括 offlineAudioContext
.
当然,只有当您的用例是进行相对较少数量的相对较长的渲染时,这才实用。
请注意,要以高效的方式传回数据,您应该发送 ArrayBuffer
个对象,它们是 Transferable
:
context.oncomplete = function (e) {
var channels = [];
for (var c = 0; c < e.renderedBuffer.numberOfChannels; c++) {
channels.push(e.renderedBuffer.getChannelData(c));
}
channels = channels.map( function(c) {return c.buffer;} );
window.parent.postMessage({
action:'renderResult',
data: channels
}, "*", channels);
}
并在接收端从中重新创建 Float32Arrays。
我正在使用 OfflineAudioContext 将 WebAudio 信号呈现到缓冲区中,以便我可以分析结果。当我反复这样做时,似乎永远不会释放关联的内存,最终导致浏览器选项卡崩溃。
这是一个最小的复制:
// render 10 minutes of audio into a big buffer
var ctx = new OfflineAudioContext(1, 44100 * 600, 44100)
var osc = ctx.createOscillator()
osc.start()
ctx.startRendering().then(buffer => {
// attempt to clean up
osc.stop()
osc = null
buffer = null
ctx = null
})
运行 在 JS 控制台中将呈现一个永远不会释放的 ~100MB 缓冲区。 运行 它会反复消耗内存,直到选项卡最终崩溃(在 mac chrome/mozilla、windows chrome/mozilla/edge 中测试)。
如何让浏览器释放与 OfflineAudioContext
关联的内存?
这已 confirmed as a bug,没有解决方法。在修复之前,这似乎是生活中的事实。
这是一个令人头疼的问题,但我终于找到了一个解决方法:创建一个 iframe
,在其中 运行 音频渲染代码,return 结果到你的主要 window 使用 postMessage
,并在收到结果时立即从 DOM 中删除 iframe
。这将清除与其关联的所有资源,包括 offlineAudioContext
.
当然,只有当您的用例是进行相对较少数量的相对较长的渲染时,这才实用。
请注意,要以高效的方式传回数据,您应该发送 ArrayBuffer
个对象,它们是 Transferable
:
context.oncomplete = function (e) {
var channels = [];
for (var c = 0; c < e.renderedBuffer.numberOfChannels; c++) {
channels.push(e.renderedBuffer.getChannelData(c));
}
channels = channels.map( function(c) {return c.buffer;} );
window.parent.postMessage({
action:'renderResult',
data: channels
}, "*", channels);
}
并在接收端从中重新创建 Float32Arrays。