V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
firhome
V2EX  ›  程序员

这个前端录屏原理是怎么实现的?有大佬知道吗?

  •  
  •   firhome · 2018-07-13 11:21:25 +08:00 · 8785 次点击
    这是一个创建于 2324 天前的主题,其中的信息可能已经有所发展或是发生改变。
    在找关于前端监控的一些资料的时候 看到 这篇文章:
    https://zhuanlan.zhihu.com/p/37182714

    非常好奇它这个记录行为的“录屏” 是怎么实现的?
    21 条回复    2020-09-16 11:05:42 +08:00
    SouUED
        1
    SouUED  
       2018-07-13 11:30:54 +08:00
    网页转换为 canvas,canvas 传帧到后台,后台在生成视频
    randyzhao
        2
    randyzhao  
       2018-07-13 11:33:45 +08:00
    感觉是通过插件,记录下每个 click 的位置,click 动作触发的时间、时长,用户的屏幕分辨率。
    然后“重放”用户行为的时候:
    实际是根据先前记录的用户屏幕分辨率 load 起来一个页面,再用 js 绘制一个“假鼠标”。
    然后根据之前记录的 click 事件的时间,位置,来模拟这个假鼠标的行走轨迹
    randyzhao
        3
    randyzhao  
       2018-07-13 11:35:08 +08:00
    咦。。。一楼说的。。。也行。。。真的生成视频么?
    好土豪的样子
    firhome
        4
    firhome  
    OP
       2018-07-13 11:42:32 +08:00
    @SouUED 效率不会有问题么? 我比较赞同 下面评论区说的那样,记录鼠标 点击,DOM 的位置。然后报错的时候再上报。 但是 网页界面的表现 不知道背后的原理
    Quarter
        5
    Quarter  
       2018-07-13 11:47:39 +08:00 via iPhone
    @randyzhao #2 你说的这个感觉数据量会少一点,但是感觉没有一楼的方便呐,另外,题外话,一秒 24 个数据,可获得电影级流畅体验😂
    OSF2E
        6
    OSF2E  
       2018-07-13 11:49:50 +08:00
    @randyzhao #3
    用四大发明之一的活字印刷术的原理类比一下:
    每修改一次活字布局就拍一张照片,并按时间顺序保存照片,把照片流转换为逐帧动画就能“场景重现”了。
    另外根据视频中动画的流畅度来看,十有八九用的 canvas,也就是一楼说的原理。
    chinaglwo
        7
    chinaglwo  
       2018-07-13 11:50:36 +08:00
    有没有 ios 或 Android 的解决方案
    firhome
        8
    firhome  
    OP
       2018-07-13 11:54:29 +08:00
    @OSF2E 但是作为一个 监控日志 的脚本 这种方法 上传照片 体积不会很大吗?
    OSF2E
        9
    OSF2E  
       2018-07-13 11:59:20 +08:00
    @firhome 不一定是直接截图,只要把视图渲染逻辑描述清楚,理论上,用 dom+css3/canvas/svg/ios-view/android-view 等视图引擎都可以复现原始视图,例如 react 的 vDOM 思想就是这个原理
    LeungJZ
        10
    LeungJZ  
       2018-07-13 12:00:25 +08:00
    #1 的方案几乎最好吧。但是截屏好像截不了鼠标,而且,最关键的是,要流畅播放,需要一秒 24 帧,那报错的时候,岂不是要上传好几十兆甚至上百兆的图片?

    #2 的方案应该最通用。
    randyzhao
        11
    randyzhao  
       2018-07-13 12:07:40 +08:00
    @OSF2E 没仔细看链接 就看了下官网的描述。。。

    又看了遍链接里的视频,应该是 #1 的做法。
    Sparetire
        12
    Sparetire  
       2018-07-13 12:30:59 +08:00 via Android
    记录各种事件生成队列,上传队列以后重放各种事件
    tjsdtc
        13
    tjsdtc  
       2018-07-13 16:01:59 +08:00
    @randyzhao 感觉还是 canvas 截屏简单点,你这个方案如果是每个用户都不同的页面就比较麻烦了,不同的页面都还要回传不同的参数,很难做通用处理
    silencefent
        14
    silencefent  
       2018-07-13 16:56:17 +08:00
    用 canvas 画,家里有矿吧
    randyzhao
        15
    randyzhao  
       2018-07-13 17:28:26 +08:00
    @tjsdtc 嗯 是的。我这个方案,简单的说,很容易出 bug。。。。。
    aryu
        16
    aryu  
       2018-07-13 21:55:17 +08:00   ❤️ 2
    不确定 fundebug 是怎么做的,不过看原理应该和国外一个很成熟的产品 logrocket 中的回放功能类似。

    首先这类功能一般是为了用户行为追踪或者捕获异常前的操作信息,以 sdk 的形式集成到用户的应用中。
    因此侵入性强、计算消耗大、网络开销多的方案都是不可能产品化的,上面讨论的 canvas 方案基本也就不可能。

    具体来说可以把这个过程看作是 DOM 快照链。

    第一步:对界面 DOM 进行一次全量快照。这一步还包括样式的收集、js 脚本的去除等,并通过一定的规则给当前的每个 DOM 元素标记一个 id。

    第二步:监听所有可能对界面产生影响的事件,例如各类鼠标事件、输入事件、滚动事件、缩放事件等等,每个事件都记录 payload 和 target,target 是某个 DOM 元素的话就记录为第一步中的 id,这样比记录一个 css selector 数据量要小不少,同时还会定时获取鼠标的绝对坐标,有变化时也记录为一个事件。这样的每一次变化事件可以记录为一次增量的快照。

    第三步:一些优化处理,比如浏览器端存一定量的增量快照后再一起发送到服务端,减少网络开销;也包括多次增量之后再进行一次全量,对齐真实状态。

    第四步:再后台观看“录制”的时候,其实就是先用全量快照渲染出界面,然后顺着快照链走,按照时间戳把对应的修改重放到页面上,就形成了像视频一样的回放。

    以上是我看 logrocket 的视频并且试用,然后逆向了一小部分 sdk 代码之后的分析,仅供参考。
    ltq918
        17
    ltq918  
       2018-07-14 07:43:44 +08:00 via iPhone
    Redux 了解一下
    SouUED
        18
    SouUED  
       2018-07-14 09:49:41 +08:00 via Android
    @aryu 整理了一个不错的思路,我提的那个只是实现的一种思路,仅供参考 工程去实现肯定有很多问题的
    SouUED
        19
    SouUED  
       2018-07-14 10:00:14 +08:00 via Android
    用 canvas 画的话,难点应该在于什么时候传递数据到后台,传哪些帧到后台,生成视频可能夸张了,直接传 gif 图到后台就行了。我觉得 canvas 网页快照加路径记录加重放的工程可行性高点,性能什么的也好很多
    marvinwilliam
        20
    marvinwilliam  
       2018-07-14 13:21:15 +08:00
    MutationObserver
    ppsspp
        21
    ppsspp  
       2020-09-16 11:05:42 +08:00
    第二个思路可以用 rrweb 这个库
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1002 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:47 · PVG 06:47 · LAX 14:47 · JFK 17:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.