因工作需要,需要将原来的ocx控件切换成webrtc控件来播放,小区端的摄像头音视频。因为webrtc官方不是针对于当前的应用场景,所以有对当前场景作一些针对性的修改。以media server作为中介,沟通device和浏览器。将media server当成p2p的p,实现p2p通信。也算是业界上的一个创新。
这篇文章主要是对当前工作的总结。
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时,传入的sdk,对应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,取固定密钥”xxxxxx”,前后端同时写死,相关参考:

因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字段,如图:这将导致srtp签名校验失败,不能播放视频流。 可以将server端的以太网mtu设置成更小值,这样不会触发网关加6字节padding。

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可传[]。

其中DtlsSrtpKeyAgreement需要为false,强制启动sdes加密,不采用默认dtls协议srtp密钥机制,因为dtls需要配置公私钥环境,协调出流媒体加密的密钥,这将更复杂,且没有必要。
10、因webrtc需要Https环境,不能与media server直接交互,故改变了原来直连视频组件的接口,由nginx路由转发到视频组件,再由视频组件管理视频预览的生命周期。
11.前端可由candidate监听中,得到当前的ip地址。如图所示:

12.如只需接收远程的视频或音频,去除sdp的video或audio描述时,
如要去除m=audio 9 RTP/SAVPF 8,及后面所有描述信息,直到出现m=video为止,此时”a=group:BUNDLE 0 1\n”,应该改成”a=group:BUNDLE 0\n”。
五、调试总结:
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、将本地的抓包文件解析成h264,lua脚本可百度,目前在windows调试成功。
3、不要开socks的全局模式,因为是在内网调试。
4、和当前mac chrome版本72.0.3626.119,对应的chrome代码,可由此查看webrtc的相关逻辑,注意开ss的全局模式才能打开: cs.chromium.org/chromium/sr…