基于开源WebRTC开发实时音视频靠谱吗
WebRTC是一个支持网页浏览器进行实时语音对话或视频对话的技术,在行业内得到了广泛的支持和应用,成为下一代视频通话的标准,所以来说还是靠谱的。
话说回来,虽然作为实时音视频领域最火的开源技术,WebRTC 点对点的架构模式却无法支持大规模并发,怎么解决呢?即构自研WebRTC网关服务器架构实践就很好解决了这个问题。
Zego-Gateway架构的改进
在加入WebRTC网关之前,即构自研系统架构如下图所示,主要分成两部分,左边是低延时用户,而右边是围观用户。低延时用户主要是通过ZEGO的实时传输网络进行推拉流。
由于RTMP的实时性并不是很好,在浏览器端没有办法通过RTMP进行上行传输达到低延时的特点,所以即构对原有的系统架构进行了升级,在低延时的实时传输网络中加入了WebRTC网关服务器,具体如下图所示。
在加入了WebRTC网关服务器后(图中红线部分所示),即构的系统已经能全面支持网页端视频互动场景,同时实现了APP、微信小程序、WebRTC三端的连麦互通。
浏览器本身不支持点对点建立信道进行通信,需通过服务器进行中转。因此浏览器之间一次通信需通过两段信道,通信效率同时受制于两段信道宽度,因此并不适合数据流的传输。
WebRTC是浏览器实时通信 RTC 的提供 JS 接口, JS 接口通过信令建立浏览器点对点(peer-to-peer,P2P)的信道,信道可发送任何数据并无需经过服务器。
WebRTC提供三个API
WebRTC使用 RTCPeerConnection 在浏览器之间传递流数据,此流数据通道是P2P的,无需服务器中转。但并不意味着能抛弃服务器,仍需服务器为传递信令(signaling)来建立信道。WebRTC没有定义用于建立信道的信令协议,信令并不是 RTCPeerConnection API 的一部分。
既然没有定义信令(signaling)的协议,可选择任意方式(如AJAX、WebSocket)任意协议(如SIP、XMPP)来传递信令,建立信道。
需要信令来交换信息分为:
通过服务器建立信道
WebRTC提供浏览器之间P2P信道进行数据传输,但建立这个信道必须有服务器的参与。
WebRTC需服务器提供:
NAT/防火墙穿越技术
在处于使用NAT设备的私有TCP/IP网络中的主机之间建立连接时需使用NAT穿越。NAT的行为是非标准化的,穿越技术大多使用公共服务器,使全球任何地方都能访问得到IP地址,在 RTCPeerConnection 中实用ICE框架来保证 RTCPeerConnection 实现NAT穿越。
ICE
ICE(Interactive Connectivity Establishment, 综合性NAT穿越技术)框架整合各种NAT穿越技术如STUN、TURN(Traversal Using Relay NAT,中继NAT实现的穿透),ICE先使用STUN尝试建立一个基于UDP的连接,失败后实用TCP(先尝试HTTP然后尝试HTTPS),若依然失败,ICE就会使用中继的TURN服务器。
RTCDataChannel
既然能建立P2P信道来传递实时音视频数据流,为什么不能使用此信道传递其他数据呢? RTCDataChannel API 可实现浏览器之间传递任意数据。 DataChannel 是建立在 PeerConnection 之上的,不能单独使用。
WebRTC原理
WebRTC的实现是建立浏览器之间的直接连接而无需服务器中转,即P2P。因此要求彼此知道对方外网地址,而计算机大多位于NAT之后,少数主机拥有外网地址。这就要求一种方式可穿透NAT技术(STUN、TRUN)。
WebRTC实用默认STUN服务器获取当前主机的外网地址和端口,Chrome默认的是Google域名下的一个STUN,国内不大稳定。
P2P建立过程需依赖服务端中转(信令服务器),需实用双工通讯方式的WebSocket来实现信令的中转。
浏览器A创建一个 RTCPeerConnection 对象, RTCPeerConnection 自动向STUN服务器获取自己的外网IP与端口,然后将自己的网络信息经过信令服务器中转后发送给浏览器B。
浏览器B接收到A的网络信息后创建一个 RTCPeerConnection 对象,将接收的信息通过 addIceCandidate 添加到对象中。
浏览器A通过 RTCPeerConnection 对象的 createOffer() 获取本地音视频编码分辨率等信息,通过 setLocalDescription 添加到 RTCPeerConnection 中,并将这些信息经过信令服务器中转后发送给浏览器B。浏览器B接收到浏览器A发送过来的信息后,使用 RTCPeerConnection 对象的 setRomoteDescription() 保存。
项目中需要做远程控制,可以传输指令和音频,领导说用前端做,整合到h5中,于是研究了一下webRTC,基本能解决需求就把项目简化写了一个demo分享出来
核心就是两端通过内网nat穿透建立p2p连接,这里我将peerB作为主控端,初始化时,连接本机获取本地icecandidate,这里icecandidate可以理解为内网nat对外网的映射,可以直接在公网访问的地址,可以是一个公网域名,也可以是服务器ip+端口,获取之后,通过http传输给TURN中继服务器,由中继服务器转发给peerA,这里peerA和peerB由登录的用户组来控制,进行不同的初始化设置
在socket初始化时,获取本地地址,进而换取icecandidate
peerB作为主控端,主动发起连接,发出offer,设置本地LocalDescription和远端RemoteDescription,都是同一个offer标志,peerA接收到请求后回复answer,设置本地LocalDescription和远端RemoteDescription,都是同一个answer标志,此时连接完成,会自动调用peerA和peerB的onopen事件,可以进行双工通信
信令格式可以自定义,我这里是简化demo,所以就简单的放置了clientX, clientY, type, target, innerText 五个参数,都是从鼠标事件中获取的,获取之后用相应的信道进行发送,远端注册相应的onmessage函数进行处理即可
鼠标事件不可连续发送,由于js线程和ui线程是互斥的,连续发送事件会造成ui阻塞,所以必须按一定的时间间隔进行发送鼠标位置
在接收端,设置一个old标志,第一次接收到数据并不绘制,保存起来,从第二次接收到数据开始与前一帧数据进行运算,插值绘制鼠标轨迹,可以有效提升性能
以上就是webRtc信令传输实现远程控制的基本思路,音频也是类似,当p2p通道建立起来之后,整个连接可以复用多条udp连接,直接进行音频推送就可以实现语音和鼠标控制事件同时发送给被控端了
demo地址: https://githubcom/gusuziyi/Remote-controlgit
0条评论