Зацикливание аудио HTML5

Недавно я играл со звуком HTML5, и хотя я могу заставить его воспроизводить звук, он будет воспроизводиться только один раз. Независимо от того, что я пытаюсь (установить свойства, обработчики событий и т. д.), я не могу заставить его зацикливаться.

Вот основной код, который я использую:

//myAudio is declared at a global scope, so it doesn't get garbage collected.
myAudio = new Audio('someSound.ogg');
myAudio.loop = true;
myAudio.play();

Я тестирую с помощью Chrome (6.0.466.0 dev) и Firefox (4 beta 1), оба из которых, кажется, рады игнорировать мои запросы на зацикливание. Любые идеи?

ОБНОВЛЕНИЕ: свойство loop теперь поддерживается во всех основных браузерах. .


person Toji    schedule 17.07.2010    source источник
comment
Не уверен насчет Chrome, но Firefox не поддерживает зацикливание.   -  person luiscubal    schedule 18.07.2010
comment
Просто запустите его, как только он закончится: myAudio.addEventListener(Завершено, function(e){myAudio.play();}, false);   -  person mattbasta    schedule 18.07.2010
comment
@ Брэндон Интересно, почему это не работает? Единственная разница между этим кодом и принятым ответом заключается в том, что в принятом ответе он устанавливает currentTime в 0 перед вызовом play. Это необходимо?   -  person mgiuca    schedule 23.06.2011
comment
@ Брэндон Да, см. Второй комментарий Кингджеффри к его собственному ответу. Вам нужно установить currentTime.   -  person mgiuca    schedule 23.06.2011
comment
Это работает просто отлично (по крайней мере, сегодня)   -  person dvlden    schedule 09.04.2016


Ответы (9)


Хотя указано loop, оно не реализовано ни в одном из известных мне браузеров Firefox [спасибо Anurag за указание на это]. Вот альтернативный способ зацикливания, который должен работать в браузерах с поддержкой HTML5:

var myAudio = new Audio('someSound.ogg'); 
myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
}, false);
myAudio.play();
person kingjeffrey    schedule 17.07.2010
comment
Хм... интересно. Раньше мне не везло с этим методом, но я не устанавливал текущее время. Однако, когда я пытаюсь это сделать, я получаю: Uncaught Error: INDEX_SIZE_ERR: DOM Exception 1 в строке this.currentTime = 0 - person Toji; 18.07.2010
comment
@Toji Вот документация для Ошибка INDEX_SIZR_ERR. Это означает, что начало песни находится за пределами диапазона, который может найти браузер. Это иногда происходит, если браузер думает, что это потоковое мультимедиа, или если серверу не хватает определенных возможностей (я забыл навскидку, что это за конкретная возможность, но я постараюсь ее отследить). Вы также можете использовать this.startTime, чтобы вернуться к самому раннему доступному времени. - person kingjeffrey; 18.07.2010
comment
@Toji Причина, по которой требуется .currentTime, связана с тем, как спецификация обрабатывает конец песни. Браузеры должны просто приостановить воспроизведение песни. Таким образом, возобновление воспроизведения происходит в конце песни. Указатель воспроизведения должен быть сброшен. - person kingjeffrey; 18.07.2010
comment
@Toji Вот еще одна мысль, если вы не можете заставить .currentTime работать. Внутри функции обратного вызова вы можете просто повторно объявить myAudio с тем же файлом и воспроизвести его снова. Повторное объявление также должно сбросить точку воспроизведения на начало песни. - person kingjeffrey; 18.07.2010
comment
установка его в this.startTime дает мне ту же ошибку, хотя теперь я начинаю задаваться вопросом, не проблема ли это с сервером. Я отдаю статические файлы с локального сервера django (это не самая надежная функция django). Соедините это с тем фактом, что Anurag действительно работает, и я думаю, что это, вероятно, только у меня. Я еще немного поиграю и сообщу вам о результатах. - person Toji; 18.07.2010
comment
Упс! Забыли об этом вопросе! Основная проблема заключалась в том, что я использовал локальный тестовый сервер Django для обслуживания своих медиафайлов, и, по-видимому, он не слишком доволен предоставлением потоковой информации. Загрузка и проверка скриптов, подобных приведенному здесь, на сервер моего сайта, позволяет зацикливаться. - person Toji; 15.09.2010
comment
FF поддерживает цикл, но на дату этого комментария (сентябрь 2012 г.) не очень хорошо. Отчет об ошибке находится здесь: bugzilla.mozilla.org/show_bug.cgi?id=449157< /а> - person Lee Goddard; 13.09.2012
comment
Возникла проблема с зацикливанием звука только при кэшировании. У кого-нибудь еще есть эта проблема? - person Josh Bedo; 10.10.2013

