Bug 205599
Summary: | Closing an AudioContext kills native audio played using an AVAudioPlayer | ||
---|---|---|---|
Product: | WebKit | Reporter: | distinctdan |
Component: | Web Audio | Assignee: | Nobody <webkit-unassigned> |
Status: | NEW | ||
Severity: | Minor | CC: | brad, webkit-bug-importer |
Priority: | P2 | Keywords: | InRadar |
Version: | Safari 13 | ||
Hardware: | iPhone / iPad | ||
OS: | iOS 13 |
distinctdan
My hybrid app uses html5 webaudio for sound effects, as well as native audio for background music. I'm closing an AudioContext as part of a hack to get iOS 12 to play audio at the correct sample rate (related to https://stackoverflow.com/a/37057640/2095953). However, when I close the context, it kills any native audio that is already playing using AVAudioPlayer. It's not a hard stop, it's a quick fadeout just like if you press the home button. This is unexpected because I wouldn't expect a webview to be able to affect native audio at all. My current workaround is delaying my native audio from starting until after I've done the context close + a short timeout.
Here's some simplified sample code to show the flow:
// Objective C - runs first
player = [[AVAudioPlayer alloc] initWithContentsOfURL:pathURL error:&err];
[player play];
// JS - play a short sound that's at 48khz, then recreate context to get iOS 12 to play audio at the correct sample rate instead of 44.1khz.
htmlAudioEl.play().then(() => {
htmlAudioEl.pause();
this.ctx.close();
this.ctx = new AudioContext({sampleRate: 48000});
});
// All audio then fades out and never plays again.
Info
----------
Using WkWebView for the webview
Replicated on:
- iPod Touch 6th gen running iOS 12.4.3
- iPad Pro 11inch running iOS 13.2.3
Attachments | ||
---|---|---|
Add attachment proposed patch, testcase, etc. |
Radar WebKit Bug Importer
<rdar://problem/58211693>
distinctdan
After further testing, I've discovered more details. There are 2 scenarios that this bug appears to impact:
Scenarios:
1) Close a javascript AudioContext and create a new one.
Effects:
- Triggers a native audio interruption "AVAudioSessionInterruptionTypeBegan".
- BUT, this interruption never ends, IE, "AVAudioSessionInterruptionTypeEnded" is never triggered. However, calling [player play] on the player will cause audio to resume playing anyways.
2) Do the above while the system is under heavy load. Ways I've tested:
- Force close the app and immediately reopen it.
- Use Safari's remote web inspector to repeatedly refresh the cordova webview.
This *sometimes* causes the following:
- The newly created javascript context will drop to the "interrupted" state 1 or more times shortly after it's been created. Resuming the context allows it to continue playing.
Needed Fix:
- iOS needs to send an "AVAudioSessionInterruptionTypeEnded" notification after the context is closed, so that the app knows it's ok to play audio again.
Hacky Workaround:
- After closing a js AudioContext, assume all native audio interruptions in the next couple of seconds are caused by the close, and tell AVAudioPlayer to play anyways. This means that if a user causes a real interruption in those few seconds, like receiving a phone call or opening Siri, the app will incorrectly keep playing audio.