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

macOS下如何识别属于同一硬件的音视频AVCaptureDevice?

解决方案:关联AVCaptureDevice与USB设备获取唯一标识

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:35:55