Функція зупинки звуку HTML5


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. Звуковий елемент продовжує завантажувати аудіо, що не має відбуватися.
Пітер

3
У Chrome <audio>продовжується завантаження також з preloadпримусовим атрибутом noneта <source>src.
Піонерське небо

6
Це працює, дякую. Зі сторони, я хотів би знати, чому w3c вирішив не включати метод зупинки у специфікацію.
Reahreic

25

спочатку потрібно встановити ідентифікатор для вашого аудіоелемента

у вашому js:

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

var oldSrc = ply.src;// просто згадати старе джерело

ply.src = "";// щоб зупинити програвач, вам доведеться нічим не замінити джерело


4
Найкраще рішення для передачі аудіо
Hossein

1
добре .. що зробить ще один мережевий запит на вихідний аудіофайл
Арафат Аль Махмуд

Аудіо не відтворюватиметься до завантаження, і це спричинить небажану затримку відтворення звуку.
Абхі

Приємне рішення проблеми під час відтворення потоку, як Інтернет-радіо та Firefox, повторює останній шматок, коли пауза / відтворення вмикається. Дуже дякую.
namikiri

14

Ось мій спосіб робити stop () метод:

Десь у коді:

audioCh1: document.createElement("audio");

а потім у зупинці ():

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

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


10

У мене було таке ж питання. Зупинка повинна зупинити потік і перейти в режим живої трансляції, якщо це радіо. Усі рішення, які я бачив, мали недолік :

  • 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.prototype.stop = function() {
    this.pause();
    this.currentTime = 0;
};

Я маю це у файлі javascript, який я назвав "AudioPlus.js", який я включаю в свій html перед будь-яким сценарієм, який буде мати справу зі звуком.

Потім ви можете викликати функцію зупинки на аудіооб'єктах:

audio.stop();

НАСІЛЬНО ВИПУСК ХРОМУ З "Програмою":

Я не перевіряв це в усіх браузерах, але це проблема, яку я натрапив на 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

Взагалі я б не рекомендував розширювати подібні прототипи. Аудіо-важкий додаток може мати різні функції зупинки для різних випадків, і возитися з прототипами, ймовірно, призведе до помилок у довгостроковій імхо
milaron

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

Іноді це не працює в хромі,

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

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

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

2

shamangeorge написав:

встановивши currentTime вручну, можна запустити подію "canplaythrough" на аудіоелементі.

Це дійсно те, що відбудеться, і пауза також призведе до pauseподії, обидві вони роблять цю методику непридатною для використання як метод "стоп". Крім того, настройка , srcяк запропоновано саки зробить спробу гравця , щоб завантажити URL поточної сторінки в якості медіа - файлу (і потерпіти невдачу) , якщо autoplayвключена - установка srcна nullне допускається; це завжди буде розглядатися як URL-адреса. Окрім знищення об’єкта програвача, схоже, немає хорошого способу надання методу "стоп", тому я б запропонував просто скинути виділену кнопку зупинки та надати замість цього паузу та пропустити кнопки назад - кнопка зупинки насправді не додасть функціональності .


1

Цей підхід є "грубою силою", але він працює, якщо використовувати jQuery "дозволено". Оточіть <audio></audio>теги "програвача " ділом (тут з ідентифікатором "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>.
користувач3062615

#FlHolderздається, помилка друку#plHolder
Pioneer Skies

1
У відповідь на коментар @ alok-jain: Я думаю, що ця відповідь абсолютно відрізняється від такої @zaki. Тут ми рендерируем елемент у DOM, в іншій відповіді він просто "зачиняє" srcатрибут гравця.
Піонерське небо

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.