Bucle de audio HTML5

80

He estado jugando con audio HTML5 recientemente, y aunque puedo hacer que reproduzca el sonido, solo se reproducirá una vez. No importa lo que intente (configurar las propiedades, los controladores de eventos, etc.), parece que no puedo hacer que se repita.

Aquí está el código básico que estoy usando:

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

Estoy probando con Chrome (6.0.466.0 dev) y Firefox (4 beta 1), los cuales parecen felices de ignorar mis solicitudes de bucle. ¿Algunas ideas?

ACTUALIZACIÓN : La propiedad de bucle ahora es compatible con todos los navegadores principales.

Toji
fuente
1
No estoy seguro de Chrome, pero Firefox no admite bucles.
luiscubal
1
Simplemente inícielo una vez que haya terminado: myAudio.addEventListener ("terminó", function (e) {myAudio.play ();}, false);
Mattbasta
@Brandon Me pregunto por qué esto no funciona. La única diferencia entre este código y la respuesta aceptada es que en la respuesta aceptada, se establece currentTimeen 0 antes de llamar play. ¿Es eso necesario?
mgiuca
2
@Brandon Sí, vea el segundo comentario de kingjeffrey sobre su propia respuesta. Necesitas configurar currentTime.
mgiuca
Esto funciona bien (al menos hoy)
dvlden

Respuestas:

118

Si bien loopse especifica, no se implementa encualquier navegador del que tenga conocimiento Firefox [agradece a Anurag por señalar esto] . Aquí hay una forma alternativa de bucle que debería funcionar en navegadores compatibles con HTML5:

var myAudio = new Audio('someSound.ogg'); 
myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
}, false);
myAudio.play();
Kingjeffrey
fuente
1
Hm ... interesante. No tuve mucha suerte con este método anteriormente, pero no estaba configurando la hora actual. Sin embargo, cuando intento esto, obtengo: "Error no detectado: INDEX_SIZE_ERR: DOM Exception 1" en la línea "this.currentTime = 0"
Toji
1
@Toji Aquí está la documentación para el error INDEX_SIZR_ERR . Significa que el comienzo de la canción está fuera del rango que el navegador puede buscar. Esto a veces ocurre si el navegador piensa que está transmitiendo contenido multimedia o si el servidor carece de ciertas capacidades (olvido de repente cuál es esta capacidad específica, pero intentaré rastrearla). También puede utilizar this.startTimepara volver a la primera hora disponible.
kingjeffrey
@Toji La razón por la que .currentTimese necesita tiene que ver con cómo la especificación maneja el final de una canción. Se supone que los navegadores solo deben pausar la canción. Entonces, reiniciar el juego lo hace al final de la canción. El cabezal de reproducción debe reiniciarse.
kingjeffrey
@Toji Aquí hay otro pensamiento si no puede .currentTimetrabajar. Dentro de la función de devolución de llamada, simplemente puede myAudiovolver a declarar con el mismo archivo y reproducirlo nuevamente. Redeclararlo también debería restablecer el cabezal de reproducción al comienzo de la canción.
kingjeffrey
establecerlo en this.startTime me da el mismo error, aunque ahora estoy empezando a preguntarme si es un problema del servidor. Estoy sirviendo archivos estáticos desde un servidor django local (que no es la característica más robusta de django). Combina eso con el hecho de que Anurag funciona y creo que probablemente sea solo yo. Jugaré un poco más y te haré saber los resultados.
Toji
61

Para agregar algunos consejos más que combinen las sugerencias de @kingjeffrey y @CMS: Puede usar loopdonde esté disponible y recurrir al controlador de eventos de kingjeffrey cuando no lo esté. Hay una buena razón por la que desea usar loopy no escribir su propio controlador de eventos: como se discutió en el informe de error de Mozilla , aunque loopactualmente no se repite sin problemas (sin un espacio) en cualquier navegador que conozca, ciertamente es posible y probable se convierta en estándar en el futuro. Su propio controlador de eventos nunca será perfecto en ningún navegador (ya que tiene que bombear a través del ciclo de eventos de JavaScript). Por lo tanto, es mejor usarlo loopsiempre que sea posible en lugar de escribir su propio evento. Como señaló CMS en un comentario sobre la respuesta de Anurag,looploop Variable: si es compatible, será un booleano (falso); de lo contrario, no estará definido, como lo está actualmente en Firefox.

Poniendo estos juntos:

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
fuente
Gracias. esto funcionó perfectamente para Opera, Firefox, Chrome ... entonces, ¿cómo podemos agregar más sonidos (mp3) para Safari .... ??? agregar más variables probablemente causaría duplicados para Chrome (que admite ogg y mp3) ...
@pixelass No estoy del todo seguro de cómo hacerlo en código. En HTML, anidaría las etiquetas <audio> una dentro de la otra, y el navegador elegiría la más externa que coincida. No sé si puede hacer ese anidamiento en el objeto de audio programático. Pero ciertamente puede programarlo usted mismo: consulte el método Audio.canPlayType.
mgiuca
Soy consciente del método html. Podría intentarlo con el método Audio.canPlayType. ahora mismo estoy usando 2 variables, por lo que en Chrome se reproducen 2 archivos. esto en realidad no importa demasiado ya que es solo un bucle de olas oceánicas que hice. ... pero simplemente agregar 2 fuentes sería mucho mejor. pixelass.com si te importa.
19

Tu código me funciona en Chrome (5.0.375) y Safari (5.0). No se repite en Firefox (3.6).

Ver ejemplo.

var song = new Audio("file");
song.loop = true;
document.body.appendChild(song);​
Anurag
fuente
+1 Muy guay. No sabía que loopse implementó en webkit.
kingjeffrey
10
+1, también puede detectar si loopes compatible, por ejemplo, por:typeof new Audio().loop == 'boolean';
Christian C. Salvadó
@CMS Evite el uso ==y el uso ===, es un mejor operador para los principiantes y mejor para el rendimiento.
Klaider
¿Es esto compatible con 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();
});

Simplemente establezca loop = true en canplaythrough eventlistener.

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

JazzCat
fuente
4

La forma más sencilla es:

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

Intente usar jQuery para el detector de eventos, luego funcionará en Firefox.

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

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

myAudio.play();

Algo como eso.

Mate
fuente
1

Lo hice de esta manera

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

y se ve así

ingrese la descripción de la imagen aquí

Tomarinator
fuente
0

Esto funciona y es mucho más fácil alternar que los métodos anteriores:

utilizar en línea: onended="if($(this).attr('data-loop')){ this.currentTime = 0; this.play(); }"

Encienda el bucle $(audio_element).attr('data-loop','1'); Apague el bucle$(audio_element).removeAttr('data-loop');

WebsterDevelopine
fuente
0

Puede probar con setInterval, si conoce la duración exacta del sonido. Puede hacer que setInterval reproduzca el sonido cada x segundos. X sería la duración de tu sonido.

Zack
fuente
Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación; siempre puede comentar sus propias publicaciones y, una vez que tenga suficiente reputación , podrá comentar cualquier publicación .
Alex Char
4
@AlexChar No estoy de acuerdo. Este es al menos un intento de responder a la pregunta. Podría beneficiarse de alguna expansión para mostrar exactamente cómo se vería el código, y probablemente no sea la mejor manera de resolver el problema, pero no "no es una respuesta".
Anthony Grist
Al hacerlo, experimenta problemas.
Klaider