视频播放弱网提示实现

作者:陈盛靖

一、背景

业务群里面经常反馈,视频播放卡顿,视频播放总是停留在某一时刻就播放不了了。后面经过排查,发现这是因为弱网导致的。然而,用户数量众多,隔三差五总有人在群里反馈,有时问题一时半会好不了,用户就会怀疑不是网络,而是我们的系统问题。因此,我们希望能在弱网的时候展示提示,这样用户体验会更友好,同时也能减少一定的客诉。

二、现状分析

我们使用的播放器是chimee(www.chimee.org/index.html)。遗憾的是,chimee并没有视频播放卡顿自动展示loading的功能,不过我们可以通过其插件能力,来编写一个自定义video-loading的插件。

三、方案设计

使用NetworkInformation

常见的方法就是我们通过设定一个标准,然后检测用户设备的网络速度,在到达一定阈值时展示弱网提示。这里需要确定一个重要的点:什么情况下才算弱网?

我们的应用是h5,这里我们可以使用window对象中的NetworkInformation(developer.mozilla.org/zh-CN/docs/...),我们可以通过浏览器的debug工具,打印window.naviagtor.connection,这个对象内部就存储着网络信息:

其中各个属性含义如下表所示:

属性 含义
downlink 返回以兆比特每秒为单位的有效带宽估计,四舍五入到最接近的 25 千比特每秒的倍数。
downlinkMax 返回底层连接技术的最大下行速度,以兆比特每秒(Mbps)为单位。
effectiveType 返回连接的有效类型(意思是"slow-2g"、"2g"、"3g"或"4g"中的一个)。此值是使用最近观察到的往返时间和下行链路值的组合来确定的。
rtt 返回当前连接的有效往返时间估计,四舍五入到最接近的 25 毫秒的倍数。
saveData 如果用户在用户代理上设置了减少数据使用的选项,则返回 true。
type 返回设备用于网络通信的连接类型。它会是以下值之一: bluetooth cellular ethernet none wifi wimax other unknown
onchange 接口的 change 事件在网络连接信息发生变化时被触发,并且该事件由 NetworkInformation(developer.mozilla.org/zh-CN/docs/...) 对象接收。

其中,我们可以通过effectiveType判断当前网络的大体情况,并且可以拿到一个预估的网络带宽(downlink)。我们可以通过监听onchange事件,在网络变差的时候,展示对应的弱网提示。

这个方案的优点是:

  • 浏览器环境原生支持
  • 实现相对简单

但缺点却十分明显:

  • 网络状态变化非实时

effectiveType的变化可能是分钟级别的,对于短暂的网络波动,状态没办法做更精细的把控

  • 存在兼容性问题

对于不同一些主流浏览器不支持,例如Firefox、Safari等

  • 不同设备间存在差异

不同的设备和浏览器,由于其差异,在不同的网络情况下,视频的播放情况是不一样的,如果我们固定一个标准,可能会导致在不同设备下,同一个网络速度,有人明明正常播放视频,但是却提示网络异常,这样用户会感到疑惑。

那有没有更好的方法呢?

监听Video元素事件

chimee底层也是在html video上进行的二次封装,我们可以在插件的生命周期中,拿到对应的video元素节点。而在video标签中,存在这样两个事件:waiting和canplay。

其事件描述如下图所示:

当视频播放卡顿时,会触发waiting事件;而当视频播放恢复正常时,会触发canplay事件。只要监听这两个事件,我们就可以实现对应的功能了。

四、功能拓展

我们知道,现在大多数网站的视频在提示弱网的时候,都会展示当前设备的网络速度是多少。因此我们也希望在展示对应的信息。那么怎么实现网络速度的检测呢?

一个简单的方法是,我们可以通过获取一张固定大小的图片资源(不一定是图片,也可以是别的类型的资源),并统计请求该资源的请求速度,从而计算当前网络的带宽是多少。当然,图片大小要尽可能小一点,一是为了节省用户流量,二是为了避免在网络不好的情况下,图片请求太慢导致一直计算不出来。

具体代码如下:

javascript 复制代码
funtion calculateSpeed() {
  // 图片大小772Byte
  const fileSize = 772;
  // 拼接时间戳,避免缓存
  const imgUrl = `https://xxx.png?timestamp=${new Date().getTime()}`;

  return new Promise((resolve, reject) => {
    let start = 0;
    let end = 1000;
    let img = document.createElement('img');
    start = new Date().getTime();
    img.onload = function (e) {
        end = new Date().getTime();
        // 计算出来的单位为 B/s
        const speed = fileSize / (end > start ? end - start : 1000) * 1000;
        resolve(speed);
    }
    img.src = imgUrl;
  }).catch(err => { throw err });
}
javascript 复制代码
function translateUnit(speed) {
  if(speed === 0) return '0.00 B/s';
  if(speed > 1024 * 1024) return `${(speed / 1024 / 1024).toFixed(2)} MB/s`;
  if(speed > 1024) return `${(speed / 1024).toFixed(2)} KB/s`;
  else return `${speed.toFixed(2)} B/s`;
}

我们可以通过setInterval来轮询调用该函数,从而实时展示当前网络情况。系统流程图如下:

五、总结

我们可以通过Chrome浏览器开发者工具中的Network中的网络配置来模拟弱网情况 具体效果如下:

成功实现视频弱网提示,完结撒花🎉🎉🎉🎉🎉🎉。

相关推荐
哈__2 小时前
入门小白到精通,玩转 React Native 鸿蒙跨平台开发:Button 按钮组件与点击事件
react native·react.js·harmonyos
哈__2 小时前
React Native 鸿蒙开发:内置 Share 模块实现无配置社交分享
javascript·react native·react.js
怕浪猫3 小时前
React从入门到出门 第五章 React Router 配置与原理初探
前端·javascript·react.js
哈__3 小时前
React Native 鸿蒙跨平台开发:LayoutAnimation 实现鸿蒙端表单元素的动态添加动画
react native·react.js·harmonyos
哈__3 小时前
React Native 鸿蒙跨平台开发:Vibration 实现鸿蒙端设备的震动反馈
javascript·react native·react.js
哈__3 小时前
React Native 鸿蒙跨平台开发:LayoutAnimation 实现鸿蒙端页面切换的淡入淡出过渡动画
javascript·react native·react.js
哈__3 小时前
React Native 鸿蒙跨平台开发:Animated 实现鸿蒙端组件的上下滑动入场动画
react native·react.js·harmonyos
UIUV17 小时前
模块化CSS学习笔记:从作用域问题到实战解决方案
前端·javascript·react.js
用户120391129472617 小时前
使用 Tailwind CSS 构建现代登录页面:从 Vite 配置到 React 交互细节
前端·javascript·react.js