aws / amazon-chime-sdk-ios

An iOS client library for integrating multi-party communications powered by the Amazon Chime service.
https://aws.amazon.com/chime/chime-sdk/
Apache License 2.0
144 stars 66 forks source link

Automatic Audio Routing when AirPods or Bluetooth headset is connected #89

Open Manny-ModMed opened 4 years ago

Manny-ModMed commented 4 years ago

Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] When starting a video call, the user could have any bluetooth headset or AirPods plugged in. When the video call starts, the audio does not route correctly to the headset. Also, during a video call, if the user decides to wear their AirPods or any bluetooth headset, the audio doesn't automatically route or update.

Describe the solution you'd like Provide an API for handling when the audio route changes, we can decide to switch to use the propose audio route or not. Or maybe the SDK could automatically handle this behind the scenes for us through AVAudioSession.

Describe alternatives you've considered We've considered listening for notification changes directly from the AVAudionSession.sharedInstance(), but we would prefer to have one source of truth when it comes to the state of the audio in the video call.

Additional context We've also looked into using the provided DeviceChangeObserver that is available on the AudioVideoFacade, but there aren't any clear examples of how to use this regarding AirPods or bluetooth headsets. The demo project currently only logs to the console when something changes.

hokyungh commented 4 years ago

Thank you for reporting. Would you be able to provide us the version of SDK and media library that is being used?

I think iPhone automatically switches to newly connected headset. I have disabled bluetooth and reconnect bluetooth earphone and it automatically switches to bluetooth earphone on my iPhone 6S Plus.

How are you testing in your case? Was it already connected beforehand?

We provide API audioDeviceDidChange, which gives you full list of audio devices available when either newly audio device added/removed.

We also provide API audioVideo.listAudioDevices which gives you current available choices. From this, you can choose audio devices by audioVideo.chooseAudioDevice. See code for choosing.

Let us know if you have more questions

Manny-ModMed commented 4 years ago

@hokyungh

We are using AmazonChimeSDK 0.8.1 and AmazonChimeSDKMedia 0.6.0 at the moment. For testing the use case, I had AirPods connected to my iPhone X running iOS 13.5.1. When starting a video call and the AirPods were already connected, the audio was being routed to the earpiece of the device.

schonfeld commented 4 years ago

I can confirm this is, in fact, the case. Without manual device handling logic, audio is always routed to the earpiece. I don't think iOS is generally responsible for doing the route switching... I believe it's up to the developer. It would definitely make sense to handle that automagically in this library.

For ref: https://developer.apple.com/documentation/avfoundation/avaudiosession/responding_to_audio_session_route_changes

FWIW, I've taken similar steps in our app to achieve this:


func audioSessionDidStart(reconnecting: Bool) {
  self.autoselectDevices()
}

...

func audioDeviceDidChange(freshAudioDeviceList: [MediaDevice]) {
  autoselectDevices()
}

...

private func autoselectDevices() {
  let devices = session.audioVideo.listAudioDevices()

  if let bluetoothDevice = devices.first(where: { $0.type == MediaDeviceType.audioBluetooth}) {
    session.audioVideo.chooseAudioDevice(mediaDevice: bluetoothDevice)
  }
  else if let wiredDevice = devices.first(where: { $0.type == MediaDeviceType.audioWiredHeadset}) {
    session.audioVideo.chooseAudioDevice(mediaDevice: wiredDevice)
  }
  // https://github.com/aws/amazon-chime-sdk-ios/blob/410c48858416efc47b7643ed62c007a5a27f075e/AmazonChimeSDK/AmazonChimeSDK/device/DefaultDeviceController.swift#L31
  else if let wiredDevice = devices.first(where: { $0.type == MediaDeviceType.audioBuiltInSpeaker || $0.label == "Build-in Speaker"}) {
    session.audioVideo.chooseAudioDevice(mediaDevice: wiredDevice)
  }
  else if let firstDevice = devices.first {
    session.audioVideo.chooseAudioDevice(mediaDevice: firstDevice)
  }
}

This logic will prioritize {bluetooth, wired headphones, built-in speaker, other} in that order, specifically.

hokyungh commented 4 years ago

@Manny-ModMed will confirm with team if this is bug or feature request.