10┃音视频直播系统之 WebRTC 中的数据统计和绘制统计图形
tjk 2022-06-22 09:27:28 2022-06-22 30 0
一、数据统计
- 在视频直播中,还有一项比较重要,那就是数据监控
- 比如开发人员需要知道收了多少包、发了多少包、丢了多少包,以及每路流的流量是多少,才能评估出目前用户使用的音视频产品的服务质量是好还是坏
- 如果用户的音视频服务质量比较差时,尤其是网络带宽不足时,可以通过降低视频分辨率、减少视频帧率、关闭视频等策略来调整用户的网络状况
- WebRTC 中的统计信息大体分为三种:inbound-rtp、outbound-rtp、data-channel
- 另外如果你需要查看 WebRTC 的统计数据,可以在 Chrome浏览器下地址栏中输入 chrome://webrtc-internals 即可看到所有的统计信息了
- 当你点进其中一个通道中查看详情,即可看到大概如下的图形界面
- 在接受视频轨信息图中你可以实时看到总共收了多少数据包、多少字节的数据,以及每秒钟接收了多少包、多少字节的数据等统计数据
- 而在发送视频轨信息图中你可以实时看到WebRTC 发送的总字节数、总包数、每秒钟发送的字节数和包数,以及重传的包数和字节数等信息
二、获取统计数据
- WebRTC 提供了一个非常强大的 API,即 getStats(),通过该 API 你就可以获取上面讲述的所有信息
- getStats API 是 RTCPeerConnecton 对象的方法,用于获取各种统计信息
- 通过向 getStats 方法中设置参数或不设置参数来决定你要获得多少统计数据或哪些统计数据
var pc = new RTCPeerConnection();// 获得速个连接的统计信息pc.getStats().then( // 在一个连接中有很多 report reports => { // 遍历每个 report reports.forEach( report => { // 将每个 report 的详细信息打印出来 console.log(report); }); }).catch( err => { console.error(err); }))
三、插件库绘制图形
- 步骤一:需要引入第三方库 graph.js
- 步骤二:启动一个定时器,每秒钟绘制一次图形
- 步骤三:在定时器的回调函数中,读取 RTCStats 统计信息,转化为可量化参数,并将其传给graph.js 进行绘制
- 就可以得到上面的视频轨信息图了
// 引入第三方库 graph.js<script src="/js/graph.js"></script><script>var pc = null;// 定义绘制比特率图形相关的变量var bitrateGraph;var bitrateSeries;// 定义绘制发送包图形相关的变理var packetGraph;var packetSeries;pc = new RTCPeerConnection(null);//bitrateSeries 用于绘制点bitrateSeries = new TimelineDataSeries();//bitrateGraph 用于将 bitrateSeries 绘制的点展示出来bitrateGraph = new TimelineGraphView('bitrateGraph', 'bitrateCanvas');bitrateGraph.updateEndDate(); // 绘制时间轴// 与上面一样,只不是用于绘制包相关的图packetSeries = new TimelineDataSeries();packetGraph = new TimelineGraphView('packetGraph', 'packetCanvas');packetGraph.updateEndDate();// 每秒钟获取一次 Report,并更新图形window.setInterval(() => { if (!pc) { // 如果 pc 没有创建直接返回 return; } // 从 pc 中获取发送者对象 const sender = pc.getSenders()[0]; if (!sender) { return; } sender.getStats().then(res => { // 获取到所有的 Report res.forEach(report => { // 遍历每个 Report let bytes; let packets; // 我们只对 outbound-rtp 型的 Report 做处理 if (report.type === 'outbound-rtp') { if (report.isRemote) { // 只对本地的做处理 return; } const now = report.timestamp; bytes = report.bytesSent; // 获取到发送的字节 packets = report.packetsSent; // 获取到发送的包数 // 因为计算的是每秒与上一秒的数据的对比,所以这里要做个判断 // 如果是第一次就不进行绘制 if (lastResult && lastResult.has(report.id)) { // 计算这一秒与上一秒之间发送数据的差值 var mybytes = (bytes - lastResult.get(report.id).bytesSent); // 计算走过的时间,因为定时器是秒级的,而时间戳是豪秒级的 var mytime = (now - lastResult.get(report.id).timestamp); const bitrate = 8 * mybytes / mytime * 1000; // 将数据转成比特位 // 绘制点 bitrateSeries.addPoint(now, bitrate); // 将会制的数据显示出来 bitrateGraph.setDataSeries([bitrateSeries]); bitrateGraph.updateEndDate();// 更新时间 // 下面是与包相关的绘制 packetSeries.addPoint(now, packets - lastResult.get(report.id).packetsSent); packetGraph.setDataSeries([packetSeries]); packetGraph.updateEndDate(); } } }); // 记录上一次的报告 lastResult = res; });}, 1000); // 每秒钟触发一次 </script>
四、Canvas绘制图形
- 分析源码可知,上面的视频轨信息图都是通过 Canvas进行绘制的
- Canvas可以绘制矩形、路径、圆弧等基本几何图形,通过这些基本图形的组合,可以绘制出其他更加复杂的图形
- 除了绘制各种图形外,Canvas还可以对图形进行颜色填充和边框涂色。而对图形的操作,如旋转、伸缩、位置变换等也是 Canvas 必备的功能
- Canvas 是 HTML5标准中的一个新元素
- Canvas坐标系的原点在画布的左上角,X 坐标从左向右增长,Y 坐标是从上到下增长
- 你可以把它想像成一块“画布”,有了它你就可以在网页上绘制图像和动画了
- 对 2D 图形渲染,使用了 CanvasRenderingContext2D类,底层使用了 Google 开源的 Skia库
- 对 3D 图形渲染,使用了 WebGLRenderingContext类,底层使用的是 OpenGL,不过在 Windows上使用的却是 D3D
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>canvas 实战</title></head><body> <canvas id="canvas" width="150" height="150"> The browser doesn't support the canvas tag. </canvas></body><script> // 从 HTML 获取到 Canvas let canvas = document.getElementById('canvas'); // 得到 Canvas 的渲染上下文 let ctx_2d = canvas.getContext('2d'); // 设置颜色为红色 ctx_2d.fillStyle = "rgb(200,0,0)"; // 设置矩型的大小 ctx_2d.fillRect(10, 10, 55, 50); // 设置颜色为蓝色,并且透明 ctx_2d.fillStyle = "rgba(0, 0, 200, 0.5)"; // 设置矩型大小 ctx_2d.fillRect(30, 30, 55, 50);</script></html>