Airplay 2 with multiple instances of AVPlayer

Our app plays two audio streams at once: a Foreground (vocal) stream, and a background (music) stream. To handle playback we have 2

AVPlayer
instances, one for foreground, and one for background.


With AirPlay 1, this works great. You choose the new route, and both streams start playing back on the selected device(s).


With AirPlay 2, however, this does not work properly. Either the foreground audio, or the background audio will begin playback, and behave in a way that makes it seem like they're competing with one another. They never overlay properly.


Is there some way to make this work when streaming to AirPlay 2 devices (i.e. HomePod) without having to resort to completely rewriting our entire app using

AVSampleBufferAudioRenderer
?

Replies

Same problem here (in my case, for a gapless music player app, where two AVAudioPlayers briefly overlap). This doesn't seem to be possible according to some Apple doc I've read the other day. Only one instance of any kind of player can ever play through AirPlay.
Indeed, I believe you would need to mix the audio streams in some way. AVSampleBufferAudioRenderer would be one way to accomplish this, but depending on your exact use case you may be able to use something like AVMutableComposition with a single AVPlayer. If the current options don't fit well with your use case, please let us know by filing a report using the feedback assistant. Make sure to include a detailed description of your use case and what you have tried so far.
I've also just run into this same problem. I have two AVPlayer objects, one which plays music and the other plays a narration.

The two AVPlayers stream just fine with Bluetooth and AirPods. But on AirPlay 2 devices like a Sonos speaker, only one or the other will stream, which was an unexpected and not very nice surprise.

The only thing I found to work is to configure your AVAudioSession to not support AirPlay 2 (i.e., don't use the .longFormAudio policy), and make sure to use the .duckOthers option, as follows:
Code Block
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.duckOthers])

This will stream both AVPlayers' content to an AirPlay 2 device like Sonos. But, the downside is you lose the lock screen / Control Center playback controls, due to the .duckOthers option. Ultimately I guess this is better than the alternative of my app being non-compatible with Sonos/HomePod. But, losing the lock screen controls is a major bummer.

Curious if anyone else has any other options, short of the suggestions above which involve a major and costly rewrite using AVSampleBufferAudioRenderer.

I would think this multiple AVPlayer pattern is a common pattern in meditation apps, as you want the music to continue looping after the narration ends, and you might want to allow the user to change the relative volume between the music AVPlayer and the narration AVPlayer. So, I'm surprised this doesn't work with AirPlay 2.

I looked at the Headspace app and they also don't support AirPlay with simultaneous narration+music, so I'm guessing they couldn't figure out a solution either?