最近在给MBWebPhone增加音视频设备配置功能界面时,发现在浏览器中正常但NWJS封装的APP中异常的bug——呼叫正常,但设备枚举为空白。
一开始以为是nwjs的bug,但翻遍他们的社区,报告同样问题的解决方案是给出了–use-fake-ui-for-media-stream
方式启动,这样能正常显示出设备列表了,但视频通话打开摄像头、桌面共享全部报错。
正常的:
异常的:
仔细看这段代码并没有特殊:
1 | navigator.mediaDevices?.enumerateDevices() |
但打印出来就是 :
1 | audioinput: (ID: ) |
又去翻google的社区,大部分回复都是localhost或http://权限限制,不可能获取设备等等说法,但这个时候webrtc通话是正常的,即:
1 | navigator.mediaDevices.getUserMedia({ |
功能完全正常。
就在快放弃时,使用chrome浏览器打开了nwjs封装的设备配置页面http://localhost:3000 ,发现问题不对了,同样是http://localhost:4444 上的页面功能完全正常。
而3000端口是由nwjs中的nodejs启动的一个内置miniweb服务器,只使用了最小参数启动。
理论上,同样的页面源码,浏览器行为不同,差距就在两个web服务器的返回标头上了:
先看正常的:
再看nodejs的http server返回的:
我们一行一行的把缺的标头加上看。
却发现还是太天真了。。。并没有用。
只有http://localhost:4444 端口能正常枚举设备,又继续翻资料,发现还应该是设备权限问题,突然发现浏览器地址栏上:
这个地址上有麦克风,摄像头权限。
而3000端口的地址栏上:
答案呼之欲出,chrome没有识别到webrtc权限请求,而权限请求只有getusermedia时才会弹出申请,enumerateDevices枚举设备时并不出现。
加上这段代码:
1 | navigator.mediaDevices.getUserMedia({audio:true, video:true}) |
顺利出现权限弹窗,允许,设备列表终于顺利出现。