some-easter-99890
02/23/2026, 7:50 AMdefaultOutput: "speaker" in AudioSession.configureAudio . I'm even then setting await AudioSession.selectAudioOutput("force_speaker") and the setting is ignored, the audio seems to play through earpiece. I want the audio to default to either a compatible connected bluetooth device (e.g. headphones), or the phone's loudspeaker - never the earpiecetall-airline-16756
02/23/2026, 7:50 AMtall-airline-16756
02/23/2026, 7:50 AMAudioSession.configureAudio / AudioSession.selectAudioOutput aren’t having any effect. I’m responding about audio routing behavior in LiveKit’s React Native SDK and next steps you can take.
What’s happening
• LiveKit’s React Native SDK does not expose an AudioSession API with configureAudio or selectAudioOutput. Audio routing is handled by the underlying WebRTC/native layer (react-native-webrtc → platform Audio session) rather than by LiveKit’s public SDK APIs.
• Because LiveKit doesn’t provide built-in APIs to select or force audio outputs, calling those AudioSession methods (which appear to be from another library or a custom module) will be ignored by the LiveKit SDK/WebRTC stack unless those calls actually change the native audio session used by WebRTC on the device.
What you can try
• Confirm the source of `AudioSession`: Identify whether AudioSession belongs to a third-party module or custom native code in your app. If it’s not a module that bridges to the same native audio session WebRTC is using, its calls won’t affect the WebRTC audio route.
• Use native audio APIs (or a bridge) that target the same audio session WebRTC uses:
◦ On iOS you need to configure AVAudioSession category/mode and set the route to speaker when appropriate.
◦ On Android you need to use AudioManager to set speakerphone on/off or route to Bluetooth.
• Use a React Native bridge library known to interact with native audio routing for WebRTC. Typical approaches are:
◦ Add small native modules that call AVAudioSession.setCategory / AVAudioSession.overrideOutputAudioPort(.speaker) on iOS.
◦ Use AudioManager.setSpeakerphoneOn(true) or AudioManager.startBluetoothSco() on Android, and ensure the app has appropriate Bluetooth permissions and SCO support.
• Ensure timing: Make routing changes before starting playback or immediately after the remote track is attached; sometimes routing calls must run at the right point in the session lifecycle to take effect.
• Test device behavior: Some Android OEMs and certain Bluetooth devices behave differently; test on both iOS and Android devices and with multiple Bluetooth devices.
Questions to narrow this down
1. Which library provides your AudioSession calls (package name), or is it custom native code?
2. Are you on iOS, Android, or both?
3. Do you see different behavior when a Bluetooth device is already connected before joining the room vs connecting after the call starts?
4. Can you share a minimal snippet showing how and when you call configureAudio / selectAudioOutput relative to joining the LiveKit room and when you attach remote audio tracks?
If you’d like, I can:
• Walk through specific iOS AVAudioSession or Android AudioManager code snippets to force speaker / prefer Bluetooth.
• Suggest where to place these calls in the React Native lifecycle so they affect WebRTC playback.
• Review a short code snippet from your app to point out where routing calls should be inserted.
Tell me the answers to the questions above or paste the relevant snippet and I’ll provide targeted steps for iOS and/or Android.
Sources: Web and mobile frontends | LiveKit Documentation | Agent speech and audio | LiveKit Documentation | LiveKit coming to React Native! | LiveKit coming to React Native! | Launch Week! :rocket:some-easter-99890
02/23/2026, 7:58 AM@livekit/react-native — AudioSession is imported directly from the LiveKit React Native SDK:
ts
import { AudioSession } from "@LiveKit/react-native";
Are you on iOS, Android, or both?
Both. The issue is most noticeable on iOS (audio going to earpiece like a phone call).
Do you see different behavior when a Bluetooth device is already connected before joining the room vs connecting after the call starts?
If a bluetooth device is connected it normally routes to that. However if we disconnect bluetooth then it typically routes to earpiece instead of speaker. If join without a bluetooth device then it typically routes to earpiece instead of loudspeaker. If we connect a bluetooth device whilst already in a room, then it typically routes to bluetooth straight away.
Can you share a minimal snippet showing how and when you call configureAudio / selectAudioOutput relative to joining the LiveKit room and when you attach remote audio tracks?
Yes — see below.
Snippet: Current Setup:
ts
// 1. Audio is configured and started before room.connect
await AudioSession.configureAudio({
ios: { defaultOutput: "speaker" },
android: {
preferredOutputList: ["bluetooth", "headset", "speaker"],
audioTypeOptions: AndroidAudioTypePresets.communication,
},
});
if (Platform.OS === "ios") {
await AudioSession.selectAudioOutput("force_speaker");
}
await AudioSession.startAudioSession();
await room.connect(serverUrl, token, { autoSubscribe: false });
We also use useIOSAudioManagement(room, true, customConfig) with:
- audioMode: "videoChat"
- audioCategory: "playAndRecord"
- audioCategoryOptions: ["mixWithOthers", "defaultToSpeaker", "allowBluetooth"]tall-airline-16756
02/23/2026, 7:58 AM@livekit/react-native, the iOS-heavy symptom (audio routing to the earpiece), and your snippet showing configure → start → connect.
Short answer
• AudioSession in @livekit/react-native is the SDK API you should use to control the native audio session.
• Your code mostly follows the right pattern, but iOS can revert to the receiver (earpiece) when routes change (e.g., no Bluetooth connected). The reliable fix is to (A) only use AudioSession (avoid conflicting hooks), (B) ensure the session is started before connecting, and (C) detect route changes and re-apply speaker forcing when needed.
What I recommend you try (concise, actionable)
1. Remove the useIOSAudioManagement hook to avoid conflicts.
2. Ensure ordering: configure → start session → force speaker → connect.
a. Call await AudioSession.configureAudio(...).
b. Call await AudioSession.startAudioSession() and wait for it to resolve.
c. Immediately call await AudioSession.selectAudioOutput("force_speaker") on iOS.
d. Then await room.connect(...).
1. Handle route changes at runtime:
◦ Listen for audio-route change events and re-apply selectAudioOutput("force_speaker") when Bluetooth disconnects or when the system switches to the receiver.
◦ Example pattern:
▪︎ Add a listener: AudioSession.addEventListener("audioRouteChanged", handler).
▪︎ In the handler, detect a Bluetooth→builtin change (or any change to receiver) and call AudioSession.selectAudioOutput("force_speaker").
1. Add logging and error handling:
◦ Log results/errors from startAudioSession() and selectAudioOutput() to confirm they succeed.
◦ If startAudioSession() fails or is delayed, the route-change calls won’t take effect.
1. Test variations:
◦ Join with Bluetooth connected (should route to BT).
◦ Join with no BT (should route to speaker after forcing).
◦ Disconnect BT while in a room (listener should reapply speaker).
Why this helps
• iOS will sometimes pick the receiver when no external device is present unless defaultToSpeaker / forcing to speaker is applied to the active AVAudioSession. Starting the LiveKit AudioSession early and re-applying the forced output on route changes ensures the active WebRTC/native session uses the speaker instead of the earpiece.
• Removing useIOSAudioManagement avoids competing native session changes.
Questions to narrow further (if you want me to dig deeper)
1. After startAudioSession() and selectAudioOutput("force_speaker"), do your logs show those calls succeed (no errors)?
2. Do you already have an audioRouteChanged listener added, and if so what events do you see when Bluetooth disconnects?
3. Which iOS versions/devices do you see the problem on? Some OEM/OS behaviors differ.
If you’d like, paste a short snippet of your new sequence (configure → start → select → connect) with any logs you get and I’ll review it and suggest exact placement for listeners and any defensive checks to make it robust.
Sources: LiveKit coming to React Native!some-easter-99890
02/23/2026, 8:09 AMaudioRouteChanged listener?tall-airline-16756
02/23/2026, 8:10 AMaudioRouteChanged listener.
Short answer
• The LiveKit React Native SDK does not document or expose a built-in audioRouteChanged event in the React Native API.
What that means and next steps
• LiveKit’s React Native SDK uses the native WebRTC/audio stack under the hood, and the Android client includes an AudioSwitchHandler (native helper) to manage routing automatically. However, the React Native surface does not provide a documented callback named audioRouteChanged for you to subscribe to directly.
• To reliably react to route changes (Bluetooth disconnects, headset plug/unplug, etc.) from React Native, you have two practical options:
◦ Use a React Native module that exposes native audio-route events:
▪︎ On iOS, that module should forward AVAudioSession route-change notifications.
▪︎ On Android, it should forward AudioManager / Bluetooth SCO events.
▪︎ Examples: community packages that expose audio route changes or a small custom native bridge that listens to AVAudioSessionRouteChangeNotification / AudioManager broadcasts and emits events to JS.
◦ Reapply your desired route proactively:
▪︎ After calling AudioSession.startAudioSession(), call AudioSession.selectAudioOutput("force_speaker") (iOS) and log success/errors.
▪︎ If you cannot observe route events, consider periodically checking the active route on your side (or add UI controls) and re-applying the speaker selection when you detect the audio is on the receiver.
How I can help next
• I can suggest specific native event names and tiny code snippets for iOS (AVAudioSessionRouteChangeNotification) and Android (AudioManager ACTION_HEADSET_PLUG, Bluetooth events) so you can implement a small bridge.
• Or I can review a short snippet of your app and propose the simplest place to add route-change handling and re-apply selectAudioOutput("force_speaker").
Which would you prefer — a ready-to-add React Native snippet that listens for route changes on iOS/Android, or starter code for a simple native bridge?
Sources: client-sdk-android | livekit/livekit_composite | DeepWiki | LiveKit coming to React Native! | LiveKit coming to React Native!some-easter-99890
02/23/2026, 8:34 AMtall-airline-16756
02/23/2026, 8:34 AM