前言:
大家周末好,今天给大家分享的是webrtc第一篇文章,在之前的音视频文章里面没有分享过关于webrtc的内容;在上个周末分享了一篇关于播放器的文章,那篇文章整体上介绍了播放器的设计结构;我个人的学习路线,主要分为两大方向:ffmpeg和webrtc,然后会具体到各种协议。
关于播放器实战学习第二篇,我会在下周分享自己的学习笔记和感悟;今天呢,主要是分享一些webrtc的通话原理:STUN 和TURN ,其中会涉及到NAT穿透原理,以及我会用实战来举例在google浏览器上打开自带的电脑摄像头。
好了,具体内容如下:
一、webrtc的通话原理:
1、什么是webrtc?
在介绍什么是webrtc之前呢,我先分析一下当前的一个背景:不知道大家平时有没有注意,短视频越来越火,你比如微信的视频号、抖音、头条、微视频、快手等,就连知乎里面在今年也开始玩起了视频,更别说特别流行的直播带货呢,这些产品都离不开音视频技术的支持,特别是当下5G时代,极大的解决了带宽问题,会让这项技术得到更大的发展和应用;作为学习者和开发人员,我们要认真学习,掌握里面的技术,才能让我们在职场上有更多的竞争优势!
好了,说了点废话,主要就是让大家知道,这些平时生活当中我们经常玩的的产品,都涉及到音视频技术的支持;那么,下面我们来看看webrtc到底是什么?
webrtc英文名为: Web Real-Time Communication ,web端实时通信,它是google公司在2011年开源的一个项目,主要是面向浏览器之间的通信,它的出现真的解决了很多问题,在后期的分享当中大家就可以看到它的强大之处了,更多详细介绍,大家可以去webrtc的官网看看,不过现在国内一般访问不了:
代码语言:javascript复制https://webrtc.org
webrtc官网关于webrtc简单介绍
2、webrtc的通话原理:
首先在介绍这个原理之前呢,我们先来考虑一个问题:就是在不同的网络环境下的浏览器,要实现点对点(也就是一对一)的实时音视频对话,那他们是如何通信的呢?
媒体协商
如上图所示,我们先考虑下两个问题:
- 浏览器Peer-A视频采用VP8(视频图像编解码器,是WebRTC视频引擎的默认的编解码器,它适合实时通信应用场景,因为它主要是针对低延时而设计的编解码器)做编码,然后发给浏览器Peer-B,那么它该如何去解码呢?
- 浏览器Peer-B采用VP9做编码,那浏览器Peer-A该如何去解码呢
看到这里,你是不是发现了,这中间少了点啥东西,因为双方不能进行通信啊,你发给我的信息,用不了,我发给你的东西,你用不了;没错,少了媒体协商SDP(session description protcol),所以利用SDP规定,双方都用h264做为共同的编解码器,这样双方都能正确的编解码了!
上面解决了浏览器双方协商的一个大问题,但是还有一个问题,就是网络问题,比如说,两个浏览器不在同一个局域网内,一端可能在深圳,另外一端可能在北京,这个时候呢,就会用到NAT(Net Address Transiation,网络地址转换),这里NAT可能会涉及到它的类型,这里不是文章的重点,不过简单说一下,分为四种类型:
- 完全锥型NAT
- IP限制锥型NAT
- 端口限制锥型NAT
- 对称型NAT
具体大家可以去网上找资料了解一下他们的区别和使用原理,也可以去看之前我推荐的李老师的课程:从0打造一个直播系统
说白了NAT就是网络地址进行一个映射,也就是转换,为啥要转换,这个应该好理解吧,你两个浏览器都不在一个局域网内,那肯定是不能直接进行通信的啊,是吧!
这里还需要STUN(Session Traversal utilities for NAT,NAT会话穿越应用程序),它主要是为终端提供公网IP地址和端口是什么,这里也就是为什么要用它的原因了,只有地址转换也没用,必须能够访问到外网;关于STUN协议的具体解析,大家可以看官网手册:
代码语言:javascript复制https://datatracker.ietf.org/doc/html/rfc5389
但是有时候呢,STUN不可能每次都可以成功的为需要NAT的通话设备分配IP地址的,所以这个时候问题就来了,我们该如何解决呢?
没错,我们还需要TURN(Traversal Using Relays around NAT,在NAT周围使用中继遍历) ,它是STUN的一个扩展,添加了Relayd功能;有了它,就可以解决上面的这个问题了
在STUN分配公网IP失败后,可以通过TURN服务器请求公网IP地址作为中继地址。关于TURN的详细介绍,大家可以看官网手册:
代码语言:javascript复制https://datatracker.ietf.org/doc/html/rfc5766
这里关于网络的转换,换句专业的语句来讲就是网络协商了:Candidate
最终要实现浏览器之间交换信息,我们还需要信令服务器(Signal Server)转发彼此的媒体信息和网络信息。关于信令服务器的介绍就没啥好介绍的了,它就是起着交换浏览器两端的媒体协商和网络协商信息。当然信令服务器还有创建房间和离开房间的作用。
二、利用vscode实战举例:
1、安装Live Server插件
利用vscode安装Live Server插件,他可以在本地开发环境中,实时重新加载(reload)页面:
这里可能会涉及到一些前端和js的知识,有c和c 的基础,很快就可以上手,大家也不用专门花时间去学习,可以看菜鸟教程就行。
2、在google浏览器上打开摄像头
代码构思流程:
- 初始化button、video控件
- 绑定“打开摄像头”响应事件onOpenCamera
- 如果要打开摄像头则点击 “打开摄像头”按钮,以触发onOpenCamera事件的调用
- 当触发onOpenCamera调用时
- 设置约束条件,即是getUserMedia函数的入参
- getUserMedia有两种情况,一种是正常打开摄像头,使用handleSuccess处理;一种是打开摄像头失败,使 用handleError处理
- 当正常打开摄像头时,则将getUserMedia返回的stream对象赋值给video控件的srcObject即可将视频显示出 来
下面是完整代码:
代码语言:javascript复制<!DOCTYPE html>
<html>
<body>
<video id="local‐video" autoplay playsinline></video>
<button id="showVideo" >打开摄像头</button>
<p>通过getUserMedia()获取视频</p>
</body>
<script >
const constraints = {
audio: false,
video: true
};
//处理打开摄像头成功
function handleSuccess(stream) {
const video = document.querySelector("#local‐video");
video.srcObject = stream;
}
// 异常处理
function handleError(error) {
console.error("getUserMedia error: " error);
}
function onOpenCamera(e) {
navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError);
}
document.querySelector("#showVideo").addEventListener("click", onOpenCamera);
</script>
</html>
最终结果如下:
暂时这只是一部分,后期添加音频进去,以及去燥等,后面会进行优化!
三、总结:
好了今天的分享就到这里了,我们下期见!
相关文章参考:
从0打造音视频直播系统
代码语言:javascript复制https://ke.qq.com/webcourse/index.html#cid=468797&term_id=100561187&taid=4217056589719357&vid=5285890796286162335