背景
window软件在适配linux uos 国产操作系统时。遇到一个问题,我们软件有个功能是使用ffmpeg打开摄像头。适配时遇到了问题,一直报错。如下图:
排查过程
wine容器
- USB权限 ?
- dshow相关库 ?
- dx相关库?
USB权限
我通过管理员运行程序和添加脚本放开USB权限,都试过不行。所以排除掉了USB权限问题。
原因如下:因为在放开后我使用容器内程序(wpf)都可以打开摄像头并且可以预览,所有排除了容器不能访问usb权限的问题
dshow相关库
在wine容器内安装了directshow
库也不行,另外我使用在容器内使用ffmpeg命令行:ffmpeg.exe -f dshow - list_devices true -i dummy
列出dshow支持的设备也是可以的,如下图:
另外我还尝试了,在容器内安装dshow调试工具GraphStudioNext
,查看dshow设备列表,都是能查看的。证明至少dshow环境是没问题的
dx相关库
在wine容器内安装了directx9
库,运行也是如此,另外还安装了一推d3dXXX.dll
。也不行排除掉这个原因
我把自己能想到的都排查了遍。未果,我反思过是不是哪些细节漏掉了…
发现问题所在
当我迷失排查方向,后在各种群里,互联网搜索了解相关情况。没有任何有用的消息。自己又尝试了使用容器内ffmpeg的各方方法。
在wine容器内得出如下结论:
- 使用ffmpeg采集麦克风声音是对的
- 使用ffpaly播放网络流视频是对的
- 使用ffmpeg视频编解码是对的
- 使用ffmpeg gdi 录制屏幕是对的
有了上面这些结论,我一直在想为什么唯独摄像头不行?
我又尝试怀疑,是不是摄像头名称ffmpeg 找不到?
这样怀疑的原因是因为我清楚的记得我笔记本的摄像头名是HD Camera
而容器内我使用ffmpeg列举的摄像头时,我摄像头名称竟然变成了:HD Camera: HD Camera
然后我又是一顿所搜ffmpeg能不能在window环境下面使用索引打开摄像头,而不用设置名称。这个研究未果!
甚至我在上周五下班的时候,我还跟一个同事调侃说会不会是摄像头名称有问题,容器内ffmpeg找不到?
回到家里我还是死磕搜索:ffmpeg Malformed dshow input string.
在使用科学上网后,我在google看到了一片文章,如下图:
这不是我遇到的问题吗?只不过我是摄像头名称带冒号,而人家是音频设备带冒号。
为了排查是不是摄像头带冒号导致的,我在wine容器内安装了屏幕驱动Video Capture Sources
然后在容器内使用ffmpeg命令行ffmpeg -f dshwo -video="Video Capture Sources" out.mpt
使用dshow打开video屏幕录制。发现可行。
到这里,基本可以确定,在wine容器内ffmpeg打开摄像头,由于摄像头名称冒号导致了报错:“Malformed dshow input string. video=xxxxx: xxxx: I/O error” !!!!
为了坐实这个结果,我和同事查看了ffmpeg源码。发现ffmpeg源码确实使用了:
进行处理。如果你输入的设备带了冒号,会导致ffmpeg把摄像头名称和麦克风名称同时设置为null。从而触发错误:Malformed dshow input string. video=xxxxx: xxxx: I/O error
解决方案
上述研究得出一个结果
在wine容器内ffmpeg打开摄像头,由于摄像头名称冒号导致了报错:“Malformed dshow input string. video=xxxxx: xxxx: I/O error” !!!!
有了这个结果后,那ffmpeg怎么使用带冒号的设备呢?解决办法就是绕过输入带名称的摄像。
办法一:
使用设备替代名称,如下图:
使用"c:/Program Files/YNsoft/YNMicroLecturer/MicroLecturer/x64/ffmpeg.exe" -f dshow -list_devices true -i dummy
列出设备,并找到这个设备替代名称,如下图:
有了上面这个名称,就可以使用替代名称打开这个摄像头了。
示例如下:
"c:/Program Files/YNsoft/YNMicroLecturer/MicroLecturer/x64/ffmpeg.exe" -f dshow -i video="@device_cm_{860BB310-5D01-11D0-BD3B-00A0C911CE86}\video0" -c:v libx264 -max_delay 10000 -b:v 1000k -bufsize 200k -r 10 out234.mp4 -y
运行结果:
方案二
修改linux摄像头/麦克风名称
理论可行,实际没验证。