Search code examples
iosavfoundationwatchkitavspeechsynthesizer

AVSpeechSynthesizer uses Apple Watch's speaker and not headset as output channel


I am using AVSpeechSynthesizer inside a WatchKit App Extension.

The logic is simple, and can be summarized as the following:

let utterance = AVSpeechUtterance(string: "Hello, World")
synth.speak(utterance)

This works fine but the speech always gets relayed via the Apple Watch's onboard speakers.
I require the speech to come through my airpods which are connected to my iPhone.

Previously I had delegated the task to the iPhone via WatchConnectivity which worked well but due to delays in WatchConnectivity communication, I moved the control logic directly onto the Apple Watch.
I thought watchOS would internally hand over the audio to the BLE device but it's not going as planned.

Maybe I am missing something?
Do I need to specify the audio channel synth.outputChannels?
Do I need to show the AirPlay popup asking user to select an audio output source?
If so how do I go about this?

I am unable to find much information on this matter online so any help would be greatly appreciated.

I am just trying to find a way to get the speech over my AirPods.


Solution

  • You can use the following code to display an audio device picker and direct audio to the selected device:

    let session = AVAudioSession.sharedInstance()
    do {
        try session.setCategory(AVAudioSession.Category.playback,
                                    mode: .default,
                                    policy: .longFormAudio,
                                    options: [])
        session.activate(options: []) { (success, error) in
                // Check for an error and play audio.
            if let err = error) {
                print(err)
            }
        }
    } catch {
        print(error)
    }