HTML5 Audio tag в Safari имеет задержку

Я пытаюсь выполнить простое поведение, похожее на каракули, когда звук mp3 / ogg звучит при щелчке, используя тег html. Предполагается, что он будет работать под Firefox, Safari и Safari. IPad очень желателен.

Я пробовал много подходов и пришел к следующему:

HTML

    <span id="play-blue-note" class="play blue" ></span>
    <span id="play-green-note" class="play green" ></span>


    <audio id="blue-note" style="display:none" controls preload="auto" autobuffer> 
        <source src="blue.mp3" />
        <source src="blue.ogg" />
        <!-- now include flash fall back -->
    </audio>

    <audio id="green-note" style="display:none" controls preload="auto" autobuffer> 
        <source src="green.mp3" />
        <source src="green.ogg" />
    </audio>

JS

function addSource(elem, path) {
    $('<source>').attr('src', path).appendTo(elem);
}

$(document).ready(function() {


    $('body').delegate('.play', 'click touchstart', function() {
        var clicked = $(this).attr('id').split('-')[1];

        $('#' + clicked + '-note').get(0).play();



    });

});  

Кажется, это отлично работает в Firefox, но Safari, похоже, имеет задержку каждый раз, когда вы нажимаете, даже если вы нажимаете несколько раз и аудиофайл загружается. В Safari на iPad ведет себя почти непредсказуемо.

Кроме того, при локальном тестировании производительность Safari, кажется, улучшается. Я предполагаю, что Safari загружает файл каждый раз. Это возможно? Как мне этого избежать? Спасибо!


person Nacho    schedule 21.03.2012    source источник
comment
Эй, есть какие-нибудь комментарии по проблеме Safari? : S   -  person Nacho    schedule 22.03.2012
comment
Текущие ответы верны и, в зависимости от их расположения, полностью соответствуют предыдущему ответу в аналогичной теме. Самый эффективный обходной путь, как цитируется автором и в этом ответе в этой ветке, - это действительно разрушить все ваше поведение в один файл и вызывать его в разных кадрах. Это большая дополнительная работа, но именно это происходит, когда Apple принимает дизайнерское решение, которому все остальные вынуждены подчиняться. (Дайте мне знать, если вы предпочитаете это в качестве ответа.)   -  person MrGomez    schedule 03.04.2012
comment
@ign вам удалось воспроизвести несколько аудио одновременно на настольном Safari? К сожалению, у меня возникают задержки с настольным Safari. FF и Chrome работают нормально.   -  person trainoasis    schedule 07.05.2014


Ответы (10)


Я только что ответил на другой вопрос по iOS / <audio> несколько минут назад. Кажется, применимо и здесь:

Предварительная загрузка <audio> и <video> на устройствах iOS отключена для экономии трафика.

В Safari на iOS (для всех устройств, включая iPad), где пользователь может быть в сотовой сети и платить за единицу данных, предварительная загрузка и автовоспроизведение отключены. Никакие данные не загружаются, пока пользователь не инициирует их.

Источник: Библиотека разработчика Safari

person j08691    schedule 21.03.2012
comment
Спасибо. Итак, я полагаю, что на iPad практически невозможно получить обратную связь в реальном времени, верно? Есть какие-нибудь сведения о Safari? - person Nacho; 21.03.2012

В настольном Safari добавление AudioContext устраняет проблему:

const AudioContext = window.AudioContext || window.webkitAudioContext;
const audioCtx = new AudioContext();

Я узнал об этом случайно, поэтому понятия не имею, почему это работает, но это устранило задержку в моем приложении.

person Jaakko Karhu    schedule 09.01.2019
comment
Я могу поручиться, что простое добавление этих двух строк кода улучшило качество звука. - person Brian Risk; 09.01.2020
comment
Не могли бы вы подробнее рассказать об этом? Как связать audioCtx с реальным аудиообъектом? Я предполагаю, что простого добавления этих строк кода без дополнительного кода, который подключается к фактическому аудио, недостаточно. - person 9gt53wS; 10.04.2020
comment
Я потратил некоторое время, пытаясь найти решение для этого, и это сработало! Для тех, кто пытается заставить это работать в TypeScript, я нашел этот обходной путь полезный. - person Jerad Rose; 06.06.2020
comment
Что имеется в виду в этом ответе? Чтобы правильно использовать fetch + AudioContext вместо обычного Audio или просто добавить эти две строки как фокус? В любом случае они будут стерты как мертвый код при связывании. - person Alexander Zinchuk; 18.06.2020
comment
@AlexanderZinchuk Да, это волшебный трюк. Я больше не помню подробностей, но на момент написания это помогло мне решить проблему. - person Jaakko Karhu; 06.07.2020
comment
Вау, это действительно устранило задержку на настольном Safari. Не знаю, как это работает. - person Zack Lee; 19.04.2021

Проблема с Safari в том, что он каждый раз запрашивает воспроизводимый аудиофайл. Вы можете попробовать создать манифест кеша HTML5. К сожалению, по моему опыту, вы можете добавлять в кеш только один аудиофайл за раз. Обходной путь может заключаться в том, чтобы последовательно объединить все ваши аудиофайлы в один аудиофайл и начать воспроизведение с определенной позиции в зависимости от необходимого звука. Вы можете создать интервал для отслеживания текущей позиции воспроизведения и приостановить его по достижении определенной отметки времени.

Подробнее о создании манифеста кеша HTML5 здесь:

http://www.html5rocks.com/en/tutorials/appcache/beginner/

http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html

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

person Reinaldo    schedule 31.03.2012
comment
Спасибо за понимание. Однако это звучит слишком сложно для простой задачи, которую я пытаюсь реализовать. - person Nacho; 02.04.2012
comment
Я не думаю, что вы правы насчет запроса каждый раз, но я думаю, что вы могли бы сделать хорошее замечание, поместив все звуковые эффекты в один файл и воспроизведя со смещениями в разных контекстах, как описано в разделе «Определение диапазона воспроизведения» по адресу developer.mozilla.org/en-US/docs/Web/Guide / HTML /. Интересно, насколько хорошо это будет работать с несколькими элементами ‹audio›, имеющими один и тот же источник, и будет ли это работать вообще. У меня аналогичная проблема с игрой, которую я разрабатываю: Chrome безупречно воспроизводит звук, но Firefox и Safari заметно отстают. - person Bart Read; 22.08.2015
comment
Это означает, что с быстро повторяющимися звуками, такими как стрельба игрока, удары пуль и т. Д., Повторы часто не воспроизводятся. Другой потенциальный обходной путь может заключаться в том, чтобы несколько элементов ‹audio› были прикреплены к одному и тому же источнику и воспроизводить их каждый по очереди по круговой схеме. Опять же, я не знаю, сработает ли это, но я планирую попробовать это позже. И, кстати, я наблюдаю эти проблемы в настольных версиях браузеров, не говоря уже о мобильных. - person Bart Read; 22.08.2015

Apple решила (чтобы сэкономить на мобильных устройствах) не загружать предварительно <audio> и <video> HTML-элементы.

От Библиотека разработчика Safari:

В Safari на iOS (для всех устройств, включая iPad), где пользователь может быть в сотовой сети и платить за единицу данных, предварительная загрузка и автовоспроизведение отключены. Никакие данные не загружаются, пока пользователь не инициирует их. Это означает, что методы JavaScript play() и load() также неактивны, пока пользователь не инициирует воспроизведение, если только метод play() или load() не запускается действием пользователя. Другими словами, инициированная пользователем кнопка воспроизведения работает, а событие onLoad = "play ()" - нет.

Воспроизводится фильм: <input type="button" value="Play" onClick="document.myMovie.play()">

На iOS ничего не происходит: <body onLoad="document.myMovie.play()">


Я не думаю, что вы можете обойти это ограничение, но, возможно, сможете.

Помните: Google - ваш лучший друг.


Обновление. Поэкспериментировав, я нашел способ поиграть в <audio> с помощью JavaScript:

var vid = document.createElement("iframe");
vid.setAttribute('src', "http://yoursite.com/yourvideooraudio.mp4"); // replace with actual source
vid.setAttribute('width', '1px');
vid.setAttribute('height', '1px');
vid.setAttribute('scrolling', 'no');
vid.style.border = "0px";
document.body.appendChild(vid);

Примечание. Я пробовал только с <audio>.


Обновление 2: jsFiddle здесь. Кажется, работает.

person Anish Gupta    schedule 02.04.2012
comment
Вопрос не в том, как воспроизводить звук, а в том, почему есть задержка. - person j08691; 03.04.2012
comment
Ваш ответ - это просто отрыгивание того, что я уже опубликовал, и фрагмент того, как воспроизводить аудиофайл. Я упускаю что-то новое или необычное, что вы предлагаете, что действительно отвечает на вопрос? - person j08691; 03.04.2012
comment
@ j08691 я помню статью о сафари, каждый раз загружающей файл, и о том, как указать сафари кэшировать его. Решением был метатег, но я не помню сайт и очистил историю :( извините - person Anish Gupta; 03.04.2012
comment
Ой, извините, я честно не читал ваш ответ, я не хотел копировать - person Anish Gupta; 03.04.2012

Задержка звука HTML5 в Safari iOS (<audio> Element vs AudioContext)

Да, в Safari iOS есть задержка звука при использовании встроенного элемента <audio> ... однако это можно преодолеть с помощью AudioContext.

Мой фрагмент кода основан на том, что я узнал из https://lowlag.alienbill.com/

Пожалуйста, проверьте функциональность на своем собственном устройстве iOS (я тестировал в iOS 12) https://fiddle.jshell.net/eLya8fxb/51/show/

Фрагмент из JS Fiddle https://jsfiddle.net/eLya8fxb/51/

// Requires jQuery 

// Adding:
// Strip down lowLag.js so it only supports audioContext (So no IE11 support (only Edge))
// Add "loop" monkey patch needed for looping audio (my primary usage)
// Add single audio channel - to avoid overlapping audio playback

// Original source: https://lowlag.alienbill.com/lowLag.js

if (!window.console) console = {
  log: function() {}
};

var lowLag = new function() {
  this.someVariable = undefined;
  this.showNeedInit = function() {
    lowLag.msg("lowLag: you must call lowLag.init() first!");
  }
  this.load = this.showNeedInit;
  this.play = this.showNeedInit;
  this.pause = this.showNeedInit;
  this.stop = this.showNeedInit;
  this.switch = this.showNeedInit;
  this.change = this.showNeedInit;
  
  this.audioContext = undefined;
  this.audioContextPendingRequest = {};
  this.audioBuffers = {};
  this.audioBufferSources = {};
  this.currentTag = undefined;
  this.currentPlayingTag = undefined;

  this.init = function() {
    this.msg("init audioContext");
    this.load = this.loadSoundAudioContext;
    this.play = this.playSoundAudioContext;
    this.pause = this.pauseSoundAudioContext;
    this.stop = this.stopSoundAudioContext;
    this.switch = this.switchSoundAudioContext;
    this.change = this.changeSoundAudioContext;

    if (!this.audioContext) {
      this.audioContext = new(window.AudioContext || window.webkitAudioContext)();
    }
  }

  //we'll use the tag they hand us, or else the url as the tag if it's a single tag,
  //or the first url 
  this.getTagFromURL = function(url, tag) {
    if (tag != undefined) return tag;
    return lowLag.getSingleURL(url);
  }
  this.getSingleURL = function(urls) {
    if (typeof(urls) == "string") return urls;
    return urls[0];
  }
  //coerce to be an array
  this.getURLArray = function(urls) {
    if (typeof(urls) == "string") return [urls];
    return urls;
  }

  this.loadSoundAudioContext = function(urls, tag) {
    var url = lowLag.getSingleURL(urls);
    tag = lowLag.getTagFromURL(urls, tag);
    lowLag.msg('webkit/chrome audio loading ' + url + ' as tag ' + tag);
    var request = new XMLHttpRequest();
    request.open('GET', url, true);
    request.responseType = 'arraybuffer';

    // Decode asynchronously
    request.onload = function() {
      // if you want "successLoadAudioFile" to only be called one time, you could try just using Promises (the newer return value for decodeAudioData)
      // Ref: https://developer.mozilla.org/en-US/docs/Web/API/BaseAudioContext/decodeAudioData

      //Older callback syntax:
      //baseAudioContext.decodeAudioData(ArrayBuffer, successCallback, errorCallback);
      //Newer promise-based syntax:
      //Promise<decodedData> baseAudioContext.decodeAudioData(ArrayBuffer);


      // ... however you might want to use a pollfil for browsers that support Promises, but does not yet support decodeAudioData returning a Promise.
      // Ref: https://github.com/mohayonao/promise-decode-audio-data
      // Ref: https://caniuse.com/#search=Promise

      // var retVal = lowLag.audioContext.decodeAudioData(request.response);

      // Note: "successLoadAudioFile" is called twice. Once for legacy syntax (success callback), and once for newer syntax (Promise)
      var retVal = lowLag.audioContext.decodeAudioData(request.response, successLoadAudioFile, errorLoadAudioFile);
      //Newer versions of audioContext return a promise, which could throw a DOMException
      if (retVal && typeof retVal.then == 'function') {
        retVal.then(successLoadAudioFile).catch(function(e) {
          errorLoadAudioFile(e);
          urls.shift(); //remove the first url from the array
          if (urls.length > 0) {
            lowLag.loadSoundAudioContext(urls, tag); //try the next url
          }
        });
      }
    };

    request.send();

    function successLoadAudioFile(buffer) {
      lowLag.audioBuffers[tag] = buffer;
      if (lowLag.audioContextPendingRequest[tag]) { //a request might have come in, try playing it now
        lowLag.playSoundAudioContext(tag);
      }
    }

    function errorLoadAudioFile(e) {
      lowLag.msg("Error loading webkit/chrome audio: " + e);
    }
  }

  this.playSoundAudioContext = function(tag) {
    var context = lowLag.audioContext;

    // if some audio is currently active and hasn't been switched, or you are explicitly asking to play audio that is already active... then see if it needs to be unpaused
    // ... if you've switch audio, or are explicitly asking to play new audio (that is not the currently active audio) then skip trying to unpause the audio
    if ((lowLag.currentPlayingTag && lowLag.currentTag && lowLag.currentPlayingTag === lowLag.currentTag) || (tag && lowLag.currentPlayingTag && lowLag.currentPlayingTag === tag)) {
      // find currently paused audio (suspended) and unpause it (resume)
      if (context !== undefined) {
        // ref: https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/suspend
        if (context.state === 'suspended') {
          context.resume().then(function() {
            lowLag.msg("playSoundAudioContext resume " + lowLag.currentPlayingTag);
            return;
          }).catch(function(e) {
            lowLag.msg("playSoundAudioContext resume error for " + lowLag.currentPlayingTag + ". Error: " + e);
          });
          return;
        }
      }
    }
    
    if (tag === undefined) {
      tag = lowLag.currentTag;
    }

    if (lowLag.currentPlayingTag && lowLag.currentPlayingTag === tag) {
      // ignore request to play same sound a second time - it's already playing
      lowLag.msg("playSoundAudioContext already playing " + tag);
      return;
    } else {
      lowLag.msg("playSoundAudioContext " + tag);
    }

    var buffer = lowLag.audioBuffers[tag];
    if (buffer === undefined) { //possibly not loaded; put in a request to play onload
      lowLag.audioContextPendingRequest[tag] = true;
      lowLag.msg("playSoundAudioContext pending request " + tag);
      return;
    }

    // need to create a new AudioBufferSourceNode every time... 
    // you can't call start() on an AudioBufferSourceNode more than once. They're one-time-use only.
    var source;
    source = context.createBufferSource(); // creates a sound source
    source.buffer = buffer; // tell the source which sound to play
    source.connect(context.destination); // connect the source to the context's destination (the speakers)
    source.loop = true;
    lowLag.audioBufferSources[tag] = source;

    // find current playing audio and stop it
    var sourceOld = lowLag.currentPlayingTag ? lowLag.audioBufferSources[lowLag.currentPlayingTag] : undefined;
    if (sourceOld !== undefined) {
      if (typeof(sourceOld.noteOff) == "function") {
        sourceOld.noteOff(0);
      } else {
        sourceOld.stop();
      }
      lowLag.msg("playSoundAudioContext stopped " + lowLag.currentPlayingTag);
      lowLag.audioBufferSources[lowLag.currentPlayingTag] = undefined;
      lowLag.currentPlayingTag = undefined;
    }

    // play the new source audio
    if (typeof(source.noteOn) == "function") {
      source.noteOn(0);
    } else {
      source.start();
    }
    lowLag.currentTag = tag;
    lowLag.currentPlayingTag = tag;
    
    if (context.state === 'running') {
      lowLag.msg("playSoundAudioContext started " + tag);
    } else if (context.state === 'suspended') {
      /// if the audio context is in a suspended state then unpause (resume)
      context.resume().then(function() {
        lowLag.msg("playSoundAudioContext started and then resumed " + tag);
      }).catch(function(e) {
        lowLag.msg("playSoundAudioContext started and then had a resuming error for " + tag + ". Error: " + e);
      });
    } else if (context.state === 'closed') {
      // ignore request to pause sound - it's already closed
      lowLag.msg("playSoundAudioContext failed to start, context closed for " + tag);
    } else {
      lowLag.msg("playSoundAudioContext unknown AudioContext.state for " + tag + ". State: " + context.state);
    }
  }

  this.pauseSoundAudioContext = function() {
    // not passing in a "tag" parameter because we are playing all audio in one channel
    var tag = lowLag.currentPlayingTag;
    var context = lowLag.audioContext;

    if (tag === undefined) {
      // ignore request to pause sound as nothing is currently playing
      lowLag.msg("pauseSoundAudioContext nothing to pause");
      return;
    }

    // find currently playing (running) audio and pause it (suspend)
    if (context !== undefined) {
      // ref: https://developer.mozilla.org/en-US/docs/Web/API/AudioContext/suspend
      if (context.state === 'running') {
      	lowLag.msg("pauseSoundAudioContext " + tag);
        context.suspend().then(function() {
          lowLag.msg("pauseSoundAudioContext suspended " + tag);
        }).catch(function(e) {
          lowLag.msg("pauseSoundAudioContext suspend error for " + tag + ". Error: " + e);
        });
      } else if (context.state === 'suspended') {
        // ignore request to pause sound - it's already suspended
        lowLag.msg("pauseSoundAudioContext already suspended " + tag);
      } else if (context.state === 'closed') {
        // ignore request to pause sound - it's already closed
        lowLag.msg("pauseSoundAudioContext already closed " + tag);
      } else {
        lowLag.msg("pauseSoundAudioContext unknown AudioContext.state for " + tag + ". State: " + context.state);
      }
    }
  }

  this.stopSoundAudioContext = function() {
    // not passing in a "tag" parameter because we are playing all audio in one channel
    var tag = lowLag.currentPlayingTag;

    if (tag === undefined) {
      // ignore request to stop sound as nothing is currently playing
      lowLag.msg("stopSoundAudioContext nothing to stop");
      return;
    } else {
      lowLag.msg("stopSoundAudioContext " + tag);
    }

    // find current playing audio and stop it
    var source = lowLag.audioBufferSources[tag];
    if (source !== undefined) {
      if (typeof(source.noteOff) == "function") {
        source.noteOff(0);
      } else {
        source.stop();
      }
      lowLag.msg("stopSoundAudioContext stopped " + tag);
      lowLag.audioBufferSources[tag] = undefined;
      lowLag.currentPlayingTag = undefined;
    }
  }

  this.switchSoundAudioContext = function(autoplay) {
    lowLag.msg("switchSoundAudioContext " + (autoplay ? 'and autoplay' : 'and do not autoplay'));

    if (lowLag.currentTag && lowLag.currentTag == 'audio1') {
      lowLag.currentTag = 'audio2';
    } else {
      lowLag.currentTag = 'audio1';
    }

    if (autoplay) {
      lowLag.playSoundAudioContext();
    }
  }

  this.changeSoundAudioContext = function(tag, autoplay) {
    lowLag.msg("changeSoundAudioContext to tag " + tag + " " + (autoplay ? 'and autoplay' : 'and do not autoplay'));

		if(tag === undefined) {
    	lowLag.msg("changeSoundAudioContext tag is undefined");
    	return;
    }
    
    lowLag.currentTag = tag;

    if (autoplay) {
      lowLag.playSoundAudioContext();
    }
  }

  this.msg = function(m) {
    m = "-- lowLag " + m;
    console.log(m);
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script>
  // AudioContext
  $(document).ready(function() {
    lowLag.init();
    lowLag.load(['https://coubsecure-s.akamaihd.net/get/b86/p/coub/simple/cw_looped_audio/f0dab49f867/083bf409a75db824122cf/med_1550250381_med.mp3'], 'audio1');
    lowLag.load(['https://coubsecure-s.akamaihd.net/get/b173/p/coub/simple/cw_looped_audio/0d5adfff2ee/80432a356484068bb0e15/med_1550254045_med.mp3'], 'audio2');
    // starts with audio1
    lowLag.changeSoundAudioContext('audio1', false);
  });

  // ----------------

  // Audio Element
  $(document).ready(function() {
    var $audioElement = $('#audioElement');
    var audioEl = $audioElement[0];
    var audioSources = {
      "audio1": "https://coubsecure-s.akamaihd.net/get/b86/p/coub/simple/cw_looped_audio/f0dab49f867/083bf409a75db824122cf/med_1550250381_med.mp3",
      "audio2": "https://coubsecure-s.akamaihd.net/get/b173/p/coub/simple/cw_looped_audio/0d5adfff2ee/80432a356484068bb0e15/med_1550254045_med.mp3"
    };
    playAudioElement = function() {
      audioEl.play();
    }
    pauseAudioElement = function() {
      audioEl.pause();
    }
    stopAudioElement = function() {
      audioEl.pause();
      audioEl.currentTime = 0;
    }
    switchAudioElement = function(autoplay) {
      var source = $audioElement.attr('data-source');

      if (source && source == 'audio1') {
        $audioElement.attr('src', audioSources.audio2);
        $audioElement.attr('data-source', 'audio2');
      } else {
        $audioElement.attr('src', audioSources.audio1);
        $audioElement.attr('data-source', 'audio1');
      }

      if (autoplay) {
        audioEl.play();
      }
    }
    changeAudioElement = function(tag, autoplay) {
      var source = $audioElement.attr('data-source');
      
      if(tag === undefined || audioSources[tag] === undefined) {
      	return;
      }

      $audioElement.attr('src', audioSources[tag]);
      $audioElement.attr('data-source', tag);

      if (autoplay) {
        audioEl.play();
      }
    }
    changeAudioElement('audio1', false); // starts with audio1
  });

</script>

<h1>
  AudioContext (<a href="https://developer.mozilla.org/en-US/docs/Web/API/AudioContext" target="blank">api</a>)
</h1>
<button onClick="lowLag.play();">Play</button>
<button onClick="lowLag.pause();">Pause</button>
<button onClick="lowLag.stop();">Stop</button>
<button onClick="lowLag.switch(true);">Swtich</button>
<button onClick="lowLag.change('audio1', true);">Play 1</button>
<button onClick="lowLag.change('audio2', true);">Play 2</button>

<hr>

<h1>
  Audio Element (<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio" target="blank">api</a>)
</h1>
<audio id="audioElement" controls loop preload="auto" src="">
</audio>
<br>
<button onClick="playAudioElement();">Play</button>
<button onClick="pauseAudioElement();">Pause</button>
<button onClick="stopAudioElement();">Stop</button>
<button onClick="switchAudioElement(true);">Switch</button>
<button onClick="changeAudioElement('audio1', true);">Play 1</button>
<button onClick="changeAudioElement('audio2', true);">Play 2</button>

введите здесь описание изображения  введите описание изображения здесь  введите описание изображения здесь  введите описание изображения здесь   введите здесь описание изображения  введите описание изображения здесь введите описание изображения здесь

person Chris Jacob    schedule 17.06.2019

ваши аудиофайлы загружаются один раз, а затем кешируются ... повторное воспроизведение звуков даже после обновления страницы не вызывало дальнейших HTTP-запросов в Safari ..

я только что взглянул на один из ваших звуков в аудиоредакторе - в начале файла была небольшая тишина .. это проявится как задержка ..

подходит ли вам Web Audio API?

person Lloyd    schedule 02.04.2012
comment
Спасибо, хотя я не думаю, что задержка вызвана тишиной в файле. Я проверю API веб-аудио. - person Nacho; 03.04.2012

У меня такая же проблема. Странно то, что я предварительно загружаю файл. Но с WiFi играет нормально, а вот на данных телефона перед запуском большая задержка. Я думал, что это как-то связано со скоростью загрузки, но я не начинаю воспроизводить свою сцену, пока не будут загружены все изображения и аудиофайл. Любые предложения были бы замечательными. (Я знаю, что это не ответ, но я подумал, что это лучше, чем делать дублированный пост).

person Doug Wolfgram    schedule 04.11.2013

К сожалению, единственный способ заставить его работать должным образом в Safari - это использовать WebAudio API или сторонние библиотеки, чтобы справиться с этим. Проверьте исходный код здесь (он не минифицирован)
https://drums-set-js.herokuapp.com/index.html
https://drums-set-js.herokuapp.com/app.js

person Donskikh Andrei    schedule 12.11.2019

Та же проблема. Пробовал предзагрузить разными способами. Наконец, я обернул логику анимации в обратный вызов "воспроизведения". Таким образом, эта логика должна работать только в том случае, если файл загружен и началось воспроизведение, но в результате я вижу, что логика анимации уже запущена, а звук воспроизводится с задержкой примерно в 2 секунды. Это тормозит мой разум, как у него может быть задержка, если звук уже вызвал обратный вызов "воспроизведение"? введите здесь описание изображения

Аудио контекст решил мою проблему. Самый простой пример, который я нашел здесь, https://developer.mozilla.org/en-US/docs/Web/API/Body/arrayBuffer getData - подготовка аудиофайла; тогда вы можете играть с source.start(0);

Эта ссылка пропустила, как получить audioCtx, вы можете скопировать его здесь let audioCtx = new (window.AudioContext || window.webkitAudioContext)();

person vpankov    schedule 08.06.2020
comment
Можете ли вы опубликовать это как вопрос со ссылкой на родительский вопрос, а также с упоминанием всех используемых вами версий? - person Sree.Bh; 08.06.2020

Я бы просто создал <audio autoplay /> элемент dom при нажатии, это работает во всех основных браузерах - нет необходимости обрабатывать события и запускать воспроизведение вручную

если вы хотите отреагировать на изменение статуса звука вручную - я бы посоветовал прослушивать событие play вместо loadeddata - это поведение более согласовано в разных браузерах

person godblessstrawberry    schedule 31.05.2021