macos 14 pyvirtualcam适配经验

317 阅读4分钟
  • macos 14 pyvirtualcam适配经验
  • 2024.2.6
  • macos objc

由于macos14以后不再支持DAL插件加载方式,只支持CMIO方式加载camera插件,之前所有virtual camera开源DAL相关代码都失效了。

同时,OBS30已经增加了CMIO支持,我这边一个需求是想要在macos14中使用virtualcamera,也就有了这篇文章。


前置条件

pyvirtualcam的问题

pyvirtualcam在macos14上失效可以参考issue,这其中开源作者们的讨论让我快速了解了该问题,甚至有三年前的开发者提出了解决路线。除此以外,开源作者已经发布了help wanted希望有人来解决,看来他们内部暂时无人解决该问题。

寻找替代者

pyvirtualcam的替代者不多,akvirtualcamera是一个,这是mac中webcamoid的开源virtualcamera实现,但我在macos14上没有配置成功,咨询了开发者,开发者称没有测试过。

详情见 issue

尝试pyobjc

由于没有任何objc/c++开发经验,一开始尝试用python来解决macos下的问题:

pyobjc封装了几乎所有macos开发接口,作为objc和python的bridge,实现方法未知。

在macos中开发摄像头插件需要用到两个模块 pyobjc-framework-CoreMediaIO,正好都有封装。

但是pyobjc的上手难度与objc本身也无差别,毕竟共用一套API,学习成本太高让我放弃了该方案,不如直接拿objc写了。

apple objc/c++/swift

为了直接接触CMIO Camera Extenstion,只能上手objc/c++/swift这些apple开发语言。

调研开源项目:

查看官方文档:

开发难度不小。


OBS是捷径

由于camera插件需要开发相应app,并且apple开发者认证(有但是无开发经验),本身写一个插件的难度过大,OBS30已经支持了CMIO,pyvirtualcam支持到OBS28,那只要让pyvirtualcam支持OBS30,不就可以向obs virtual camera推流了?

早期OBS中virtual camera的实现是基于第三方插件,现在已经合并到了OBS官方库,但还是以插件的形式,核心代码位于: plugin-main.mm

使用chatgpt阅读该代码,并于pyvirtualcam引入的old version(967bce5e155e182ba6686a5781f3e88a85217c77 (28.0.2))逐行对比,发现最大的不同是在原来的DAL插件基础上支持了一套新的CMIO插件。

于是我花了2-3天将该CMIO代码移植到了pyvirtualcam源代码中,对应virtual_output.h


开发过程和问题

OBS官方代码是objc,而pyvirtualcam是基于C++的,此前是通过调用单独的DAL插件代码(.mm)植入到C++中,而现在必须将objc的CMIO代码改成C++

  • import问题,objc与C++的import不同,在setup.py编译选项中也要指明引用的mac库
  • 类定义不同,我尝试将objc的类引入到C++中使用,遇到了诸多麻烦
  • OBS代码中引入了大量OBS基础库,而这部分库我不想带进来(包括log等)
  • 我没有使用xcode或者clion开发,而是pycharm,每次修改代码都需要重新build python库,然后用test code测试
  • 使用最简单的打印方式std::out进行debug

一个重大问题:

获取camera UID的代码获取了空值0x0,这使得python测试代码崩溃并且不报错,我只能用二分查找的方式定位问题:

NSString *OBSVirtualCamUUID = [[NSBundle bundleWithIdentifier:@"com.obsproject.mac-virtualcam"]
            objectForInfoDictionaryKey:@"OBSCameraDeviceUUID"];

为了解决该问题,我手动获取系统中obs virtual camera的UID顺序并且写死在代码里:

if (i == 1) {
            deviceID = cmioDevice;
            CFRelease(uid);
            break;

同时我尝试用objc的代码写该函数获取UUID,然后传给.h头文件调用,没有成功。

总结

为了快速开发,我删除了DAL所有代码,删除了OBS源代码大量关于异常的判断,这使得代码停留在dev version,没有任何适配。

当然我的问题已经解决了,后续就丢给pyvirtualcam官方开发者去完善和测试了。

我的repo

提出的PR

本文由mdnice多平台发布