• 10┃音视频直播系统之 WebRTC 中的数据统计和绘制统计图形


    一、数据统计

    • 在视频直播中,还有一项比较重要,那就是数据监控

    • 比如开发人员需要知道收了多少包、发了多少包、丢了多少包,以及每路流的流量是多少,才能评估出目前用户使用的音视频产品的服务质量是好还是坏

    • 如果用户的音视频服务质量比较差时,尤其是网络带宽不足时,可以通过降低视频分辨率、减少视频帧率、关闭视频等策略来调整用户的网络状况

    • WebRTC 中的统计信息大体分为三种:inbound-rtpoutbound-rtpdata-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 必备的功能

    • CanvasHTML5 标准中的一个新元素

    • 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>

     

     

  • 相关阅读:
    java基础知识一
    汽车标定技术(五)--基于模型开发如何生成完整的A2L文件(1)
    如何在Nuxt3.0中使用MongoDB数据库
    C++ opencv图像直方图
    ROS系统通过类定义实现数据处理并重新发布在另一话题
    激活Windows时出现错误代码0xC004C003怎么办?
    发现区块链世界的新大门——AppBag.io DApp导航网站全面解析
    记录一个hive中因没启yarn导致的spark引擎跑insert语句的报错
    学习笔记-Power-Linux
    对抗训练理论分析:自适应步长快速对抗训练
  • 原文地址:https://www.cnblogs.com/autofelix/p/16287408.html