HTML5音频对象无法在iPad上播放(从setTimeout调用时)

时间:2012-06-11 16:05:10

标签: javascript ipad html5 audio 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

我已检查@_audiothis._audio)是否在范围内且其play()方法是否存在。为什么这不适用于iPad?

编辑:实际上,实际上面的简化测试用例有效。请参阅下面的@apsillers的回答以及我对它的评论。

3 个答案:

答案 0 :(得分:11)

请参阅Apple's iOS considerations guide

  

... JavaScript play()load()方法在用户启动播放之前也处于非活动状态,除非用户操作触发play()load()方法。换句话说,用户启动的“播放”按钮有效,但onLoad="play()"事件不起作用。

尽管setTimeout()本身位于用户启动的功能中,但您的setTimeout()回调似乎不符合用户启动的操作。

建议:我没有要测试的iOS设备,但是当用户按下按钮时可能会进行初始播放/暂停将减轻此限制。也就是说,您拨打play(),然后立即暂停,然后通过setTimeout()电话拨打动画和play()功能。这使得用户启动的功能让iOS知道将来加载和播放此视频是可以的。

答案 1 :(得分:1)

有些设备无法自动调用播放音频系统你是否尝试使用按钮并点击播放,看看是否有效,如果是这样的话它是如何工作的呢?如果是这样你就不能自动播放音频播放器来播放它如果我没记错的话,媒体这与视频标签相同

我认为safari会检查触发音频的事件因此点击工作的原因

答案 2 :(得分:1)

@apsillers在他的回答中建议我可以重新安排我的代码以满足iPad的“用户启动的操作”要求。我做了一些挖掘,事实证明这是真的。

要求似乎是play()调用可能只在一个 setTimeout内(因此,我在原始问题中给出的简化示例< / em>工作 - 我最初有play()几个setTimeout s深。)

所以这个工作:

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()再次“太深”。