因公司业务发展需要,需要将原来的ocx控件切换成webrtc video控件来播放小区端的摄像头音视频。因为webrtc官方不是针对于当前的应用场景,只适用浏览器与浏览器之间、或者与app之间,所以有对当前场景作一些针对性的修改。
以media server作为中介,沟通device和浏览器。将media server当成p2p的p,实现p2p通信。也算是业界对webrtc的一个创新应用。
这篇文章主要是对当前工作的总结。主要难点有:
a、stun协议在media server上的实现,将media servers模拟成p2p的p;
b、公司内部网关对>=1464字节的报文追加了6字节vss-monitor尾部数据,填充为00.
c、相应sdp报文在浏览器、和摄像头之间的交互协商;
d、webrtc使用sdes模式,协商key,作为srtp加密的密钥。
e、chrome的webrtc未开源,只能通过开启日志模式,记录全程日志,和查看相类似的chrome开源代码来查看相似逻辑,因为webrtc小版本间代码修改很小,所以基本可以参考。且日志文件可能有1个g,对debug技术有点要求。
一、Webrtc可视对讲整体集成流程:
a. 原来由ocx发startvideo、stopvideo、heartbeat三个请求,因为去除了ocx,所以由前端完成;
b. 将所有object标签替换成video标签。
三、前端webrtc启动流程:
四、相关坑点总结:
1、remote sdp中的fmtp字段,需要与rtp包中的payload type对应,如推给client的h264的payload type是96,则setRemoteDescription时,传入的sdp,对应h264的fmtp值也应该为96。
2、海康可视对讲发出的音视频ssrc是相同的,这将导致webrtc将音频视频一起解析,将导致rtp index索引重复的问题。要在server端将ssrc设置成不同即可。
3、stun协议,需要server push给client相应的唤醒包,相当于心跳;需要发USERNAME、PRIORITY、MESSAGE-INTEGRITY、FINGERPRINT。
a、其中username是固定的,server固定写死为:LzAA,client固定为LzAB。
b、PRIORITY固定值为1853824767,取自chrome发出的stun request。
c、MESSAGE-INTEGRITY,取固定密钥,前后端同时写死,相关参考:
经对turn和p2p的场景分别抓包分析,long-term在turn中转服务器方案才会使用及出现,需要相应bind-fail,重新交互等流程,也需要realm等参数,而realm是域名,一般只在turn服务器中出现。故推测p2p方案适用于short-term方案。 SASLprep算法的作用,是析取适用于username、password命名规则的字符,会将特殊字符去除,因为media server未实现算法,故建议password为字母数字组合。
d、FINGERPRINT,循环冗余校验字段直接调用stunlib-master里参考的代码生成。
4、stun协议,server需要实现与client对应的stun response包;需要包含MESSAGE-INTEGRITY、FINGERPRINT,不然chrome webrtc将当作非法stun response处理,ice连通性检测失败,直接抛弃音视频流。
5、以太网包大小超过1464字节时,公司网关将追加6字节padding字段,字段名为:VSS-Monitoring ethernet trailer,如图:
6、stun协议,client需要指定server与client的ice-ufrag密钥,用于计算message签名; 及指定client与server固定硬编码的用户名; 及srtp的密钥也硬编码成固定密钥,media server与client使用同一密钥加解密音视频流(存在安全风险,可由websocket push给密户端密钥,每次会议都不一致,后期可优化)。
7、stun协议bind request间隔建议50ms,这样client能保持在当前会话失效前,又能收到bind request,从而继续保活当前的流媒体会话。
8、需修改remote sdp为”a=rtpmap:8 PCMA/8000\n”,这样将支持g.711a解码,同时对rtp payload type为8的当作g.711a处理。
9、前端需要调用this.pc.addStream(this.localStream),这样才能将本地音频或视频push给media server。 this.localStream为本地流,this.pc为RTCPeerConnection对象,因为没有使用stun(ice外网ip辅助服务器)、turn(中转服务器),iceServers可传[]。
10、因webrtc需要Https环境,不能与media server直接交互,故改变了原来直连视频组件的接口,由nginx路由转发到视频组件,再由视频组件管理视频预览的生命周期。
11.前端可由candidate监听中,得到当前的ip地址。如图所示:
在” typ host”之前的数字即是ip和端口,可截取” typ host”前面的字符串,再根据空格拆分成数组,得到最后面的两个值,即为ip和port。
12.如只需接收远程的视频或音频,去除sdp的video或audio描述时,
13.海康摄像头发的是ps流,需将ps转成h264,再封成rtp包,再转成srtp,发送给client。这里server端rtp封包时,分包的h264各片time没有保持一致,而是累增,导致重新组合成h264帧时,webrtc解析失败。先报vda:error 3,unreadable_input,不能读取输入流。再尝试软解码,调用ffmpeg的decode方法里失败了。故推断为输入流有问题。
五、调试总结:
1、chrome端开启日志输出到本地目录:
a、export CHROME_LOG_FILE=~/Documents/chrome_debug.log
b、open /Applications/Google\ Chrome.app --args --enable-logging --v=4 --vmodule=/webrtc/=1
2、可用lua肢本将本地的抓包文件解析成h264,目前在windows调试成功。
3、不要开socks的全局模式,因为是在内网调试。
4、和当前mac chrome版本72.0.3626.119,对应的chrome代码,可由此查看webrtc的相关逻辑,注意开ss的全局模式才能打开: cs.chromium.org/chromium/sr…