浅谈WebRTC技术原理与应用

285次阅读  |  发布于3年以前

一、技术背景

自2010年至今,WebRTC的出现和发展简要背景

(线上实时音视频交互)

(图引用自W3C重点报告,2021.10版[7])

二、简要特征

WebRTC内容丰富,主要的技术特征包含以下几点:

1. 实时通讯

是一项实时通讯技术,允许网络应用或者站点,在不借助中间媒介的情况下,建立浏览器之间点对点(Peer-to-Peer)的连接,实现视频流和(或)音频流或者其他任意数据的传输。

2. 无依赖/插件

WebRTC包含的这些标准使用户在无需安装任何插件或者第三方的软件的情况下,创建点对点(Peer-to-Peer)的数据分享和电话会议成为可能。

3. 协议栈 众多

它并不是单一的协议,包含了媒体、加密、传输层等在内的多个协议标准以及一套基于 JavaScript的 API,它包括了音视频的采集、编解码、网络传输、显示等功能。通过简单易用的 JavaScript API ,在不安装任何插件的情况下,让浏览器拥有了 P2P音视频和数据分享的能力。

(WebRTC依赖众多协议栈图)

相关协议 介绍与作用
ICE、STUN、TURN 用于内网穿透, 解决了获取与绑定公网映射地址
DTLS 用于对传输内容进行加密
SRTP 、 SRTCP 对媒体数据的封装与传输控制协议

同时WebRTC 并不是一个孤立的协议,它拥有灵活的信令,可以便捷的对接现有的SIP 和电话网络的系统。

三、兼容覆盖

主流浏览器的兼容情况

(浏览器兼容性覆盖图)

四、技术框架

结合技术框架图来认知和理解官方技术框架的基本内容

如下图的技术框架描述了WebRTC的核心内容和面向不同开发者的API设计。

(技术框架图)

从上述框架中看到,主要有音频、视频引擎和传输三部分主要内容,其中又包含众多的协议和方法等

1 . Voice Engine(音频引擎)

a . Voice Engine包含iSAC/iLBC Codec(音频编解码器,前者是针对宽带和超宽带,后者是针对窄带)

b. NetEQ for voice(处理网络抖动和语音包丢失)

c . Echo Canceler(回声消除器)/ Noise Reduction(噪声抑制)

2 . Video Engine(视频引擎)

a . VP8 Codec(视频图像编解码器)

b . Video jitter buffer(视频抖动缓冲器,处理视频抖动和视频信息包丢失)

c . Image enhancements(图像质量增强)

3 . Transport

六、实现原理

a . SRTP(安全的实时传输协议,用于音视频流传输)

b . Multiplexing(多路复用)

c . P2P,STUN+TURN+ICE(用于NAT网络和防火墙穿越的)

d . 除此之外,安全传输可能还会用到DTLS(数据报安全传输),用于加密传输和密钥协商

e . 整个WebRTC通信是基于UDP的

不细致介绍音视频采集、编码和处理等内容,仅介绍实时通讯的建立过程原理的核心内容

1 . 公网IP映射:明确网络定位信息

(STUN服务器用于辅助内网穿透得到对应主机的公网网络地址和端口信息图)

2 . 信令服务器:网络协商与信息交换

(概念图)

(信令服务器信息交互过程图)

3 . 会话描述协议SDP:统一的媒体协商方式

//SDP的结构体
Session description(会话级别描述)
         v=  (protocol version)
         o=  (originator and session identifier)
         s=  (session name)
         c=* (connection information -- not required if included in all media)
         One or more Time descriptions ("t=" and "r=" lines; see below)
         a=* (zero or more session attribute lines)
         Zero or more Media descriptions

Time description
         t=  (time the session is active)

Media description(媒体级别描述), if present
         m=  (media name and transport address)
         c=* (connection information -- optional if included at session level)
         a=* (zero or more media attribute lines)
v=0 //代表版本,目前一般是`v=0`.
o=- 3883943731 1 IN IP4 127.0.0.1
s=
t=0 0 //会话处于活动状态的时间
a=group:BUNDLE audio video //:描述服务质量,传输层复用相关信息
m=audio 1 RTP/SAVPF 103 104 0 8 106 105 13 126 // ... 

a=ssrc:2223794119 label:H4fjnMzxy3dPIgQ7HxuCTLb4wLLLeRHnFxh81

4.一对一连接建立过程

以建立一对一的Web RTC连接过程为

(一对一过程图)

(简要过程图)

