端对端1V1传输基本流程 十、第一节 媒体能力协商过程

今天我们就进入到了WebRTC学习最关键的一部分知识,那就是端对端的连接,当我们学习完这一部分知识之后,大家就可以自己实现一套实时互动直播系统了,但是这部分知识呢涉及到知识点非常多相应的学习难道也会陡然增加,所以大家 一定要做好心理准备,大家要不断的加深自己的理解,那么下面我们就开始讲解我们这部分知识。

RTCPeerConnection

下面我们介绍一下最关键的概念就是RTCPeerConnection,其实在一开始的时候就给大家做了一个简单的介绍,这个类是整个WebRTC的一个核心类,它是上层的一个统一的接口,但是在底层做了非常多的复杂逻辑,包括了整个媒体的协商,流和轨道的处理,接收与发送,统计数据,都是由这一个类类处理的,所以对上层来说,你可能简单的调用了这个类或者里面的几个简单的API,但是实际在底层做了大量的工作,所以这个类是整个WebRTC的一个核心,我们一定要把这个类弄清楚,下面我们看一下这个类它的基本形式是什么样的。

基本格式

pc = new RTCPeerConnection([configuration];

其实也比较简单,在我们创建这个对象的时候就是new一个RTCPeerConnection,它带一个配置参数,这个参数是可选的,就是可有可无,在我们后面的这个例子里,首先是没有参数的,看它是什么样子的,后面我们在看有参数的时候是什么样子的,但是我们就想用创建这个对象,直接就new一个这个对象就好了,这是它的基本格式,非常简单。

这个类我们可以将它的方法按分类分成下面的四类:

RTCPeerConnection方法分类

媒体协商

那么第一类呢,就是媒体协商相关的,一会儿我们会看到,就是比较简单,就四个方法,但是通过这个方法之后呢,我们就拿到了整个双方之间的媒体信息,然后他们会进行交换,然后去协商那你用的编码器是吗对吧,我用的这个编码器承包你用的音频格式,什么什么我用的音频格式,大概协商一致之后,他才真正地进行数据传输与编解码。

Stream/Track

第二大类就是流与轨道,在整个WebRTC当中,每一路它是一路流,这个流里面有很多轨,有音频轨和视频轨,多路音频轨多路视频轨,在此前MediaStream 那节中已经做过介绍,那在这里是同样的理念,在传输中我们传输的就是Stream和轨,在轨道中就包含了音频数据和视频数据。

传输的相关方法

那么第三个呢,是与传输相关的,就是我们用的是什么协议去传输,HTTP协议,那么通过这个链路的质量好坏,通过HTTP,然后进行反馈。再通过这个数据的统计分析,查看你整个链路的质量是怎样的,是不是已经发生拥塞了?还是说本身的你这个链路就是不太好的,都可以通过这个传输相关的方法来获取到去计算。

统计相关方法

最后一类的就是统计相关的,包括你的这个编解码器,你的这个音频格式,视频格式,你的这个整个传输相关的数据都可以通过这个统计相关的方法回报在后面的课程中呢,我们也会一一看到怎么通过这些方法来获取到这些数据,来为我们真正的这个产品的质量提供帮助,这是RTCPeerConnection方法的分类.

在下面呢,我们就来一类一类的看每一类方法该怎么用,它起到的作用是什么?

媒体协商过程

媒体协商的过程在我们使用这个方法之前呢,我们要了解他的协议是什么,对吧,他媒体是怎样协商出来的?但是这个过程之后呢,我们再看这些API的时候就知道这个调用是非常简单了,否则的话,你即使拿到了这些API,也不知道怎么用。但是它的协商过程呢,就如这张图所示,对于这两个端来说,一个假设是A,第二个是B,对吧,那么A呢,首先是要创建一个offer,创建offer之后呢,实际就形成了一个SDP在我们之前的课程都已经给大家做了一个简单介绍,SDP是什么对吧,他是包含了一些媒体信息和编解码信息,包括这个传输的相关的信息。

在后边儿还会对SDP做详细的介绍。大家现在不用太担心,但首先呢就是A创建了一个offer,这个offer就是SDP的一种描述格式去描述的,创建完了之后呢,他通过云端的信令Channel让他传给谁呢?传给B,但是传之前的那他还要调一个方法叫什么呢?就调setLocalDescription,那他调这个方法是干什么呢?他会触发一个非常重要的动作,大家一定要记住,就是setLocalDescription会触发一个非常重要动作就是去收集candidate,就是收集候选者。那么在我们的传输的相关基础知识部分呢,我实际跟大家做了介绍,当我们去创建这个连接之前呢,是我们首先要拿到所有的那种候选者,就收集候选者,那怎么收集呢?实际我是像这个stun或者是turn发送一个请求,咱们在这个请求过程中呢,我会拿到我本地的IP地址,还有通过NAT之后反射的这个地址以及TURN服务的中继地址。

那它是什么时候触发的呢?什么时候去触发去获取这些候选者呢,就是通过这个setLocalDescription这个方法,当这个方法一调用就开始做这件事儿了,当然是并行的,其实这些事儿就通知去做这件事儿,同时呢,他就将这个offer通过信令服务发给了这个B端了,OK。B端呢,收到这个offer之后,他首先做什么事儿呢?就调用了那个setRemoteDescription,那就将这个offer所形成的SDP的这个数据放到自己远端的这个描述信息的槽里,对他是成为一个槽儿,OK,这样就好了,但这步做完之后呢,他做什么事儿呢?他要回一个answer,也就说他要通过这个PeerConnection就是通过这个链接调用这个创建answer这个方法,也就是说创建一个我本身的这个媒体信息,也就offer的是A这个用户的整个机子的媒体信息,也就是我的编解码器,视频是什么、音频是什么?

我的这个与编解码相关的这个参数也都在里边呢,形成了这个SDP传给B,B收到之后呢,把它放在他的远程的这个描述槽里之后呢,他自己在回个answer,这个answer回的是什么呢?就是我本机我这个B这台机子所有的媒体信息,以及这个网络信息。OK,那它也包括了它的支持的这个音频格式视频格式音频编解码器、视频编解码器对吧,比如音频的参数双声道还是单声道,是这个采样率是一万六一还是三万二还是多少,它也形成这个,它调完之后它也形成这个setLocalDescription,它也做同样的事情,去触发收集候选者,我的这个网络有多少个候选者都要收集起来形成一个列表,调用这个函数之后它触发这个answer,通过这个信令服务就转给了A。A收到这个answer之后它又把它存到这个setRemoteDescription,存到它的远程槽里,这样在每一端实际都有两个SDP,

 

那么第一个SDP是我自己的这个媒体信息,第二个SDP是描述对方的媒体信息。那个拿着这两个媒体信息之后呢,他在内部就进行一个协商,那看我支持的这些格式有没有你支持的,把这一协商之后呢,就取出他们的交集,但你支持的音频最好的是哪个呢?我支持的音频是什么?再取一个交集,同样视频也是,这是视频是什么?我支持的视频是什么啊?那取出这个交集之后,整个协商过程就算建立好了,这个时候他才能进行后面的操作,进行真正的编解码,对吧,传输都传到对方之后呢,因为他们协商好了之后,但对方也知道这是我支持的,所以他也能进行解码,让他去渲染这个音频也好,视频就播放那个视频就渲染。这就是整个儿的一个协商过程。

OK,所以他有四个步骤,对。第一个就是每一端是有四个步骤,但是创建offer啊,设置LocalDescription,然后是接收answer,当设置RemoteDescription,这个调用方;但被调用方,他就是先接收offer,然后设置setRemoteDescription,然后是创建answer上设置setLocalDescription。这就是他们的顺序。

那么下面呢,我们再看看她的一个协商的状态的变化,当我们一开始创建这个RTCPeerConnection的时候呢

他处于stable状态,就是处于一个稳定状态,那么这个时候实际connection就可以用了,但用的时候它是不能进行这个编解码的,为什么呢?因为他没有进行数据协商对吧,虽然我这个connection类是可以用,但是并没有进行数据协商,所以他没法儿进行数据的传输与编解码,怎么才能进行数据传输编解码呢,那就发生了一个状态的改变,就是比如对于调用者来说,他首先创建了connection之后他要创建这个offer,创建offer之后呢通过调用那个setLocalDescription将这个offer设进去之后他就状态变化了,变成什么呢,变成have-local-offer,但是我设完这个之后如果对方没有给我回他的answer的时候,那实际我的状态就一直处于have-local-offer呢,无论我在接受多少次这个setLocalDescription方法仍在处理这个状态对吧,所以他自己对自己的一个循环对我仍然处于这个状态,那这个状态是不会变的,那什么时候才会变呢,只有在你远端的answer回来的时候,像我刚才讲的远端的answer创建好,然后通过消息传给这个调用者的时候,那它才会调用这个setRemoteDescription,那么将answer设进去之后,他又回到了stable状态,这个时候RTCpeerConnection又可以用了,并且呢是已经协商过的了,对吧,这时候他可以进行编解码,进行传输了,这是对于调用者来说,那么对于这个被调用者来说呢,同样道理,那当他收到这个offer之后呢,它要调用setRemote offer,这个时候呢,他从那个stable状态就变成了have-remote-offer,那同样的,当他自己创建了一个answer之后,并且调用了setLocalDescription这个方法将answer设置进去之后,他又从这个remote-offer变成了stable状态,那这个时候他又可以工作了。

 

我们介绍的这个协商,还有这个协商状态并没有讲完,那么今天我们继续完成这部分的这个讲解,那在上节课里头,我们将这个have-local-offer以及have-remote-offer,这两种状态呢,给大家讲完了,也就是说对于调用者来说,首先在创建offer之后呢,会调用赛特logo description将这个offer设置进去,那他的状态呢,就变成了have-local-offer,那当他收到对端的这个answer之后呢,它会调用setRemoteDescription将这个offer设置进去,这样呢,就完成了一个协商,所以呢,他就从这个have-local-offer变为了stable状态,那他就可以继续下面的工作了,而对于被调用者,他首先呢是从信令服务器收到一个offer,那他首先调用setRemoteDescription这个offer,那它就变成了have-remote-offer状态,

这个时候呢他在调用自己的这个create answer, 创建完自己的这个answer之后呢它调用SetLocal description answer那就从这个have-remote-offer变为了stable状态,这样的被调用者他也就完成了自己的协商工作,可以继续下面的这个操作了,但是还是两种情况,会有一种中间的这个状态叫做PRanswer,就是提前应答,这个状态是什么时候会产生呢,就是在双方通讯的时候其中被调用者还没有准备好数据的时候,那可以先创建一个临时的这个answer,那这个临时的answer有一个特点就是它没有媒体数据也就是说没有音频流和视频流,并且将这个发送的方向设置成send  only,什么意思呢, 对于B来说,他回的这个answer是一个什么样的answer呢 ,就是说,我的媒体流还没有准备好,所以就没有媒体流,但是我呢,只能发送,不能接受,当他发给对方A的时候,A收到这样一个send  only,他就知道,对方还不能进入数据,所以这时候他们的通讯虽然是做了的协商,但是他们之间还不能进行通讯。因为第一个是对方没有媒体流,第二个是对方不接受我的数据。处于这样一个状态有什么好处呢?那就是可以提前建立这个链路的连接,也就是说包括ICE,包括这个DLS这些跟链路相关的这个协商其实都已经创建好了,对刚才我们已经介绍了,就是对于B来说,他已经提前准备好了一个answer,但这个answer里有没有媒体数据,但是呢,实际是有网络数据的,我收集的各种各种候选者实际都已经有了。

那么就可以提前交给这个A,那AB之间,实际就是链路层已经协商好了,包括这个DLS还要进行这个握手对吧,它因为是安全加密,加密所以要进行握手,握手的时间其实还是蛮长的,那在B准备好这个自己的流之前,将所有的链路都准备好,那一旦这个B向那个用户申请说想开启音频和视频,当用户授权说可以,这个时候呢,他们拿到数据之后,只要将数据传进去,就可以进行这个通讯了。所以呢,在B没有准备好之前,他可以使用一个PRanswer,就是提前预定好的一个answer给这个A发过去,发过去之后呢,它就变成了这个have-remote-offer这个状态,这是一个中间状态,在这个状态下,双方的这个链路是可以协商好的,只是没有这个媒体数据,当那个B设置好他自己的媒体流之后,就是一切都准备好之后,然后再给他回一个最终的answer,当调用者收到它这个最终的answer之后呢,他又变成了stable状态,那双方就可以就真正协商好了,这时候呢,实际是减少了底层的这个网络流的这个握手,以及一些其他的逻辑处理工作,这样就节省了时间,但对于被调用者也是类似的,所以在他回这个真正的answer之前呢,他是处于这have-local-PRanswer的,当真正的这个最终的Answer,准备好之后呢,再重新设一下setLocalAnswer,他又变成了stable状态,这就是一个整个协商完整的一个状态变化,只有在整个协商完成之后,才能进行我们后边儿的真正的音视频数据的传输以及编解码。这就是协商状态的变化。

那么我看媒体协商有哪些方法呢?

媒体协商方法

createOffer

createAnswer

setLocalDescription

setRemoteDescription

其实在我们刚才已经给大家做过介绍,就是我们上节课有createOffer,那时候就创建一个本地的这个媒体信息,音频编解码视频编解码等等。对于这个对端呢,就是收到offer之后呢,它会创建一个createAnswer,这是第二个方法,也就是说我本地的一个信息最终要传给这个调用者。那第三个就是setLocalDescription,我把我自己本地的这个SDP的描述信息设置好之后我就可以触发去采集这个收集候选者了 。那第四个就是setRemoteDescription,当受到对端的这个描述信息之后,SDP之后呢,将它设的setRemoteDescription这个槽儿里去,在内部他就做了这个真正的协商,就是媒体协商的方法。

createOffer

aPromise =  myPeerConnection.createOffer([options]);
aPromise = myPeerConnection.createAnswer([options]);
aPromise = myPc.setLocalDescription(sessionDescription);
aPromise = myPc.setRemoteDescription(sessionDescription);

我们再来看看这个createAnswer,他的基本格式什么,,就是PeerConnection下边有一个方法就createOffer,那它有一个可选的option,这个option后面我们还会做详细的介绍,还有几个选项,每个选项都有其特殊的意义,当我们做完这个实验之后呢,我们后边儿会对他做详细的介绍啊,那他返回的是一个promise,她会创建成功之后有一个逻辑处理,对吧,创业失败会做另外一个逻辑处理,那这个createAnswer这个格式其实跟他是类似的,就变成了createAnswer,还有一个option,这个option其实就是作用不大,主要是createOffer是这个option有很多作用啊,setLocalDescription的格式就是将createOffer或者createAnswer的结果,包括参数设置到这里就设置好了,同样道理,setRemoteDescription。那这个格式也比较简单,也是刚那个对端的这个sessionDescription设置进来就好了,这是四个协商相关的方法。

Track方法

addTrack

removeTrack

rtpSender = myPc.addTrack(track,stream...);

Parametere

参数说明
track添加到RTCPeerConnection中的媒体轨
stream指定track所在的stream

removeTrack

myPc.remoteTrack(rtpSender);

那么在下来呢,就是Tack方法。要在RTCPeerConnection里就有两个重要的这个Track的方法,一个是添加,一个是移除,这个比较简单,但我们来看看添加添加的格式就是第一个是你要添加的这个Track的是音频的Track还是视频的Track,那么第二个是stream,那么这个stream从哪儿来呢?实际就是我们之前介绍的getUserMedia那里我们会拿到一个流,这个流里面可能有音频Track有视频Track,那你就要遍历一下,让他们一个个都加入到这个PeerConnection里去,这样呢,PeerConnection就可以控制这每一路轨了,对,就从他们那个里边儿可以获取到数据进行这个发送,这是添加。

那么他有一些参数。这个参数刚才我已经介绍,这Track呢,就是媒体轨,对吧,这个stream的就是我们getUserMedia获取的stream。removeTrack这个比较简单,就是将Addtrack里头这个send放进去,然后他就可以这个移除掉了,后边儿呢,我们会看到具体的例子,这些方法都比较简单啊,那除了这个Track这个事件方法之外呢,还有这个事件.

重要事件

onnegotiationneeded

onicecandidate

就是PeerConnection还有几个比较重要的事件,现在呢,我们首先介绍两个,那么第一个是这个协商事件,当我们那个进行媒体协商的时候,就会触发这个,那个onnegotiationneeded就是需要协商,只要协商的时候会触发这个事件啊,那么第二个呢,是onicecandidate,这次就是当我们收到一个ICE的候选者的时候,也会从底层触发这个事件,告诉我们现在有一个候选者来了,那么我们要拿到这个候选者,将它添加到我们的这个ICE里去,这样呢就可以进行这个ICE的这个通讯了,那这是两个重要的事件,通过上面的讲解呢,大家已经对这个整个这个媒体的协商,以及我们一些重要的协商API,还有这个Stream和track的API,以及两个重要的事件,一个是协商的事件,一个是这个候选者,就是我们ICE收集的候选者的一个事件,那么有了这些API和事件之后呢,那我们后边儿就可以做一个真实的例子,那么在下节课里呢,我们会通过一个真实的例子给大家讲解如何使用这些API以及事件,那我们今天就到这里。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值