-
Notifications
You must be signed in to change notification settings - Fork 63
Description
On iOS, when joining a LiveKit room without the local microphone enabled, remote audio plays through the physical earpiece (receiver) instead of the bottom loudspeaker, despite using configureAudio({ ios: { defaultOutput: "speaker" } }), selectAudioOutput("force_speaker"), and setAppleAudioConfiguration. The only reliable workaround is briefly enabling the microphone, which causes an audible bleep and risks transmitting audio when users should not speak (listen-only sessions).
To Reproduce
Steps to reproduce the behavior:
- Create an Expo app with
@livekit/react-native,@livekit/react-native-webrtc, callregisterGlobals()at startup - Connect to a LiveKit room with remote audio (e.g. host speaking) using the connect flow below
- Join without enabling the microphone
- Hold phone at arm's length — audio is inaudible (routed to earpiece)
- Enable microphone — audio immediately switches to loudspeaker ✅
Minimal connect flow:
await AudioSession.configureAudio({ ios: { defaultOutput: 'speaker' } });
await AudioSession.startAudioSession();
// selectAudioOutput before connect throws OSStatus -50
await room.connect(url, token);
// After connect: selectAudioOutput + setAppleAudioConfiguration have no effect
if (Platform.OS === 'ios') {
await AudioSession.setAppleAudioConfiguration({
audioCategory: 'playAndRecord',
audioCategoryOptions: ['defaultToSpeaker', 'allowBluetooth', 'allowBluetoothA2DP', 'allowAirPlay'],
audioMode: 'videoChat',
});
await AudioSession.selectAudioOutput('force_speaker');
}Expected behavior
- Audio should route to loudspeaker when
defaultOutput: "speaker"is set selectAudioOutput("force_speaker")should work after connect without errorsselectAudioOutputbefore connect should not throw OSStatus -50
Screenshots
N/A — audio routing behavior.
Device Info:
- Device: testing on iPhone 13
- OS: iOS 26.2.1
Dependencies Info (please reference your package-lock.json or yarn.lock file, not just your package.json):
- @livekit/react-native: 2.9.6
- livekit-client: 2.16.1
- react-native-webrtc: @livekit/react-native-webrtc 137.0.2
Additional context
What we've tried (none work):
selectAudioOutput("force_speaker")before connect → throws OSStatus -50 (paramErr)selectAudioOutput+setAppleAudioConfigurationat 100ms, 300ms, 800ms, 2s, 4s after connect → no error, no effectroom.on("trackSubscribed", ...)→ apply config when first remote audio subscribes → no effect- Patched
selectAudioOutputto use RTCAudioSession instead of AVAudioSession → OSStatus -50, connection fails showAudioRoutePicker()shows Speaker selected, but physical output is still earpiece → suggests session/config mismatch
Behavior summary:
| Scenario | Result |
|---|---|
| Join (no mic) | ❌ Earpiece |
| Join with Bluetooth | ❌ Earpiece |
| Bluetooth disconnect mid-call | ❌ Earpiece (expected: loudspeaker) |
| Enable mic | ✅ Loudspeaker |
| If speaker already on → BT connect → BT disconnect | ✅ Loudspeaker |