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
相关产品推荐
相关产品推荐

