简析hotjar录屏功能实现原理
简析hotjar录屏功能实现原理
众所周知,hotjar中录屏功能是其重要的一个卖点,看着很牛X酷炫的样子,今天就简单的分析一下其可能实现(这里只根据其请求加上个人理解分析,并不代表hotjar中真实实现必然如此)的原理。
1、获取完整DOM内容
如果要实现完整的录屏功能,在客户端在没有客户允许的前提下,目前是无法做到的,所以只能考虑在服务端来实现,在服务端实现的第一步,就必然需要重现客户端的渲染结果,此时需要完整的发送客户端内容到服务端,在服务端进行完整的渲染。
从布玛的效果来看,获取DOM内容会涉及如下三个请求:
请求1 用来判断该页面内容在服务端是否存在
Request URL: https://in.hotjar.com/api/v1/sites/848493/pages/2338866123/content-id/34b2f50d09fbe08a4444e6691b1be779
Request Method: GET
Status Code: 200
//响应结果
{"exists": false}
请求2 预检请求 没啥说的,应该都知道干啥的
Request URL: https://in.hotjar.com/api/v1/sites/848493/url-hash/4f9e7b2f60ba35900e873ed12b1502ec/content
Request Method: OPTIONS
Status Code: 200
请求3 发送完整DOM内容
Request URL: https://in.hotjar.com/api/v1/sites/848493/url-hash/4f9e7b2f60ba35900e873ed12b1502ec/content
Request Method: POST
Status Code: 200
Request Payload
content: "{"docType":"<!DOCTYPE html>\n","rootId":1,"childre" .......
content_md5: "34b2f50d09fbe08a4444e6691b1be779"
page_id: 2338866123
page_url: "xxxxxxxxx.html"
//响应结果
{"page_content_id": 8784354270, "success": true}
从请求3 中可以看到,content部分其实就是对完整html的json化,这部分内容比较长,只贴出部分内容。
2、获取鼠标移动轨迹
只是获取完整DOM内容只是第一步,在hotjar的录屏功能中,还有一个是获取鼠标运动轨迹,想要绘制运动轨迹,必然要知悉鼠标在时间轴上的位置信息,所以hotjar中,必然要采集鼠标在不同时间点的位置信息,这个可以通过其websocket 请求
Request URL: wss://ws7.hotjar.com/api/v1/client/ws
Request Method: GET
Status Code: 101 Switching Protocols
在ws 请求过程中,会有mouse-move数据包的发送,其基本结构如下:
mouse_move: [{time: 106597, x: 215, y: 115}, {time: 106695, x: 181, y: 105}, {time: 106796, x: 134, y: 139},…]
page_visit_id: 14777325238
page_visit_key: "e9fa998e-5811-4d2f-81d2-bd296c7129af"
其中可以看到mouse_move 数据结构中,包含了时间轴上不断变化的坐标值(x,y),有了基于时间轴的xy坐标,我们绘制内容就变的不那么复杂了。
3、检测并发送DOM变化
除了鼠标运行轨迹之外,用户在页面上的所有行为都会被完整的记录下来,页面的任何变化也都被记录了下来,如果需要在服务端完整的重新演化这种变化,那么需要把完整的变化结构发送到服务器,让服务端进行变化回溯,hotjar是通过ws中发送mutation发送这种结构包的,当然要发送这种结构包,首先要先观测DOM变化,这里也有一种简单的方式(暂时不确定hotjar的实现)HTML5 DOM4级MutatioObserver方法,可以检查页面中的DOM是否发生变化,大家可以做一下简单的测试:
//选择目标观测节点
let target = document.querySelector('目标节点选择器');
// 创建观察者对象
var observer = new window.MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
console.log(mutation);
});
});
// 观测项配置:
var config = { attributes: true, childList: true }
// 开始观测目标节点
observer.observe(target, config);
获取到变化的DOM结构(这种变化也是时序的变化,因为任何操作都可能导致变化,变化必然是有先后顺序的),然后通过ws发送到服务器,通过chrome network可以看到ws中mutation基本的包结构如下:
mouse_move: [{time: 118994, x: 404, y: 135}]
mutation: [{time: 118308,…}, {time: 118312,…}, {time: 118336, c: [{id: 7480,…}]}
page_visit_id: 14777325238
page_visit_key: "e9fa998e-5811-4d2f-81d2-bd296c7129af"
里面包含了DOM节点变化,其中包含变化节点如何变化的(通过节点的所有attribute来应用)
4、变化和轨迹回溯生成视频
最后一切数据准备完毕,需要生成视频了,生成视频当然涉及很多的计算,因为要演化和回溯用户的所有操作,我猜可能的思路是这样的:
- 在服务器启动浏览器 并 启动录屏软件(录屏软件只是猜测可能有其它多种方式)
- 根据页面发送的完整DOM进行初始化内容展示
- 按照时序合并鼠标轨迹和mutation包数据
- 根据时间轴自动操作改变DOM
- 访次结束完成录制
总结
hotjar中还涉及到更多的细节实现,里面很多内容也并没有考虑,比如发送view_port report_content包等都没什么在文章中体现出来,但这些并不影响主线分析,另外因为只是简要分析,所以并不涉及实现细节,有兴趣的欢迎留言讨论。
简析hotjar录屏功能实现原理的更多相关文章
- iOS的录屏功能
iOS的录屏功能其实没什么好说的,因为网上的教程很多,但是网上的Demo无一例外几乎都有一个bug,那就是iPad上会出现闪退,这也体现了国内的教程文档的一个特点,就是抄袭,教程几乎千篇一律,bug也 ...
- 【转载】华为荣耀V9的手机录屏功能如何开启
手机录屏有时候对我们的帮助很大,例如可以录制相应的APP使用教程.微信小程序使用流量讲解视频等,针对于软件开发人员等来说,手机录屏功能针对功能演示视频非常的有帮助.在华为荣耀V9手机中,进行手机录屏有 ...
- 原生 js 录屏功能
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8& ...
- QT+OPENCV实现录屏功能
本文使用QT+opencv来实现对指定窗体画面录制,并保存为avi文件. (1)获取窗体界面 QScreen类有一个grabWindow函数,可以用来获取窗体的画面,这个函数使用很简单,就是传入窗体句 ...
- 【Android 界面效果29】研究一下Android滑屏的功能的原理,及scrollTo和scrollBy两个方法
Android中的滑屏功能的原理是很值得我们去研究的,在知道这两个原理之前,有必要先说说View的两个重要方法,它们就是scrollTo 和scrollBy. Android View视图是没有边界的 ...
- EV录屏 --- 免费无水印,集视频录制与直播功能于一身的桌面录屏软件, 支持录屏涂鸦、实时按键显示、视频体积压缩等实用功能
https://www.ieway.cn/index.html 免费无水印,集视频录制与直播功能于一身的桌面录屏软件,支持录屏涂鸦.实时按键显示.视频体积压缩等实用功能 EVCapture 3.9.7 ...
- 手游录屏直播技术详解 | 直播 SDK 性能优化实践
在上期<直播推流端弱网优化策略 >中,我们介绍了直播推流端是如何优化的.本期,将介绍手游直播中录屏的实现方式. 直播经过一年左右的快速发展,衍生出越来越丰富的业务形式,也覆盖越来越广的应用 ...
- 基于FFMpeg的C#录屏全攻略
最近负责一个录屏的小项目,需要录制Windows窗口内容并压缩保存到指定文件夹,本想使用已有的录屏软件,但是本着学习的态度去探索了FFMpeg,本文主要介绍基于FFMpeg开源项目的C#录屏软件开发. ...
- Fundebug前端JavaScript插件更新至1.7.1,拆分录屏代码,还原部分Script error.
摘要: BUG监控插件压缩至18K. 1.7.1拆分了录屏代码,BUG监控插件压缩至18K,另外我们还原了部分Script error,帮助用户更方便地Debug.请大家及时更新哈~ 拆分录屏代码 从 ...
随机推荐
- 远程唤醒UP Board
前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验和正常的图片.链接,请访问我的博客: http://www.cnblogs.co ...
- JS 计算2个日期相差的天数
<span style="font-size:18px;">function getDays(strDateStart,strDateEnd){ var strSepa ...
- Distributed Management Task Force----分布式管理任务组
http://baike.baidu.com/link?url=Y9HGLs8Qj6pXbbgY6xPdfiGDsQO8Eu1e80B4giQtQ_hAfGNF59byxnLoERYri4Duw7Gw ...
- 全卷积神经网络FCN理解
论文地址:https://people.eecs.berkeley.edu/~jonlong/long_shelhamer_fcn.pdf 这篇论文使用全卷积神经网络来做语义上的图像分割,开创了这一领 ...
- BZOJ 1042: [HAOI2008]硬币购物 容斥+背包
1042: [HAOI2008]硬币购物 Description 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请 ...
- 【bzoj4240】有趣的家庭菜园
只要统计每一个左右分别有多少比他高的去min,然后求和 #include<algorithm> #include<iostream> #include<cstdlib&g ...
- ResultSetMetaData类的介绍
ResultSetMetaData .DatabaseMetaData中的方法介绍 利用ResultSet的getMetaData的方法可以获得ResultSetMeta对象,而ResultSetMe ...
- SDUT oj 选拔赛1 迷之好奇
迷之好奇 Time Limit: 2000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 FF得到了一个有n个数字的集合.不要问我为什么,有钱,任性. FF很好奇 ...
- jconsole工具检测堆内存变化的使用
jconsole将Java写的程序检测. 从Java 5开始 引入了 JConsole.JConsole 是一个内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行.您可以轻松地使 ...
- CSS animation-timing-function 属性中的 steps() 与 step-start,step-end
steps() 设置间隔参数,可以实现分步过渡 第一个参数指定了时间函数中的间隔数量(必须是正整数)第二个参数可选,接受 start 和 end 两个值,指定在每个间隔的起点或是终点发生阶跃变化,默认 ...