Функция HTML5 Audio Stop


147

Я проигрываю небольшой аудиоклип по нажатию каждой ссылки в моей навигации.

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>

JS код:

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

Пока все отлично работает.

Проблема в том, что аудиоклип уже запущен, и я нажимаю на любую ссылку, ничего не происходит.

Я пытался остановить уже воспроизводимый звук при нажатии на ссылку, но прямого события для этого в Audio API HTML5 нет.

Я попробовал следующий код, но он не работает

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

Любые предложения, пожалуйста?

Ответы:


350

Вместо этого stop()вы можете попробовать:

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

Это должно иметь желаемый эффект.


6
Это не работает в Chrome. Элемент audio продолжает загружать звук, чего не должно быть.
Питер

3
В Chrome <audio>загрузка продолжается также с preloadпринудительным атрибутом noneи <source>s src удален.
Pioneer Skies

6
Это работает, спасибо. Кстати, я хотел бы знать, почему w3c решил не включать в спецификацию метод stop.
Реахрейк

25

Сначала вы должны установить идентификатор для вашего аудио элемента

в вашем JS:

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

var oldSrc = ply.src;// просто чтобы запомнить старый источник

ply.src = "";// чтобы остановить плеер, вы должны заменить источник ничем


4
Лучшее решение для потоковой передачи аудио
Хоссейн

1
хорошо ... это сделает еще один сетевой запрос для файла источника звука
Md. Арафат Аль Махмуд

Звук не будет воспроизводиться до загрузки, и это приведет к нежелательной задержке воспроизведения звука.
Абхи

Хорошее решение проблемы при воспроизведении потока, такого как интернет-радио, и Firefox повторяет последний фрагмент, когда переключается пауза / воспроизведение. Большое тебе спасибо.
Намикири

14

Вот мой способ сделать метод stop ():

Где-то в коде:

audioCh1: document.createElement("audio");

а затем в stop ():

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

Таким образом, мы не производим дополнительный запрос, старый отменяется, а наш аудиоэлемент находится в чистом состоянии (проверено в Chrome и FF):>


10

У меня была такая же проблема. Остановка должна остановить поток и onplay идти в прямой эфир , если это радио. Все решения, которые я видел, имели недостаток :

  • player.currentTime = 0 продолжает скачивать стрим.
  • player.src = ''поднять errorсобытие

Мое решение:

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

И HTML

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

