NEW 205599
Closing an AudioContext kills native audio played using an AVAudioPlayer
https://bugs.webkit.org/show_bug.cgi?id=205599
Summary Closing an AudioContext kills native audio played using an AVAudioPlayer
distinctdan
Reported 2019-12-26 14:48:05 PST
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
Radar WebKit Bug Importer
Comment 1 2019-12-26 19:35:51 PST
distinctdan
Comment 2 2020-01-08 18:53:22 PST
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.
Note You need to log in before you can comment on or make changes to this bug.