1。什么是WebRTC? WebRTC是一组JavaScriptAPI,可以在两个浏览器之间建立点对点连接,实现音频和视频等数据的传输,可以用它创建有语音视频通话功能的应用程序。 WebRTC的特别之处是,一旦建立了连接,就可以直接在浏览器之间实时传输数据,不需要借助服务器,因此降低了延迟,所以用户都喜欢用webRTC直接传输音视频。 在WebRTC诞生之前,开发实时音视频应用的成本是非常高,需要考虑的技术问题很多,如音视频的编解码,数据传输延时、丢包、网络抖动、回音处理和消除等,如果要兼容浏览器端的实时音视频通信,还需要额外安装插件。可喜的是,本文的主角WebRTC在2021年1月被W3C和IETF发布为正式标准,而且得到了大多数主流浏览器的支持。 CanIUse中WebRTC的浏览器支持情况2。WebRTC与WebSockets的区别 在讨论WebRTC的工作原理之前,先看看WebRTC和WebSockets的对比,因为很多人都会觉得听着跟WebSockets一样,用WebSockets就好了,为什么需要WebRTC? 使用websockets也可以建立点对点连接,实时传输数据,但这种连接是在客户端和服务器之间。因此,如果我向某一对等点发送消息,这个消息会先传送到服务器,然后服务器再把这个消息发送给另一个对等点。通常来说,这种传输非常快,如果大家发送的是聊天信息或某些通知,即使有一些延迟也注意不到。 但如果我们用websockets传输音视频情况就不一样了。用websockets传输音视频时,即使有非常轻微的延迟也会非常明显,还会导致很多其他问题。当视频数据到达服务器并返回对等点时,用户会感觉到明显的延迟。 而这就是webRTC的优势所在,在两个浏览器之间建立连接并直接交换数据,消除了服务器可能导致的延迟,WebRTC还使用了用户数据报协议(UDP),这些都有利于数据的快速传输。 通常WebRTC会与WebSocket配合使用,WebSocket的作用主要是用来交换客户端的SDP与网络信息,Websocket传输的内容与真正通信数据无关,只是协助WebRTC建立连接。3。用webRTC传输数据这么快,为什么还需要websockets? webRTC有一定的局限性,所以通常会同时使用webRTC和websockets。 首先,webRTC使用UDP,但是用UDP传输重要数据会有点不太可靠。UDP的优势在于传输数据非常快,劣势在于它不检查数据是否被成功接收。所以,可以用UDP来传输视频,就算传输过程中丢失了几帧,也没啥大问题;但如果是发送文件,丢失几个字节的数据就会导致整个文件的损坏。 另外,WebRTC没有内置信令,所以只用WebRTC没法建立点对点的连接,但一旦建立了连接,WebRTC就可以处理所有问题,至于如何传输初始数据来连接两个对等点则由我们决定。 4。两个客户端之间传送什么,如何发送? 首先,信息的发送通常是通过一个叫做信令的过程。由于两个对等点不了解对方的情况,我们通常会使用WebSockets或其他第三方信令服务将两个对等点引入同一个频道。 当把两个对等点引入同一个频道或房间时,他们就可以通过连接细节发出信号。这些连接细节以会话描述协议(SDP)和ICE(InteractiveConnectivityEstablishment,交互式连接创建)候选人的形式出现。 SDP会话描述协议(SDP),是一个包含会话连接(如编解码器、地址、媒体类型、音频和视频等)信息的对象。两个对等点会交换SDP来了解如何实现连接。一个是SDPOffer形式,另一个是SDPAnswer形式。 ICE候选人ICE候选人是公共IP地址和端口,可以做接收数据的地址。通常来说,每个用户会有多个ICE候选人,这些ICE候选人是向STUN服务器发出一系列请求来收集的。 5。事件发生顺序 首先,两个对等点会使用某种信令方法来传输SDP。一旦两个SDP传输完成,对等点就连接成功,但这时还不能传输数据。 要在两个对等点之间交换数据,我们要先传输数据。问题是,现在大多数设备都位于防火墙和NAT设备后面,因此,为了协调公共IP地址的发现,我们使用ICE(InteractiveConnectivityEstablishment,交互式连接创建)方法。 一旦后台传输了SDP提议,每个对等点就会向STUN服务器发出一系列请求,该服务器会生成一个ICE候选人列表。STUN服务器的成本很低,并且容易维护,有非常多的免费服务,所以大家可以设置一个。 一旦对等点1从STUN服务器获得这些ICE候选人,就会把这些候选人发送给对等点2,让网络决定要使用的最佳候选人。对等点2会进行同样的操作,请求ICE候选人,然后将其发送给等点1。 当这些候选人传输成功并发现一条最佳路径时,数据就可以开始在两个对等点之间流动。5。WebRTCAPI调用5。1RTCPeerConnection RTCPeerConnection用于点对点之间建立连接以传输音视频数据流,这是RTCPeerConnection的任务,为此需要借助一个信令服务器(signalingserver)来进行,信令包括3种类型的信息:Sessioncontrolmessages:初始化和关闭通信,及报告错误;Networkconfiguration:双方的IP地址和端口号(局域网内部IP地址需转换为外部的IP地址);Mediacapabilities:双方的浏览器支持使用何种编码以及多高的视频分辨率。varPeerConnectionwindow。RTCPeerConnectionwindow。mozRTCPeerConnectionwindow。webkitRTCPeerConnection;navigator。getUserMedianavigator。getUserMedia?getUserMedia:navigator。mozGetUserMedia?mozGetUserMedia:navigator。webkitGetUserMedia?webkitGetUserMedia:getUserMedia;varvdocument。createElement(video);创建信令(createOffer)varpcnewPeerConnection();pc。addStream(video);pc。createOffer(function(desc){pc。setLocalDescription(desc,function(){sendtheoffertoaserverthatcannegotiatewitharemoteclient});})创建回复(createAnswer)varpcnewPeerConnection();pc。setRemoteDescription(newRTCSessionDescription(offer),function(){pc。createAnswer(function(answer){pc。setLocalDescription(answer,function(){sendtheanswertotheremoteconnection});});})5。2RTCDataChannel RTCDataChannel接口代表在两者之间建立了一个双向数据通道的连接,可以用RTCPeerConnection。createDataChannel()或者在现有的RTCPeerConnection上用RTCDataChannelEvent类型的datachannel事件接收,创建出RTCDataChannel类型的对象。varpcnewRTCPeerConnection();获取RTCPeerConnection对象vardcpc。createDataChannel(mychannel);创建DataChannel对象dc。onmessagefunction(event){console。log(received:event。data);};dc。onopenfunction(){console。log(datachannelopen);};dc。onclosefunction(){console。log(datachannelclose);};5。3访问用户摄像头及麦克风getUserMedia WebRTC支持直接传输音频流和视频流(https:appr。tc):constpcnewRTCPeerConnection();获取RTCPeerConnectionnavigator。getUserMedia({video:true},stream{添加视频流到会话中stream。getTracks()。forEach(trackpc。addTrack(track,stream))在网页中预览自己摄像头拍摄到的内容,其中localVideo表示一个Video对象localVideo。srcObjectstream;}) navigator。getUserMedia()还可以和webAudioAPI相结合,用来处理音频效果:varrangedocument。querySelector(input);window。AudioContextwindow。AudioContextwindow。webkitAudioContext;varaudioCtxnewAudioContext();navigator。getUserMedia({audio:true},function(stream){创建音频流varsourceaudioCtx。createMediaStreamSource(stream);双二阶滤波器varbiquadFilteraudioCtx。createBiquadFilter();biquadFilter。typelowshelf;biquadFilter。frequenc。value1000;biquadFilter。gain。valuerange。value;source。connect(biquadFilter);biquadFilter。connect(audioCtx。destination);},function(error){console。log(error);}); 其实,WebRTC并不只是用来做视频、音频,它还可以用来传输任意数据,包括文件,文本等。上面代码示例可以看到,WebRTC规定了dataChannel这个双工数据通道,而https:snapdrop。net这个网站就是通过WebRTC进行文件分享。constpcnewRTCPeerConnection()constdataChannelpc。createDataChannel(chat)监听datachannel事件pc。addEventListener(datachannel,event{接收通信方发送过来的数据event。channel。addEventListener(message,event{console。log(message,event。message)})})dataChannel。addEventListener(open,(){发送数据,可发送任意数据dataChannel。send(Hi!)})dataChannel。addEventListener(close,event{}) 参考资料 https:medium。comagoraiohowdoeswebrtcwork996748603141 https:www。agora。iocncommunityblog24640 https:www。yuque。comguiqulaixi2ciw1ltzgfdxqgx3h9zdwxxszd9 https:developer。mozilla。orgenUSdocsWebAPIRTCDataChannel https:caniuse。com?searchWebRTC https:www。jianshu。comp1022f559a805 https:zhuanlan。zhihu。comp421503695 https:github。comnashaofuwebrtcdemo https:blog。csdn。netxyphfarticledetails107297616