Функция 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;

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

kr1
источник
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):>

MrHetii
источник
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>
Mikel
источник
Это работает в 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();
};
Zuks
источник
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. Так что, если у вас есть поведение, связанное с этим событием, вы можете оказаться в аудио цикле.

shamangeorge
источник
3

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

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

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

sound.currentTime = 0;
sound.pause();
gogog
источник
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
}
user3062615
источник
То же самое объясняет Заки в своем ответе выше, без использования 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();
NoviceLearner
источник
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;
Helzgate
источник
0

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

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

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

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

Джеймс Маркс
источник