electron 播放的音频文件越多,AudioContext的应用性能就越差

ruarlubt  于 2022-12-08  发布在  Electron
关注(0)|答案(1)|浏览(252)

我正在开发一个Elecron应用程序(JavaScript)来实现音频可视化。有一个Playlist()示例,它接收用户想要播放的音频文件路径。当第一个音频播放完后,它会播放下一个。到目前为止一切都很好。这个应用程序进行了大量的计算工作,从每个通道提取音频特征,重新渲染画布和动画情节。它做得很漂亮。
问题是:每次应用播放下一个文件时,速度就越慢,就好像之前的所有音频数据都还在某个地方一样。我在文档中找到了AudioContext()中的close()方法:
AudioContext接口的close()方法关闭音频上下文,释放它使用的任何系统音频资源。
AudioContext现在可以显式关闭,从而释放与AudioContext相关得所有硬件资源.如果没有此功能,开发人员必须依靠AudioContext得垃圾回收来释放硬件资源.
我还发现了关闭和重新启动音频上下文的示例:
https://github.com/mdn/webaudio-examples/blob/master/audiocontext-states/index.html
https://mdn.github.io/webaudio-examples/audiocontext-states/
问题是我使用的是audioContext.createMediaElementSource(HTMLelementID),它不允许我像示例中那样重新启动所有节点。代表我之前所做操作的简化代码是:

class Audio() {
   constructor(audioElementID, playlistObj) {
      this.audioContext = new AudioContext();
      this.audioElement = document.getElementById(audioElementID);
      this.track = this.audioContext.createMediaElementSource(this.audioElement);
      this.gainNode = this.audioContext.createGain();
      this.track.connect(this.gainNode);
      this.gainNode.connect(this.audioContext.destination);

      this.audioElement.addEventListener('ended', () => {
         playlistObj.playnextTrack() // changes the src from the html element (audioElementID) and sets this.audioElement.currentTime to 0
      }
   }
 // everything is a property here for debugging reasons 
}

const audio = new Audio('audioID', playlist);

// playlist defined somewhere else

为了实现close()方法,我必须更改(与示例完全相同,一个重新创建所有内容的函数):

class Audio() {
   constructor(audioElementID, playlistObj) {
      this.createAudioContext = () => {
         this.audioContext = new AudioContext();
         this.audioElement = document.getElementById(audioElementID);
         this.track = this.audioContext.createMediaElementSource(this.audioElement);
         this.gainNode = this.audioContext.createGain();
         this.track.connect(this.gainNode);
         this.gainNode.connect(this.audioContext.destination);

         this.audioElement.addEventListener('ended', () => {
            playlistObj.playNextTrack() // changes the src from the html element (audioElementID) and sets this.audioElement.currentTime to 0
         }
      }
      
      this.createAudioContext();
   } 
}

playlist.playNextTrack()中,我暂停audioElement,调用audio.audioContext.close(),等待它(这是一个承诺),调用audio.createAudioContext()重新创建所有内容并播放。
“无法在'BaseAudioContext'上执行'createMediaElementSource':HTMLMediaElement先前已连接到位于音频的其他MediaElementSourceNode。createAudioContext”
在本示例中,音频源只是随机振荡器,而不是mp3音频文件。
我真的被困在这里了。不知道该怎么办。我甚至不确定AudioContext()是否真的在导致这个性能问题之前保存了所有音频文件的数据。如果是这样的话,如何将HTMLMediaElement重新连接到audio.createAudioContext()创建的新节点?我已经尝试了audio.track.disconnect(),但它不起作用(因为这里我把trackgainNode断开了连接,所以不应该这样做)。而且audioElement没有disconnect()方法,因为它只是一个html元素。
你知道吗?
最新消息:
我忽略了重新创建音频上下文的问题,删除并重新创建html元素。但问题仍然存在:播放的新音频文件越多,应用程序的运行速度就越慢。现在更准确地说:创建的新AudioContext()越多,速度就越慢(即使我关闭了前一个)。

vnjpjtjt

vnjpjtjt1#

我真的被困在这里了。不知道该怎么办。我甚至不确定AudioContext()是否真的在导致这个性能问题之前保存了所有音频文件的数据。
不,这不太可能。AudioContext设置了采样率、输出目标和图形等内容。仅此而已。
AudioContext接口的close()方法关闭音频上下文,释放它使用的任何系统音频资源。
您误解了这一点的含义。那些“系统音频资源”是声音设备。当AudioContext运行时,会请求一个音频设备。这在低功率环境中特别有意义,如移动的设备。另一个例子是蓝牙。如果AudioContext保持运行,您的蓝牙耳机可能会保持打开状态。如果允许关闭AudioContext,则蓝牙耳机可以进入睡眠。
如果是这样,我如何将HTMLMediaElement重新连接到audio.createAudioContext()创建的新节点?
你不需要。如果API支持这一点就好了,但似乎没有。只需创建一个新的HTMLMediaElement。
你应该做的是正确地分析你的应用程序,找出速度变慢的地方。使用你的开发人员工具。虽然只是开始注解掉正在运行的部分可能会更快。我们当然不能告诉你问题在哪里,特别是从你所显示的代码。

相关问题