Skip to content

Commit

Permalink
Record canvas snapshots N times per second (#859)
Browse files Browse the repository at this point in the history
* Only record canvas when recordCanvas is true

* All should be compiled first

Makes recompiling+debugging a lot faster

* Add support for compiling web workes

Replaces @rollup/plugin-typescript for rollup-plugin-typescript2 as the former is incompatible with rollup-plugin-web-worker-loader

* Update yarn.lock

* Upgrade to typescript 4.5.5

* add support for replay of ImageBitmap in 2d canvas

* Snapshot canvases in a web-worker on FPS basis

* Fix performance of canvas recording and playback

* Wait for all images to be preloaded before checking results

* flatten base64 strings, as encoding isn't consistent

* Cleanup

* Add serializing to 2d canvases as well

* Disable blob serialize test

We don't have any code for it yet

* Upgrade @rollup/plugin-commonjs to 21.0.2

Fixes
https://linguinecode.com/post/import-export-appear-at-the-top-level

* Move canvas recording options to `sampling`

Based on: #859 (comment)
  • Loading branch information
Juice10 authored Apr 18, 2022
1 parent 93fec1f commit e238462
Show file tree
Hide file tree
Showing 43 changed files with 1,199 additions and 350 deletions.
12 changes: 12 additions & 0 deletions docs/recipes/canvas.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@ rrweb.record({
});
```

Alternatively enable image snapshot recording of Canvas at a maximum of 15 frames per second:

```js
rrweb.record({
emit(event) {},
recordCanvas: true,
sampling: {
canvas: 15,
},
});
```

Enable replaying Canvas:

```js
Expand Down
12 changes: 12 additions & 0 deletions docs/recipes/canvas.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ rrweb.record({
});
```

或者启用每秒 15 帧的 Canvas 图像快照记录:

```js
rrweb.record({
emit(event) {},
recordCanvas: true,
sampling: {
canvas: 15,
},
});
```

回放时对 Canvas 进行回放:

```js
Expand Down
1 change: 1 addition & 0 deletions docs/recipes/optimize-storage.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Some common patterns may emit lots of events are:
- long list
- complex SVG
- element with JS controlled animation
- canvas animations

## Sampling

Expand Down
1 change: 1 addition & 0 deletions docs/recipes/optimize-storage.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
- 长列表
- 复杂的 SVG
- 包含 JS 控制动画的元素
- canvas 动画

## 抽样策略

Expand Down
78 changes: 39 additions & 39 deletions guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,30 +135,30 @@ setInterval(save, 10 * 1000);

The parameter of `rrweb.record` accepts the following options.

| key | default | description |
| -------------------- | ------------------ | ------------------------------------------------------------ |
| emit | required | the callback function to get emitted events |
| checkoutEveryNth | - | take a full snapshot after every N events<br />refer to the [checkout](#checkout) chapter |
| checkoutEveryNms | - | take a full snapshot after every N ms<br />refer to the [checkout](#checkout) chapter |
| blockClass | 'rr-block' | Use a string or RegExp to configure which elements should be blocked, refer to the [privacy](#privacy) chapter |
| blockSelector | null | Use a string to configure which selector should be blocked, refer to the [privacy](#privacy) chapter |
| ignoreClass | 'rr-ignore' | Use a string or RegExp to configure which elements should be ignored, refer to the [privacy](#privacy) chapter |
| maskTextClass | 'rr-mask' | Use a string or RegExp to configure which elements should be masked, refer to the [privacy](#privacy) chapter |
| maskTextSelector | null | Use a string to configure which selector should be masked, refer to the [privacy](#privacy) chapter |
| maskAllInputs | false | mask all input content as \* |
| maskInputOptions | { password: true } | mask some kinds of input \*<br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/588164aa12f1d94576f89ae0210b98f6e971c895/packages/rrweb-snapshot/src/types.ts#L77-L95) |
| maskInputFn | - | customize mask input content recording logic |
| maskTextFn | - | customize mask text content recording logic |
| slimDOMOptions | {} | remove unnecessary parts of the DOM <br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/588164aa12f1d94576f89ae0210b98f6e971c895/packages/rrweb-snapshot/src/types.ts#L97-L108) |
| inlineStylesheet | true | whether to inline the stylesheet in the events |
| hooks | {} | hooks for events<br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L207) |
| packFn | - | refer to the [storage optimization recipe](./docs/recipes/optimize-storage.md) |
| sampling | - | refer to the [storage optimization recipe](./docs/recipes/optimize-storage.md) |
| recordCanvas | false | whether to record the canvas element |
| inlineImages | false | whether to record the image content |
| collectFonts | false | whether to collect fonts in the website |
| key | default | description |
| -------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| emit | required | the callback function to get emitted events |
| checkoutEveryNth | - | take a full snapshot after every N events<br />refer to the [checkout](#checkout) chapter |
| checkoutEveryNms | - | take a full snapshot after every N ms<br />refer to the [checkout](#checkout) chapter |
| blockClass | 'rr-block' | Use a string or RegExp to configure which elements should be blocked, refer to the [privacy](#privacy) chapter |
| blockSelector | null | Use a string to configure which selector should be blocked, refer to the [privacy](#privacy) chapter |
| ignoreClass | 'rr-ignore' | Use a string or RegExp to configure which elements should be ignored, refer to the [privacy](#privacy) chapter |
| maskTextClass | 'rr-mask' | Use a string or RegExp to configure which elements should be masked, refer to the [privacy](#privacy) chapter |
| maskTextSelector | null | Use a string to configure which selector should be masked, refer to the [privacy](#privacy) chapter |
| maskAllInputs | false | mask all input content as \* |
| maskInputOptions | { password: true } | mask some kinds of input \*<br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/588164aa12f1d94576f89ae0210b98f6e971c895/packages/rrweb-snapshot/src/types.ts#L77-L95) |
| maskInputFn | - | customize mask input content recording logic |
| maskTextFn | - | customize mask text content recording logic |
| slimDOMOptions | {} | remove unnecessary parts of the DOM <br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/588164aa12f1d94576f89ae0210b98f6e971c895/packages/rrweb-snapshot/src/types.ts#L97-L108) |
| inlineStylesheet | true | whether to inline the stylesheet in the events |
| hooks | {} | hooks for events<br />refer to the [list](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L207) |
| packFn | - | refer to the [storage optimization recipe](./docs/recipes/optimize-storage.md) |
| sampling | - | refer to the [storage optimization recipe](./docs/recipes/optimize-storage.md) |
| recordCanvas | false | Whether to record the canvas element. Available options:<br/>`false`, <br/>`true` |
| inlineImages | false | whether to record the image content |
| collectFonts | false | whether to collect fonts in the website |
| userTriggeredOnInput | false | whether to add `userTriggered` on input events that indicates if this event was triggered directly by the user or not. [What is `userTriggered`?](https://github.com/rrweb-io/rrweb/pull/495) |
| plugins | [] | load plugins to provide extended record functions. [What is plugins?](./docs/recipes/plugin.md) |
| plugins | [] | load plugins to provide extended record functions. [What is plugins?](./docs/recipes/plugin.md) |

#### Privacy

Expand Down Expand Up @@ -286,23 +286,23 @@ replayer.pause(5000);

The replayer accepts options as its constructor's second parameter, and it has the following options:

| key | default | description |
| ------------------- | ------------- | ------------------------------------------------------------ |
| speed | 1 | replay speed ratio |
| root | document.body | the root element of replayer |
| loadTimeout | 0 | timeout of loading remote style sheet |
| skipInactive | false | whether to skip inactive time |
| showWarning | true | whether to print warning messages during replay |
| showDebug | false | whether to print debug messages during replay |
| blockClass | 'rr-block' | element with the class name will display as a blocked area |
| liveMode | false | whether to enable live mode |
| insertStyleRules | [] | accepts multiple CSS rule string, which will be injected into the replay iframe |
| triggerFocus | true | whether to trigger focus during replay |
| UNSAFE_replayCanvas | false | whether to replay the canvas element. **Enable this will remove the sandbox, which is unsafe.** |
| key | default | description |
| ------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| speed | 1 | replay speed ratio |
| root | document.body | the root element of replayer |
| loadTimeout | 0 | timeout of loading remote style sheet |
| skipInactive | false | whether to skip inactive time |
| showWarning | true | whether to print warning messages during replay |
| showDebug | false | whether to print debug messages during replay |
| blockClass | 'rr-block' | element with the class name will display as a blocked area |
| liveMode | false | whether to enable live mode |
| insertStyleRules | [] | accepts multiple CSS rule string, which will be injected into the replay iframe |
| triggerFocus | true | whether to trigger focus during replay |
| UNSAFE_replayCanvas | false | whether to replay the canvas element. **Enable this will remove the sandbox, which is unsafe.** |
| mouseTail | true | whether to show mouse tail during replay. Set to false to disable mouse tail. A complete config can be found in this [type](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L407) |
| unpackFn | - | refer to the [storage optimization recipe](./docs/recipes/optimize-storage.md) |
| logConfig | - | configuration of console output playback, refer to the [console recipe](./docs/recipes/console.md) |
| plugins | [] | load plugins to provide extended replay functions. [What is plugins?](./docs/recipes/plugin.md) |
| unpackFn | - | refer to the [storage optimization recipe](./docs/recipes/optimize-storage.md) |
| logConfig | - | configuration of console output playback, refer to the [console recipe](./docs/recipes/console.md) |
| plugins | [] | load plugins to provide extended replay functions. [What is plugins?](./docs/recipes/plugin.md) |

#### Use rrweb-player

Expand Down
2 changes: 1 addition & 1 deletion guide.zh_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ setInterval(save, 10 * 1000);
| hooks | {} | 各类事件的回调<br />类型详见[列表](https://github.com/rrweb-io/rrweb/blob/9488deb6d54a5f04350c063d942da5e96ab74075/src/types.ts#L207) |
| packFn | - | 数据压缩函数,详见[优化存储策略](./docs/recipes/optimize-storage.zh_CN.md) |
| sampling | - | 数据抽样策略,详见[优化存储策略](./docs/recipes/optimize-storage.zh_CN.md) |
| recordCanvas | false | 是否记录 canvas 内容 |
| recordCanvas | false | 是否记录 canvas 内容, 可用选项:false, true |
| inlineImages | false | 是否将图片内容记内联录制 |
| collectFonts | false | 是否记录页面中的字体文件 |
| userTriggeredOnInput | false | [什么是 `userTriggered`](https://github.com/rrweb-io/rrweb/pull/495) |
Expand Down
2 changes: 1 addition & 1 deletion packages/rrweb-player/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "rrweb-player",
"version": "0.7.14",
"devDependencies": {
"@rollup/plugin-commonjs": "^11.0.0",
"@rollup/plugin-commonjs": "^21.0.2",
"@rollup/plugin-node-resolve": "^7.0.0",
"@rollup/plugin-typescript": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^3.7.0",
Expand Down
10 changes: 6 additions & 4 deletions packages/rrweb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@
},
"homepage": "https://github.com/rrweb-io/rrweb#readme",
"devDependencies": {
"@rollup/plugin-node-resolve": "^7.0.0",
"@rollup/plugin-typescript": "^8.3.1",
"@rollup/plugin-node-resolve": "^13.1.3",
"@types/chai": "^4.1.6",
"@types/inquirer": "0.0.43",
"@types/jest": "^27.4.1",
"@types/jest-image-snapshot": "^4.3.1",
"@types/jsdom": "^16.2.14",
"@types/node": "^17.0.21",
"@types/offscreencanvas": "^2019.6.4",
"@types/prettier": "^2.3.2",
"@types/puppeteer": "^5.4.4",
"cross-env": "^5.2.0",
Expand All @@ -63,10 +63,12 @@
"jsdom-global": "^3.0.2",
"prettier": "2.2.1",
"puppeteer": "^9.1.1",
"rollup": "^2.45.2",
"rollup": "^2.68.0",
"rollup-plugin-postcss": "^3.1.1",
"rollup-plugin-rename-node-modules": "^1.1.0",
"rollup-plugin-rename-node-modules": "^1.3.1",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.31.2",
"rollup-plugin-web-worker-loader": "^1.6.1",
"ts-jest": "^27.1.3",
"ts-node": "^10.7.0",
"tslib": "^2.3.1",
Expand Down
Loading

0 comments on commit e238462

Please sign in to comment.