使用puppeteer,puppeteer-recorder,timecut,timesnap对web网页的操作浏览等行为进行录播,并输出视频

前言

前段时间,使用了rrweb对web网页进行了录制与回放的功能开发,那么问题来了,虽然rrweb可以实现这个功能,但是它最终生成的就是一串json格式的数据。无法可以很好的提供给第三方一个很直观的表现,除非我们可以在这个行业里面统一使用rrweb这套框架,统一提供数据格式来实现行业内的统一原则,但是大众心理还是希望可以提供一个很直观的东西去呈现这样的效果,比如一个MP4格式的视频。web录屏的最终呈现的目的就是类似一个“犯罪”过程中的证据,比如我们出现bug了,但是我们不知道是哪里出现问题了,但是我们可以看web页面快照,而快照呈现的就是我们出现bug的证据。很清楚的发现问题的所在。

调研

面临的问题

  1. rrweb框架回放的功能,只能在web网页中可以播放
  2. 使用什么去录制你的web 网页
  3. 如何去生成mp4格式的视频

解决方案

  1. rrweb知乎博客给出了一个意见:

可以考虑用 puppeteer 控制 chrome 重放,再用 ffmpeg 录制 chrome。

再讨论的第二页给出的解决方案,大家可以查看知乎—SmartX 技术博客

  1. rrweb github 官网,有其他人给出了使用timecut对web网页进行录制的方法。

For example, you can use timecut, which uses puppeteer and FFmpeg under the hood.
First, you need to prepare an HTML file including the recorded events and the replayer code, then you can do something like this with timecut:

#you can customize viewport size, fps, etc
#you need set duration time
timecut ./YOUR_HTML_FILE --viewport=800,600 --fps=30 --duration=4 --output=video.mp4

An example: http://lab.myriptide.com/syncit-demo/record-2020-08-17_23.00.55.mp4

具体的讨论,大家可以查看这个issure的讨论Export to Video

基础知识

puppeteer是什么?

Puppeteer 是一个 Node 库,它提供了一个高级 API 来通过 DevTools 协议控制 Chromium 或 Chrome。Puppeteer 默认以 headless 模式运行,但是可以通过修改配置文件运行“有头”模式。

puppeteer 能做什么?

你可以在浏览器中手动执行的绝大多数操作都可以使用 Puppeteer 来完成! 下面是一些示例:

  1. 生成页面 PDF。
  2. 抓取 SPA(单页应用)并生成预渲染内容(即“SSR”(服务器端渲染))。
  3. 自动提交表单,进行 UI 测试,键盘输入等。
  4. 创建一个时时更新的自动化测试环境。 使用最新的 JavaScript 和浏览器功能直接在最新版本的Chrome中执行测试。
  5. 捕获网站的 timeline trace,用来帮助分析性能问题
  6. 测试浏览器扩展。
    相关功能演示地址

puppeteer-recorder 是什么?

Puppeteer Recorder 是Chrome扩展程序,可记录你的浏览器交互并生成Puppeteer脚本。说白点就是一个 Chrome 上的 Recorder 能帮你录制你在浏览器上的操作,然后生成一个脚本。
Puppeteer Recorder 扩展呈现

puppeteer-recorder 原理

puppeteer-recorder 的原理是使用puppeteer 以 headless 模式运行浏览器,通过脚本打开浏览器截取每一帧图片,然后使用 ffmpeg 生成视频。

ffmpeg是什么?

FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。FFmpeg官网

timecut 是什么?

timecut is a Node.js program that records smooth videos of web pages that use JavaScript animations. It uses timesnap and puppeteer to open a web page, overwrite its time-handling functions, take snapshots of the web page, and then passes the results to ffmpeg to encode those frames into a video. This allows for slower-than-realtime and/or virtual high-fps capture of frames, while the resulting video is smooth.

中文的意思:timecut是Nodejs 库,使用JavaScript动画把网页平滑的记录成视频。它使用timesnap和puppeteer来打开一个网页,使用脚本处理功能,获取网页的快照,然后将结果传递给ffmpeg来进行转换成帧视频。采用slower-than-realtime(低速实时) 和/或 virtual high-fps capture (虚拟高帧率相机)的框架,从而生成平滑的视频。

timesnap 是什么?

timesnap is a Node.js program that records screenshots of web pages that use JavaScript animations. It uses puppeteer to open a web page, overwrite its time-handling functions, and record snapshots at virtual times. For some web pages, this allows frames to be recorded slower than real time, while appearing smooth and consistent when recreated into a video.

下面的描述:

To record screenshots and compile them into a video using only one command, see timecut.

从而我们清楚知晓,timecut 起始就是 timesnap 里面的一个独立的功能,是timesnap的一个子集。其参与的原理都是一直的,两者的各种用法与API都差不多是一样的。timesnap官网

开始准备

安装puppeteer

在项目中使用 Puppeteer:

npm i puppeteer
// or 
yarn add puppeteer

