WebRTC(Web RealTime Communication)是 Google于2010以6829万美元从 Global IP Solutions 公司购买,并于2011年将其开源,旨在建立一个互联网浏览器间的实时通信的平台,让 WebRTC技术成为 H5标准之一。官网webrtc.org
各平台支持情况:
所有主要的浏览器的兼容
WebRTC现在得到了所有主要浏览器的支持和采用,包括谷歌Chrome、苹果Safari、Mozilla Firefox 、QQ浏览器、360浏览器和Microsoft Edge。
IE支不支持webrtc
威胁传统音视频提供商 声网(跨国,跨印度)、即构科技、融云
WebRTC可靠性和易用性
WebRTC通过web浏览器普及会议体验,支持点击开始,并消除了额外软件的麻烦。
一、webRTC框架
作为web应用开发者,我们只要关心紫色部分。 特别是图中的 PeerConnection 为 Web 开发人员提供了一个抽象,从复杂的内部结构中抽象出来。我们只需要关注PeerConnection这个对象即可以开发音视频通话应用。(我们的p2p应用也是基于此对象实现)。
1.1、了解彼此的媒体格式(SDP)
比如:PeerA端可支持VP8、H264多种编码格式,而PeerB端支持VP9、H264,要保证二端都正确的编解码,最简单的办法就是取它们的交集H264。
注:有一个专门的协议 ,称为Session Description Protocol (SDP),可用于描述上述这类信息,在WebRTC中,参与视频通讯的双方必须先交换SDP信息,这样双方才能知根知底,而交换SDP的过程,也称为"媒体协商"。
1.2、网络协商(p2p通话直接用到的是stun服务器)
理想的网络情况是每个浏览器的电脑都是私有公网IP,可以直接进行点对点连接。
实际情况是:我们的电脑和电脑之间都是在某个局域网中,需要NAT(Network Address Translation,网络地址转换),显示情况如下图:
STUN
STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序)是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址
,
查出自己位于哪种类型的NAT之后,NAT为某一个本地端口关联的Internet端端口。
这些信息被用来在两个同时处于NAT路由器之后的主机之间创建UDP通信。
我们建立stun服务器,用一句话概括:告诉我你的公网IP地址+端口是什么。
ICE
:Interactive Connectivity Establishment
,交互式连接建立协议,用于在两个主机之间建立连接,它可以在两个主机之间建立连接,即使它们之间的防火墙阻止了直接连接。(可以不借助一个公网 server 完成端到端(Peer to peer,P2P)的通信)。
二、代码应用层面具体流程
简单的框架图
2.1、创建RTCPeerConnection对象
// 创建一条由本地计算机到远端的 WebRTC 连接
const pc = new RTCPeerConnection({
iceServers: [{ urls: 'stun:stun.voipbuster.com ' }], //stun服务器
})
2.2、挂载视频流
创建两个video标签
<video id="local" autoplay playsinline muted></video>
<video id="remote" autoplay playsinline></video>
采集视频流
// 初始化
const init = async () => {
// 获取本地端视频标签
const localVideo = document.getElementById('local') as HTMLVideoElement
// 获取远程端视频标签
const remoteVideo = document.getElementById('remote') as HTMLVideoElement
// 获取本地媒体流
localStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true,
})
// 设置本地视频流
localVideo.srcObject = localStream
// 添加本地流到 pc
localStream.getTracks().forEach((track) => {
pc.addTrack(track, localStream)
console.log(pc);
})
// 监听远程流:
pc.ontrack = (event) => {
remoteVideo.srcObject = event.streams[0]
}
}
2.3、创建连接
1、创建offer(提案)
// 创建 offer(提案)
const createOffer = async () => {
const offer = await pc.createOffer()
console.log(offer);
await pc.setLocalDescription(offer)
// await pc.setLocalDescription()
// 到这里,我们本地的 offer 就创建好了,一般在这里通过信令服务器发送 offerSdp 给远端
//setLocalDescription后,创建 ice 候选 (ice candidates)
// 监听 RTCPeerConnection 的 onicecandidate 事件,当 ICE 服务器返回一个新的候选地址时,就会触发该事件
pc.onicecandidate = async (event) => {
console.log(pc)
if (event.candidate) {
offerSdp.value = JSON.stringify(pc.localDescription)
}
}
}
offer的内容:
包含一个类型字段和sdp字符串
打印一下sdp
查看分配的ip + 端口
正如我们上面所说,sdp相当于一个身份证,保留了你所有的基本信息,所以参与视频通话的前提是交换这些信息。
2、远端创建answer
接受方拿到出传过来的offer,就可以在本地创建answer,然后更新到RTCPeerConnection对象中
// 创建 answer
const offerSdp2 = ref('')
const createAnswer = async () => {
// 解析字符串
const offer = JSON.parse(offerSdp2.value) //A端offer
pc.onicecandidate = async (event) => {
// Event that fires off when a new answer ICE candidate is created
if (event.candidate) {
answerSdp.value = JSON.stringify(pc.localDescription)
}
}
await pc.setRemoteDescription(offer) //将A端的offer设置成B端的远端description
const answer = await pc.createAnswer() //B端生成answer
await pc.setLocalDescription(answer) // 在B端设置本地的descriptiona
}
查看B端的远程描述,其中就包含A端的ip和端口
再查看B端的本地描述
3、A端收到answer, 设置到远程端的描述中
// 添加 answer(应答)
const answerSdp2 = ref('')
const addAnswer = async () => {
const answer = JSON.parse(answerSdp2.value)
if (!pc.currentRemoteDescription) {
pc.setRemoteDescription(answer)
}
}
这时候的远端描述,和B端的ip和端口号相同
设置完成以后,通讯成功!
一个简单的webRTC的p2p的流程就完成了。
三、注意事项
3.1、公网环境下,webRTC只能在https环境。
本文代码部分来自这篇文章,需要代码得请看原文! juejin.cn/post/716553…