Чтобы добавить еще несколько советов, объединяющих предложения @kingjeffrey и @CMS: вы можете использовать loop там, где он доступен, и использовать обработчик событий kingjeffrey, когда он недоступен. Есть веская причина, по которой вы хотите использовать loop, а не писать собственный обработчик событий: как обсуждалось в отчете об ошибках Mozilla, хотя в настоящее время loop не зацикливается плавно (без пробелов) ни в одном из известных мне браузеров, это, безусловно, возможно и, вероятно, станет стандартом в будущем. Ваш собственный обработчик событий никогда не будет бесшовным в любом браузере (поскольку он должен прокачиваться через цикл событий JavaScript). Поэтому по возможности лучше использовать loop вместо того, чтобы писать собственное событие. Как указала CMS в комментарии к ответу Анурага, вы можете обнаружить поддержку loop, запросив переменную loop - если она поддерживается, это будет логическое значение (false), в противном случае оно будет неопределенным, как в настоящее время в Firefox.

Соединяем их вместе:

myAudio = new Audio('someSound.ogg'); 
if (typeof myAudio.loop == 'boolean')
{
    myAudio.loop = true;
}
else
{
    myAudio.addEventListener('ended', function() {
        this.currentTime = 0;
        this.play();
    }, false);
}
myAudio.play();
person mgiuca    schedule 23.06.2011
comment
Спасибо. это отлично работало для Opera, Firefox, Chrome... так как же мы можем добавить больше звуков (mp3) для Safari.... ??? добавление дополнительных переменных, вероятно, приведет к дублированию для Chrome (который поддерживает ogg и mp3)... - person ; 02.01.2012
comment
@pixelass Я не совсем уверен, как это сделать в коде. В HTML вы должны вкладывать теги «аудио» один в другой, и браузер выберет самый внешний, который соответствует. Я не знаю, можете ли вы сделать это вложение в программный объект Audio. Но вы, конечно, можете запрограммировать его самостоятельно: посмотрите метод Audio.canPlayType. - person mgiuca; 02.01.2012
comment
я знаю о методе html. Я мог бы попробовать использовать метод Audio.canPlayType. сейчас я использую 2 переменные, поэтому в хроме проигрываются 2 файла. на самом деле это не имеет большого значения, так как это всего лишь петля из океанских волн, которую я сделал. ... но было бы гораздо лучше просто добавить 2 источника. pixelass.com, если вам интересно. - person ; 02.01.2012

Ваш код работает для меня в Chrome (5.0.375) и Safari (5.0). Не зацикливается на Firefox (3.6).

См. пример.

var song = new Audio("file");
song.loop = true;
document.body.appendChild(song);​
person Anurag    schedule 17.07.2010
comment
+1 Очень круто. Я не знал, что loop был реализован в webkit. - person kingjeffrey; 18.07.2010
comment
+1, вы также можете определить, поддерживается ли loop, например. автор: typeof new Audio().loop == 'boolean'; - person Christian C. Salvadó; 18.07.2010
comment
@CMS Избегайте использования == и используйте ===, это лучший оператор для начинающих и лучше для производительности. - person Klaider; 26.02.2016
comment
Совместимо ли это с Firefox 80? - person Mostafiz Rahman; 15.07.2020

Самый простой способ:

bgSound = new Audio("sounds/background.mp3");
bgSound.loop = true;
bgSound.play();
person jai3232    schedule 29.03.2018

var audio = new Audio("http://rho.nu/pub/Game%20Of%20Thrones%20-%20Main%20Theme%20-%20Soundtrack.mp3");

audio.addEventListener('canplaythrough', function() {
    this.currentTime = this.duration - 10;
    this.loop = true;
    this.play();
});

Просто установите loop = true в прослушивателе событий canplaythrough.

http://jsbin.com/ciforiwano/1/edit?html,css,js,output

person JazzCat    schedule 29.04.2015

Попробуйте использовать jQuery для прослушивателя событий, тогда он будет работать в Firefox.

myAudio = new Audio('someSound.ogg');

$(myAudio).bind('ended', function()  {
    myAudio.currentTime = 0;
    myAudio.play();
});

myAudio.play();

Что-то такое.

person Matt    schedule 02.03.2012

Я сделал это так,

<audio controls="controls" loop="loop">
<source src="someSound.ogg" type="audio/ogg" />
</audio>

и это выглядит так

введите здесь описание изображения

person Tomarinator    schedule 11.06.2012

Это работает, и его намного проще переключать, чем описанные выше методы:

использовать встроенный: onended="if($(this).attr('data-loop')){ this.currentTime = 0; this.play(); }"

Включите зацикливание, нажав $(audio_element).attr('data-loop','1');. Выключите зацикливание, нажав $(audio_element).removeAttr('data-loop');.

person WebsterDevelopine    schedule 30.10.2013

Вы можете попробовать setInterval, если знаете точную длину звука. Вы можете заставить setInterval воспроизводить звук каждые x секунд. X будет длиной вашего звука.

person Zack    schedule 10.03.2015
comment
Это не дает ответа на вопрос. Чтобы подвергнуть критике или запросить разъяснения у автора, оставьте комментарий под его сообщением — вы всегда можете прокомментировать свои собственные сообщения, и как только у вас будет достаточно репутация, вы сможете комментировать любой пост. - person Alex Char; 11.03.2015
comment
@AlexChar Я не согласен. Это как минимум попытка ответить на вопрос. Было бы полезно немного расширить, чтобы показать, как именно может выглядеть код, и это, вероятно, не лучший способ решить проблему, но это не ответ. - person Anthony Grist; 11.03.2015
comment
Делая это так получить неприятности опыта. - person Klaider; 04.03.2016