【监控】应用无感录屏

为了提高下单流程的监控能力,二三年初接入了无感录制与播放,现与大家简单分享。

相关文章

应用无感录屏


一、背景

随着互联网技术飞速发展,网页录屏技术已趋于成熟。例如可将录屏技术运用到在线考试中,实现远程监考、屏幕共享以及录屏等;而在我们开发人员研发过程中,对于部分偶发事件,异常监控系统仅仅只能告知程序出错,而不能清晰的告知错误的复现路径,而录屏技术或许能帮我们定位并复现问题。

二、什么是有感录屏

有感录屏一般指通过获得用户的授权或者通知用户接下来的操作将会被录制成视频,并且在录制过程中,用户有权关闭中断录屏。即无论在录屏前还是录屏的过程中,用户都始终能够决定录屏能否进行。

基于 WebRTC 的有感录屏

1
2
3
4
5
6
7
navigator.mediaDevices.getDisplayMedia({ video: true })
.then(stream => {
// 处理屏幕流
})
.catch(error => {
// 处理错误
});

三、什么是无感录屏

无感录屏指在用户无感知的情况,对用户在页面上的操作进行录制。实现上与有感录制区别在于,无感录制通常是利用记录页面的 DOM 来进行录制。常见的有 canvas 截图绘制视频和 rrweb 录制等方案。

1、canvas 截图绘制视频

用户在浏览页面时,可以通过 canvas 绘制多个 DOM 快照截图,再将多个截图合并成一段录屏视频。但是考虑到假设视频帧数为 30 帧,帧数代表着每秒所需的截图数量,为了视频的流畅和清晰,每张截图为 400 KB ,那么当视频长度为 1 分钟,则需要上传 703.125 MB 的资源,这么大的带宽浪费无疑会造成性能,甚至影响用户体验,不推荐使用。

2、rrweb 录制

rrweb (record and replay the web) 是一个对于 DOM 录制的支持性非常好,利用现代浏览器所提供的强大 API 录制并回放任意 web 界面中的用户操作,能够将页面 DOM 结构通过相应算法高效转换 JSON 数据的开源库。相比较于使用 canvas 绘制录屏,rrweb 在保证录制不掉帧的基础上,让网络传输数据更加快速和轻量化,极大地优化了网络性能。

rrweb 提供 record 和 replay 两个 API,分别实现记录所有增量数据和将记录的数据按照时间戳回放的两个功能。

record

1
2
3
4
5
rrweb.record({
emit(event) {
// 用任意方式存储 event
},
});

rrweb 在录制时会不断将各类 event 传递给配置的 emit 方法,你可以使用任何方式存储这些 event 以便之后回放。

调用 record 方法将返回一个函数,调用该函数可以终止录制:

1
2
3
4
5
6
7
8
let stopFn = rrweb.record({
emit(event) {
if (events.length > 100) {
// 当事件数量大于 100 时停止录制
stopFn();
}
},
});

以下是我工作中真实的调用方式;每200次事件重新制作一次全量快照

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let eventsMatrix = [];
rrweb.record({
emit(event, isCheckout) {
if (isCheckout) {

// 请求接口保存数据
saveData()
// 重置
eventsMatrix = []
}
eventsMatrix.push(event);
},
checkoutEveryNth: 200, // 每 200 个 event 重新制作快照
});

由于每次保存快照的时机依赖于事件的次数或者毫秒数,导致在特定场景下可能你没到阈值但页面发生了跳转而丢失

1
2
3
4
5
6
7
router.beforeEach(async (to, from, next) => {

// 请求接口保存数据
saveData()
// 重置
eventsMatrix = []
})

或者是页面没有跳转,但是报错了,这个时候也应当执行一次剩余事件的上报

隐私

页面中可能存在一些隐私相关的内容不希望被录制,rrweb 为此做了以下支持:

  • 在 HTML 元素中添加类名 .rr-block 将会避免该元素及其子元素被录制,回放时取而代之的是一个同等宽高的占位元素。
  • 在 HTML 元素中添加类名 .rr-ignore 将会避免录制该元素的输入事件。
  • 所有带有.rr-mask类名的元素及其子元素的 text 内容将会被屏蔽。
  • input[type=”password”] 类型的密码输入框默认不会录制输入事件。

replay

1
2
3
4
const events = YOUR_EVENTS;

const replayer = new rrweb.Replayer(events);
replayer.play();

使用 API 控制回放

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const replayer = new rrweb.Replayer(events);

// 播放
replayer.play();

// 从第 3 秒的内容开始播放
replayer.play(3000);

// 暂停
replayer.pause();

// 暂停至第 5 秒处
replayer.pause(5000);

// 销毁播放器 (提示: 这个操作不可逆)
replayer.destroy();

使用 rrweb-player

rrweb 自带的回放只提供所有的 JS API 以及最基本的 UI,如果需要功能更强的回放播放器 UI,可以使用 rrweb-player。

1
2
3
4
5
npm install --save rrweb-player


import rrwebPlayer from 'rrweb-player';
import 'rrweb-player/dist/style.css';

使用

1
2
3
4
5
6
7
new rrwebPlayer({
target: document.body, // 可以自定义 DOM 元素
// 配置项
props: {
events,
},
});

四、常见问题

1、上传的events数据是否超级大

经过实战,其实并不夸张;首先它是增量数据,其次它经过了深度压缩算法;最后,它的大小与页面的复杂度和用户的操作力度成正比;可以放心使用。


喜欢这篇文章?打赏一下支持一下作者吧!
【监控】应用无感录屏
https://www.cccccl.com/20230101/监控/应用无感录屏/
作者
Jeffrey
发布于
2023年1月1日
许可协议