Bug 134925 - iOS 8 prevents audio playback outside of user gesture even after Web Audio unmutes
Summary: iOS 8 prevents audio playback outside of user gesture even after Web Audio un...
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: 528+ (Nightly build)
Hardware: iPhone / iPad Other
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-15 07:36 PDT by Ashley Gullen
Modified: 2014-07-16 08:26 PDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ashley Gullen 2014-07-15 07:36:48 PDT
Apparently by design, creating a new Audio() in javascript and playing it will cause no audio playback to occur unless the play() call is in a user input event like touchstart. This report is being made because this design makes no sense now that the Web Audio API has been introduced, and exists solely to impede legitimate use cases.

After a first touch, the Web Audio API becomes unmuted and can play audio at any time. However even after that Audio objects cannot play any sound unless in a user input event. The workaround is to AJAX the entire music track and play it with the Web Audio API. This has several drawbacks: the entire track must be downloaded and decoded entirely before playback can begin, as opposed to the HTML5 Audio element's ability to stream and start playback sooner; and the entire decompressed track must be held in memory, which is unacceptable on memory-constrained mobile devices. Therefore HTML5 audio is still necessary for playback of longer tracks such as music.

Once the Web Audio API is unmuted, continuing to limit Audio object playback serves no purpose. If the intent is to avoid surprising the user with sudden audio playback, the Web Audio API can do that anyway. If the intent is to avoid unexpectedly wasting bandwidth, the Web Audio API workaround will do that anyway, and then obnoxiously use loads of memory as well.

Legitimate use cases such as playing music in HTML5 games are still impeded by the limitation. For example if at some point after the Web Audio API unmutes the game switches to a "game over" screen which is dismissed on the first touch, it is impossible to play music on that screen, because the first touch is necessary to start music playback but also dismisses the screen. Even if a "dismiss" button is provided, the user is likely to press that immediately without providing another touch somewhere else to start music playback, so the game over screen music is still never heard.

iOS should treat Audio() objects the same way as the Web Audio API: after the first touch, playback is fully unmuted and can occur at any time. Continuing to limit Audio() playback while allowing arbitrary Web Audio playback serves no useful purpose and impedes legitimate use cases.
Comment 1 Alexey Proskuryakov 2014-07-15 20:38:03 PDT
Is this a change from iOS 7 behavior? The title implies that it is, but the description doesn't appear to support that.
Comment 2 Eric Carlson 2014-07-15 20:50:40 PDT
play() or load() must be called ONCE from a user gesture handler for each <video> and <audio> element. This is to prevent pages from loading potentially large media files which the user never plays, which is especially important in markets with expensive metered bandwidth. 

iOS does treat <audio>/Audio() like WebAudio - a user gesture is only required for the first load/play. The restriction is removed after that point, so you can load/play one file and then change 'src' and load and play another without a user gesture.
Comment 3 Ashley Gullen 2014-07-16 08:26:15 PDT
What is the rationale for applying the restriction per-element rather than per-page?  Our engine happens to create different Audio objects for different music tracks. Why should a second Audio object created after the first one is unmuted still require a user gesture, when setting a different source on the first one does not?