Zapętlanie dźwięku HTML5

80

Ostatnio bawiłem się dźwiękiem HTML5 i chociaż mogę go zmusić do odtwarzania dźwięku, będzie on odtwarzany tylko raz. Bez względu na to, co próbuję (ustawianie właściwości, programów obsługi zdarzeń itp.) Nie wydaje się, żebym zapętlał to.

Oto podstawowy kod, którego używam:

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

Testuję na Chrome (6.0.466.0 dev) i Firefox (4 beta 1), z których oba wydają się być szczęśliwe, ignorując moje żądania zapętlenia. Jakieś pomysły?

UPDATE : Właściwość loop jest teraz obsługiwana we wszystkich głównych przeglądarkach.

Toji
źródło
1
Nie jestem pewien co do przeglądarki Chrome, ale Firefox nie obsługuje zapętlania.
luiscubal
1
Po prostu uruchom go po zakończeniu: myAudio.addEventListener ("zakończone", funkcja (e) {myAudio.play ();}, false);
mattbasta
@Brandon Zastanawiam się, dlaczego to nie działa? Jedyną różnicą między tym kodem a zaakceptowaną odpowiedzią jest to, że w zaakceptowanej odpowiedzi ustawia się currentTimena 0 przed wywołaniem play. Czy to konieczne?
mgiuca
2
@Brandon Tak, zobacz drugi komentarz królajeffreya dotyczący jego własnej odpowiedzi. Musisz ustawić currentTime.
mgiuca
To działa dobrze (przynajmniej dzisiaj)
dvlden

Odpowiedzi:

118

Chociaż loopjest określony, nie jest zaimplementowany w programiejakąkolwiek przeglądarkę, którą znam Firefox [dziękuje Anurag za wskazanie tego] . Oto alternatywny sposób zapętlania, który powinien działać w przeglądarkach obsługujących HTML5:

var myAudio = new Audio('someSound.ogg'); 
myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
}, false);
myAudio.play();
kingjeffrey
źródło
1
Hm ... ciekawe. Wcześniej nie miałem szczęścia z tą metodą, ale nie ustawiałem aktualnego czasu. Jednak gdy próbuję tego, otrzymuję: „Niezłapany błąd: INDEX_SIZE_ERR: DOM Wyjątek 1” w wierszu „this.currentTime = 0”
Toji,
1
@Toji Oto dokumentacja dotycząca błędu INDEX_SIZR_ERR . Oznacza to, że początek utworu znajduje się poza zakresem, którego może szukać przeglądarka. Zdarza się to czasami, gdy przeglądarka uważa, że ​​to media strumieniowe, lub jeśli serwer nie ma pewnych możliwości (od ręki zapominam, czym jest ta konkretna funkcja, ale spróbuję to wyśledzić). Możesz także użyć, this.startTimeaby powrócić do najwcześniejszego dostępnego czasu.
kingjeffrey
@Toji Powód .currentTimejest potrzebny, dotyczy tego, jak specyfikacja radzi sobie z końcem piosenki. Przeglądarki mają po prostu wstrzymać piosenkę. Tak więc ponowne rozpoczęcie odtwarzania robi to pod koniec utworu. Głowicę należy zresetować.
kingjeffrey
@Toji Oto kolejna myśl, jeśli nie możesz rozpocząć .currentTimepracy. Wewnątrz funkcji wywołania zwrotnego możesz po prostu ponownie zadeklarować myAudioten sam plik i odtworzyć go ponownie. Ponowne zadeklarowanie powinno również zresetować głowicę odtwarzania do początku utworu.
kingjeffrey
ustawienie tego na this.startTime daje mi ten sam błąd, chociaż teraz zaczynam się zastanawiać, czy jest to problem z serwerem. Obsługuję pliki statyczne z lokalnego serwera django (co nie jest najbardziej niezawodną funkcją django). Połącz to z faktem, że Anurag działa i myślę, że to prawdopodobnie tylko ja. Będę się tym trochę bardziej bawić i przedstawię wyniki.
Toji,
61

