WebRTC介绍及简单应用


WebRTC,即Web Real-Time Communication,web实时通信技术。简单地说就是在web浏览器里面引入实时通信,包括音视频通话等。

  • WebRTC实时通信技术介绍
  • 如何使用
  • 媒体介绍
  • 信令
  • STUN和TURN介绍
  • 对等连接和提议/应答协商
  • 数据通道
  • NAT和防火墙穿透
  • 简单应用
  • 其它

WebRTC实时通信技术介绍

WebRTC实现了基于网页的语音对话或视频通话,目的是无插件实现web端的实时通信的能力。

WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、展示等功能,并且还支持跨平台,包括linux、windows、mac、android等。

1. WebRTC三角形

2. WebRTC梯形

3. WebRTC的多方会话

WebRTC支持多个浏览器参与的多方会话或会议会话,要建立这类会话有如下两种模式:

4. WebRTC新功能特性


如何使用WebRTC

WebRTC易于使用,只需极少步骤便可建立媒体会话。有些消息在浏览器和服务器之间流动,有些则直接在两个浏览器(成为对等端)之间流动。

1、建立WebRTC会话

建立WebRTC连接需要如下几个步骤:

  • 获取本地媒体(getUserMedia()MediaStream API
  • 在浏览器和对等端(其它浏览器或终端)之间建立对等连接(RTCPeerConnection API
  • 将媒体和数据通道关联至该连接
  • 交换会话描述(RTCSessionDescription

  • 浏览器M从Web服务器请求网页
  • Web服务器向M返回带有WebRTC js的网页
  • 浏览器L从Web服务器请求网页
  • Web服务器向L返回带有WebRTC js的网页
  • M决定与L通信,通过M自身的js将M的会话描述对象(offer,提议)发送至Web服务器
  • Web服务器将M的会话描述对象发送至L上的js
  • L上的js将L的会话描述对象(answer,应答)发送至Web服务器
  • Web服务器转发应答至M上的js
  • M和L开始交互,确定访问对方的最佳方式
  • 完成后,M和L开始协商通信密钥
  • M和L开始交换语音、视频或数据

WebRTC三角形会话具体的调用流程:

说明:
SDP对象的传输可能是一个来回反复的过程,并且该过程采用的协议并未标准化

WebRTC梯形会话方式具体的调用流程:

说明:
此场景中,浏览器M和L直接交换媒体,只是它们运行的Web服务器不用而已。每个浏览器的会话描述对象都会映射至Jingle[XEP-0166]session-initiate消息和session-accept方法。

媒体介绍

先来看下WebRTC中的本地媒体:

1、WebRTC中的媒体

  • 轨道(MediaStreamTrack,代表设备或录制内容可返回的单一类型的媒体,唯一关联一个“源”,WebRTC不能直接访问或控制“源”,对“源”的一切控制都通过轨道实施;一个“源”可能对应多个轨道对象)
  • 流(MediaStream,轨道对象的集合)

轨道和流的示意如下:

2、捕获本地媒体

如下代码展示了本地媒体的简单获取,并展示:

// 注意getUserMedia()在各浏览器中的区别
// Opera --> getUserMedia
// Chrome --> webkitGetUserMedia
// Firefox --> mozGetUserMedia
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; // 只获取video:
var constraints = {audio: false, video: true};
var video = document.querySelector("video"); function successCallback(stream) {
// Note: make the returned stream available to console for inspection
window.stream = stream; if (window.URL) {
// Chrome浏览器
video.srcObject = stream;
} else {
// Firefox和Opera: 可以直接把视频源设置为stream
video.src = stream;
}
// 播放
video.play();
} function errorCallback(error){
console.log("navigator.getUserMedia error: ", error);
} navigator.getUserMedia(constraints, successCallback, errorCallback);

运行效果如下:

完整代码查看:https://github.com/caiya/webrtc-demo.git


信令

在WebRTC中,信令起着举足轻重的作用。但实现没有标准化,比如http、websocket、xmpp等。

1、信令的作用

  • 协商媒体功能和设置
  • 标识和验证会话参与者的身份(交换SDP对象中的信息:媒体类型、编解码器、带宽等元数据)
  • 控制媒体会话、指示进度、更改会话、终止会话
  • 双占用分解

简单地说,信令就是协调通讯的过程,一旦信令服务建立好了,两个客户端之间建立了连接,理论上它们就可以进行点对点通讯了。

2、信令的传输

WebRTC要求在两个对等端建立双向的信令通道,通常有三种方式来传输WebRTC信令:http、websocket、数据通道

http方式如下:

websocket代理信令传输:

3、WebRTC中的服务器

WebRTC提供了浏览器端的P2P通信,但并不意味着WebRTC不需要服务器。撇开应用服务器不说,至少以下两种服务器是必须的:

  • 浏览器之间建立通信前交换各种元数据(信令)的服务器(信令服务)
  • 穿越NAT和防火墙的服务器(stun、turn、rsip等)
说明:
元数据是通过信令服务器中转发给另一个客户端,但是对于流媒体数据,一旦会话建立,首先尝试使用点对点连接。简单一点说就是:每个客户端都有一个唯一的地址,他能用来和其他客户端进行通讯和数据交换。 STUN服务器:用来取外网地址的。(见下节) TURN服务器:在P2P失败时进行转发的。(见下节) ICE:*Interactive Connectivity Establishment*,即交互式连通建立方式。并非一种新的协议,它通过综合利用现有NAT穿透协议,以一种更有效的方式来组织会话建立过程,使之在不增加任何延迟同时比STUN等单一协议更具有健壮性、灵活性。

4、信令交互和RTCPeerConnection的建立

WebRTC使用RTCPeerConnection建立连接传送流数据,在建立RTCPeerConnection实例之后,想要建立点对点的信道,需要做两件事:

  • 确定本机上的媒体流的特性,比如分辨率、编解码能力啥的(SDP描述符)
  • 连接两端的主机的网络地址(ICE Candidate)

通过offer和answer交换SDP描述符:

  • 甲和乙各自建立一个PC实例
  • 甲通过PC所提供的createOffer()方法建立一个包含甲的SDP描述符的offer信令
  • 甲通过PC所提供的setLocalDescription()方法,将甲的SDP描述符交给甲的PC实例
  • 甲将offer信令通过服务器发送给乙
  • 乙将甲的offer信令中所包含的的SDP描述符提取出来,通过PC所提供的setRemoteDescription()方法交给乙的PC实例
  • 乙通过PC所提供的createAnswer()方法建立一个包含乙的SDP描述符answer信令
  • 乙通过PC所提供的setLocalDescription()方法,将乙的SDP描述符交给乙的PC实例
  • 乙将answer信令通过服务器发送给甲
  • 甲接收到乙的answer信令后,将其中乙的SDP描述符提取出来,调用setRemoteDescripttion()方法交给甲自己的PC实例

通过ICE框架建立NAT/防火墙穿越的连接:

WebRTC使用ICE框架来获得这个外界可以直接访问的地址,RTCPeerConnection在创立的时候可以将ICE服务器的地址传递进去,如:

var iceServer = {
"iceServers": [{
"url": "stun:stun.l.google.com:19302"
}]
};
var pc = new RTCPeerConnection(iceServer);
  • 甲、乙各创建配置了ICE服务器的PC实例,并为其添加onicecandidate事件回调
  • 当网络候选可用时,将会调用onicecandidate函数
  • 在回调函数内部,甲或乙将网络候选的消息封装在ICE Candidate信令中,通过服务器中转,传递给对方
  • 甲或乙接收到对方通过服务器中转所发送过来ICE Candidate信令时,将其解析并获得网络候选,将其通过PC实例的addIceCandidate()方法加入到PC实例中

这样连接就创立完成了,可以向RTCPeerConnection中通过addStream()加入流来传输媒体流数据。


STUN和TURN介绍

浏览器位于网络地址转换设备(NAT)之后是一种极为普遍的设计。举个栗子:

再来看个图,了解下“公共地址”和“私有地址”:

NAT主要负责维护内部ip地址和端口号与外部ip地址和端口号之间的映射表。

1、STUN服务器

STUN,Session Traversal Utilities for NAT,称为NAT会话遍历实用工具服务器。简单地说,就是获取内网设备的最外层NAT(公共ip地址)信息。

2、TURN服务器

TURN,Traversal Using Relay around NAT,称为中继型NAT遍历服务器。

说明:
媒体中继地址是一个公共地址,用于转发接收到的包,或者将收到的数据包转发给浏览器。如果两个对等端因为NAT类型等原因不能直接建立P2P连接的话,那么可以使用中继地址。 ps:相比较直接使用web服务器提供媒体中继理想点。

对等连接和提议/应答协商

上一节中有简单介绍对等连接和offer/answer交互流程,这节再说明下。

其实WebRTC定义了两组主要的功能,分别是:媒体捕获(getUserMedia(),前面已介绍)、媒体传输。对等连接和提议/应答协商的概念是媒体传输的核心。

1、对等连接

RTCPeerConnection接口是WebRTC的主要API,用来在P2P端建立媒体连接及数据连接路径。RTCPeerConnection对象的构造函数有一系列属性,最主要的是iceServers属性,表示服务器地址列表。用于帮助透过NAT和防火墙建立会话。

var pc = new RTCPeerConnection({
iceServers: [{
url: 'stun:stun.l.google.com:19302'
},{
url: 'turn:user@turn.myserver.com',
credential: 'test'
}]
}) getUserMedia({
audio: true,
video: true
}, successCB, failureCB) function successCB(stream) {
// 告知浏览器,我要发送MediaStream
pc.addStream(stream) // removeStream()
}

2、提议/应答协商

要在二者之间建立连接,必须在二者之间建立会话。offer/answer是一种“一次性通过”型协商机制。实际中该过程可能会反复多次。

WebRTC使用RTCSessionDescription对象表示提议和应答。每个浏览器都将生成一个该对象。

3、JavaScript提议/应答协商控制

本地浏览器只关注两个特定的调用:

// 将我的会话描述告知我的浏览器
pc.setLocalDescription(mySessionDescription)
...
// 将对等端的会话描述告知我的浏览器
pc.setRemoteDescription(yourSessionDescription)

生成提议、应答:

// 生成提议
pc.createOffer(gotOffer, didntGetOffer) function gotOffer(aSessionDescription) {
setLocalDescription(aSessionDescription)
...
// 现在可以将会话描述(提议offer)发送给对等端,以便对等端
// a)、将提议传递给setRemoteDescription
// b)、调用createAnswer
} // 生成应答
pc.createAnswer(gotAnswer, didntGetAnswer) function gotAnswer(aSessionDescription) {
setLocalDescription(aSessionDescription)
...
// 现在将会话描述(应答answer)发送给对等端,以便对等端
// a)、将应答传递给setRemoteDescription
}

4、测试demo说明

以下测试demo展示在两个浏览器中进行实时视频通话,源码地址:https://github.com/caiya/webrtc-p2p.git


数据通道

RTCDataChannel,数据通道是浏览器之间建立的非媒体的交互连接。即不传递媒体消息,绕过服务器直接传递数据。相比WebSocket、http消息,数据通道支持流量大、延迟低。

注意:
单个对等连接中的多个数据通道底层共享一个流,所以只需一次offer、answer即可建立首个数据通道。之后再建立数据通道无需再次进行offer、answer交换。 典型应用:游戏实时状态更新。

数据通道的使用

只有在创建完RTCPeerConnection实例之后才能创建数据通道,如下:

pc = new RTCPeerConnection()
dc = pc.createDataChannel('')

一端创建完数据通道后,另一端只需要监听ondatachannel事件即可:

pc = new RTCPeerConnection()
pc.ondatachannel = function(e) {
dc = e.channel
}

此时,两个对等端已经彼此建立数据通道,可以直接相互发送消息:

dc.send('i am a text string for sending')
dc.send(new Blob(['i am a blob object'], {type: 'text/plain'}))
dc.send(new arrayBuffer(32)) // 发送arrayBuffer
dc.onmessage = function(e) {
console.log('收到消息:', e.data)
}

加入数据通道后的测试demo

项目源代码地址:https://github.com/caiya/webrtc-p2p-datachannel

部分截图:


作者 @晁州

2017 年 11月 27日

WebRTC介绍及简单应用的更多相关文章

  1. 《Getting Started with WebRTC》第一章 WebRTC介绍

    <Getting Started with WebRTC>第一章 WebRTC介绍 ​ 本章是对WebRTC做概念性的介绍. 阅读完本章后.你将对下面方面有一个清晰的理解:   .  什么 ...

  2. Android之WebRTC介绍

    参考自:Introduction to WebRTC on AndroidAndroid之WebRTC介绍 WebRTC被誉为是web长期开源开发的一个新启元,是近年来web开发的最重要创新.WebR ...

  3. 【转载】Ssh整合开发介绍和简单的登入案例实现

    Ssh整合开发介绍和简单的登入案例实现 Ssh整合开发介绍和简单的登入案例实现 一  介绍: Ssh是strtus2-2.3.1.2+ spring-2.5.6+hibernate-3.6.8整合的开 ...

  4. python模块介绍- HTMLParser 简单的HTML和XHTML解析器

    python模块介绍- HTMLParser 简单的HTML和XHTML解析器 2013-09-11 磁针石 #承接软件自动化实施与培训等gtalk:ouyangchongwu#gmail.comqq ...

  5. 基于.NET CORE微服务框架 -surging的介绍和简单示例 (开源)

    一.前言 至今为止编程开发已经11个年头,从 VB6.0,ASP时代到ASP.NET再到MVC, 从中见证了.NET技术发展,从无畏无知的懵懂少年,到现在的中年大叔,从中的酸甜苦辣也只有本人自知.随着 ...

  6. 1. pyhanlp介绍和简单应用

    1. pyhanlp介绍和简单应用 2. 观点提取和聚类代码详解 1. 前言 中文分词≠自然语言处理! 中文分词只是第一步:HanLP从中文分词开始,覆盖词性标注.命名实体识别.句法分析.文本分类等常 ...

  7. C#串口介绍以及简单串口通信程序设计实现

    C#串口介绍以及简单串口通信程序设计实现 周末,没事干,写个简单的串口通信工具,也算是本周末曾来过,废话不多,直接到主题 串口介绍 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口) ...

  8. 消息队列介绍、RabbitMQ&Redis的重点介绍与简单应用

    消息队列介绍.RabbitMQ&Redis的重点介绍与简单应用 消息队列介绍.RabbitMQ.Redis 一.什么是消息队列 这个概念我们百度Google能查到一大堆文章,所以我就通俗的讲下 ...

  9. 进击的Python【第十二章】:mysql介绍与简单操作,sqlachemy介绍与简单应用

    进击的Python[第十二章]:mysql介绍与简单操作,sqlachemy介绍与简单应用 一.数据库介绍 什么是数据库? 数据库(Database)是按照数据结构来组织.存储和管理数据的仓库,每个数 ...

随机推荐

  1. 锁对象Lock

    Lock 实现提供了比使用synchronized 方法和语句可获得的更广泛的锁定操作,它能以更优雅的方式处理线程同步问题: public class LockTest { publicstaticv ...

  2. python内置方法总结

    abs() #求绝对值 >>> abs(-19) 19 all() #里面的元素全部为真才是真 >>> all([1,2,3,'',2]) False any #只 ...

  3. ubuntu中python3.4安装pip

    这两天碰到在ubuntu中安装pip的问题. 第一种方法 用百度搜索了一下,基本上都是这个命令: sudo apt-get install python3-pip 但是,用这条命令下载速度特别慢. 第 ...

  4. 关于Makefile,Makefile.in,Makefile.am,Configure功能及相互关系的问题

    makefile写法 在 Unix 上写程式的人大概都碰过 Makefile,尤其是用 C 来开发程式的人.用 make来开发和编译程式的确很方便,可是要写出一个 Makefile就不简单了.偏偏介绍 ...

  5. 交换知识 VLAN VTP STP 单臂路由

    第1章 交换基础 1.1 园区网分层结构 层次 作用 出口层 广域网接入 出口策略 带宽控制 核心层 高速转发 服务器接入 路由选择 汇聚层 流量汇聚 链路冗余 设备冗余 路由选择 接入层 用户接入 ...

  6. MapReduce简单分析

    在Map端 数据从Map中写入环形缓冲区,进行分区,分区时达到80%后溢出写入到磁盘,这几步同步进行 中间有个Shuffle过程 Reduce端 执行完Map 后到Reduce内存中,进行sort和m ...

  7. js中的浅复制和深复制

    浅复制:浅复制是复制引用,复制后的引用都是指向同一个对象的实例,彼此之间的操作会互相影响 深复制:深复制不是简单的复制引用,而是在堆中重新分配内存,并且把源对象实例的所有属性都进行新建复制,以保证深复 ...

  8. 一键生成koa/koa2项目:

    一键生成koa/koa2项目: 1. npm install -g koa-generator 2.新建项目目录 koa mytest (koa1项目) koa2 koa2test (koa2项目) ...

  9. mac链接linux终端,shell脚本发布代码

    项目的业务需求:从mac端直接连上linux服务终端,并发布相关的代码 一.使用ssh链接上linux服务端 1.cd ~/.ssh 2.vi config,按照下面的内容配置config文件,然后: ...

  10. 运放的PID电路

    PID就是(比例(proportion).积分(integral).导数(derivative)),在工程实际中,应用最为广泛的调节器控制规律为比例.积分.微分控制,简称PID控制,又称PID调节. ...