- 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开发语言。
调研开源项目:
- OffcutsCam 基于官方文档CMIO开发一个简单camera app
- CameraEX 一个日本开发者基于CMIO开发的virtual camera插件,有详细的doc
- [UniCamEx](github.com/creativeIKE… camera app
查看官方文档:
开发难度不小。
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多平台发布