HTML5 Audio Looping

80

Ich habe in letzter Zeit mit HTML5-Audio gespielt, und obwohl ich es dazu bringen kann, den Sound abzuspielen, wird es immer nur einmal abgespielt. Egal was ich versuche (Festlegen der Eigenschaften, Ereignishandler usw.), ich kann es scheinbar nicht in eine Schleife bringen.

Hier ist der grundlegende Code, den ich verwende:

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

Ich teste mit Chrome (6.0.466.0 dev) und Firefox (4 Beta 1), die beide meine Anfragen nach Schleifen gerne ignorieren. Irgendwelche Ideen?

UPDATE : Die Schleife Eigenschaft wird jetzt unterstützt in allen gängigen Browsern.

Toji
quelle
1
Ich bin mir bei Chrome nicht sicher, aber Firefox unterstützt keine Schleifen.
luiscubal
1
Starten Sie es einfach, sobald es beendet ist: myAudio.addEventListener ("beendet", Funktion (e) {myAudio.play ();}, false);
Mattbasta
@Brandon Ich frage mich, warum das nicht funktioniert? Der einzige Unterschied zwischen diesem Code und der akzeptierten Antwort besteht darin, dass in der akzeptierten Antwort currentTimevor dem Anruf 0 gesetzt wird play. Ist das notwendig
mgiuca
2
@Brandon Ja, siehe Kingjeffreys zweiten Kommentar zu seiner eigenen Antwort. Sie müssen einstellen currentTime.
mgiuca
Dies funktioniert gut (zumindest heute)
dvlden

Antworten:

118

Während loopangegeben, ist es nicht implementiert inJeder Browser, den ich kenne Firefox [danke Anurag für den Hinweis] . Hier ist eine alternative Art der Schleife, die in HTML5-fähigen Browsern funktionieren sollte:

var myAudio = new Audio('someSound.ogg'); 
myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
}, false);
myAudio.play();
Kingjeffrey
quelle
1
Hm ... interessant. Ich hatte vorher nicht viel Glück mit dieser Methode, aber ich habe die aktuelle Zeit nicht eingestellt. Wenn ich dies versuche, erhalte ich jedoch: "Nicht erfasster Fehler: INDEX_SIZE_ERR: DOM-Ausnahme 1" in der Zeile "this.currentTime = 0"
Toji
1
@Toji Hier ist die Dokumentation für den INDEX_SIZR_ERR-Fehler . Dies bedeutet, dass der Anfang des Songs außerhalb des Bereichs liegt, den der Browser suchen kann. Dies tritt manchmal auf, wenn der Browser denkt, dass es sich um Streaming-Medien handelt oder wenn dem Server bestimmte Funktionen fehlen (ich vergesse sofort, was diese spezielle Funktion ist, aber ich werde versuchen, sie aufzuspüren). Sie können auch verwenden this.startTime, um zur frühesten verfügbaren Zeit zurückzukehren.
Kingjeffrey
@Toji Der Grund, der .currentTimebenötigt wird, hängt damit zusammen, wie die Spezifikation das Ende eines Songs behandelt. Browser sollen das Lied einfach anhalten. Die Wiederaufnahme des Spiels geschieht also am Ende des Songs. Der Abspielkopf muss zurückgesetzt werden.
Kingjeffrey
@Toji Hier ist ein weiterer Gedanke, wenn Sie nicht in der Lage sind, zu .currentTimearbeiten. Innerhalb der Rückruffunktion können Sie einfach myAudiodieselbe Datei neu deklarieren und erneut abspielen. Durch erneutes Deklarieren sollte auch der Abspielkopf auf den Anfang des Songs zurückgesetzt werden.
Kingjeffrey
Wenn ich es auf this.startTime setze, erhalte ich den gleichen Fehler, obwohl ich mich jetzt frage, ob es sich um ein Serverproblem handelt. Ich stelle statische Dateien von einem lokalen Django-Server bereit (was nicht die robusteste Funktion von Django ist). Kombiniere das mit der Tatsache, dass Anurag funktioniert und ich denke, dass es wahrscheinlich nur ich bin. Ich werde ein bisschen mehr damit spielen und Sie über die Ergebnisse informieren.
Toji
61

