如何让浏览器释放 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。