Aby dodać więcej porad łączących sugestie @kingjeffrey i @CMS: Możesz użyć looptam, gdzie jest dostępny, i wrócić do obsługi zdarzeń kingjeffrey, gdy nie jest. Jest dobry powód, dla którego chcesz używać loopi nie pisać własnego modułu obsługi zdarzeń: jak omówiono w raporcie o błędzie Mozilli , chociaż loopobecnie nie jest to płynna pętla (bez przerwy) w żadnej przeglądarce, którą znam, z pewnością jest to możliwe stać się standardem w przyszłości. Twój własny moduł obsługi zdarzeń nigdy nie będzie działał bezproblemowo w żadnej przeglądarce (ponieważ musi przepływać przez pętlę zdarzeń JavaScript). Dlatego najlepiej jest używać, loopjeśli to możliwe, zamiast pisać własne wydarzenie. Jak wskazał CMS w komentarzu do odpowiedzi Anurag,looploop zmienna - jeśli jest obsługiwana, będzie wartością logiczną (fałsz), w przeciwnym razie będzie niezdefiniowana, tak jak obecnie jest w Firefoksie.

Składając je razem:

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
źródło
Dzięki. to działało idealnie dla Opery, Firefoksa, Chrome ... więc jak możemy dodać więcej dźwięków (mp3) dla Safari ... ??? dodanie większej liczby zmiennych prawdopodobnie spowodowałoby duplikaty dla Chrome (który obsługuje ogg i mp3) ...
@pixelass Nie jestem do końca pewien, jak to zrobić w kodzie. W HTML zagnieździłbyś tagi <audio> wewnątrz siebie, a przeglądarka wybrałaby najbardziej zewnętrzny, który pasuje. Nie wiem, czy potrafisz to zagnieżdżać w programowym obiekcie Audio. Ale z pewnością możesz to zaprogramować samodzielnie: sprawdź metodę Audio.canPlayType.
mgiuca
znam metodę HTML. Mogę spróbować z metodą Audio.canPlayType. w tej chwili używam 2 zmiennych, więc w chrome 2 pliki są odtwarzane. to właściwie nie ma większego znaczenia, ponieważ zrobiłem tylko kilka pętli fal oceanicznych. ... ale po prostu dodanie 2 źródeł byłoby o wiele przyjemniejsze. pixelass.com, jeśli ci zależy.
19

Twój kod działa u mnie w Chrome (5.0.375) i Safari (5.0). Nie zapętla się w przeglądarce Firefox (3.6).

Zobacz przykład.

var song = new Audio("file");
song.loop = true;
document.body.appendChild(song);​
Anurag
źródło
+1 Bardzo fajnie. Nie wiedziałem, że loopzostał zaimplementowany w webkit.
kingjeffrey
10
+1, możesz również looptypeof new Audio().loop == 'boolean';
sprawdzić,
@CMS Unikaj używania ==i używania ===, jest to lepszy operator dla początkujących i lepszy pod względem wydajności.
Klaider
Czy jest to zgodne z przeglądarką Firefox 80?
Mostafiz Rahman
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();
});

Po prostu ustaw loop = true w programie canplaythrough eventlistener.

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

JazzCat
źródło
4

Najprostszy sposób to:

bgSound = new Audio("sounds/background.mp3");
bgSound.loop = true;
bgSound.play();
jai3232
źródło
2

Spróbuj użyć jQuery jako nasłuchiwania zdarzeń, będzie wtedy działać w przeglądarce Firefox.

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

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

myAudio.play();

Coś w tym stylu.

Matt
źródło
1

Zrobiłem to w ten sposób

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

i wygląda to tak

wprowadź opis obrazu tutaj

Tomarinator
źródło
0

To działa i znacznie łatwiej jest przełączać powyższe metody:

użyj w tekście: onended="if($(this).attr('data-loop')){ this.currentTime = 0; this.play(); }"

Włącz pętlę przez $(audio_element).attr('data-loop','1'); Wyłącz pętlę przez$(audio_element).removeAttr('data-loop');

WebsterDevelopine
źródło
0

Możesz spróbować setInterval, jeśli znasz dokładną długość dźwięku. Możesz ustawić setInterval na odtwarzanie dźwięku co x sekund. X byłby długością twojego dźwięku.

Zack
źródło
To nie daje odpowiedzi na pytanie. Aby skrytykować lub poprosić autora o wyjaśnienie, zostaw komentarz pod jego postem - zawsze możesz komentować własne posty, a gdy zdobędziesz wystarczającą reputację , będziesz mógł skomentować każdy post .
Alex Char
4
@AlexChar Nie zgadzam się. To przynajmniej próba odpowiedzi na pytanie. Przydałoby się pewne rozwinięcie, aby dokładnie pokazać, jak może wyglądać kod, i prawdopodobnie nie jest to najlepszy sposób rozwiązania problemu, ale nie jest to „nie odpowiedź”.
Anthony Grist
Robiąc to, miej problemy z doświadczeniem.
Klaider