Funkcja zatrzymania dźwięku HTML5


147

Odtwarzam mały klip audio po kliknięciu każdego łącza w mojej nawigacji

Kod 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>

Kod JS:

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

Jak dotąd działa dobrze.

Problem polega na tym, że klip dźwiękowy jest już uruchomiony i klikam dowolny link, nic się nie dzieje.

Próbowałem zatrzymać już odtwarzany dźwięk po kliknięciu linku, ale nie ma bezpośredniego zdarzenia w interfejsie API audio HTML5

Próbowałem śledzić kod, ale nie działa

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

Jakieś sugestie?

Odpowiedzi:


350

Zamiast stop()ciebie możesz spróbować:

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

Powinno to przynieść pożądany efekt.


6
To nie działa w Chrome. Element audio ciągle ładuje dźwięk, co nie powinno się zdarzyć.
Pieter

3
W Chrome <audio>ładuje się również z preloadatrybutem wymuszonym nonei <source>usuniętym src.
Pioneer Skies

6
To działa, dzięki. Na marginesie chciałbym wiedzieć, dlaczego w3c zdecydował się nie uwzględniać metody stop w specyfikacji.
Reahreic

25

najpierw musisz ustawić identyfikator dla swojego elementu audio

w twoim js:

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

var oldSrc = ply.src;// tylko po to, by zapamiętać stare źródło

ply.src = "";// aby zatrzymać odtwarzacz, musisz zastąpić źródło niczym


4
Najlepsze rozwiązanie do strumieniowego przesyłania dźwięku
Hossein

1
no cóż ... to spowoduje kolejne żądanie sieciowe dla pliku źródłowego
Md. Arafat Al Mahmud

Dźwięk nie będzie odtwarzany, dopóki nie zostanie załadowany, co spowoduje niepożądane opóźnienie w odtwarzaniu dźwięku.
Abhi

Ładne rozwiązanie problemu podczas odtwarzania strumienia, takiego jak radio internetowe, a Firefox powtarza ostatni fragment po przełączeniu pauza / odtwarzanie. Dziękuję bardzo.
namikiri

14

Oto mój sposób na zrobienie metody stop ():

Gdzieś w kodzie:

audioCh1: document.createElement("audio");

a następnie w stop ():

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

W ten sposób nie generujemy dodatkowego żądania, stary jest anulowany, a nasz element audio jest w stanie czystym (testowane w Chrome i FF):>


10

Miałem ten sam problem. Zatrzymanie powinno zatrzymać transmisję i włączyć odtwarzanie, jeśli jest to radio. Wszystkie rozwiązania, które widziałem, miały jedną wadę :

  • player.currentTime = 0 ciągle pobiera strumień.
  • player.src = ''podnieść errorwydarzenie

Moje rozwiązanie:

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

I HTML

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

Działa to w Chrome i Firefox. Jednak w Firefoksie powoduje to następujący błąd (w konsoli) [ Security Error: Content at https://localhost/url.html may not load data from blob:https://localhost/cac32534-78b0-4a62-8355-cc8f1e708d64.] Wydaje się, że nie ma to żadnego negatywnego wpływu, ponieważ kod nadal jest wykonywany po tym (w przeciwieństwie do nieprzechwyconego wyjątku).
BReddy

6

Ta metoda działa:

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

Ale jeśli nie chcesz pisać tych dwóch wierszy kodu za każdym razem, gdy zatrzymujesz dźwięk, możesz zrobić jedną z dwóch rzeczy. Myślę, że drugi jest bardziej odpowiedni i nie jestem pewien, dlaczego „bogowie standardów javascript” nie stworzyli tego standardu.

Pierwsza metoda: utwórz funkcję i przekaż dźwięk

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

//then using it:
stopAudio(audio);

Druga metoda (preferowana): rozszerz klasę Audio:

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

Mam to w pliku javascript, który nazwałem „AudioPlus.js”, który umieszczam w moim html przed każdym skryptem, który będzie zajmował się dźwiękiem.

Następnie możesz wywołać funkcję stop na obiektach audio:

audio.stop();

WRESZCIE PROBLEM Z CHROMEM Z „Canplaythrough”:

Nie testowałem tego we wszystkich przeglądarkach, ale jest to problem, na który natknąłem się w Chrome. Jeśli spróbujesz ustawić currentTime dla dźwięku, do którego jest dołączony detektor zdarzenia „canplaythrough”, ponownie uruchomisz to zdarzenie, co może prowadzić do niepożądanych rezultatów.

Tak więc rozwiązaniem, podobnym do wszystkich przypadków, w których dołączyłeś detektor zdarzeń, który naprawdę chcesz mieć pewność, że nie zostanie ponownie uruchomiony, jest usunięcie nasłuchiwania zdarzeń po pierwszym wywołaniu. Coś takiego:

//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 ...
});

