我播放的音频文件越多,AudioContext 就会影响应用程序性能
AudioContext compromising app performance the more audio files I play
好的,我正在开发一个用于音频可视化的 Elecron 应用程序 (javascript)。有一个 Playlist()
实例接收用户想要播放的音频文件路径。当第一个音频结束时,它会播放下一个。到目前为止,一切都很好。该应用程序执行密集的计算工作,从每个通道中提取音频特征,重新渲染画布和动画图。它做得很漂亮。问题是:应用程序每次播放下一个文件时,速度越慢,就好像之前的所有音频数据都还在某个地方。我在文档中找到了方法 close()
来自 AudioContext()
:
"The close() method of the AudioContext Interface closes the audio context, releasing any system audio resources that it uses."
"An AudioContext can now be explicitly closed, thereby releasing any hardware resources associated with the AudioContext. Without this, developers had to depend on garbage collection of the AudioContext to release hardware resources."
我也找到了这个关闭和重启音频上下文的例子:
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()
重新创建所有内容并播放。逻辑 returns 在 this.track = this.audioContext.createMediaElementSource(this.audioElement)
处出现错误:
"Failed to execute 'createMediaElementSource' on 'BaseAudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode, at Audio.createAudioContext"
在示例中,音频源只是一个随机振荡器,而不是 mp3 音频文件。
我真的被困在这里了。不知道该怎么办。在导致此性能问题之前,我什至不确定 AudioContext()
是否真的保存了所有音频文件的数据。如果是这样,我如何将 HTMLMediaElement
重新连接到 audio.createAudioContext()
创建的新节点?我已经尝试 audio.track.disconnect()
但它不起作用(因为它不应该因为我在这里断开 track
与 gainNode
的连接)。而且 audioElement
没有 disconnect()
方法,因为它只是一个 html 元素。
有什么想法吗?
更新:
我忽略了重新创建音频上下文的问题,删除并再次创建 html 元素。但问题仍然存在:播放的新音频文件越多,应用程序变得越慢。现在更准确地说:创建的新 AudioContext() 越多,它就越慢(即使我关闭了前一个)。
I'm really stuck here. Don't know what to do. I'm not even sure if AudioContext() really holds data from all the audio files before causing this performance problem.
不,这种情况真的不太可能。 AudioContext 设置采样率、输出目标和图表等内容。就这些了。
The close() method of the AudioContext Interface closes the audio context, releasing any system audio resources that it uses.
您误解了这意味着什么。那些 "system audio resources" 是声音设备。当 AudioContext 为 运行 时,请求了一个音频设备。这在移动设备等低功耗环境中尤为重要。另一个例子是蓝牙。如果 AudioContext 保持 运行,您的蓝牙耳机可能会保持打开状态。如果允许关闭AudioContext,那么蓝牙耳机可能会进入休眠状态。
And if so, how could I recconect the HTMLMediaElement to a new node audio.createAudioContext() creates?
你不知道。如果 API 支持这个就好了,但似乎不支持。只需创建一个新的 HTMLMediaElement。
您应该做的是正确分析您的应用程序,找出速度变慢的地方。使用您的开发人员工具。可能会更快,但只是开始注释掉 运行 的部分内容。我们当然不能告诉你问题出在哪里,具体来说,从你展示的代码中。
好的,我正在开发一个用于音频可视化的 Elecron 应用程序 (javascript)。有一个 Playlist()
实例接收用户想要播放的音频文件路径。当第一个音频结束时,它会播放下一个。到目前为止,一切都很好。该应用程序执行密集的计算工作,从每个通道中提取音频特征,重新渲染画布和动画图。它做得很漂亮。问题是:应用程序每次播放下一个文件时,速度越慢,就好像之前的所有音频数据都还在某个地方。我在文档中找到了方法 close()
来自 AudioContext()
:
"The close() method of the AudioContext Interface closes the audio context, releasing any system audio resources that it uses."
"An AudioContext can now be explicitly closed, thereby releasing any hardware resources associated with the AudioContext. Without this, developers had to depend on garbage collection of the AudioContext to release hardware resources."
我也找到了这个关闭和重启音频上下文的例子:
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()
重新创建所有内容并播放。逻辑 returns 在 this.track = this.audioContext.createMediaElementSource(this.audioElement)
处出现错误:
"Failed to execute 'createMediaElementSource' on 'BaseAudioContext': HTMLMediaElement already connected previously to a different MediaElementSourceNode, at Audio.createAudioContext"
在示例中,音频源只是一个随机振荡器,而不是 mp3 音频文件。
我真的被困在这里了。不知道该怎么办。在导致此性能问题之前,我什至不确定 AudioContext()
是否真的保存了所有音频文件的数据。如果是这样,我如何将 HTMLMediaElement
重新连接到 audio.createAudioContext()
创建的新节点?我已经尝试 audio.track.disconnect()
但它不起作用(因为它不应该因为我在这里断开 track
与 gainNode
的连接)。而且 audioElement
没有 disconnect()
方法,因为它只是一个 html 元素。
有什么想法吗?
更新:
我忽略了重新创建音频上下文的问题,删除并再次创建 html 元素。但问题仍然存在:播放的新音频文件越多,应用程序变得越慢。现在更准确地说:创建的新 AudioContext() 越多,它就越慢(即使我关闭了前一个)。
I'm really stuck here. Don't know what to do. I'm not even sure if AudioContext() really holds data from all the audio files before causing this performance problem.
不,这种情况真的不太可能。 AudioContext 设置采样率、输出目标和图表等内容。就这些了。
The close() method of the AudioContext Interface closes the audio context, releasing any system audio resources that it uses.
您误解了这意味着什么。那些 "system audio resources" 是声音设备。当 AudioContext 为 运行 时,请求了一个音频设备。这在移动设备等低功耗环境中尤为重要。另一个例子是蓝牙。如果 AudioContext 保持 运行,您的蓝牙耳机可能会保持打开状态。如果允许关闭AudioContext,那么蓝牙耳机可能会进入休眠状态。
And if so, how could I recconect the HTMLMediaElement to a new node audio.createAudioContext() creates?
你不知道。如果 API 支持这个就好了,但似乎不支持。只需创建一个新的 HTMLMediaElement。
您应该做的是正确分析您的应用程序,找出速度变慢的地方。使用您的开发人员工具。可能会更快,但只是开始注释掉 运行 的部分内容。我们当然不能告诉你问题出在哪里,具体来说,从你展示的代码中。