当你安装 Puppeteer 时,它会下载最新版本的Chromium,这个包的大概的体积(170MB Mac,282MB Linux,280MB Win),如果你们安装过程中,无法安装或者安装失败的,可以安装puppeteer-core, 这个不会下载安装Chromium。

npm i puppeteer-core
// or 
yarn add puppeteer-core

puppeteer-core 是一个的轻量级的 Puppeteer 版本,用于启动现有浏览器安装或连接到远程安装。
关于具体的 puppeteer vs puppeteer-core 的区别,大家可以查看。官网给出的详细解释
puppeteer vs puppeteer-core
关于Chromium的下载,大家可以查看当前连接chromium相关版本下载地址去下载,基本上下载哪种版本的问题,需要与你们下载的puppeteer的版本有关联的。基本上遵循的原则是puppeteer的版本是最新的,就下载最新的就可以了。如果中间操作发现不行,那么需要你们自己去多尝试些版本。

当前我自己的版本配置是:

"puppeteer": "^5.2.1"
.local-chromium/mac-782078/chrome-mac/Chromium.app

其他782078就是Chromium的版本,手动下载的Chromium的,我们要做node_modules里面的puppeteer包使用的话,需要再puppeteer包里面新建文件.local-chromium / mac-782078 / chrome-mac /, 其中chrome-mac 文件夹下面的就是下载的Chromium文件。而文件名mac-782078 这个mac电脑上的命名是 mac-版本号。window 系统上的命名是 win-版本号。也可以自定义一个文件,在调用puppeteer的时候对指定Chromium的位置。

const browser = await puppeteer.launch({
    executablePath: './chrome-mac/Chromium.app/Contents/MacOS/Chromium', //当前Chromium的路径位置
    headless: false
  });

也有些人的电脑就是无法很好的下载 puppeteer,网上也有人给出了一些 puppeteer 安装时跳过 chrome 安装的方法,以及配置环境变量来实现下载的,比如
puppeteer 手动下载 chrome
Window安装Puppeteer

安装puppeteer-recorder

npm i puppeteer-recorder
// or 
yarn add puppeteer-recorder

安装ffmpeg

访问ffmpeg官方网站 ,点击ffmpeg下载地址。下载本地,然后解压,把整个文件放到当前项目中即可。

安装timecut

npm i timecut
// or 
yarn add timecut

具体文档与API等相关请查看 timecut

代码实践

使用puppeteer,puppeteer-recorder实践 Demo

初步尝试使用 puppeteer,puppeteer-recorder 来实现web url 页面使用rrweb 播放页面录播内容,讲当前操作轨迹转换成视频。

代码如下:

//testModel.js
const puppeteer = require('puppeteer');
const { record } = require('puppeteer-recorder');
let globalBrowser; 
initPuppeteer();

async function initPuppeteer() {
	globalBrowser = await puppeteer.launch({headless: false , args: ['--no-sandbox', '--disable-setuid-sandbox']});
	testModelChangeVideo()
};
async function testModelChangeVideo()
{
    try {
        const page = await globalBrowser.newPage();
        await page.setViewport({width: 1000, height: 1100});
        await record({
            ffmpeg: "ffmpeg",
            browser: globalBrowser ,
            page: page, 
            output: 'output.webm', // 输出文件名称
            fps: 1, // 每秒多少帧 尽量小  
            frames:  48,  // 生成多少频视频 
            prepare: async function (browser, page) {
            /* 生成视频前执行操作 */
                try {
                    await page.goto('使用rrweb播放的web页面url地址')
                }catch (e) { }
            },
            render: async function (browser, page, frame) {
            /* 截取每一帧图片时运行 */
            },
        }).then(function () {
            console.log('finish');
        })
        await page.close();
    }catch (e) {
        console.log('ERROR ---------------------');
        console.log(e);
    }
}

上述实现的原理就是使用puppeteer打开浏览器,然后开始访问web页面。然后使用puppeteer-recorder 监听页面,使用ffmpeg 记录并转换成视频。

上述代码解析:

  1. ffmpeg: “ffmpeg”, 后面可以配置成你ffmpeg下载到你本地的具体位置路径,我这边把ffmpeg解压到了当前testModel.js 同一层级中的ffmpeg 文件夹下。
  2. browser: globalBrowser ,//设置浏览器属性
  3. page: page, //配置打开的浏览器页面属性
  4. output: ‘output.webm’, //输出文件的名称,默认都是webm格式的,其他的格式的没有尝试过。
  5. fps: 1, //设置视频的每秒多少帧
  6. frames: 48, //设置生成多少频的视频
  7. prepare:()=>{} //生成视频前执行操作
  8. render:()=>{} //每一频的执行操作

上述代码执行之后,视频生成完成,会有个回调结果,log的结果是 finish。