Um weitere Ratschläge hinzuzufügen, die die Vorschläge von @kingjeffrey und @CMS kombinieren: Sie können verwenden, loopwo es verfügbar ist, und auf den Ereignishandler von kingjeffrey zurückgreifen, wenn dies nicht der Fall ist. Es gibt einen guten Grund, warum Sie loopIhren eigenen Ereignishandler verwenden und nicht schreiben möchten : Wie im Mozilla-Fehlerbericht erläutert , ist dies loopderzeit möglich und wahrscheinlich , obwohl er in keinem mir bekannten Browser nahtlos (ohne Lücke) wiederholt wird in Zukunft zum Standard werden. Ihr eigener Ereignishandler wird in keinem Browser nahtlos sein (da er durch die JavaScript-Ereignisschleife pumpen muss). Daher ist es am besten, loopwenn möglich zu verwenden , anstatt eine eigene Veranstaltung zu schreiben. Wie CMS in einem Kommentar zu Anurags Antwort betonte,looploop Variable - Wenn es unterstützt wird, ist es ein Boolescher Wert (false), andernfalls ist es undefiniert, wie es derzeit in Firefox ist.

Zusammenfügen:

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
quelle
Danke. Dies funktionierte perfekt für Opera, Firefox, Chrome ... also wie können wir mehr Sounds (MP3) für Safari hinzufügen ... ??? Das Hinzufügen weiterer Variablen würde wahrscheinlich zu Duplikaten für Chrome führen (das ogg und mp3 unterstützt) ...
@pixelass Ich bin mir nicht ganz sicher, wie ich es im Code machen soll. In HTML würden Sie die <audio> -Tags ineinander verschachteln und der Browser würde das äußerste auswählen, das übereinstimmt. Ich weiß nicht, ob Sie diese Verschachtelung im programmatischen Audioobjekt durchführen können. Aber Sie können es auf jeden Fall selbst programmieren: Schauen Sie sich die Audio.canPlayType-Methode an.
mgiuca
Ich bin mir der HTML-Methode bewusst. Ich könnte es mit der Audio.canPlayType-Methode versuchen. Im Moment verwende ich 2 Variablen, also werden in Chrome 2 Dateien abgespielt. Das ist eigentlich nicht so wichtig, da es nur eine Ozeanwellenschleife ist, die ich gemacht habe. ... aber einfach 2 Quellen hinzuzufügen wäre viel schöner. pixelass.com wenn es dich interessiert.
19

Ihr Code funktioniert für mich unter Chrome (5.0.375) und Safari (5.0). Schleift nicht in Firefox (3.6).

Siehe Beispiel.

var song = new Audio("file");
song.loop = true;
document.body.appendChild(song);​
Anurag
quelle
+1 Sehr cool. Ich loopwusste nicht , dass im Webkit implementiert wurde.
Kingjeffrey
10
+1 können Sie auch erkennen, ob loopunterstützt wird, z. B.:typeof new Audio().loop == 'boolean';
Christian C. Salvadó
@CMS Vermeiden Sie die Verwendung ==und Verwendung ===, es ist ein besserer Bediener für Anfänger und eine bessere Leistung.
Hydroper
Ist das mit Firefox 80 kompatibel?
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();
});

Setzen Sie einfach loop = true im canplaythrough eventlistener.

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

JazzCat
quelle
4

Der einfachste Weg ist:

bgSound = new Audio("sounds/background.mp3");
bgSound.loop = true;
bgSound.play();
jai3232
quelle
2

Versuchen Sie, jQuery für den Ereignis-Listener zu verwenden. Dies funktioniert dann in Firefox.

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

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

myAudio.play();

So ähnlich.

Matt
quelle
1

Ich habe es so gemacht,

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

und es sieht so aus

Geben Sie hier die Bildbeschreibung ein

Tomarinator
quelle
0

Dies funktioniert und es ist viel einfacher, die oben genannten Methoden umzuschalten:

Inline verwenden: onended="if($(this).attr('data-loop')){ this.currentTime = 0; this.play(); }"

Schalten Sie die Schleife ein durch $(audio_element).attr('data-loop','1'); Schalten Sie die Schleife aus aus$(audio_element).removeAttr('data-loop');

WebsterDevelopine
quelle
0

Sie können ein setInterval ausprobieren, wenn Sie die genaue Länge des Sounds kennen. Sie können das SetInterval den Sound alle x Sekunden abspielen lassen. X wäre die Länge Ihres Sounds.

Zack
quelle
Dies gibt keine Antwort auf die Frage. Um einen Autor zu kritisieren oder um Klarstellung zu bitten, hinterlassen Sie einen Kommentar unter seinem Beitrag. Sie können jederzeit Ihre eigenen Beiträge kommentieren. Sobald Sie einen ausreichenden Ruf haben, können Sie jeden Beitrag kommentieren .
Alex Char
4
@ AlexChar Ich bin anderer Meinung. Dies ist zumindest ein Versuch, die Frage zu beantworten. Es könnte von einer Erweiterung profitieren, um genau zu zeigen, wie der Code aussehen könnte, und es ist wahrscheinlich nicht der beste Weg, um das Problem zu lösen, aber es ist keine "keine Antwort".
Anthony Grist
Wenn Sie dies tun, erhalten Sie Probleme mit der Erfahrung.
Hydroper