HTML5 Audio Looping

80

Недавно я играл со звуком 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), оба из которых, кажется, счастливы игнорировать мои запросы на зацикливание. Есть идеи?

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

Тодзи
источник
1
Не уверен насчет Chrome, но Firefox не поддерживает цикл.
luiscubal
1
Просто запустите его, как только он закончится: myAudio.addEventListener («завершено», function (e) {myAudio.play ();}, false);
mattbasta
@Brandon Интересно, почему это не работает? Единственная разница между этим кодом и принятым ответом заключается в том, что в принятом ответе currentTimeперед вызовом он устанавливается на 0 play. Это необходимо?
mgiuca
2
@Brandon Да, см. Второй комментарий Кингжеффри к его собственному ответу. Вам нужно установить currentTime.
mgiuca
Это действительно отлично работает (по крайней мере, сегодня)
dvlden 09

Ответы:

118

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

var myAudio = new Audio('someSound.ogg'); 
myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
}, false);
myAudio.play();
Kingjeffrey
источник
1
Хм ... интересно. Раньше мне не очень везло с этим методом, но я не устанавливал текущее время. Однако когда я пытаюсь это сделать, я получаю: «Неперехваченная ошибка: INDEX_SIZE_ERR: DOM Exception 1» в строке «this.currentTime = 0»
Тоджи
1
@Toji Вот документация по ошибке INDEX_SIZR_ERR . Это означает, что начало песни находится за пределами диапазона, который браузер может искать. Иногда это происходит, если браузер думает, что это потоковая передача мультимедиа, или если серверу не хватает определенных возможностей (я сразу забываю, что это за конкретная возможность, но я попытаюсь отследить ее). Вы также можете использовать this.startTimeдля возврата к самому раннему доступному времени.
kingjeffrey
@Toji Причина, по которой .currentTimeэто нужно, связана с тем, как спецификация обрабатывает конец песни. Браузеры должны просто приостанавливать воспроизведение песни. Таким образом, возобновление игры происходит в конце песни. Точка воспроизведения должна быть сброшена.
kingjeffrey
@Toji Вот еще одна мысль, если вы не можете приступить к .currentTimeработе. Внутри функции обратного вызова вы можете просто повторно объявить myAudioтот же файл и воспроизвести его снова. При повторном объявлении точка воспроизведения также должна быть сброшена на начало песни.
kingjeffrey
установка this.startTime дает мне ту же ошибку, хотя теперь я начинаю задаваться вопросом, не проблема ли это сервера. Я обслуживаю статические файлы с локального сервера django (что не является самой надежной функцией django). Соедините это с тем фактом, что Anurag's действительно работает, и я думаю, что это, вероятно, только я. Я поиграю с этим еще немного и дам вам знать результаты.
Toji
61

Чтобы добавить еще несколько советов, объединяющих предложения @kingjeffrey и @CMS: вы можете использовать loopтам, где он доступен, и вернуться к обработчику событий kingjeffrey, когда его нет. Есть веская причина, по которой вы хотите использовать loopсвой собственный обработчик событий, а не писать его: как обсуждалось в отчете об ошибке Mozilla , хотя в loopнастоящее время не происходит плавного цикла (без пробелов) в любом известном мне браузере, это, безусловно, возможно и, скорее всего, стать стандартом в будущем. Ваш собственный обработчик событий никогда не будет безупречным в любом браузере (поскольку он должен прокачивать цикл событий JavaScript). Поэтому лучше использовать loopтам, где это возможно, вместо написания собственного события. Как отметила CMS в комментарии к ответу Anurag,looploop переменная - если она поддерживается, это будет логическое значение (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();
mgiuca
источник
Спасибо. это отлично работало для Opera, Firefox, Chrome ... так как мы можем добавить больше звуков (mp3) для Safari .... ??? добавление дополнительных переменных, вероятно, приведет к дублированию Chrome (который поддерживает ogg и mp3) ...
@pixelass Я не совсем уверен, как это сделать в коде. В HTML вы должны вложить теги <audio> друг в друга, и браузер выберет самый внешний из подходящих. Я не знаю, можете ли вы сделать такое вложение в программный объект Audio. Но вы, конечно, можете запрограммировать его самостоятельно: посмотрите метод Audio.canPlayType.
mgiuca 02
я знаю о методе html. Я могу попробовать использовать метод Audio.canPlayType. прямо сейчас я использую 2 переменные, поэтому в chrome воспроизводятся 2 файла. на самом деле это не имеет особого значения, так как это всего лишь петля океанских волн, которую я сделал. ... но просто добавить 2 источника было бы намного лучше. pixelass.com, если вам не все равно.
19

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

См. Пример.

var song = new Audio("file");
song.loop = true;
document.body.appendChild(song);​
Анураг
источник
+1 Очень круто. Я не знал, что loopэто реализовано в webkit.
kingjeffrey
10
+1, вы также можете определить, loopподдерживается ли это, например:typeof new Audio().loop == 'boolean';
Кристиан С. Сальвадо,
@CMS Избегайте использования ==и использования ===, это лучший оператор для новичков и лучше для производительности.
Klaider
Совместимо ли это с Firefox 80?
Мостафиз Рахман
4
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

JazzCat
источник
4

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

bgSound = new Audio("sounds/background.mp3");
bgSound.loop = true;
bgSound.play();
jai3232
источник
2

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

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

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

myAudio.play();

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

Мэтт
источник
1

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

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

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

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

Томаринатор
источник
0

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

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

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

WebsterDevelopine
источник
0

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

Зак
источник
Это не дает ответа на вопрос. Чтобы критиковать или запрашивать разъяснения у автора, оставьте комментарий под его сообщением - вы всегда можете комментировать свои собственные сообщения, и когда у вас будет достаточная репутация, вы сможете комментировать любое сообщение .
Alex Char
4
@AlexChar Я не согласен. Это как минимум попытка ответить на вопрос. Было бы полезно немного расширить, чтобы точно показать, как может выглядеть код, и, вероятно, это не лучший способ решить проблему, но это не «не ответ».
Энтони Грист,
Делая это, вы получите неприятности.
Klaider