10

I have been trying to track this down and there doesn't seem to be a consistent answer. If I have a website that tries to play multiple songs in a row (think playlist) using the HTML 5 audio element, can it continue to work on the iOS lock screen?

For some background, this answer seems to indicate it may be possible. But then this article suggests it is not.

I tried following the closest example of what Apple recommends, as found here, to replicate this. I am using plain, vanilla javascript and HTML, nothing fancy. I copied their example exactly and just substituted the audio tag for the video one, picking two random mp3 songs. All it does is wait for one song to end, then switch the src, load, and play the next track.

When I hit Play on the website, I then lock the iPhone. The first song will play, then stop. It does not continue to the next song.

If the website is open to the page, it will properly transition to the next song. On Android, it will continue to the next song even if the phone is locked.

I tried this with iOS 11 and 12. Neither worked. I have read many differing answers about how javascript is stopped when the website isn't in the foreground, and how iOS requires user interaction to play audio (even going from one song to the next). So it doesn't seem like this would work. But then other answers out there seem to indicate this is possible.

Is there a definitive yes or no? Am I doing something wrong here? Or is it just not possible?

Eric Ely
  • 101
  • 1
  • 4
  • 1
    I would also love to know about this, but my small experiments seem to have ended like yours. Have you opened a bug report on Webkit's bugzilla? That might be a good next step to getting this implemented – lastmjs May 20 '19 at 16:16
  • Did you figure something out? I have exactly the same problem. – user0103 Jun 14 '19 at 12:43
  • It's a shame that it's almost 2020 and we're not able to do seomthing as simple as this on iOS. – INT Dec 02 '19 at 13:52

1 Answers1

8

There are multiple issues, which is causing some of the confusion.

First track plays, second does not due to user permission

If the first track was started with user permission, then the only way you can switch to a new track via script is with Apple's recommendation. Handle the ended event and swap in a new src, and call .play() before the callback completes. Otherwise, your code will not have permission to start the new audio.

Cannot get to ended event due to time-constrained source (#t=5,10)

Say you have a 30-second audio file and you tell the browser to only load seconds 5 through 10, via something like #t=5,10 at the end of the URL. When you reach 10, a paused event will fire, not ended. Therefore, it isn't possible to go on to the next track normally, as this event is not "blessed" by Apple to count as a relay of the previous user interaction.

I got around this by having my JavaScript check the currentTime repeatedly, and when it crossed a threshold, seek it to the duration (end) of the file myself. This allows ended to fire normally.

iOS doesn't allow scripts to run after the screen is locked or other apps are in use

This one is a real problem to debug, since it doesn't turn up in any of the simulators. In any case, you're right, your JavaScript is going to get suspended so even if you follow Apple's recommendations, you're out of luck. Or, are you?

A hack... set up a ScriptProcessorNode on a Web Audio context. Set the buffer size to like 512 samples or something. Then, on script process, force a timeupdate event for your Audio Element. This keeps your JavaScript there ticking away. ScriptProcessorNode has to have special privileges here, by its nature.

Apple: If you read this, please fix your browser. It would be great if we didn't have to hack around things to make something as simple as an audio playlist to work. Other browsers don't have nearly this level of problems.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • 2
    Seems to have been resolved recently. https://bugs.webkit.org/show_bug.cgi?id=173332 – AshotN Dec 04 '19 at 07:37
  • 1
    Very nice writeup. I tried using a ScriptProcessorNode to regularly change the `currentTime` but as soon as I locked the screen it stopped updating the `currentTime`. Do you know if there are any current workarounds to automatically play the next track in the background? Thanks. – Collin Anderson May 04 '22 at 21:15
  • @CollinAnderson You can still handle the `ended` event to play the next track. – Brad May 04 '22 at 22:15
  • It can stream though, this may be a workaround – Barak Binyamin Dec 27 '22 at 06:54
  • @Brad thank for the suggestions above. I am trying to resolve playback issues on Ipad for my HTML5 media player. I am using a nosleep.js library which allows me to play around 50-55m of playback before the next track just doesn't download the stream. (The screen will be off by this time). It stops at 605 bytes. Is this a wifi sleep issue and can I resolve that with bove solutions? – Mattijs Apr 18 '23 at 07:08
  • @Mattijs Can you post a new question, and include your exact browser and iOS versions, and some sample code that reproduces the problem? It's likely that this has changed a bit since this answer was posted. – Brad Apr 18 '23 at 19:05
  • @brad Do you mean post an stackoverflow question and start a new discussion? Sample code I can do, but to provide the exact scenario is going to be hard. I am running streams from SevenDigital, a stream provider from the UK and as I mentioned before, at some track number 15-23 (it varies) the next track stream will not be downloaded. I am just using a HTML5 Audio object and put in a the next source when the `ended` event fires. Browser on Ipad is Safari, IpadOs 15.6.1 – Mattijs Apr 20 '23 at 04:19