(工作流程图)

  1. A和B双方先调用 getUserMedia 打开本地摄像头,作为本地待输出媒体流;

  2. 向信令服务器发送加入房间请求;

  3. Peer B 接收到 Peer A 发送的 offer SDP 对象,并通过PeerConnection的SetLocalDescription方法保存 Answer SDP 对象并将它通过信令服务器发送给 Peer A。

  4. 在 SDP 信息的 offer/answer 流程中,Peer A 和 Peer B 已经根据 SDP 信息创建好相应的音频 Channel 和视频 Channel,并开启Candidate 数据的收集,Candidate数据(本地IP地址、公网IP地址、Relay服务端分配的地址)。

  5. 当 Peer A 收集到 Candidate 信息后通过信令服务器发送给 Peer B。同样的过程 Peer B 对 Peer A 也会再发送一次。

6 . 多对多的建立

(多对多建立点到点连接概念图,以三个用户点对点的连接为例)

7 . JavaScript主要接口

//请求媒体类型
const constraints = {
  video: true
  audio:true
};

const video = document.querySelector('video');

//挂载流到相应dom展示本地媒体流
function handleSuccess(stream) {
  video.srcObject = stream;
}

function handleError(error) {
  console.error('getUserMedia error: ', error);
}
//利用摄像头捕获多媒体流
navigator.mediaDevices.getUserMedia(constraints).
  then(handleSuccess).catch(handleError);
// 允许 RTC 服务器配置。
const server = { 
    "iceServers": 
            [{ "urls": "stun:stun.stunprotocol.org"}] 
};

// 创建本地连接
const localPeerConnection = new RTCPeerConnection(servers);

// 收集Candidate 数据
localPeerConnection.onicecandidate=function(event){
    ...
}
// 监听到媒体流接入时的操作
localPeerConnection.ontack=function(event){
    ...
}
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel("my channel");
//接受数据
dc.onmessage = function (event) {
  console.log("received: " + event.data);
};
//打开传输
dc.onopen = function () {
  console.log("datachannel open");
};
//关闭传输
dc.onclose = function () {
  console.log("datachannel close");
};

七、应用案例

多人视频案例为实践应用

  1. 设计框架

(多人视频基本框架图)

2.关键代码

1.1 媒体捕获

//摄像头兼容性处理
navigator.getUserMedia = ( navigator.getUserMedia ||
               navigator.webkitGetUserMedia ||
               navigator.mozGetUserMedia ||
               navigator.msGetUserMedia);
// 获取本地音频和视频流
navigator.mediaDevices.getUserMedia({
                "audio": false,
                "video": true
}).then( (stream)=> {
//显示自己的输出流,挂到页面Video元素上
    document.getElementById("myVido").srcObject=stream
})

(捕获本地视频媒体流的显示结果截图)

 // stun和turn服务器  const iceServer = {
    "iceServers": [{
        urls:"stun:stun.l.google.com:19302"
    }]
};
//为点到点的连接创建RTCPeerConnection
const peerRTCConn=new RTCPeerConnection(iceServer);

1.2 网络协商

交互式连通性建立(Interactive Connectivity Establishment — ICE)是一个允许实时对等端发现对方并且彼此连接的框架。此技术允许对等方发现有关彼此拓扑的足够信息,从而有可能在彼此之间找到一条或多条通信路径。ICE 代理负责:收集本地IP,端口元组候选、在同级之间执行连接检查和发送连接保持活动

 // 发送ICE候选到其他客户端 peerRTCConn.onicecandidate = function(event){
    if (event.candidate) {
        //向信令服务器转发收集到的ICE候选          socket.send(JSON.stringify({
            "event": "relayICECandidate",
            "data": {
                'iceCandidate': {
                    'sdpMLineIndex': event.candidate.sdpMLineIndex,
                    'candidate': event.candidate.candidate
                }
            },
            "fromID":signalMsg['data']['peerId']
        }));
    }
}
//有媒体流介入就挂载dom peerRTCConn.ontrack=function(event){
    let v=document.createElement("video")
    v.autoplay=true
    v.style="width:200px"

    document.getElementById("peer").appendChild(v)
    v.srcObject=event.streams[0]
}

1.3 媒体协商

 //新加入节点发起offer  if(canOffer){
    peerRTCConn.createOffer(
        function (localDescription) { 
             peerRTCConn.setLocalDescription(localDescription,
                function() { 
                    //发送描述信息给信令服务器                         socket.send(JSON.stringify({
                        "event":"relaySessionDescription",
                        "data":localDescription,
                        "fromID":peerId
                    }))
                 },
                function() { alert("offer failed"); }
            );
        },
        function (error) {
            console.log("error sending offer: ", error);
        }
    )
}
//创建Answer会话
peer.createAnswer(
function(_remoteDescription) {
     peer.setLocalDescription(_remoteDescription,
        function() { 
               //发送描述信息给信令服务器                  socket.send(JSON.stringify({
                    "event":"relaySessionDescription",
                    "data":_remoteDescription,
                    "callerID":signalMsg['fromId'],
                    "fromID":signalMsg['fromId']
                }))        },
        function() { alert("answer failed"); }
    );
},
function(error) {
    console.log("error creating answer: ", error);
});
 //对应的RTCPeerConnection
