Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML5 audio object doesn't play on iPad (when called from a setTimeout)

I have a page with a hidden <audio> object which is being started and stopped using a custom button via javascript. (The reason being I want to customise the button, and that drawing an audio player seems to destroy rendering performance on iPad anyway). A simplified example (in 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

The audio plays fine when triggered from a function bound to a click event, but I actually want an animation to complete before the file plays so I put .play() inside a setTimeout. However I just can't get this to work:

// 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

I've checked that @_audio (this._audio) is in scope and that its play() method exists. Why doesn't this work on iPad?

Edit: As it happens, the simplified test case above actually does work. See @apsillers' answer below and my comments on it.

like image 729
Dan Halliday Avatar asked Jun 11 '12 16:06

Dan Halliday


2 Answers

See Apple's iOS considerations guide:

...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.

It appears that your setTimeout() callback does not qualify as user-initiated action, despite the fact that the setTimeout() itself was in a user-initiated function.

Suggestion: I don't have an iOS device to test on, but maybe doing an initial play/pause when the user presses the button will relieve this restriction. That is, you call play() and then pause it at once, then make your call to animate and the setTimeout() function with the play() call. This makes the user-initiated function let iOS know that it is okay to load and play this video in the future.

like image 182
apsillers Avatar answered Nov 16 '22 23:11

apsillers


Some devices you cant automate the call to play Audio system have you tried using a button and clicking play see if that works if so how does it work does it open an audio player to play it if so your not allowed to automatic play the media this is the same as the Video tag if I remember correctly

I think safari checks for an event to fire the audio Hence why clicking works

like image 43
HotHeadMartin Avatar answered Nov 16 '22 22:11

HotHeadMartin