macOS下如何识别属于同一硬件的音视频AVCaptureDevice?
AVCaptureDevice本身没有直接提供获取厂商序列号的API,但可以通过其底层关联的硬件信息,结合CoreMediaIO或IOKit框架,将音视频设备与对应的USB设备绑定,进而拿到序列号等唯一标识。以下是具体实现思路:
1. 从AVCaptureDevice提取关键标识
首先,获取目标AVCaptureDevice的两个核心属性:
uniqueID:设备的全局唯一字符串标识,用于后续关联底层硬件transportType:确认设备是USB类型(判断值为.usb)
示例Swift代码:
import AVFoundation func getDeviceIdentifiers(_ device: AVCaptureDevice) -> (uniqueID: String, isUSB: Bool) { return (device.uniqueID, device.transportType == .usb) }
2. 用CoreMediaIO获取USB设备关联ID
CoreMediaIO框架提供了访问媒体设备底层硬件信息的接口,可以通过AVCaptureDevice的uniqueID找到对应的CMIO设备对象,再提取USB设备的传输ID(对应IOKit中的设备路径):
示例代码片段(Swift):
import CoreMediaIO func getUSBTransportID(for deviceUniqueID: String) -> String? { guard let cmioDevice = CMIOObjectGetDeviceWithUniqueID(deviceUniqueID as CFString) else { return nil } var propertyAddress = CMIOObjectPropertyAddress( mSelector: kCMIODevicePropertyTransportDeviceID, mScope: kCMIOObjectPropertyScopeGlobal, mElement: kCMIOObjectPropertyElementMain ) var transportID: CFString? var dataSize = CFIndex(MemoryLayout<CFString?>.size) let status = CMIOObjectGetPropertyData( cmioDevice, &propertyAddress, 0, nil, &dataSize, &transportID ) return status == 0 ? transportID as String? : nil }
这个transportID对应USB设备在IOKit中的路径标识,可用于下一步匹配。
3. 通过IOKit枚举USB设备并匹配序列号
使用IOKit框架枚举所有USB设备,提取每个设备的序列号、vendor ID、product ID等信息,再通过CoreMediaIO拿到的transportID进行匹配:
示例代码片段(Swift):
import IOKit.usb func getUSBSerialNumber(for transportID: String) -> String? { let matchingDict = IOServiceMatching(kIOUSBDeviceClassName) as NSMutableDictionary matchingDict[kUSBLocationIDKey] = transportID var iterator: io_iterator_t = 0 guard IOServiceGetMatchingServices(kIOMainPortDefault, matchingDict, &iterator) == KERN_SUCCESS else { return nil } defer { IOObjectRelease(iterator) } var usbDevice: io_service_t = 0 while usbDevice = IOIteratorNext(iterator), usbDevice != 0 { defer { IOObjectRelease(usbDevice) } if let serialNumber = IORegistryEntryCreateCFProperty( usbDevice, kUSBSerialNumberString as CFString, kCFAllocatorDefault, 0 )?.takeRetainedValue() as? String { return serialNumber } } return nil }
4. 整合流程实现音视频设备配对
将上述步骤整合:当用户选择视频设备时,先获取其uniqueID和transportID,再通过transportID找到对应的USB序列号;随后遍历所有音频输入设备,用同样的方法获取它们的USB序列号,匹配相同序列号的音频设备即可。
替代方案:解析system_profiler输出
如果不想依赖底层框架,也可以执行system_profiler SPUSBDataType -xml命令,解析XML输出中的USB设备信息(包括序列号、设备名称、位置ID),再将其与AVCaptureDevice的modelID或uniqueID做关联。不过这种方法依赖系统输出格式,稳定性不如原生API。
内容的提问来源于stack exchange,提问作者sv_lane