const peer = peers[signalMsg["fromID"]];
//ICE候选添加到远程对等点描述
peer.addIceCandidate(new RTCIceCandidate(signalMsg["data"].iceCandidate));

(多人视频结果截图<本地模拟效果>)

1.4 信令中转

wss.on('connection', function (ws) { 
    ws.on('message', function (message) { 
        let meeageObj=JSON.parse(message)
        //交换ICE候选         if (meeageObj['event'] =='relayICECandidate') {             wss.clients.forEach(function (client) {
                console.log("send iceCandidate")
                    client.send(JSON.stringify({
                        "event": "iceCandidate",
                        "data": meeageObj['data'],
                        "fromID": meeageObj['fromID']
                    }));          
            });
        }
        //交换SDP         if (meeageObj['event'] =='relaySessionDescription') {
            console.log(meeageObj["fromID"],meeageObj["data"].type) 
            wss.clients.forEach(function (client) {
                if (client!=ws) {
                    client.send(JSON.stringify({
                        "event": "sessionDescription",
                        "fromId":meeageObj["fromID"],
                        "data": meeageObj["data"],
                    }));
                }
            });
        }
    })
})

八、应用场景

WebRTC在当下和未来具有丰富的应用场景,此文档不再赘述,可见下面URL的内容

https://webrtcforthecurious.com/zh/docs/08-applied-webrtc/

九、重要意义

WebRTC的出现、发展和被业内标准(如W3C)等普遍认可,对于当下和未来大前端技术发展具有重要的意义

1 . 降低在web端的音视频交互开发门槛

a . 以往的音视频交互开发对于Web开发者而言具有一定技术门槛,

b . 现在借助于WebRTC,Web开发者通过调用JS接口,可快速的实现音视频交互应用。

2 . 避免依赖、插件造成的次生问题

a . 以往的音视频交互应用构建依赖于各种插件、软件和服务器等

b . 现在借助于主流浏览器即可形成端到端的音视频交互

3 . 统一化和标准化对传统音视频交互环境差异性的规避

a . 以往音视频交互需要面对不同的 NAT 、防火墙对媒体 P2P 的建立带来了很大的挑战

b . 现在WebRTC 中有P2P 打洞的开源项目 libjingle ,支持 STUN,TURN 等协议

4 . 更高效优化的算法、技术对于音视频交互性能的提升

a . WebRTC 通过NACK、FEC技术,避免了经过服务端路由中转,减少了延迟和带宽消耗。还有 TCC + SVC + PACER + JitterBuffer 等技术对于音视频流畅性进行了优化

十、参考

本文档相关内容参考自下面的众多文章、项目Markdown和代码等内容,在此一一列出

  1. https://github.com/Tinywan/WebRTC-tutorial

  2. https://www.bookstack.cn/read/webrtc-book-cn/spilt.6.05_putting_it_all_together.md

  3. https://www.html5rocks.com/en/tutorials/webrtc/basics/

  4. https://zh.wikipedia.org/wiki/WebRTC

  5. https://zhuanlan.zhihu.com/p/93107411

  6. https://github.com/muaz-khan/WebRTC-Experiment

  7. https://xie.infoq.cn/article/ddceaa09b2c3ec4b357bf0d26

  8. https://juejin.cn/post/6969030139120189477

  9. https://www.jianshu.com/p/24363820b3b2

  10. https://zhuanlan.zhihu.com/p/79489847

  11. https://www.researchandmarkets.com/reports/5116130/global-web-real-time-communication-webrtc

十一、QA

参考资料

[1]网页浏览器: https://zh.wikipedia.org/wiki/%E7%B6%B2%E9%A0%81%E7%80%8F%E8%A6%BD%E5%99%A8

[2]Global : https://zh.wikipedia.org/wiki/Global_IP_Solutions

[3]IP: https://zh.wikipedia.org/wiki/Global_IP_Solutions

[4]Solutions: https://zh.wikipedia.org/wiki/Global_IP_Solutions

[5]Mozilla Firefox: https://zh.wikipedia.org/wiki/Mozilla_Firefox

[6]WebRTC 1.0: Real-Time Communication Between Browsers: https://www.w3.org/TR/2021/REC-webrtc-20210126/

[7]2021.10版: https://www.w3.org/2021/10/w3c-highlights/zh.Overview.html

[8]getUserMedia(): https://webrtc.github.io/samples/src/content/getusermedia/gum/

[9]RTCPeerConnection: https://webrtc.github.io/samples/src/content/peerconnection/pc1/

[10]RTCDataChannel: https://webrtc.github.io/samples/src/content/datachannel/basic/

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8