client-sdk-flutter icon indicating copy to clipboard operation
client-sdk-flutter copied to clipboard

[bug] Cannot change audio output to earpiece if a bluetooth device is connected.

Open aqeelshamz opened this issue 7 months ago • 4 comments

Describe the bug

When a Bluetooth audio device (e.g., AirPods, earbuds) is connected, it becomes impossible to route audio to the phone's earpiece using Room.setAudioOutputDevice() or Room.setSpeakerOn(false). The audio continues to route to the Bluetooth device instead of the earpiece, even after explicit device selection.

This appears to be due to the mobile OS (iOS/Android) prioritizing Bluetooth audio routing over earpiece routing. While switching from Bluetooth to speaker works correctly via setSpeakerOn(true), switching from Bluetooth to earpiece does not work as expected.

To Reproduce

  1. Connect Bluetooth earbuds/headphones to the device
  2. Join a LiveKit room with audio enabled
  3. Get available audio output devices using Hardware.instance.audioOutputs()
  4. Attempt to switch to earpiece using either:
    • room.setAudioOutputDevice(earpiece_device)
    • room.setSpeakerOn(false) after Bluetooth was active
  5. Observe that audio continues playing through Bluetooth device instead of earpiece

Expected behavior

When selecting the earpiece device from the available audio outputs, the audio should route to the phone's earpiece/receiver, not continue playing through the Bluetooth device. The behavior should be:

  • Bluetooth → Speaker: ✅ Works (via setSpeakerOn(true))
  • Bluetooth → Earpiece: ❌ Fails (audio stays on Bluetooth)
  • Speaker → Earpiece: ✅ Works
  • Earpiece → Bluetooth: ✅ Works

Platform information

  • Flutter version: 3.35.1
  • Plugin version: livekit_client: ^2.4.9
  • Flutter target OS: Android (Model: Pixel 6a, Real Device)
  • Flutter target OS version: Android 16 Baklava

Additional context

We've tested various workarounds including:

  • Multiple calls to setAudioOutputDevice()
  • Toggling setSpeakerOn(true) then setSpeakerOn(false) with delays
  • Attempting audio session resets via microphone disable/enable cycles

None of these approaches reliably route audio from Bluetooth to earpiece. This seems to be a limitation of how mobile operating systems handle audio routing priorities (Bluetooth > Speaker > Earpiece), but it would be valuable if LiveKit could provide a way to override this behavior or document the limitation.

Workaround

Currently hiding the earpiece option in the UI when Bluetooth devices are detected to prevent user confusion.

aqeelshamz avatar Aug 26 '25 06:08 aqeelshamz

Can you please check on this? @bcherry

aqeelshamz avatar Aug 26 '25 06:08 aqeelshamz

Can you please check on this? @cloudwebrtc

mubarakmuhammed007 avatar Sep 19 '25 12:09 mubarakmuhammed007

setAudioOutputDevice onlyfor desktop or web Future selectAudioOutput(MediaDevice device) async { if (!lkPlatformIsDesktop()) { logger.warning('selectAudioOutput is only supported on Desktop'); return; } selectedAudioOutput = device; await rtc.Helper.selectAudioOutput(device.deviceId); }

zhanchen18 avatar Oct 13 '25 10:10 zhanchen18

I have the same question. I'm trying to develop a feature: when a Bluetooth headset is connected, I still want to choose the phone's earpiece (not the headset) to play audio. But currently, I can only use the simple method setSpeakerOn, which only allows turning the speaker off or on. It doesn't enable the earpiece.

zhanchen18 avatar Oct 13 '25 10:10 zhanchen18

Hardware.selectAudioOutput only allows this method on desktop, but flutter-webrtc implements this method for all platforms:

  /// Note: This method is only used for Flutter native,
  /// supported on iOS/Android/macOS/Windows.
  ///
  /// Android/macOS/Windows: Can be used to switch all output devices.
  /// iOS: you can only switch directly between the
  /// speaker and the preferred device
  /// web: flutter web can use RTCVideoRenderer.audioOutput instead
  static Future<void> selectAudioOutput(String deviceId) async {

@cloudwebrtc is there any reason for this restriction?

bdlukaa avatar Jan 17 '26 16:01 bdlukaa

I believe mobile devices should let the system manage audio routing. This is because input/output devices on mobile devices typically appear in pairs. For example, with AirPods, you can't simultaneously use the AirPods microphone and the phone's earpiece for output, and using selectAudioOutput also changes the input, making management confusing. Therefore, mobile devices don't have the ability to independently modify input or output.

cloudwebrtc avatar Jan 19 '26 05:01 cloudwebrtc