Аудиообъект HTML5 не воспроизводится на iPad (при вызове из setTimeout)

У меня есть страница со скрытым<audio> Объект, который запускается и останавливается с помощью пользовательской кнопки с помощью JavaScript. (Причина в том, что я хочу настроить кнопку, а рисование аудиоплеера, похоже, в любом случае снижает производительность рендеринга на iPad). Упрощенный пример (в coffeescript):

// Works fine on all browsers

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play          // Bind button's click event with jQuery

_play: (e) =>
  @_audio[0].play()                    // Call play() on audio element

Звук воспроизводится нормально при запуске из функции, связанной сclick событие, но я на самом деле хочу завершить анимацию до воспроизведения файла, поэтому я поставил.play() внутриsetTimeout, Однако я просто не могу заставить это работать:

// Will not play on iPad

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play          // Bind button's click event with jQuery

_play: (e) =>
  setTimeout (=>                       // Declare a 300ms timeout
    @_audio[0].play()                  // Call play() on audio element
  ), 300

Я проверил это@_audio (this._audio) находится в области применения и что егоplay() метод существует. Почему это не работает на iPad?

Edit: Как оказалось, приведенный выше упрощенный тест на самом делеdoes Работа. Смотрите @ apsillers & apos; ответ ниже и мои комментарии к нему.

 Dan Halliday11 июн. 2012 г., 18:12
Также я положилtry/catch вокруг метода воспроизведения, и, похоже, не выдается никакой ошибки.
 mplungjan11 июн. 2012 г., 18:14
Вы пробовали @_button [0] .click () или trigger ()?
 Dan Halliday11 июн. 2012 г., 18:09
Просто чтобы добавить, я проверил это на симулятореand настоящий iPad.
 fcalderan11 июн. 2012 г., 18:12
Я полагаю, что вы не можете воспроизводить видео / аудио на iPad / iPhone без явного действия пользователя ... для использования полосы пропускания

Ответы на вопрос(3)

Решение Вопроса

Руководство по iOS для Apple:

...the JavaScript play() and load() methods are also inactive until the user initiates playback, unless the play() or load() method is triggered by user action. In other words, a user-initiated Play button works, but an onLoad="play()" event does not.

Похоже, что вашsetTimeout() обратный вызов не квалифицируется как действие, инициированное пользователем, несмотря на то, чтоsetTimeout() Сам был в пользовательской функции.

Suggestion: У меня нет устройства iOS для тестирования, но, возможно, выполнение начального воспроизведения / паузы, когда пользователь нажимает кнопку, снимет это ограничение. То есть вы звонитеplay() а затем приостановить его сразу,then позвоните, чтобы оживить иsetTimeout() функция сplay() вызов. Это делает инициированную пользователем функцию, позволяющую iOS знать, что в будущем можно загружать и воспроизводить это видео.

 Dan Halliday11 июн. 2012 г., 18:46
Вы совершенно правы @apsillers, то, что я делал, не квалифицировалось как «действие, инициированное пользователем». Однако есть решение - я еще немного покопался, и важно отметить, что я ошибся, когда написал упрощенный контрольный пример в своем вопросе & # x2014; Этоdoes на самом деле работа. Смотрите мой ответ ниже, почему.
 Dan Halliday11 июн. 2012 г., 19:15
Решение моего первоначального вопроса состояло в том, чтобы продолжать использовать мою сложную анимационную последовательность с несколькими тайм-аутами, но запустить функцию с одним тайм-аутом для.play() метод, с соответствующей большей продолжительностью. Затем он работает «параллельно». Очевидно, что он не является надежным, так как таймеры в последовательности анимации могут не находиться наplay() можно назвать рано. Но в моем случае все работает нормально.

@apsillers предлагает в своем ответе, что я мог бы изменить свой код для выполнения действия, инициированного пользователем на iPad.. Я немного покопался, и это оказалось правдой.

Требование заключается в том, чтоplay() звонок может быть только в пределахone setTimeout (Следовательно, упрощенный пример, который я привел в оригинальном вопросеdoes работа & # x2014; У меня изначально былplay() несколькоsetTimeoutглубоко).

Так этоwill Работа:

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play

_play: (e) =>
  setTimeout (=>
    @_audio[0].play()                  // play() is only inside one setTimeout
  ), 300

И это также будет работать:

constructor: (@_button, @_audio) ->
  @_button.on 'click', =>
    setTimeout ((e) =>
      @_play(e)
    ), 300

_play: (e) =>
  @_audio[0].play()                    // Still only inside one setTimeout

Но это не сработает

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play

_play: (e) =>
  setTimeout (=>
    // Something useful
    setTimeout (=>
      @_audio[0].play()                // play() is inside two setTimeouts
    ), 300
  ), 300

И не будет этого (моя первоначальная настройка):

constructor: (@_button, @_audio) ->
  @_button.on 'click', @_play

_play: (e) =>

  @_button
    .animate { prop: value }, 300, =>

      setTimeout (=>
        @_audio[0].play()              // play() still 'too deep'
      ), 300

В последнем примере кажется, что анимированный обратный вызов jQuery вызывается из другогоsetTimeout внутри библиотеки такplay() снова "слишком глубоко".

 08 авг. 2016 г., 08:38
Обратите внимание, что это работает, только если оно составляет 300 мс или менее.

которые вы не можете автоматизировать вызовом для воспроизведения аудиосистемы, вы пытались использовать кнопку и нажимать кнопку воспроизведения, чтобы увидеть, работает ли она, если да, то как она работает, открывает ли он аудиоплеер, чтобы воспроизвести его, если вам не разрешено автоматическое воспроизведение мультимедиа? такой же, как тег видео, если я правильно помню

Я думаю, что сафари проверяет событие для запуска звука.

Ваш ответ на вопрос