Skip to content

react-native: hard-coded preferredOutputList ["speaker"] blocks Bluetooth/wired headset audio on Android #881

Description

@oparinov

Summary

@elevenlabs/react-native hard-codes the LiveKit audio session config inside reactNativeSessionSetup (src/index.react-native.ts):

await AudioSession.configureAudio({
  android: {
    preferredOutputList: ["speaker"],
    audioTypeOptions: AndroidAudioTypePresets.communication,
  },
  ios: {
    defaultOutput: "speaker",
  },
});

On Android, preferredOutputList is the entire automatic routing order — any output not on the list is never auto-selected. ["speaker"] therefore removes Bluetooth and wired headsets from routing completely: with a BT earpiece (or hearing aid) connected, conversation audio always plays through the phone speaker and the user may hear nothing at all. LiveKit's own default for this option is bluetooth > headset > speaker > earpiece, which the SDK silently overrides.

Because the SDK calls configureAudio inside every startSession(), right before connecting, an app cannot fix this from the outside — any app-level AudioSession.configureAudio(...) is overwritten by the SDK's copy. Still present in 1.2.14 (latest at time of writing).

iOS is less affected: the LiveKit native module keeps .allowBluetooth/.allowBluetoothA2DP in the category options, and defaultOutput: "speaker" only adds .defaultToSpeaker, which yields to a connected headset.

Real-world impact

We build a voice companion app for elderly users. A user with a connected Bluetooth earpiece went through three consecutive sessions unable to hear the agent; app restarts and a phone reboot (obviously) didn't help. Hearing-aid users are the worst-affected group, and they're exactly the users least able to troubleshoot audio routing.

Repro

  1. Android device, pair any Bluetooth audio device (earbud/headset).
  2. Start a conversation via useConversation().startSession(...).
  3. Agent audio plays from the phone speaker; the BT device receives nothing. AudioSession.selectAudioOutput is the only escape hatch, and app-level configureAudio before the session has no effect (the SDK re-applies its own config).

Proposed fix

Either (or both):

  1. Change the hard-coded list to LiveKit's default order, ["bluetooth", "headset", "speaker", "earpiece"] — speaker behavior is unchanged when no headset is connected, and headsets work like they do in a phone call.
  2. Expose the audio configuration (e.g. an optional audioSessionConfig on startSession options, or respect a previously applied app-level configureAudio instead of overwriting it).

Current workaround

We ship a pnpm patchedDependencies patch rewriting the hard-coded list, plus a unit test that fails if an SDK bump drops the patch. Works, but every consumer of this SDK with headset users is hitting the same bug.

Happy to open a PR for either variant if you tell me which direction you'd prefer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions