资源下载地址:https://download.csdn.net/download/sheziqiong/85773105
资源下载地址:https://download.csdn.net/download/sheziqiong/85773105

基于HTML5实现的录屏器

1.项目简介

如果你爱打游戏,一定打过魔兽争霸3(暴露年纪),你也许会游戏导出的录像文件感到好奇,明明打了一个小时游戏,为什么录像才几百KB而已。不过很快你又发现另一个问题,在每次导入录像的时候需要重新加载一次地图,否则就不能播放。

录像记录的数据不是一个视频文件,而是带着时间戳的一系列动作,导入地图的时候,实际相当于初始了一个状态,在这个状态的基础上,只需要对之前的动作进行还原,也就还原了之前的游戏过程,这就是repl的基本原理了

相关问题:《魔兽争霸》的录像,为什么长达半小时的录像大小只有几百 KB?

但是这样有什么好处呢?

首先是对于一个录像,这样的方式极大程度的减小了体积,假设我们需要录一个小时的1080p24f视频,在视频未压缩的情况下

总帧数 = 3600s * 24 = 86400frame假设每个逻辑像素用RGB三基色表示,每个基色8bits(256色)
帧大小 = (1920 * 1080)pixels * 8bits * 3 = 49766400bits换算成KB是 49766400bits / 8 / 1024 = 6075KB总视频体积 = 6075KB * 86400 = 524880000KB ≈ 500GB

所以对比传统的视频录像方法,假设录像是500KB,那么理论上体积上缩小了大约 524880000KB / 500KB ≈ 1000000倍

Web录屏器其实也借鉴这样的一种思路,工程上一般称之为Operations Log, 本质上他的实现也是通过记录一系列的浏览器事件数据,利用浏览器引擎重新渲染,还原了之前的操作过程,也就达到了“录屏器”的效果

从实际来看,即使对比采用H.265压缩比达到几百倍的压缩视频,体积上至少也能节省200倍以上

对比传统的视频流,它的优势也是显而易见的

1. 极大程度减小录像文件体积
2. 极低的CPU与内存占用比率
3. 无损显示,可以进行无极缩放,窗口自适应等
4. 非常灵活的时间跳转,几乎无法感知的缓冲时间
5. 所有信息都是活的,文本图片可以复制,链接可以点击,鼠标可以滚动
6. 可以方便的录制声音,并让声音和画面同步,还以类似YouTube那样把声音翻译成字幕
7. 方便进行视频细节的修改,例如显示的内容进行脱敏,生成热力图等
8. 记录的序列化数据,十分利于知乎进行数据分析   ...

那么问题来了:为什么要对网页录像?有哪些应用场景?

我能想到的主要有以下几个方面

  1. 异常监控系统,例如LogRocket,可以理解他是一个整合了Sentry + 录屏器的工具,能回放网页错误时的图形界面与数据日志,从而帮助Debug
  2. 记录用户的行为进行分析,例如MouseFlow。甚至还可以是直播的方式LiveSession,“连接”到用户的浏览中,看看用户是怎么使用网站的
  3. 对客服人员的监控,例如阿里的有十万级别的客服小二人员分散在全国各地,需要对他们的服务过程进行7x24小时的录屏,在这个数量级上的对监控的性能要求就非常高了,阿里内部的工具叫XReplay
  4. 协同工具,例如协同文档和协同编辑器等,会涉及类似的技术


2.Web录屏器的技术细节

对DOM进行快照

通过DOM的API可以很轻易的拿到页面的节点数据,但是对于我们的需求而言,显而DOM Node提供的数据太冗余了,这一步通过参考VirtualDom的设计,把信息精简一下

interface VNode{id: numbertag: stringattrs: { [key: string]: string }children: (VNode | string )[]
}

对DOM进行深度遍历后,DOM被映射成了VNode类型节点,需要记录的 Node 主要是三种类型 ELEMENT_NODECOMMENT_NODETEXT_NODE,之后在播放时,只需要对VNode进行解析,就可以还原成记录时的状态了

在这过程中,有一些节点和属性需要特殊处理,例如

  • InputElement等类型的Value是从DOM无法获取的,需要从节点中对象中获取
  • script标签的内容由于之后不会去执行,所以可以直接skip或者标记为noscript
  • SVG可以直接获取,但是它本身以及它的子元素重新转换为DOM的时候需要使用createElementNS("http://www.w3.org/2000/svg", tagName)的方法创建元素
  • srchref属性如果是相对路径,需要把他们转换为绝对路径

2.1记录影响页面元素变化的Action

DOM的变化可以使用MutationObserver, 监听到attributes,characterData,childList 三种类型的变化

const observer = new MutationObserver((mutationRecords, observer) => {// Record the data
})
observer.observe(target, options)

再借助WindowEventHandlers addEventListener 等的能力组合,就可以监听到页面一系列的操作事件了

- Add Node Action
- Delete Node Action
- Change Attribute Action
- Scroll Action
- Change Location Action
...

通过 mouseMoveclick 事件记录鼠标动作

对于 mouseMove 事件,在移动的过程中会频繁的触发,产生很容冗余的数据,这样的数据会浪费很多的空间,因此对于鼠标的轨迹,我们只采集少量的关键点,最简单的办法是使用节流来减小事件产生的数据量,但是也有一些缺点:
1. 截流的间隔中可能会丢失关键的鼠标坐标数据
2. 即时通过截流在移动距离足够长的时候任然会产生巨大的数据量,更好的办法是通过 Spline Curves(样条曲线) 函数来计算得出移动轨迹、抖动、加速度等生成一条路径曲线用来控制鼠标的移动

Input的变换我们可以通过Node.addEventListenerinput blur focus 事件监听,不过这只能监听到用户的行为,如果是通过JavaScript对标签进行赋值,我们是监听不到数据的变化的,这时我们可以通过Object.defineProperty来对一些表单对象的特殊属性进行劫持,在不影响目标赋值的情况下,把value新值转发到自定的handle上,统一处理状态变化

const elementList: [HTMLElement, string][] = [[HTMLInputElement.prototype, 'value'],[HTMLInputElement.prototype, 'checked'],[HTMLSelectElement.prototype, 'value'],[HTMLTextAreaElement.prototype, 'value']]elementList.forEach(item => {const [target, key] = itemconst original = Object.getOwnPropertyDescriptor(target, key)Object.defineProperty(target, key, {set: function(value: string | boolean) {setTimeout(() => {handleEvent.call(this, key, value)})if (original && original.set) {original.set.call(this, value)}}})})

2.2通过样条曲线模拟鼠标轨迹

用户在网页中移动鼠标会产生很多mouseMove事件,通过 const {x,y} = event.target 获取到了轨迹的坐标与时间戳

假如我在页面上用鼠标划过一个的轨迹,可能会得到下图这样的坐标点

但是对于录屏这个业务场景来说,大部分场合我们并不要求100%还原精确的鼠标轨迹,我门只会关心两种情况:

1. 鼠标在哪里点击?
2. 鼠标在哪里停留?

那么通过这个两个策略对鼠标轨迹进行精简后,画一个大约只需要6个点,通过样条曲线来模拟鼠标的虚拟轨迹,当 t = 0.2 的时候,就可以得到一个下图这样带着弧度的轨迹了

通过规则筛选出关键点后,利用B样条曲线计算函数,按照最小间隔进行取样并插入我们的鼠标路径队执行列里,当渲染时重绘鼠标位置的时候,就可以得到一个近似曲线的鼠标轨迹了

2.3通过鼠标数据生成热力图

之前已经通过鼠标事件记录了完整的坐标信息,通过heatmap.js可以很方便的生成热力图,用于对用户的行为数据进行分析。

这里需要注意的地方是当页面切换的时候我们需要重置热力图,如果是单页应用,通过 Historypopstatehashchange 可以监听页面的变化

2.4对于用户隐私的脱敏

对于一些客户个人隐私数据,通过在开发时DOM进行标注的 Node.COMMENT_NODE(例如: <!-- ... -->)信息申明,我们是可以获取并加工的。通过约定好的声明对需要脱敏的DOM块进行处理,在渲染的时候通过CSS打上马赛克或模糊处理即可

2.5沙箱化提升安全

录制的内容有可能属于第三方提供,这意味着可能存在一定的风险,网站中可能有一些恶意的脚本并没有被我们完全过滤掉,例如:<div onload="alert('something'); script..."></div>,或者我们的播放器中的一些事件也可能对播放内容产生影响,这时候我们需要一个沙盒来隔离播放内容的环境,HTML5 提供的 iframe sandbox是不错的选择,这可以帮助我们轻易的隔离环境:

- script脚本不能执行
- 不能发送ajax请求
- 不能使用本地存储,即localStorage,cookie等
- 不能创建新的弹窗和window, 比如window.open or target="_blank"
- 不能发送表单
- 不能加载额外插件比如flash等
- 不能执行自动播放的tricky. 比如: autofocused, autoplay

2.6基于视频GOP(I/B/P帧)算法的压缩技术

// TODO

2.7播放、跳转与快进

播放:播放器会内置一个精确的计时器,动作的数据存储在一个栈中,栈中的每一个对象就是一帧,通过RAF(requestAnimationFrame) 对数据帧的时间戳进行扫描从而得知下一帧在什么时间发生

暂停:通过cancelAnimationFrame暂停计时器

快进:加速采集速率的倍速

跳转:跳转相当于一个最快速的快进功能,但是如果跳转的距离太远,性能会非常差,这时需要按一定的距离对播放轴插入预先的snapshot,再从最近的snapshot进行跳转

2.8在客户端进行的Gzip压缩

Gzip一般是在网络应用层里对传输数据进行压缩,但是我们的数据不一定只存在数据库里,可能会有三种储存方式

  1. 服务器存储 TCP => DB
  2. 本地储存 localStorage、indexDB、web SQL
  3. 保存为本地文件,例如直接导出可运行的HTML文件

利用客户端的运算能力,在进行导出或者传输之前,可以对数据进行压缩,极大程度的减小体积

在客户端可以进行基于 Gzip 的数据包压缩,Gzip是基于哈夫曼二叉树的

相关文章:How gzip uses Huffman coding

2.9数据上传

对于客户端的数据,可以利用浏览器提供的IndexDB进行存储,毕竟IndexDB会比LocalStorage容量大得多,一般来说不少于 250MB,甚至没有上限,此外它使用object store存储,而且支持transaction,另外很重要的一点它是异步的,意味着不会阻塞录屏器的运行
之后数据可以通过WebSocket或其他方式持续上传到OSS服务器中,由于数据是分块进行传输的,在同步之后还可以增加数据校验码来保证一致性避免错误。

资源下载地址:https://download.csdn.net/download/sheziqiong/85773105
资源下载地址:https://download.csdn.net/download/sheziqiong/85773105

