AVAudioEngine macOS Sonoma下USB设备音频直通报CoreAudio错误-10875
问题描述
我是开发新手,在macOS Sonoma系统上尝试实现Elgato HD60 X的音频直通功能,编写了如下Swift代码:
import Foundation import AVFoundation private var audioEngine = AVAudioEngine() var inputNode = audioEngine.inputNode var outputNode = audioEngine.outputNode class UVCAudio { init() { startAudio() } func startAudio() { //_ = AudioEnumerable() //print(AudioDevice(deviceID: 72).name) var inputDeviceID: AudioDeviceID = 72 let sizeOfAudioDevId = UInt32(MemoryLayout<AudioDeviceID>.size) var audioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 48000, channels: 2, interleaved: false) let error = AudioUnitSetProperty(audioEngine.inputNode.audioUnit!, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDeviceID, sizeOfAudioDevId) if error > 0 { print("Error setting input device: \(error)") } let format = inputNode.inputFormat(forBus: 0) if format.sampleRate != 0 { audioEngine.connect(inputNode, to: audioEngine.mainMixerNode, format: nil) audioEngine.connect(audioEngine.mainMixerNode, to: audioEngine.outputNode, format: nil) do { try audioEngine.start() } catch { print("Error: \(error.localizedDescription)") } } else { print("Error audio type mismatch") } } }
调用audioEngine.start()时触发错误,AudioUnitSetProperty无报错。注释该代码后在系统设置切换输入设备可正常工作;将AudioDeviceID改为麦克风设备ID也能正常运行,已授予麦克风访问权限。疑惑:AVAudioEngine是否仅支持麦克风?还是初始化方式有误?
错误输出:
AVAEInternal.h:88 required condition is false: [AVAudioEngineGraph.mm:1357:Initialize: (IsFormatSampleRateAndChannelCountValid(outputHWFormat))] Error: The operation couldn’t be completed. (com.apple.coreaudio.avfaudio error -10875.)
解决思路与修正方案
AVAudioEngine并非只支持麦克风,问题出在设备属性设置错误和格式不兼容上,以下是具体修正:
核心问题分析
- 错误使用
kAudioOutputUnitProperty_CurrentDevice设置输入设备:这个属性是给输出音频单元用的,输入设备应该用kAudioInputUnitProperty_CurrentDevice,属性不匹配导致引擎内部格式校验失败。 - 未明确指定设备兼容格式:直接用
nil连接节点,AVAudioEngine自动匹配格式时可能和Elgato设备的原生格式冲突。 - 全局变量污染引擎状态:把
audioEngine设为全局变量,容易导致状态混乱。
修正后的代码
import Foundation import AVFoundation class UVCAudio { private let audioEngine = AVAudioEngine() init() { startAudio() } func startAudio() { let targetDeviceID: AudioDeviceID = 72 // 替换为你的Elgato设备ID var inputDeviceID = targetDeviceID let propertySize = UInt32(MemoryLayout<AudioDeviceID>.size) // 获取输入节点的AudioUnit,设置正确的输入设备属性 let inputUnit = audioEngine.inputNode.audioUnit! let error = AudioUnitSetProperty(inputUnit, kAudioInputUnitProperty_CurrentDevice, // 改用输入设备专属属性 kAudioUnitScope_Global, 0, &inputDeviceID, propertySize) guard error == noErr else { print("设置输入设备失败: \(error)") return } // 获取输入设备的原生格式 let inputFormat = audioEngine.inputNode.inputFormat(forBus: 0) guard inputFormat.sampleRate != 0 else { print("音频格式不匹配") return } do { // 明确用输入设备格式连接节点,AVAudioEngine会自动处理格式转换 audioEngine.connect(audioEngine.inputNode, to: audioEngine.outputNode, format: inputFormat) try audioEngine.start() print("音频引擎启动成功") } catch { print("启动失败: \(error.localizedDescription)") } } }
关键修正点
- 替换属性常量:把
kAudioOutputUnitProperty_CurrentDevice改为kAudioInputUnitProperty_CurrentDevice,这是解决错误的核心。 - 明确格式连接:使用输入设备的原生格式连接节点,避免自动匹配时的格式冲突。
- 封装引擎实例:将
audioEngine设为类内部私有属性,避免全局状态干扰。 - 错误码说明:
-10875对应kAudioUnitErr_FormatNotSupported,本质就是格式不兼容,修正属性设置后即可解决。
内容的提问来源于stack exchange,提问作者Rybo
相关产品推荐
相关产品推荐

