如何用AVAudioEngine实现手机麦克风输入、AirPods/耳机输出?
解决AVAudioEngine内置麦克风音频无法输出到AirPods的问题
我来帮你排查这个问题——你已经能通过AirPods麦克风实现输入输出,但切换到iPhone内置麦后没声音到AirPods,核心问题大概率出在音频会话的路由配置上,下面是具体的排查和修复步骤:
1. 完善音频会话配置,强制指定蓝牙输出
当你把首选输入切换到iPhone内置麦克风时,系统默认会把输出路由切回手机扬声器/听筒,所以需要手动指定输出到AirPods。同时要确保会话配置的选项足够,并且正确激活:
let audioSession = AVAudioSession.sharedInstance() do { // 配置playAndRecord类别,允许蓝牙设备(适配AirPods的HFP语音通话模式) try audioSession.setCategory(.playAndRecord, options: [.allowBluetooth, .mixWithOthers]) try audioSession.setMode(.voiceChat) // 设置首选输入为iPhone内置麦克风 if let builtInMic = audioSession.availableInputs?.first(where: { $0.portType == .builtInMic }) { try audioSession.setPreferredInput(builtInMic) } // 手动指定输出路由到已连接的蓝牙设备(AirPods) if let bluetoothOutput = audioSession.availableOutputs?.first(where: { $0.portType == .bluetoothHFP || $0.portType == .bluetoothA2DP }) { try audioSession.setPreferredOutput(bluetoothOutput) } // 必须激活会话才能让配置生效 try audioSession.activate() } catch { print("音频会话配置失败:\(error.localizedDescription)") }
2. 检查AudioEngine的启动与连接逻辑
确保你的AudioEngine连接正确,并且启动时没有抛出错误:
// 确认节点连接逻辑(你的现有代码没问题,但要确保启动前连接完成) self.audioEngine.connect(self.audioEngine.inputNode, to: drc, format: self.audioEngine.inputNode.outputFormat(forBus: Config.bus)) self.audioEngine.connect(drc, to: self.audioEngine.mainMixerNode, format: self.audioEngine.outputNode.outputFormat(forBus: Config.bus)) // 启动引擎并捕获错误 do { try self.audioEngine.start() } catch { print("AudioEngine启动失败:\(error.localizedDescription)") }
3. 处理路由变化的情况
如果AirPods是在你的App启动后才连接的,需要监听路由变化通知,自动切换输出到蓝牙设备:
// 在初始化方法中添加监听 NotificationCenter.default.addObserver( self, selector: #selector(audioRouteChanged(_:)), name: AVAudioSession.routeChangeNotification, object: nil ) // 路由变化处理方法 @objc private func audioRouteChanged(_ notification: Notification) { guard let userInfo = notification.userInfo, let reasonRawValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt, let reason = AVAudioSession.RouteChangeReason(rawValue: reasonRawValue) else { return } // 当有新设备连接时,重新设置蓝牙输出 if reason == .newDeviceAvailable { let session = AVAudioSession.sharedInstance() if let bluetoothOutput = session.availableOutputs?.first(where: { $0.portType == .bluetoothHFP || $0.portType == .bluetoothA2DP }) { try? session.setPreferredOutput(bluetoothOutput) } } }
关键说明
- 你提到已经能在Tap中拿到音频数据,说明输入链路是正常的,问题完全出在输出路由没有指向AirPods。
.voiceChat模式适配AirPods的语音通话协议(HFP),如果需要更高音质的媒体输出,可以尝试把模式改成.default,并把会话选项换成.allowBluetoothA2DP。
内容的提问来源于stack exchange,提问作者tallen11
相关产品推荐
相关产品推荐

