Bug 173332 - HTML5 audio .ended event not fired when app in background or phone screen is off
Summary: HTML5 audio .ended event not fired when app in background or phone screen is off
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Media (show other bugs)
Version: Safari 10
Hardware: iPhone / iPad iOS 10
: P2 Major
Assignee: Jer Noble
URL: http://bitshuvafiles01.com/iOSAudioBu...
Keywords: HTML5, InRadar
: 204080 (view as bug list)
Depends on:
Blocks:
 
Reported: 2017-06-13 14:48 PDT by Judah Gabriel Himango
Modified: 2019-11-20 10:32 PST (History)
17 users (show)

See Also:


Attachments
Patch (11.88 KB, patch)
2019-11-13 14:07 PST, Jer Noble
no flags Details | Formatted Diff | Diff
Patch for landing (11.94 KB, patch)
2019-11-15 15:07 PST, Jer Noble
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Judah Gabriel Himango 2017-06-13 14:48:26 PDT
When HTML5 audio finishes playing, the .ended event doesn't fire if the web app is running in the background or if the screen is off. 

Here's a simple page that demonstrates the problem: http://bitshuvafiles01.com/iOSAudioBugRepro/audioError.html

Steps to reproduce: 

1. Create web page with a single <audio> element.
2. In JavaScript, set audio.src = "song1.mp3", and .play();
3. Add an .ended event handler to the audio element. In the .ended event handler, set audio.src = "song2.mp3", and .play().
4. While song1.mp3 is playing, turn off the phone screen.
5. Wait for the audio to finish. When it finishes, audio will stop; song2.mp3 will never.

Expected results: The audio.ended event fires and the next song starts playing.

Actual results: The audio.ended event never fires because the screen is off or because Safari is in the background; JS execution is suspended.

Additional info: While suspending JS execution is wise for battery life reasons, it harms the user experience when listening to audio on the web. Either don't suspend JS execution for tabs playing audio, or at least fire the .ended event so we can play the next song.
Comment 1 Radar WebKit Bug Importer 2017-06-13 20:11:12 PDT
<rdar://problem/32757402>
Comment 2 Eric Carlson 2017-06-14 08:26:30 PDT
The web proces, normally suspended when in the background, is kept alive while playing audio (and for a few other reasons). The 'ended' event is fired asynchronously, so while the event is scheduled immediately when playback finishes, the task is suspended before the next runloop so the event doesn't fire until the process resumes. 

We should probably postpone suspension for a few cycles when playback stops to give scripts an opportunity to restart playback.
Comment 3 Judah Gabriel Himango 2017-06-14 09:53:29 PDT
>> "We should probably postpone suspension for a few cycles when playback stops to give scripts an opportunity to restart playback."

Ah, that would wonderful and would fix the problem perfectly.
Comment 4 craigwharding 2017-08-11 04:29:31 PDT
Hi any idea when this could be committed and it starts to hit upstream?
Comment 5 Brady Eidson 2017-08-11 06:50:23 PDT
(In reply to craigwharding from comment #4)
> Hi any idea when this could be committed and it starts to hit upstream?

There's nothing to be committed because there's no patch yet.

(This is an open source project)
Comment 6 Judah Gabriel Himango 2018-01-22 08:25:22 PST
This morning I received more reports of this same bug from my users on iOS. Any chance we get this fixed in 2018?
Comment 7 Mathias Rechtzigel 2019-01-18 10:45:15 PST
Confirmed still an issue.
Comment 8 Jer Noble 2019-11-13 12:53:01 PST
*** Bug 204080 has been marked as a duplicate of this bug. ***
Comment 9 Jer Noble 2019-11-13 14:07:44 PST
Created attachment 383493 [details]
Patch
Comment 10 Eric Carlson 2019-11-14 05:12:42 PST
Comment on attachment 383493 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=383493&action=review

r=me once the bots are happy

> LayoutTests/media/audio-background-playback-playlist-expected.txt:2
> +RUN(internals.setMediaElementRestrictions(audio, "RequireUserGestureForAudioRateChange"))

Oops, look like you need to regenerate this file.

> LayoutTests/media/audio-background-playback-playlist.html:20
> +        run('audio.load()');
> +        testExpected('internals.bestMediaElementForShowingPlaybackControlsManager("NowPlaying")', audio);

It would be better to test for NowPlaying status after a delay, e.g. after an 'emptied' event.
Comment 11 Jer Noble 2019-11-15 15:07:09 PST
Created attachment 383656 [details]
Patch for landing
Comment 12 WebKit Commit Bot 2019-11-20 10:32:09 PST
Comment on attachment 383656 [details]
Patch for landing

Clearing flags on attachment: 383656

Committed r252692: <https://trac.webkit.org/changeset/252692>
Comment 13 WebKit Commit Bot 2019-11-20 10:32:11 PST
All reviewed patches have been landed.  Closing bug.