Função de parada de áudio HTML5


147

Estou reproduzindo um pequeno clipe de áudio no clique de cada link na minha navegação

Código HTML:

<audio tabindex="0" id="beep-one" controls preload="auto" >
    <source src="audio/Output 1-2.mp3">
    <source src="audio/Output 1-2.ogg">
</audio>

Código JS:

$('#links a').click(function(e) {
    e.preventDefault();
    var beepOne = $("#beep-one")[0];
    beepOne.play();
});

Está funcionando bem até agora.

Problema é quando um clipe de som já está em execução e eu clico em qualquer link que nada acontece.

Tentei parar o som que já estava sendo reproduzido ao clicar no link, mas não há nenhum evento direto na API de áudio do HTML5

Eu tentei seguir o código, mas não está funcionando

$.each($('audio'), function () {
    $(this).stop();
});

Alguma sugestão, por favor?

Respostas:


350

Em vez de stop()você poderia tentar com:

sound.pause();
sound.currentTime = 0;

Isso deve ter o efeito desejado.


6
Isso não está funcionando no Chrome. O elemento de áudio continua carregando o áudio, o que não é o que deveria acontecer.
27516 Pieter (

3
No Chrome, o <audio>carregamento continua também com o preloadatributo forçado a nonee o <source>src do sif.
Pioneer Skies

6
Isso funciona, obrigado. Em uma nota lateral, eu adoraria saber por que o w3c decidiu não incluir um método de parada nas especificações.
Reahreic

25

primeiro você precisa definir um ID para o seu elemento de áudio

em seus js:

var ply = document.getElementById('player');

var oldSrc = ply.src;// apenas para lembrar a fonte antiga

ply.src = "";// para parar o player, você precisa substituir a fonte por nada


4
Melhor solução para streaming de áudio
Hossein

1
well..that vai fazer outra solicitação de rede para o arquivo fonte de áudio
. Md Arafat Al Mahmud

O áudio não será reproduzido até ser carregado e isso causará atraso indesejado na reprodução do áudio.
Abhi

Uma boa solução para o problema ao reproduzir um fluxo como o rádio da Internet e o Firefox repete a última parte quando a pausa / reprodução é alternada. Muito obrigado
namikiri

14

Aqui está a minha maneira de fazer o método stop ():

Em algum lugar no código:

audioCh1: document.createElement("audio");

e depois em stop ():

this.audioCh1.pause()
this.audioCh1.src = 'data:audio/wav;base64,UklGRiQAAABXQVZFZm10IBAAAAABAAEAVFYAAFRWAAABAAgAZGF0YQAAAAA=';

Dessa forma, não produzimos pedidos adicionais, o antigo é cancelado e nosso elemento de áudio está em estado limpo (testado no Chrome e FF):>


9

Eu estava tendo o mesmo problema. A parada deve parar o fluxo e onplay ir ao vivo se ele é um rádio. Todas as soluções que vi tinham uma desvantagem :

  • player.currentTime = 0 continua baixando o fluxo.
  • player.src = ''aumentar errorevento

Minha solução:

var player = document.getElementById('radio');
player.pause();
player.src = player.src;

E o HTML

<audio src="http://radio-stream" id="radio" class="hidden" preload="none"></audio>

Isso funciona no Chrome e Firefox. No entanto, no Firefox, resulta no seguinte erro (no console) [ Security Error: Content at https://localhost/url.html may not load data from blob:https://localhost/cac32534-78b0-4a62-8355-cc8f1e708d64.] Parece não ter efeito negativo, pois o código continua a ser executado depois disso (diferente de uma exceção não detectada).
BReddy 12/07

6

Este método funciona:

audio.pause();
audio.currentTime = 0;

Mas se você não quiser escrever essas duas linhas de código toda vez que parar um áudio, poderá fazer uma de duas coisas. O segundo, eu acho que é o mais apropriado, e não sei por que os "deuses dos padrões javascript" não fizeram esse padrão.

Primeiro método: crie uma função e passe o áudio

function stopAudio(audio) {
    audio.pause();
    audio.currentTime = 0;
}

//then using it:
stopAudio(audio);

Segundo método (preferido): estenda a classe Audio:

Audio.prototype.stop = function() {
    this.pause();
    this.currentTime = 0;
};

Eu tenho isso em um arquivo javascript chamado "AudioPlus.js", que incluo no meu html antes de qualquer script que lide com áudio.

Em seguida, você pode chamar a função de parada em objetos de áudio:

audio.stop();

QUESTÃO FINAL DO CHROME COM "canplaythrough":

Não testei isso em todos os navegadores, mas esse é um problema que encontrei no Chrome. Se você tentar definir currentTime em um áudio que tenha um ouvinte de evento "canplaythrough" conectado a ele, você acionará esse evento novamente, o que pode levar a resultados indesejáveis.

Portanto, a solução, semelhante a todos os casos em que você anexou um ouvinte de evento que realmente deseja garantir que ele não seja acionado novamente, é remover o ouvinte de evento após a primeira chamada. Algo assim:

//note using jquery to attach the event. You can use plain javascript as well of course.
$(audio).on("canplaythrough", function() {
    $(this).off("canplaythrough");

    // rest of the code ...
});

BÔNUS:

Observe que você pode adicionar ainda mais métodos personalizados à classe Audio (ou qualquer classe javascript nativa).

Por exemplo, se você quiser um método "restart" que reinicie o áudio, ele pode ser algo como:

Audio.prototype.restart= function() {
    this.pause();
    this.currentTime = 0;
    this.play();
};

function stopAudio(audio) { audio.pause(); this.audioStream.src = ""; } Fazer isso acabou funcionando para mim e removeu o ícone do alto-falante no navegador Chrome que aparece quando o áudio está sendo reproduzido na página. testado no Chrome Versão 59.0.3071.109
lasec0203 26/06

Em geral, eu não recomendaria a extensão de protótipos como este. Um aplicativo com alto
consumo de

5

Da minha própria função javascript para alternar entre Reproduzir / Pausar - já que estou lidando com um fluxo de rádio, queria que ele limpe o buffer para que o ouvinte não acabe sincronizado com a estação de rádio.

function playStream() {

        var player = document.getElementById('player');

        (player.paused == true) ? toggle(0) : toggle(1);

}

function toggle(state) {

        var player = document.getElementById('player');
        var link = document.getElementById('radio-link');
        var src = "http://192.81.248.91:8159/;";

        switch(state) {
                case 0:
                        player.src = src;
                        player.load();
                        player.play();
                        link.innerHTML = 'Pause';
                        player_state = 1;
                        break;
                case 1:
                        player.pause();
                        player.currentTime = 0;
                        player.src = '';
                        link.innerHTML = 'Play';
                        player_state = 0;
                        break;
        }
}

Acontece que apenas limpar o currentTime não o reduz no Chrome, necessário também para limpar a fonte e carregá-la novamente. Espero que isso ajude.


4

Como uma observação lateral e porque recentemente usei o método de parada fornecido na resposta aceita, de acordo com este link:

https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Media_events

Ao definir currentTime manualmente, é possível disparar o evento 'canplaythrough' no elemento de áudio. No link, ele menciona o Firefox, mas eu encontrei esse evento disparando depois de definir o currentTime manualmente no Chrome. Portanto, se você tiver um comportamento associado a esse evento, poderá terminar em um loop de áudio.


3

Às vezes não funciona no chrome,

sound.pause();
sound.currentTime = 0;

apenas mude assim,

sound.currentTime = 0;
sound.pause();

2

shamangeorge escreveu:

Ao definir currentTime manualmente, é possível disparar o evento 'canplaythrough' no elemento de áudio.

É isso mesmo que acontecerá, e a pausa também acionará o pauseevento, os quais tornam essa técnica inadequada para uso como um método de "parada". Além disso, definir o srcsugerido por zaki fará com que o player tente carregar o URL da página atual como um arquivo de mídia (e falhe) se autoplayestiver ativado - definir srccomo nullnão é permitido; sempre será tratado como um URL. Antes de destruir o objeto player, parece não haver uma boa maneira de fornecer um método de "parada", então eu sugiro apenas soltar o botão de parada dedicado e fornecer os botões de pausa e pular para trás - um botão de parada não adicionaria nenhuma funcionalidade .


1

Essa abordagem é "força bruta", mas funciona assumindo que o uso do jQuery é "permitido". <audio></audio>Coloque as tags "player" com uma div (aqui com o ID "plHolder").

<div id="plHolder">
     <audio controls id="player">
     ...
     </audio>
<div>

Então este javascript deve funcionar:

function stopAudio() {
    var savePlayer = $('#plHolder').html(); // Save player code
    $('#player').remove(); // Remove player from DOM
    $('#FlHolder').html(savePlayer); // Restore it
}

A mesma coisa é explicada por zaki em sua resposta acima, sem o uso de jquery.
Alok Jain

Não experimentei, mas não tinha certeza de que o método dele funcionaria se houvesse várias tags <source>.
user3062615

#FlHolderparece um erro de digitação para#plHolder
Pioneer Skies

1
Em resposta ao comentário @ alok-jain: Eu acho que essa resposta é completamente diferente da resposta do @zaki. Aqui estamos re-renderizando um elemento no DOM, na outra resposta ele está apenas "apagando" o srcatributo do jogador.
Pioneer Skies

0

Acredito que seria bom verificar se o áudio está sendo reproduzido e redefinir a propriedade currentTime.

if (sound.currentTime !== 0 && (sound.currentTime > 0 && sound.currentTime < sound.duration) {
    sound.currentTime = 0;
}
sound.play();

0

para mim esse código funcionando bem. (IE10 +)

var Wmp = document.getElementById("MediaPlayer");                
    Wmp.controls.stop();

<object classid="clsid:6BF52A52-394A-11D3-B153-00C04F79FAA6"
    standby="Loading áudio..." style="width: 100%; height: 170px" id="MediaPlayer">...

Espero que esta ajuda.


0

O que eu gosto de fazer é remover completamente o controle usando o Angular2 e depois recarregá-lo quando a próxima música tiver um caminho de áudio:

<audio id="audioplayer" *ngIf="song?.audio_path">

Então, quando eu quero descarregá-lo no código, faço o seguinte:

this.song = Object.assign({},this.song,{audio_path: null});

Quando a próxima música é atribuída, o controle é completamente recriado do zero:

this.song = this.songOnDeck;

0

A maneira mais simples de contornar esse erro é pegá-lo.

audioElement.play () retorna uma promessa, portanto, o seguinte código com um .catch () deve ser suficiente para gerenciar esse problema:

function playSound(sound) {
  sfx.pause();
  sfx.currentTime = 0;
  sfx.src = sound;
  sfx.play().catch(e => e);
}

Nota: convém substituir a função de seta por uma função anônima para compatibilidade com versões anteriores.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.