Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Playing audio live from Bluetooth headset on iPhone speaker

Hi guys,

I am having issue in live-streaming audio from Bluetooth headset and playing it live on the iPhone speaker.

I am able to redirect audio back to the headset but this is not what I want.

The issue happens when I am trying to override output - the iPhone switches to speaker but also switches a microphone.

This is example of the code:

import AVFoundation

class AudioRecorder {
    let player:  AVAudioPlayerNode
    let engine:AVAudioEngine
    let audioSession:AVAudioSession
    let audioSessionOutput:AVAudioSession
    
    init() {
        self.player = AVAudioPlayerNode()
        self.engine = AVAudioEngine()
        self.audioSession = AVAudioSession.sharedInstance()
        self.audioSessionOutput = AVAudioSession()
        do {
            try self.audioSession.setCategory(AVAudioSession.Category.playAndRecord, options: [.defaultToSpeaker])
            try self.audioSessionOutput.setCategory(AVAudioSession.Category.playAndRecord, options: [.allowBluetooth]) // enables Bluetooth HFP profile
            try self.audioSession.setMode(AVAudioSession.Mode.default)
            try self.audioSession.setActive(true)
            // try self.audioSession.overrideOutputAudioPort(.speaker) // doens't work
        } catch {
            print(error)
        }
        
        let input = self.engine.inputNode
        self.engine.attach(self.player)
        let bus = 0
        let inputFormat = input.inputFormat(forBus: bus)
        self.engine.connect(self.player, to: engine.mainMixerNode, format: inputFormat)
        input.installTap(onBus: bus, bufferSize: 512, format: inputFormat) { (buffer, time) -> Void in
            self.player.scheduleBuffer(buffer)
           print(buffer)
        }
    }
    
    public func start() {
        try! self.engine.start()
        self.player.play()
    }
    
    public func stop() {
        self.player.stop()
        self.engine.stop()
        
    }
}

I am not sure if this is a bug or not.

Can somebody point me into the right direction? I there a way to design a custom audio routing?

I would also appreciate some good documentation besides AVFoundation docs.

Playing audio live from Bluetooth headset on iPhone speaker
 
 
Q