基于AudioKit的iOS音频输入输出设备切换技术问询
实现iOS音频输入输出设备切换的完整方案
嘿,我来帮你搞定这个能同时录播的iOS应用的设备切换需求!结合你给出的代码片段,我整理了一套完整的实现方案,涵盖设备切换、音频会话配置、错误处理和设备状态监听。
核心思路
- 借助AudioKit的设备管理API完成输入/输出设备的切换
- 配置正确的音频会话类别,确保支持同时录制和播放的多路由场景
- 完善错误捕获逻辑,处理设备不可用、权限不足等异常情况
- 监听设备列表变化,实时更新UI避免无效操作
完整代码实现
首先创建一个单例的音频设备管理器,统一处理设备相关操作:
import AudioKit import AVFoundation class AudioDeviceManager { static let shared = AudioDeviceManager() private init() { // 初始化时配置音频会话 setupAudioSession() // 开始监听设备变化 startMonitoringDeviceChanges() } /// 配置音频会话,支持同时播放和录制,兼容蓝牙设备 private func setupAudioSession() { do { let session = AVAudioSession.sharedInstance() // 设置会话类别为playAndRecord,开启多路由支持 try session.setCategory( .playAndRecord, mode: .default, options: [ .allowBluetooth, .allowBluetoothA2DP, .mixWithOthers, .allowAirPlay ] ) try session.setActive(true) } catch { print("音频会话配置失败: \(error.localizedDescription)") } } /// 获取所有可用输入设备 func getAvailableInputDevices() -> [AudioDevice]? { return AudioKit.inputDevices } /// 获取所有可用输出设备 func getAvailableOutputDevices() -> [AudioDevice]? { return AudioKit.outputDevices } /// 切换到指定索引的输入设备 func switchToInputDevice(at index: Int) { guard let inputDevices = getAvailableInputDevices(), index >= 0, index < inputDevices.count else { print("⚠️ 无效的输入设备索引") return } do { let targetDevice = inputDevices[index] try AudioKit.setInputDevice(targetDevice) print("✅ 已切换输入设备到: \(targetDevice.name)") } catch { print("❌ 切换输入设备失败: \(error.localizedDescription)") } } /// 切换到指定索引的输出设备 func switchToOutputDevice(at index: Int) { guard let outputDevices = getAvailableOutputDevices(), index >= 0, index < outputDevices.count else { print("⚠️ 无效的输出设备索引") return } do { let targetDevice = outputDevices[index] try AudioKit.setOutputDevice(targetDevice) print("✅ 已切换输出设备到: \(targetDevice.name)") } catch { print("❌ 切换输出设备失败: \(error.localizedDescription)") } } /// 监听设备连接/断开事件 private func startMonitoringDeviceChanges() { NotificationCenter.default.addObserver( self, selector: #selector(handleDeviceListUpdate), name: .AudioKitDeviceListChanged, object: nil ) } @objc private func handleDeviceListUpdate() { print("🔄 音频设备列表已更新,请刷新UI") // 这里可以添加UI刷新逻辑,比如重新加载设备选择列表 } }
在UI中使用(以TableView为例)
比如你有两个TableView分别用来选择输入和输出设备,在didSelectRowAt中调用切换方法:
// 输入设备选择列表的点击事件 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { AudioDeviceManager.shared.switchToInputDevice(at: indexPath.row) tableView.deselectRow(at: indexPath, animated: true) } // 输出设备选择列表的点击事件 override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { AudioDeviceManager.shared.switchToOutputDevice(at: indexPath.row) tableView.deselectRow(at: indexPath, animated: true) }
关键注意事项
- 权限申请:必须在
Info.plist中添加NSMicrophoneUsageDescription键,填写麦克风使用说明,否则应用会因权限不足崩溃 - 设备兼容性:确保音频会话的options包含
.allowBluetooth和.allowBluetoothA2DP,这样才能识别并使用蓝牙耳机/音箱 - 错误处理:所有AudioKit的设备操作都要放在
do-catch块中,捕获设备不可用、音频会话未激活等异常 - 实时更新:通过
AudioKitDeviceListChanged通知监听设备变化,及时刷新UI,避免用户选择已断开的设备
内容的提问来源于stack exchange,提问作者Andrew Dubenkov
相关产品推荐
相关产品推荐