基于HTML5+JavaScript实现的网页录屏器设计相关推荐

  1. 补充记录vue3中rrweb-player组件实现网页录屏的一个BUG解决

    项目场景: vue3中rrweb-player组件实现网页录屏功能 问题描述 提示:这里描述项目中遇到的问题: 录制的视频会重复记录录制中这个按钮的状态,每打开一次开始录制视频中就会多一个按钮,bug ...

  2. 网页录屏将视频截图保存成gif图片并压缩的方法超详细

    我在一个网站上找到一个视频素材很不错.于是利用360浏览器的网页录屏功能.先把视频录下来了.然后.使用迅雷播放器的gif工具.截取了需要的界面.然后手动选中要生成的时间轴!然后选择不同的分辨率即可! ...

  3. html5+javascript+css实现---网页版坦克大战---无需运行环境

    html5+javascript+css实现-网页版坦克大战-无需运行环境,只需一个浏览器,重拾少年情. 运行环境-除老版IE浏览器都可以: 源码需要请:点赞留言邮箱: 可以跳关,回退关卡.支持双人坦 ...

  4. 网页录屏怎么录制?有哪些好用的录屏方法?

    有时候我们需要录制网页上的视频或操作过程,这时候就需要使用录屏软件来进行录制.下面将介绍几种好用的录屏方法. 使用在线录屏工具 有一些在线录屏工具可以直接在网页上进行录制,无需下载安装任何软件.其中比 ...

  5. 基于JAVA智慧公寓系统演示录屏2021计算机毕业设计源码+系统+lw文档+部署

    基于JAVA智慧公寓系统演示录屏2021计算机毕业设计源码+系统+lw文档+部署 基于JAVA智慧公寓系统演示录屏2021计算机毕业设计源码+系统+lw文档+部署 本源码技术栈: 项目架构:B/S架构 ...

  6. c语言六位抢答器课程设计,基于c语言单片机8位竞赛抢答器设计课程设计.docx

    基于c语言单片机8位竞赛抢答器设计课程设计 课程设计报告课程名称:单片机课程设计报告题目:8位竞赛抢答器的设计学生姓名:所在学院:信息科学与工程学院专业班级:学生学号:指导教师:2013 年12月25 ...

  7. 单片机包络检波c语言,基于AVR单片机的125kHz简易RFID阅读器设计.PDF

    基于AVR单片机的125kHz简易RFID阅读器设计 基于AVR单片机的125 敖 华1,陈渊睿1'2,骆祖国1,李婷1 510640) (1.华南理工大学电力学院,广东广州510640:2.华南理工 ...

  8. 基于Qt的仿酷狗音乐播放器设计(二)

    简述 在上一文"基于Qt的仿酷狗音乐播放器设计(一)"中,博主给出了仿酷狗界面的部分内容,在本文中将继续分析酷狗界面,并作出相应的分析. 下面我们来看一下酷狗界面中的左侧滑动页控制 ...

  9. 【毕业设计】爱琴海——基于HTML5的婚庆用品商城网页设计

    一.内容简介 (一)背景与意义 "婚俗"是指结婚的风俗,各国各族人民按照自己的习俗,举行各具特色的婚礼,具有各自浓厚的民族独特风采.婚俗元素在是中国婚俗文化的媒介,承载了中华儿女对 ...

最新文章

  1. 创建节约内存的JavaBean
  2. JUnit4测试框架设计与实现
  3. 数据回显---SpringMVC学习笔记(九)
  4. Cannot find module '@babel/plugin-proposal-class-properties'
  5. Spark基础学习笔记20:RDD持久化、存储级别与缓存
  6. Unity Shader:Waveform波形(3)-复合波
  7. MTK 驱动开发(54)---MTK-thermal.conf温度参数修改的方法
  8. 别再瞎找了,设计师日常工作需要的软件都在这里了
  9. 企业应用大数据探索发展新路径
  10. HTML5与phonegap接口对比
  11. SDN核心技术与内容
  12. [大学物理实验-0]修约规则和常见的实验数据的处理
  13. 算法 | 你知道算法为什么这么重要吗?
  14. HMC5883L 电子指南针
  15. [VOT10](2022CVPR)TCTrack: Temporal Contexts for Aerial Tracking
  16. 暗黑地牢dlc文件夹或mods文件夹中某个mod在初始界面开新档不显示/不加载的解决办法
  17. 樱花樱花想见你:关于不一样的爱
  18. 共享软件开发者、独立软件开发者
  19. 【OFDM系列6】MIMO-OFDM系统模型、迫零(ZF)均衡检测和最小均方误差(MMSE)均衡检测原理和公式推导
  20. docker 搭建在线office--onlyoffice (一)

热门文章

  1. 深度模型的日志异常检测,还有谁不会?
  2. 没有技巧的运营公众号,大概率是用爱发电吧!
  3. 2022程序员都推荐的算法编程课程终于来了!新手从入门到面试考点全覆盖,学到就是赚到!...
  4. 鸿蒙os跑分,预装鸿蒙OS 2.0!华为MatePad Pro2跑分曝光:麒麟9000、8GB内存
  5. FAT文件系统(stm32)
  6. NYOJ-71 独木舟上的旅行
  7. 树莓派4B安装Ubuntu Mate20.04
  8. Ubuntu20.04安装中国版firefox
  9. 笔记本发烫很卡很慢 占CPU100%
  10. 解决xhtmlrenderer flying-saucer-pdf-itext5 生成pdf时html中table分页内容太多挤到第二页问题。