PREMIA:

Zauważ, że możesz dodać jeszcze więcej niestandardowych metod do klasy Audio (lub dowolnej natywnej klasy javascript).

Na przykład, jeśli potrzebujesz metody „restartu”, która ponownie uruchamia dźwięk, może to wyglądać mniej więcej tak:

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

function stopAudio(audio) { audio.pause(); this.audioStream.src = ""; } W końcu zadziałało to dla mnie i usunęło ikonę głośnika w przeglądarce Chrome, która pojawia się podczas odtwarzania dźwięku na stronie. testowano na Chrome w wersji 59.0.3071.109
lasec0203

Generalnie nie polecałbym rozszerzania takich prototypów. Aplikacja z dużą
ilością

5

Z mojej własnej funkcji javascript do przełączania odtwarzania / wstrzymywania - ponieważ obsługuję strumień radiowy, chciałem, aby wyczyścił bufor, aby słuchacz nie stracił synchronizacji ze stacją radiową.

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;
        }
}

Okazuje się, że samo wyczyszczenie currentTime nie powoduje przerwania go w Chrome, konieczne jest również wyczyszczenie źródła i ponowne załadowanie. Mam nadzieję, że to pomoże.


4

Na marginesie i ponieważ ostatnio korzystałem z metody stop podanej w zaakceptowanej odpowiedzi, zgodnie z tym linkiem:

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

ustawiając ręcznie currentTime można uruchomić zdarzenie „canplaythrough” na elemencie audio. W linku wspomina o Firefoksie, ale napotkałem to zdarzenie uruchamiające się po ręcznym ustawieniu currentTime w Chrome. Więc jeśli masz jakieś zachowanie związane z tym wydarzeniem, możesz skończyć w pętli audio.


3

Czasami nie działa w chrome,

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

po prostu zmień się w ten sposób,

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

2

shamangeorge napisał:

ustawiając ręcznie currentTime można uruchomić zdarzenie „canplaythrough” na elemencie audio.

Tak właśnie się stanie, a wstrzymanie również wyzwoli pausezdarzenie, co sprawia, że ​​ta technika nie nadaje się do stosowania jako metoda „stop”. Co więcej, ustawienie srczgodnie z sugestią zaki spowoduje, że odtwarzacz spróbuje załadować adres URL bieżącej strony jako plik multimedialny (i zakończy się niepowodzeniem), jeśli autoplayjest włączony - ustawienie srcnanull nie jest dozwolone; zawsze będzie traktowany jako adres URL. Oprócz zniszczenia obiektu gracza, wydaje się, że nie ma dobrego sposobu na zapewnienie metody „stop”, więc sugerowałbym po prostu upuszczenie dedykowanego przycisku zatrzymania i zamiast tego zapewnienie przycisków pauzy i przeskoku - przycisk zatrzymania nie dodawałby żadnej funkcjonalności .


1

To podejście jest „brutalną siłą”, ale działa przy założeniu, że używanie jQuery jest „dozwolone”. Otocz <audio></audio>znaczniki „player” znacznikiem div (tutaj z identyfikatorem „plHolder”).

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

Wtedy ten javascript powinien działać:

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

To samo wyjaśnia zaki w swojej odpowiedzi powyżej, bez użycia jquery.
Alok Jain

Nie eksperymentowałem z tym, ale nie byłem pewien, czy jego metoda zadziała, jeśli będzie wiele tagów <source>.
user3062615

#FlHolderwydaje się być literówką#plHolder
Pioneer Skies

1
W odpowiedzi na komentarz @ alok-jain: Myślę, że ta odpowiedź jest zupełnie inna niż odpowiedź @zaki. Tutaj ponownie renderujemy element w DOM, w drugiej odpowiedzi po prostu „wygasza” srcatrybut gracza.
Pioneer Skies

0

Uważam, że dobrze byłoby sprawdzić, czy dźwięk jest odtwarzany i zresetować właściwość currentTime.

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

0

dla mnie ten kod działa dobrze. (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">...

Mam nadzieję, że to pomoże.


0

Lubię całkowicie usuwać kontrolkę za pomocą Angular2, a następnie ładować ją ponownie, gdy następny utwór ma ścieżkę audio:

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

Następnie, gdy chcę wyładować go w kodzie, robię to:

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

Po przypisaniu następnego utworu formant zostanie całkowicie odtworzony od zera:

this.song = this.songOnDeck;

0

Prostym sposobem obejścia tego błędu jest wychwycenie błędu.

audioElement.play () zwraca obietnicę, więc poniższy kod z .catch () powinien wystarczyć do rozwiązania tego problemu:

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

Uwaga: możesz chcieć zastąpić funkcję strzałkową funkcją anonimową w celu zapewnienia zgodności z poprzednimi wersjami.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.