Это работает в Chrome и Firefox. Однако в Firefox это приводит к следующей ошибке (в консоли) [ Security Error: Content at https://localhost/url.html may not load data from blob:https://localhost/cac32534-78b0-4a62-8355-cc8f1e708d64.] Похоже, что она не оказывает отрицательного влияния, поскольку код продолжает выполняться после этого (в отличие от неперехваченного исключения).
BReddy

6

Этот метод работает:

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

Но если вы не хотите писать эти две строки кода каждый раз, когда останавливаете звук, вы можете сделать одну из двух вещей. Второе, я думаю, является более подходящим, и я не уверен, почему «боги стандартов javascript» не сделали этот стандарт.

Первый способ: создать функцию и передать аудио

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

//then using it:
stopAudio(audio);

Второй метод (предпочтительный): расширить класс Audio:

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

У меня есть это в файле JavaScript, который я назвал «AudioPlus.js», который я включаю в свой HTML-код перед любым сценарием, который будет иметь дело с аудио.

Затем вы можете вызвать функцию остановки на аудиообъектах:

audio.stop();

ЗАКЛЮЧИТЕЛЬНО ВЫПУСК ХРОМА С «canplaythrough»:

Я не проверял это во всех браузерах, но это проблема, с которой я столкнулся в Chrome. Если вы попытаетесь установить currentTime для аудио, к которому подключен прослушиватель событий canplaythrough, то вы снова вызовете это событие, что может привести к нежелательным результатам.

Таким образом, решение, аналогичное всем случаям, когда вы подключили прослушиватель событий, который вы действительно хотите удостовериться, что он больше не запускается, состоит в том, чтобы удалить прослушиватель событий после первого вызова. Что-то вроде этого:

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

БОНУС:

Обратите внимание, что вы можете добавить еще больше пользовательских методов в класс Audio (или любой собственный класс javascript в этом отношении).

Например, если вам нужен метод «рестарт», который перезапускает аудио, он может выглядеть примерно так:

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

function stopAudio(audio) { audio.pause(); this.audioStream.src = ""; } Это помогло мне убрать значок динамика в браузере Chrome, который появляется, когда на странице воспроизводится звук. протестировано на Chrome версии 59.0.3071.109
lasec0203

В общем, я бы не рекомендовал расширять прототипы подобным образом. Аудио-тяжелое приложение может иметь разные функции останова для разных случаев, и беспорядок с прототипами может привести к ошибкам в долгосрочной перспективе imho
milesaron

5

От моей собственной функции javascript до переключения Play / Pause - поскольку я обрабатываю радиопоток, я хотел, чтобы он очистил буфер, чтобы слушатель не заканчивал синхронизацию с радиостанцией.

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

Оказывается, просто очистка currentTime не обрезает его в Chrome, необходимо также очистить исходный код и загрузить его обратно. Надеюсь, это поможет.


4

В качестве примечания и потому, что я недавно использовал метод остановки, указанный в принятом ответе, по этой ссылке:

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

установив currentTime вручную, можно запустить событие canplaythrough для аудиоэлемента. В ссылке упоминается Firefox, но я столкнулся с этим событием после того, как вручную установил currentTime в Chrome. Так что, если у вас есть поведение, связанное с этим событием, вы можете оказаться в аудио цикле.


3

Иногда это не работает в Chrome,

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

просто так изменить,

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

2

Shamangeorge писал (а):

установив currentTime вручную, можно запустить событие canplaythrough для аудиоэлемента.

Это действительно то, что произойдет, и пауза также вызовет pauseсобытие, оба из которых делают эту технику непригодной для использования в качестве метода «остановки». Более того, установка параметра, srcпредложенного zaki, заставит проигрыватель попытаться загрузить URL-адрес текущей страницы как файл мультимедиа (и потерпеть неудачу), если autoplayон включен - установка srcна nullнедопустима; он всегда будет рассматриваться как URL. Если не считать уничтожения объекта проигрывателя, кажется, нет хорошего способа обеспечить метод «стоп», поэтому я бы предложил просто отпустить выделенную кнопку «стоп» и вместо этого предоставить кнопки «пауза» и «назад» - кнопка «стоп» на самом деле не добавит никакой функциональности. ,


1

Этот подход "грубая сила", но он работает, предполагая, что использование jQuery "разрешено". Окружите свои <audio></audio>теги "player" div (здесь с идентификатором "plHolder").

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

Тогда этот JavaScript должен работать:

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

То же самое объясняет Заки в своем ответе выше, без использования jquery.
Alok Jain

Я не экспериментировал с этим, но я не был уверен, что его метод сработает, если будет несколько тегов <source>.
user3062615

#FlHolderкажется опечаткой для#plHolder
Pioneer Skies

1
В ответ на комментарий @ alok-jain: я думаю, что этот ответ полностью отличается от ответа @zaki. Здесь мы повторно визуализируем элемент в DOM, в другом ответе он просто «закрывает» srcатрибут игрока.
Pioneer Skies

0

Я считаю, что было бы хорошо проверить, воспроизводится ли звук, и сбросить свойство currentTime.

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

0

для меня этот код работает нормально. (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">...

Надеюсь, это поможет.


0

Что мне нравится делать, так это полностью удалять элемент управления с помощью Angular2, затем он перезагружается, когда следующая песня имеет звуковой путь:

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

Затем, когда я хочу выгрузить его в коде, я делаю это:

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

Когда назначается следующая песня, элемент управления полностью воссоздается с нуля:

this.song = this.songOnDeck;

0

Самый простой способ обойти эту ошибку - поймать ее.

audioElement.play () возвращает обещание, поэтому для решения этой проблемы должно быть достаточно следующего кода с .catch ():

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

Примечание: вы можете заменить функцию стрелки на анонимную функцию для обратной совместимости.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.