You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:42:45