как остановить воспроизведение конструктора аудио js?
Написал сайт по воспроизведению аудиофайлов с визуализацией;
window.addEventListener('click', (e) => {
const targetTrack = e.target.closest('.audio-block')
if(e.target.closest('.audio-block')) {
const srcAudio = targetTrack.querySelector('audio')
let newAudio = new Audio()
newAudio.src = srcAudio.getAttribute('src')
context = new AudioContext()
analyser = context.createAnalyser();
analyser.connect(context.destination)
if(newAudio.paused) {
newAudio.play()
} else {
newAudio.pause()
}
src = context.createMediaElementSource(newAudio)
src.connect(analyser)
}
}
как остановить проигрывание аудиозаписи??? при повторном нажатии на блок, этот же аудиотрек воспроизводится поверх уже играющего
Ответы (2 шт):
Лучше всего, думаю сделать класс Player который будет заниматься воспроизведением и инкапсулировать всю логику.
В данном случае newAudio создается 1 раз, newAudio.src меняется только если это новый источник, так как установка этого свойства автоматически переводит аудио в режим проигрывания.
let newAudio = new Audio()
window.addEventListener('click', (e) => {
const targetTrack = e.target.closest('.audio-block')
if(e.target.closest('.audio-block')) {
const srcAudio = targetTrack.querySelector('audio')
if (newAudio.src !== srcAudio.getAttribute('src')){
newAudio.src = srcAudio.getAttribute('src')
}
//context = new AudioContext()
//analyser = context.createAnalyser()
//analyser.connect(context.destination)
if(newAudio.paused) {
newAudio.play()
} else {
newAudio.pause()
}
//src = context.createMediaElementSource(newAudio)
//src.connect(analyser)
}
})
<div class="audio-block">file_example_OOG_1MG.ogg
<audio src ="https://file-examples.com/storage/fe7d3a0d44631509da1f416/2017/11/file_example_OOG_1MG.ogg"></audio>
</div>
Доработанный вариант ответа:
C учетом потенциальной утечки памяти сделаны ограничение на создание объектов а так же высвобождение ресурсов при необходимости
На снимке видно, что освобождение памяти происходит. Тесты проводились на 2х аудиозаписях с быстрым переключением с одной на другую, что соответсвенно запускало функцию initSrc основной источник утечки памяти.
let srcAudio
let src
let audioCtx
let analyser
function initSrc(item) {
if (src){
src.disconnect(); // освобождаем ресурс
}
if (!audioCtx) { // единожды создаем контекст и анализатор
audioCtx = new AudioContext()
analyser = audioCtx.createAnalyser()
analyser.connect(audioCtx.destination)
}
src = new MediaElementAudioSourceNode(audioCtx, {
mediaElement: item // связываем контекст и аудио элемент
})
src.connect(analyser) // пробрасываем данные в анализатор
}
window.addEventListener('click', (e) => {
const targetTrack = e.target.closest('.audio-block')
if(e.target.closest('.audio-block')) {
const clickedAudio = targetTrack.querySelector('audio')
if( srcAudio && !srcAudio.paused && srcAudio !== clickedAudio ){
srcAudio.pause() // останавливает проигрывание из другого источника
}
srcAudio = clickedAudio
if(srcAudio.paused) {
srcAudio.play()
// создание контекста (инициируется только пользователем)
initSrc(srcAudio)
} else {
srcAudio.pause()
}
}
})
Ответ выше поможет с ошибкой, но создаст еще ошибку именно с audioContext(). В моем случае я еще должен обновлять Audio, иначе медиаэлемент будет выдавать ошибку:
HTMLMediaElement already connected previously to a different MediaElementSourceNode.
В общем смог решить проблему:
let audioArray = []; //создаем массив, в дальнейшем будем закладывать принцип работы AudioContext в нем. обновлять элемент, дабы обойти ошибку
let newAudio = new Audio();
window.addEventListener('click', (e) => {
const targetTrack = e.target.closest('.audio-block')
if(e.target.closest('.audio-block')) {
const srcAudio = targetTrack.querySelector('audio')
if(audioArray.length > 0) { //если длина массива больше одного элемента то....
audioArray.shift() //.....удаляем первый элемент
}
audioArray.push(newAudio) //закидываем в конец массива аудио, по которому был совершен клик
context = new AudioContext()
audioArray.forEach((item) => {
if(srcAudio.paused && item.paused) {
srcAudio.play()
item.play()
} else {
srcAudio.pause()
item.pause()
}
if(!src) {
src = context.createMediaElementSource(item)
analyser = context.createAnalyser()
src.connect(analyser)
}
})
}
}
У меня по крайней мере все заработало.
