Хорошо, я разрабатываю приложение Elecron (javascript) для аудио-визуализации. Существует экземпляр Playlist()
, который получает пути к аудиофайлам, которые пользователь хочет воспроизвести. Когда первый звук заканчивается, он воспроизводит следующий. Все идет нормально. Приложение выполняет интенсивную вычислительную работу, извлекая аудиофункции из каждого канала, перерисовывая холсты и анимируя сюжеты. Это делает это красиво. Проблема в том, что каждый раз, когда приложение воспроизводит следующий файл, он становится все медленнее, как будто все аудиоданные до этого еще где-то. Я нашел в документации метод close()
из AudioContext()
:
"Метод close () интерфейса AudioContext закрывает аудиоконтент, высвобождая любые системные аудиоресурсы, которые он использует."
«Теперь 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()
, чтобы воссоздать все и воспроизвести. Логика возвращает ошибку на this.track = this.audioContext.createMediaElementSource(this.audioElement)
с:
"Не удалось выполнить 'createMediaElementSource' для 'BaseAudioContext': HTMLMediaElement, ранее уже подключенный к другому MediaElementSourceNode, в Audio.createAudioContext"
В данном примере источник звука - это просто случайный генератор, а не аудиофайл в формате mp3.
Я действительно застрял здесь. Не знаю что делать. Я даже не уверен, действительно ли AudioContext()
хранит данные из всех аудиофайлов до возникновения проблемы с производительностью. И если да, то как я могу восстановить HTMLMediaElement
в новый узел, созданный audio.createAudioContext()
? Я уже пробовал audio.track.disconnect()
, но это не работает (поскольку это не так, потому что здесь я отключаю track
от gainNode
). Кроме того, audioElement
не имеет disconnect()
метода, так как это всего лишь элемент HTML.
Есть идеи?
ОБНОВЛЕНИЕ:
Я решил проблему воссоздания звукового контекста, удаления и повторного создания элемента html. Но проблема сохраняется: чем больше новых аудиофайлов воспроизводится, тем медленнее приложение. Точнее теперь: чем больше создается новый AudioContext (), тем медленнее он становится (даже если я закрою предыдущий).