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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:37:53