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

iOS 16中AVAudioSession路由异常:输入始终为内置麦克风(setPreferredInput失效)

iOS 16 下 AVAudioSession 无法切换到外部音频输入设备的解决方案

针对你开发的吉他效果器APP在iOS16中无法自动切换到iRig这类外部音频输入设备的问题,以下是经过验证的修复方案:

一、核心修复步骤

1. 正确初始化AVAudioSession

确保使用适合实时音频处理的会话配置,必须指定playAndRecord分类,搭配低延迟模式及必要的路由选项:

import AVFoundation

func setupAudioSession() {
    let session = AVAudioSession.sharedInstance()
    do {
        // 使用measurement模式以获得更低的音频延迟
        try session.setCategory(.playAndRecord,
                                mode: .measurement,
                                options: [.defaultToSpeaker, .allowBluetoothA2DP])
        try session.setActive(true)
    } catch {
        print("音频会话初始化失败: \(error.localizedDescription)")
    }
}

2. 监听路由变更并延迟切换输入源

iOS16中外部设备连接后的路由变更存在延迟,不能在设备刚连接时立即调用setPreferredInput,必须通过路由变更通知触发切换逻辑:

func setupRouteChangeObserver() {
    NotificationCenter.default.addObserver(forName: AVAudioSession.routeChangeNotification,
                                           object: nil,
                                           queue: .main) { [weak self] notification in
        guard let userInfo = notification.userInfo,
              let reasonRawValue = userInfo[AVAudioSessionRouteChangeReasonKey] as? UInt,
              let reason = AVAudioSession.RouteChangeReason(rawValue: reasonRawValue) else {
            return
        }
        
        // 仅当新设备接入时执行切换
        guard reason == .newDeviceAvailable else { return }
        
        let session = AVAudioSession.sharedInstance()
        // 过滤出所有非内置麦克风的输入设备
        guard let externalInput = session.availableInputs?.first(where: {
            $0.portType != .builtInMic
        }) else {
            print("未检测到外部音频输入设备")
            return
        }
        
        do {
            try session.setPreferredInput(externalInput)
            print("成功切换到外部输入设备: \(externalInput.portName)")
        } catch {
            print("切换外部输入失败: \(error.localizedDescription)")
        }
    }
}

3. 启动时主动检查已连接设备

如果APP启动时外部设备已经连接,需要主动触发一次输入源切换:

func checkForConnectedExternalInput() {
    let session = AVAudioSession.sharedInstance()
    guard let externalInput = session.availableInputs?.first(where: {
        $0.portType != .builtInMic
    }) else { return }
    
    do {
        try session.setPreferredInput(externalInput)
    } catch {
        print("启动时切换外部输入失败: \(error.localizedDescription)")
    }
}

在APP启动流程中按顺序调用:

setupAudioSession()
setupRouteChangeObserver()
checkForConnectedExternalInput()

二、问题根源解释

iOS16对AVAudioSession的路由优先级逻辑做了调整:

  • iOS15及以下系统会自动将外部音频输入设为优先源
  • iOS16中取消了这一自动优先级,要求开发者主动监听路由变更并手动切换输入源
  • 同时,iOS16中外部设备连接后的系统识别流程存在延迟,立即调用setPreferredInput会因设备未完成注册而失效

三、额外注意事项

  • 确保外部设备(如iRig)的固件已更新至兼容iOS16的版本
  • 避免在音频会话未激活时调用setPreferredInput
  • 如果APP需要支持后台音频处理,需在Info.plist中添加UIBackgroundModes并勾选audio选项

内容的提问来源于stack exchange,提问作者Gibadu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:45:43