ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

rrweb Canvas 录制与回放完整指南:recordCanvas、图像快照采样与 WebRTC 流式传输

rrweb Canvas 录制与回放完整指南:recordCanvas、图像快照采样与 WebRTC 流式传输 前端可观测性开发工具【免费下载链接】rrwebrecord and replay the web项目地址https://gitcode.com/gh_mirrors/rr/rrweb点击查看免费下载Canvas 是 HTML 中一种特殊的绘图元素其像素内容默认不会被 rrweb 观测和记录。本文以 docs/recipes/canvas.md 为主线系统讲解如何通过recordCanvas、sampling.canvas、dataURLOptions三个录制配置与UNSAFE_replayCanvas回放配置实现对 Canvas 内容的高保真录制与回放并进一步介绍基于 WebRTC 的实时流式传输插件方案。读完本文你将掌握从“命令级录制”到“按帧图像快照”再到“低延迟实时直播”的完整 Canvas 处理技术栈。为什么 Canvas 默认不被记录普通 DOM 元素的状态可以直接从 HTML 结构、样式与属性中还原但 Canvas 的内容由脚本通过绘图 API 不断绘制而成像素数据不体现在 DOM 中。rrweb 的序列化逻辑packages/rrweb-snapshot/src/snapshot.ts只有在recordCanvas打开时才会对canvas标签执行toDataURL()抓取图像快照否则 Canvas 在快照中只是一个空元素。同时Canvas 绘制指令属于高频、可增量的事件流与 rrweb 的增量快照IncrementalSnapshot模型天然契合因此 rrweb 提供了命令级录制与帧级图像快照两种互补方案分别由recordCanvas与sampling.canvas控制。录制端配置开启 Canvas 观测在 packages/rrweb/src/types.ts 中recordCanvas定义于recordOptionsT其默认值为false见 packages/rrweb/src/record/index.ts。最简单的开启方式如下import { record } from rrweb/record; record({ emit(event) {}, recordCanvas: true, });仅仅设置recordCanvas: true时sampling.canvas缺省为all即记录 Canvas 的每一次绘图调用。此时record()内部会创建CanvasManagerpackages/rrweb/src/record/index.ts并同时挂载三种观察器见 packages/rrweb/src/record/observers/canvas/canvas-manager.tsCanvas 上下文观察器initCanvasContextObserver监听canvas.getContext(2d | webgl | webgl2)的调用记录 Canvas 使用哪种绘图上下文见CanvasContext枚举 packages/types/src/index.ts2D 绘图调用观察器initCanvas2DMutationObserver代理CanvasRenderingContext2D上的方法fillRect、drawImage、arc等逐个记录绘图命令WebGL/WebGL2 绘图调用观察器initCanvasWebGLMutationObserver代理 WebGL 上下文方法并通过“变量表 索引”的方式序列化program、shader、buffer等 WebGL 对象回放端对应 packages/rrweb/src/replay/canvas/webgl.ts 与variableListFor机制 packages/rrweb/src/replay/canvas/deserialize-args.ts。采集到的命令会按requestAnimationFrame帧对齐进行合并startRAFTimestamping与flushPendingCanvasMutations见 canvas-manager.ts最终通过mutationCb产出CanvasMutation增量事件事件类型定义见 packages/types/src/index.ts。命令级录制的适用场景与注意点命令级录制sampling: all保真度最高事件体积也最小但存在两个明显限制只适用于能被完整序列化的绘图调用例如getImageData这类读回操作以及依赖外部资源状态的方法无法原样还原WebGL 命令依赖运行时重建对象program、shader、texture实现复杂度高遇到无法序列化的参数时可能导致个别绘制指令失败回放端会调用errorHandler记录失败见 packages/rrweb/src/replay/canvas/2d.ts。因此对大量使用drawImage、WebGL 渲染或第三方 Canvas 库如 WebGL 地图、游戏引擎的场景帧级图像快照往往是更稳妥的选择。帧级图像快照sampling.canvas 与 dataURLOptionssampling.canvas在 packages/types/src/index.ts 中被定义为all | numberall记录每一次 Canvas 绘制调用默认160 之间的数字以“每秒最多 N 帧”的速率抓取 Canvas 图像快照并在 Web Worker 中编码为图片数据。import { record } from rrweb/record; record({ emit(event) {}, recordCanvas: true, sampling: { canvas: 15, }, // 可选图像格式设置 dataURLOptions: { type: image/webp, quality: 0.6, }, });快照模式的工作原理当sampling.canvas为数字时CanvasManager走initCanvasFPSObserver分支canvas-manager.ts其核心流程为帧率节流通过requestAnimationFrame循环检查时间差timeBetweenSnapshots 1000 / fps未到间隔直接跳过确保每秒最多产生 N 帧canvas-manager.ts全页面扫描getCanvas()遍历document.querySelectorAll(canvas)并用isBlocked过滤被blockClass/blockSelector屏蔽的元素尺寸与上下文保护跳过width或height为 0 的 Canvas避免createImageBitmap抛DOMException对webgl/webgl2且preserveDrawingBuffer false的上下文先执行一次context.clear(COLOR_BUFFER_BIT)把绘制缓冲重新载入内存确保createImageBitmap能读到内容Worker 内编码将ImageBitmap移交ImageBitmapDataURLWorker编码见 packages/rrweb/src/record/workers/image-bitmap-data-url-worker.ts避免编码阻塞主线程Worker 返回 base64 后CanvasManager将其包装为clearRectdrawImage两条 2D 命令写入事件canvas-manager.ts从而复用 2D 命令的回放管线。dataURLOptions 图像格式参数DataURLOptions定义于 packages/types/src/index.ts仅有两个可选字段参数类型默认值说明typestring浏览器默认如image/png输出图片的 MIME 类型如image/webp、image/jpegqualitynumber浏览器默认有损格式jpeg/webp的压缩质量取值范围 01数值越大质量越高、体积越大该选项不只作用于 Canvas 快照同样的dataURLOptions还会被快照序列化逻辑用于2D Canvas 全量快照snapshot.ts和内联图片inlineImages见 snapshot.ts的编码是一组全局的图片编码偏好设置。全量快照中的 Canvas 还原值得注意帧级快照之外的另一个数据来源是全量快照full snapshot。当recordCanvas: true时snapshot.ts会在全量快照阶段为 Canvas 生成rr_dataURL属性2D 上下文先调用is2DCanvasBlank()按 50×50 像素分块检测是否空白packages/rrweb-snapshot/src/utils.ts非空白才序列化toDataURL(...)避免为空白画布产生无意义的大体积数据上下文未知生成同尺寸空白 Canvas 的 dataURL 作为对照仅当两者不同才记录rr_dataURL。回放端在重建节点时遇到rr_dataURL会创建img并绘制到 Canvas 上packages/rrweb-snapshot/src/rebuild.ts从而保证回放一开始就能呈现完整的初始画面。回放端配置UNSAFE_replayCanvas录制的事件需要配合回放配置才能渲染出 Canvas 内容import { Replayer } from rrweb/replay; const replayer new Replayer(events, { UNSAFE_replayCanvas: true, }); replayer.play();UNSAFE_replayCanvas在Replayer中的默认值是falsepackages/rrweb/src/replay/index.ts。当它为true时Replayer的构造逻辑发生如下变化replay/index.tsif (this.config.UNSAFE_replayCanvas) { this.iframe document.createElement(iframe); this.iframe.setAttribute(sandbox, allow-same-origin allow-scripts); } else { this.iframe createSandboxedIframe({ root: this.wrapper }); }即回放 iframe 的 sandbox 属性从默认的受限沙盒变为显式添加allow-scripts从而允许回放内的脚本执行绘图调用。安全警告务必阅读启用 canvas 回放会向回放 iframe 添加allow-scripts并退出 rrweb 沙盒的脚本执行保护。仅在你接受该风险的回放数据上使用UNSAFE_replayCanvas。rrweb 的回放沙盒详见 docs/sandbox.md旨在阻止回放数据中的脚本在 iframe 中执行而 Canvas 回放本质上是“重新执行录制下来的绘图命令”必须放开脚本执行权限因此会显著扩大恶意回放数据的攻击面。生产环境应只对可信来源的回放数据开启该选项优先将录制端与回放端都部署在受控环境中若数据经过第三方传输应配套鉴权与完整性校验。回放阶段的行为差异开启UNSAFE_replayCanvas后回放端还会同步开启以下行为全量快照重建后自动调用preloadAllImages()预加载事件内的图片资源replay/index.ts确保后续drawImage时图像已就绪收到IncrementalSource.CanvasMutation事件时不再提前返回而是进入 canvas 增量应用流程replay/index.ts增量事件通过 packages/rrweb/src/replay/canvas/index.ts 分发WebGL/WebGL2 命令交给webglMutation其余按 2D 处理默认回退兼容 rrweb 1.1.x 之前的格式2D 命令应用时会先异步反序列化参数——ImageBitmap、Blob、ArrayBuffer等序列化参数被还原为真实对象再按序调用上下文方法2d.ts、deserialize-args.ts过程中失败的调用通过warnCanvasMutationFailed记录告警。进阶方案WebRTC 实时流式传输 Canvas对于实时直播类场景如在线协作白板、游戏观战命令级录制会持续产生大量增量事件网络传输与回放端的命令重放都存在延迟。rrweb 为此提供了两个官方插件通过 WebRTC 将 Canvas 内容以视频流方式实时传输rrweb-plugin-canvas-webrtc-record录制端rrweb-plugin-canvas-webrtc-replay回放端录制端接入import { record } from rrweb/record; import { RRWebPluginCanvasWebRTCRecord } from rrweb/rrweb-plugin-canvas-webrtc-record; const webRTCRecordPlugin new RRWebPluginCanvasWebRTCRecord({ signalSendCallback: (msg) { // 提供 webrtc sdp offer 信号与连接消息 // 务必发送给回放端的 webRTCReplayPlugin.signalReceive(signal) sendSignalToReplayer(msg); }, }); record({ emit: (event) { // 将事件发送给回放端的 replayer.addEvent(event) sendEventToReplayer(event); }, plugins: [ webRTCRecordPlugin.initPlugin(), ], recordCanvas: false, // Canvas 录制交给插件处理这里显式关闭 });插件构造参数说明详见 插件 READMEsignalSendCallback发送 WebRTC 信令SDP offer、连接消息的回调负责与回放端建立 P2P 连接recordCrossOriginIframes默认关闭与 rrweb 的recordCrossOriginIframes选项相互独立。开启后插件会接受来自任意源的postMessage命令但它不校验嵌入页面身份也不做信令白名单因此仅在页面能通过Content-Security-Policy: frame-ancestors等机制限制嵌入来源时才建议开启同源命令无需开启即可工作而来自无allow-same-origin沙盒帧的不透明源消息必须显式开启才能接收。回放端接入import { Replayer } from rrweb/replay; import { RRWebPluginCanvasWebRTCReplay } from rrweb/rrweb-plugin-canvas-webrtc-replay; const webRTCReplayPlugin new RRWebPluginCanvasWebRTCReplay({ canvasFoundCallback(canvas, context) { // 找到需要直播的 canvas 后把 id 发回录制端 // 由录制端调用 webRTCRecordPlugin.setupStream(id) sendCanvasIdToRecordScript(context.id); }, signalSendCallback(signal) { // 把信令发回录制端由 webRTCRecordPlugin.signalReceive(signal) 接收 sendSignalToRecordScript(signal); }, }); const replayer new Replayer([], { UNSAFE_replayCanvas: true, // 必须开启 canvas 回放 liveMode: true, // 直播模式用于持续接收事件 plugins: [webRTCReplayPlugin.initPlugin()], }); replayer.startLive(); // 以直播模式启动 replayer.addEvent(event); // 每当从录制端收到事件时调用回放端同样要求UNSAFE_replayCanvas: trueWebRTC 回放本质仍是执行绘图命令因此上述安全警告同样适用。整体信令流程为录制端signalSendCallback→ 回放端signalReceive回放端canvasFoundCallback上报 canvas id → 录制端setupStream(id)开始推流。配置速查表与选型建议配置位置取值效果recordCanvasrecord()true/false默认是否记录 Canvas 内容的总开关sampling.canvasrecord()all默认/ 160all记录每次绘图调用数字表示每秒最多 N 帧图像快照dataURLOptionsrecord(){ type, quality }快照与内联图片的编码格式与质量UNSAFE_replayCanvasnew Replayer()true/false默认回放 Canvas开启后 iframe 增加allow-scriptspluginsrecordCanvas: false两侧两个 WebRTC 插件通过 WebRTC 实时流式传输 Canvas方案选型参考高保真、低流量、可回放快进选择recordCanvas: truesampling: all命令级录制适合绘制调用可完整序列化的 2D/WebGL 应用兼容性强、实现简单选择recordCanvas: truesampling.canvas: 15帧级快照适合大量drawImage、第三方库或无法保证命令可序列化的场景帧率建议在 530 之间权衡体积与流畅度实时直播、低延迟优先使用两个 WebRTC 插件将 Canvas 内容以流方式传输并显式关闭recordCanvas避免双重采集。在实施前建议先在目标浏览器尤其是 WebGL 与OffscreenCanvas支持情况上验证所选方案的帧率与事件体积再根据实际数据规模调整sampling.canvas与dataURLOptions.quality。赞分享前端可观测性开发工具【免费下载链接】rrwebrecord and replay the web项目地址https://gitcode.com/gh_mirrors/rr/rrweb点击查看免费下载相关推荐rrweb Canvas 录制与回放实战指南从 recordCanvas 配置到 WebRTC 插件方案rrweb Canvas 录制与回放实战指南从 recordCanvas 配置到 WebRTC 插件方案 导读 Canvas 是 Web 上最特殊的 HTML前端可观测性开发工具rrweb与Canvas/WebGL实现网页多媒体内容录制与回放的终极指南rrweb与Canvas/WebGL实现网页多媒体内容录制与回放的终极指南 rrwebrecord and replay the web是一个强大的开源项前端可观测性开发工具如何使用rrweb实现网页交互录制与回放完整实用指南如何使用rrweb实现网页交互录制与回放完整实用指南 rrweb 是一款强大的开源网页交互录制与回放工具能够精准记录用户在网页上的所有操作并完美重现。无论是前端可观测性开发工具上一篇Quarkus安全与认证授权深度指南下一篇Mac Mouse Fix终极指南让你的普通鼠标在macOS上超越触控板体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表