当前的基础Demo的实现,我们后续可以考虑将当前Demo改善成一个微服务来操作,通过去跑这个服务自动生成视频,然后我们将生成的视频上传到服务端或者阿里云上面,返回一个视频的url地址。这样就对应某个web页面操作轨迹的对会有一个视频的真实记录。而这个微服务,我们可以直接使用nodejs来实现。只需要引入 express 或者koa2 框架,然后再引入 multer-aliyun-oss 插件来做上传阿里云,然后再通过页面访问接口返回url地址。到时候我们调用接口就可以返回视频的地址。这样我们就可以实现从操作轨迹的数据到web页面的呈现再到具体视频文件的输出,整个一套完成的工作链路就打通并完成了。后续再给出具体的nodejs的整套方案。当前只是一个Demo,可行性的实践而已。

使用timecut,timesnap实践 Demo

timesnap ,timecut 源码解析

具体查看了 timesnap ,timecut的源码,具体的源码github 链接地址 timesnap源码 timecut 源码

先看timesnap,源码里面

const puppeteer = require(‘puppeteer’);
const path = require(‘path’);
const defaultDuration = 5;
const defaultFPS = 60;
const { overwriteRandom } = require(’./lib/overwrite-random’);
const { promiseLoop, getBrowserFrames } = require(’./lib/utils’);
const initializePageUtils = require(’./lib/page-utils’);
const initializeMediaTimeHandler = require(’./lib/media-time-handler’);

从源码上看,实际上它也就是使用了puppeteer来实践的,只是做了一系列的封装而已。

再看timecut,源码里面

const timesnap = require(‘timesnap’);
const path = require(‘path’);
const fs = require(‘fs’);
const spawn = require(‘child_process’).spawn;
const defaultFPS = 60;

timecut里面使用了timesnap,而timesnap使用了puppeteer,说明timecut里面使用的工具本质上还是使用puppeteer来实现的

而且timesnap ,timecut 里面都使用到了ffmpeg,
所以从本质上来讲 timesnap ,timecut 也都是使用了puppeteer 与 ffmpeg 工具,实现不同功能的封装而已。相对于我们单纯的使用puppeteer与ffmpeg的结合而已, timesnap ,timecut 提供的一些API和相关的事件回调等对于使用者而已会比较方便也易于操作。无需关系内部的具体实践,我们只需要去调用就可以了。

timesnap 实践

timesnap的具体使用如下:

1.命令行的形式:

timesnap https://breathejs.org/examples/Drawing-US-Counties.html \
  -V 1920,1080 -S "#draw-canvas" --fps=60 --duration=10 \
  --round-to-even-width --round-to-even-height \
  --output-stdout | ffmpeg -framerate 60 -i pipe:0 -y -pix_fmt yuv420p video.mp4

2.js调用的形式:

const timesnap = require('timesnap');
timesnap({
  url: 'https://tungs.github.io/truchet-tiles-original/#autoplay=true&switchStyle=random',
  viewport: {
    width: 800,               // sets the viewport (window size) to 800x600
    height: 600
  },
  selector: '#container',     // crops each frame to the bounding box of '#container'
  left: 20, top: 40,          // further crops the left by 20px, and the top by 40px
  right: 6, bottom: 30,       // and the right by 6px, and the bottom by 30px
  fps: 30,                    // saves 30 frames for each virtual second
  duration: 20,               // for 20 virtual seconds 
  outputDirectory: 'frames'   // to frames/001.png... frames/600.png
                              // of the current working directory
}).then(function () {
  console.log('Done!');
});

命令行的方式有许多的,上述给出的都是其官方的使用方式,个人比较推崇这种,具体的使用大家可以参考timesnap官网 timesnap文档

timecut 实践

timecut的具体使用如下:

1.命令行的形式:

timecut index.html --viewport=800,600 --fps=60 --duration=5 \
  --frame-cache --pix-fmt=yuv420p --output=video.mp4

2.js调用的形式:

timecut({
  url: 'https://tungs.github.io/truchet-tiles-original/#autoplay=true&switchStyle=random',
  viewport: {
    width: 800,               // sets the viewport (window size) to 800x600
    height: 600
  },
  selector: '#container',     // crops each frame to the bounding box of '#container'
  left: 20, top: 40,          // further crops the left by 20px, and the top by 40px
  right: 6, bottom: 30,       // and the right by 6px, and the bottom by 30px
  fps: 30,                    // saves 30 frames for each virtual second
  duration: 20,               // for 20 virtual seconds 
  output: 'video.mp4'         // to video.mp4 of the current working directory
}).then(function () {
  console.log('Done!');
});

命令行的方式有许多的,上述给出的都是其官方的使用方式,个人比较推崇这种,具体的其他使用大家可以参考timecut官网
timecut文档

总结

从上述的调用结果以及可行性Demo的实践,后续我们还是需要把这些工具进行整合,可以尝试二次封装的可能。其实Demo的实现,而是为了后面整套业务流程的输出提供了参考,也让我们对于puppeteer,puppeteer-recorder,timecut,timesnap 这类工具的使用,有了深刻的影响,而前端可以依赖nodejs这个工具,提供接口服务来实践。这个后续再提供具体的代码实现。

参考网址:
puppeteer官网
puppeteer-vs-puppeteer-core
chromium安装路径
timecut
timesnap
puppeteer-recorder 使用参考文章
puppeteer介绍
Puppeteer的入门教程和实践

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值