WebRTC Internals

1. 概览介绍

打开 Chrome 浏览器,在地址栏输入chrome://webrtc-internals 即可打开调试工具,进入后可以看到类似的页面

image.png

1.1 Create Dump 保存日志

数据包含所有 PeerConnection 涉及到的信息,可供后续问题复盘。

1.2 读取状态日志

WebRTC 读取状态日志的2种标准,两种标准之间存在较大的差异。

  • Standardized:符合W3C的新标准,其代码调用是基于 Promise
  • Legacy Non-Standard:废弃的 google 定义的旧标准,基代码调用是基于 callback
// Standardized 
pc.getStats().then(stats => console.log(stats)) 
// Legacy Non-Standard 
pc.getStats(stats => console.log(stats))

1.3 GetUserMedia

是浏览器获取摄像头和麦克风媒体流的接口,GetUserMedia Request 的 Tab 中可以看到近期调用该API的记录,以及调用参数,有关 getUserMedia 的基本使用。每条记录都会包括:调用的域名、调用时间、音频约束、视频约束,如图:

image.png

navigator.mediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等

  • mediaDevices 上提供了4个方法和一个监听事件

  • enumerateDevices: 获取系统可用的媒体输入和输出设备

  • getSupportedConstraints: 返回一个输入设备可支持的约束属性

  • getDisplayMedia: 开启屏幕共享

  • getUserMedia: 开启媒体输入设备

2. RTCPeerConnection 监控信息详解

可以看到除了GetUserMedia Requests,还有其他的Tab,这些每一个Tab都对应了一个 PeerConnection对象,打开后又可以分为4部分:

image.png

2.1 构造 PeerConnection 的参数

这一部分可以看到我们在构造 PeerConnection的 参数,这个参数是传入参数与默认参数的合并后的结果,PeerConnection 的构造函数详情可以参考 MDN

2.2 PeerConnection 的操作与事件

这里按照时间顺序记录了对 PeerConnection 的一些操作和回调事件

操作

  • createOffer、createAnswer:生成 offer 和 answer,点击展开后可以看到调用参数(参数同样是合并后的值)
  • setLocalDescription、setRemoteDescription: 设置的 local sdp 和 remote sdp,展开后可以看到详情
  • addIceCandidate:将对端的 candidate 添加到 PeerConnection 中

回调事件

  • createOfferOnSuccess、createAnswerOnSuccess:由于 createOffer 和 createAnswer 是异步的,所以这里显示了调用成功之后的结果
  • setLocalDescriptionOnSuccess、setRemoteDescriptionOnSuccess:同样 setLocalDescription 和setRemoteDescription 也是异步的,这里表明是正确调用(也会有调用Failed的情况)
  • signalingstatechange:信令状态的回调,信令状态是调用 setLocalDescription、setRemoteDescription 等API的结果,具体变化情况可以参考下图(信令状态同样重要,比如在'stable'的状态是不能直接设置remote sdp)
image.png

信令状态变化这里可能有点绕,但是如果像下图这样,设置时序或者任何SDP设置的问题可以很明显地看到

image.png
  • icecandidate:收集本地的 candidate,收集动作一般是 setLocalDescription 后由 WebRTC 内部自动完成,然后由回调抛到 JS 层
  • iceconnectionstatechange:ICE 的连接状态发生变化,具体可以参考MDN
  • connectionstatechange:PeerConnection的连接状态发生变化,具体可以参考MDN

2.3 流数据(数值格式 & 图表格式)

这里可以真正的可以看到上行、下行的流数据,其中可以重点观注以下4行(上下连接部分分别的数值和图表格式,其含义和数据源是一致的):

  • inbound-rtp:下行数据,可以分为音频和视频
  • outbound-rtp:上行数据,可以分为音频和视频


    image.png

2.3.1 audio outbound-rtp/remote-inbound-rtp

image.png
  • Kind: audio
  • SSRC: 2840249774 和sdp的mline相对应
  • bytesSent_in_bits/s:上行码率,音频一般在30k左右(静音后会减半),该值并不直接体现在getStats的返回值中,而是需要两次stats计算得出:码率 = (delta bytesSent) / (delta timestamp)
  • packetsSent/s: 每秒发送的数据包 同理是由计算得出
  • retransmittedPacketsSent: 重传包
  • packetsLost:丢包,除以发送的总包数可以得到丢包率
image.png
image.png
  • packetsLost:丢包,除以发送的总包数可以得到丢包率
const deltaLost = currentLost - prevLost; 
const deltaSent = (currentPacketsSent + currentLost) - (prevPacketsSent + prevLost); 
const lostRate = deltaLost / deltaSent; 
  • roundTripTime: 单位是秒

2.3.2 video outbound-rtp/remote-inbound-rtp

视频上行和音频类似,可以重点关注以下几个字段:

image.png

ssrc、codec、packetsSent、bytesSent_in_bit/s这些和音频统计一致

  • frameWidth: 上行视频宽度
  • frameHeight: 上行视频高度

同样可以对应的remote-inbound-rtp里看到远端接收的情况来计算丢包率和roundTripTime

image.png

2.3.3 audio inbound-rtp、video inbound-rtp

这里代表下行数据,大体和outbound-rtp类似,只是这里会包含丢包、audioLevel等数据

3. 实战问题分析

3.1 收到画面模糊

一般发生成通话刚建立时,下图是一个码率比较大的视频上行数据,可以看到刚开始有个明显爬坡的过程,这是因为WebRTC刚建立连接时并不知道网络状况如何,会一点点放开上行的码率,以确保视频的流畅,所以对端刚开始接收的是比较模糊的画面,这个属于正常现象。

image.png

如果在通话中画面模糊一直未恢复,可能是发送端网络比较差,或者采集码率极大,但是限制了 RTC 的上行码率,限制码率可以查看sdp 中是否有b=AS:行,或者如果是通过sender来限制可以通过 transceiverModified 事件来确定是否有maxBitrate的限制

3.2 拉流画面黑屏

需要查看 video 的 inbound-rtp 的下行码率是否有值,如果有值可以排查渲染的问题,如果无值的话,可以查看下发流方的码率,排除发流方发送异常。如果也正常的话需要服务器排查问题。

3.3 拉流无声

需要查看 audio 的 inbound-rtp 接收的 audioLevel 和 totalAudioEnergy,audioLevel 由 totalAudioEnergy 计算得出,值在 [0, 1] 之间,正常说话应该在 0.1 以上

image.png

在实际应用中可能会遇到各种各样的问题,比如打开通话Demo页面开始通话,查看audioLevel是正常有值的,但是如果在开始通话前在控制台输入:

Array(50).fill(0).forEach(() => new AudioContext()); 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容