@betterbugs/rrvideo 2.0.0-alpha.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +212 -0
- package/README.zh_CN.md +210 -0
- package/build/cli.d.ts +2 -0
- package/build/cli.js +68 -0
- package/build/cli.js.map +1 -0
- package/build/index.d.ts +11 -0
- package/build/index.js +177 -0
- package/build/index.js.map +1 -0
- package/package.json +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# rrvideo
|
|
2
|
+
|
|
3
|
+
[中文文档](./README.zh_CN.md)
|
|
4
|
+
|
|
5
|
+
rrvideo is a tool for transforming the session recorded by [rrweb](https://github.com/rrweb-io/rrweb) into a video.
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Install rrvideo
|
|
10
|
+
|
|
11
|
+
1. Install [Node.JS](https://nodejs.org/en/download/)。
|
|
12
|
+
2. Run `npm i -g rrvideo` to install the rrvideo CLI.
|
|
13
|
+
|
|
14
|
+
## Use rrvideo
|
|
15
|
+
|
|
16
|
+
### Transform a rrweb session(in JSON format) into a video.
|
|
17
|
+
|
|
18
|
+
```shell
|
|
19
|
+
rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_FILE
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Running this command will output a `rrvideo-output.webm` file in the current working directory.
|
|
23
|
+
|
|
24
|
+
### Config the output path
|
|
25
|
+
|
|
26
|
+
```shell
|
|
27
|
+
rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_FILE --output OUTPUT_PATH
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Config the replay
|
|
31
|
+
|
|
32
|
+
You can prepare a rrvideo config file and pass it to CLI.
|
|
33
|
+
|
|
34
|
+
```shell
|
|
35
|
+
rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_JSON_FILE --config PATH_TO_YOUR_RRVIDEO_CONFIG_FILE
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
You can find an example of the rrvideo config file [here](./rrvideo.config.example.json).
|
|
39
|
+
|
|
40
|
+
## Sponsors
|
|
41
|
+
|
|
42
|
+
[Become a sponsor](https://opencollective.com/rrweb#sponsor) and get your logo on our README on Github with a link to your site.
|
|
43
|
+
|
|
44
|
+
### Gold Sponsors 🥇
|
|
45
|
+
|
|
46
|
+
<div dir="auto">
|
|
47
|
+
|
|
48
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/0/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
49
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/1/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
50
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/2/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
51
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/3/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
52
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/4/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
53
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/5/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
54
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/6/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
55
|
+
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
### Silver Sponsors 🥈
|
|
59
|
+
|
|
60
|
+
<div dir="auto">
|
|
61
|
+
|
|
62
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/0/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
63
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/1/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
64
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/2/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
65
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/3/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
66
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/4/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
67
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/5/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
68
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/6/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
69
|
+
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
### Bronze Sponsors 🥉
|
|
73
|
+
|
|
74
|
+
<div dir="auto">
|
|
75
|
+
|
|
76
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/0/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
77
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/1/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
78
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/2/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
79
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/3/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
80
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/4/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
81
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/5/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
82
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/6/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
83
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/7/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/7/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
84
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/8/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/8/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
85
|
+
|
|
86
|
+
</div>
|
|
87
|
+
|
|
88
|
+
### Backers
|
|
89
|
+
|
|
90
|
+
<a href="https://opencollective.com/rrweb#sponsor" rel="nofollow"><img src="https://opencollective.com/rrweb/tiers/backers.svg?avatarHeight=36"></a>
|
|
91
|
+
|
|
92
|
+
## Core Team Members
|
|
93
|
+
|
|
94
|
+
<table>
|
|
95
|
+
<tr>
|
|
96
|
+
<td align="center">
|
|
97
|
+
<a href="https://github.com/Yuyz0112">
|
|
98
|
+
<img
|
|
99
|
+
src="https://avatars.githubusercontent.com/u/13651389?s=100"
|
|
100
|
+
width="100px;"
|
|
101
|
+
alt=""
|
|
102
|
+
/>
|
|
103
|
+
<br /><sub><b>Yuyz0112</b></sub>
|
|
104
|
+
<br /><br />
|
|
105
|
+
</a>
|
|
106
|
+
</td>
|
|
107
|
+
<td align="center">
|
|
108
|
+
<a href="https://github.com/YunFeng0817">
|
|
109
|
+
<img
|
|
110
|
+
src="https://avatars.githubusercontent.com/u/27533910?s=100"
|
|
111
|
+
width="100px;"
|
|
112
|
+
alt=""
|
|
113
|
+
/>
|
|
114
|
+
<br /><sub><b>Yun Feng</b></sub>
|
|
115
|
+
<br /><br />
|
|
116
|
+
</a>
|
|
117
|
+
</td>
|
|
118
|
+
<td align="center">
|
|
119
|
+
<a href="https://github.com/eoghanmurray">
|
|
120
|
+
<img
|
|
121
|
+
src="https://avatars.githubusercontent.com/u/156780?s=100"
|
|
122
|
+
width="100px;"
|
|
123
|
+
alt=""
|
|
124
|
+
/>
|
|
125
|
+
<br /><sub><b>eoghanmurray</b></sub>
|
|
126
|
+
<br /><br />
|
|
127
|
+
</a>
|
|
128
|
+
</td>
|
|
129
|
+
<td align="center">
|
|
130
|
+
<a href="https://github.com/Juice10">
|
|
131
|
+
<img
|
|
132
|
+
src="https://avatars.githubusercontent.com/u/4106?s=100"
|
|
133
|
+
width="100px;"
|
|
134
|
+
alt=""
|
|
135
|
+
/>
|
|
136
|
+
<br /><sub><b>Juice10</b></sub>
|
|
137
|
+
<br /><sub>open for rrweb consulting</sub>
|
|
138
|
+
</a>
|
|
139
|
+
</td>
|
|
140
|
+
</tr>
|
|
141
|
+
</table>
|
|
142
|
+
|
|
143
|
+
## Who's using rrweb?
|
|
144
|
+
|
|
145
|
+
<table>
|
|
146
|
+
<tr>
|
|
147
|
+
<td align="center">
|
|
148
|
+
<a href="http://www.smartx.com/" target="_blank">
|
|
149
|
+
<img width="195px" src="https://www.rrweb.io/logos/smartx.png">
|
|
150
|
+
</a>
|
|
151
|
+
</td>
|
|
152
|
+
<td align="center">
|
|
153
|
+
<a href="https://posthog.com?utm_source=rrweb&utm_medium=sponsorship&utm_campaign=open-source-sponsorship" target="_blank">
|
|
154
|
+
<img width="195px" src="https://www.rrweb.io/logos/posthog.png">
|
|
155
|
+
</a>
|
|
156
|
+
</td>
|
|
157
|
+
<td align="center">
|
|
158
|
+
<a href="https://statcounter.com/session-replay/" target="_blank">
|
|
159
|
+
<img width="195px" src="https://statcounter.com/images/logo-statcounter-arc-blue.svg">
|
|
160
|
+
</a>
|
|
161
|
+
</td>
|
|
162
|
+
<td align="center">
|
|
163
|
+
<a href="https://recordonce.com/" target="_blank">
|
|
164
|
+
<img width="195px" alt="Smart screen recording for SaaS" src="https://uploads-ssl.webflow.com/5f3d133183156245630d4446/5f3d1940abe8db8612c23521_Record-Once-logo-554x80px.svg">
|
|
165
|
+
</a>
|
|
166
|
+
</td>
|
|
167
|
+
</tr>
|
|
168
|
+
<tr>
|
|
169
|
+
<td align="center">
|
|
170
|
+
<a href="https://cux.io" target="_blank">
|
|
171
|
+
<img style="padding: 8px" alt="The first ever UX automation tool" width="195px" src="https://cux.io/cux-logo.svg">
|
|
172
|
+
</a>
|
|
173
|
+
</td>
|
|
174
|
+
<td align="center">
|
|
175
|
+
<a href="https://remsupp.com" target="_blank">
|
|
176
|
+
<img style="padding: 8px" alt="Remote Access & Co-Browsing" width="195px" src="https://remsupp.com/images/logo.png">
|
|
177
|
+
</a>
|
|
178
|
+
</td>
|
|
179
|
+
<td align="center">
|
|
180
|
+
<a href="https://highlight.io" target="_blank">
|
|
181
|
+
<img style="padding: 8px" alt="The open source, fullstack Monitoring Platform." width="195px" src="https://github.com/highlight/highlight/raw/main/highlight.io/public/images/logo.png">
|
|
182
|
+
</a>
|
|
183
|
+
</td>
|
|
184
|
+
<td align="center">
|
|
185
|
+
<a href="https://analyzee.io" target="_blank">
|
|
186
|
+
<img style="padding: 8px" alt="Comprehensive data analytics platform that empowers businesses to gain valuable insights and make data-driven decisions." width="195px" src="https://cdn.analyzee.io/assets/analyzee-logo.png">
|
|
187
|
+
</a>
|
|
188
|
+
</td>
|
|
189
|
+
</tr>
|
|
190
|
+
<tr>
|
|
191
|
+
<td align="center">
|
|
192
|
+
<a href="https://requestly.io" target="_blank">
|
|
193
|
+
<img style="padding: 8px" alt="Intercept, Modify, Record & Replay HTTP Requests." width="195px" src="https://github.com/requestly/requestly/assets/16779465/652552db-c867-44cb-9bb5-94a2026e04ca">
|
|
194
|
+
</a>
|
|
195
|
+
</td>
|
|
196
|
+
<td align="center">
|
|
197
|
+
<a href="https://gleap.io" target="_blank">
|
|
198
|
+
<img style="padding: 8px" alt="In-app bug reporting & customer feedback platform." width="195px" src="https://assets-global.website-files.com/6506f3f29c68b1724807619d/6506f56010237164c6306591_GleapLogo.svg">
|
|
199
|
+
</a>
|
|
200
|
+
</td>
|
|
201
|
+
<td align="center">
|
|
202
|
+
<a href="https://uxwizz.com" target="_blank">
|
|
203
|
+
<img style="padding: 8px" alt="Self-hosted website analytics with heatmaps and session recordings." width="195px" src="https://github.com/UXWizz/public-files/raw/main/assets/logo.png">
|
|
204
|
+
</a>
|
|
205
|
+
</td>
|
|
206
|
+
<td align="center">
|
|
207
|
+
<a href="https://www.howdygo.com" target="_blank">
|
|
208
|
+
<img style="padding: 8px" alt="Interactive product demos for small marketing teams" width="195px" src="https://assets-global.website-files.com/650afb446f1dd5bd410f00cc/650b2cec6188ff54dd9b01e1_Logo.svg">
|
|
209
|
+
</a>
|
|
210
|
+
</td>
|
|
211
|
+
</tr>
|
|
212
|
+
</table>
|
package/README.zh_CN.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# rrvideo
|
|
2
|
+
|
|
3
|
+
rrvideo 是用于将 [rrweb](https://github.com/rrweb-io/rrweb) 录制的数据转为视频格式的工具。
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## 安装 rrvideo
|
|
8
|
+
|
|
9
|
+
1. 安装 [Node.JS](https://nodejs.org/en/download/)。
|
|
10
|
+
2. 执行 `npm i -g rrvideo` 以安装 rrvideo CLI。
|
|
11
|
+
|
|
12
|
+
## 使用 rrvideo
|
|
13
|
+
|
|
14
|
+
### 将一份 rrweb 录制的数据(JSON 格式)转换为视频。
|
|
15
|
+
|
|
16
|
+
```shell
|
|
17
|
+
rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_FILE
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
运行以上命令会在执行文件夹中生成一个 `rrvideo-output.webm` 文件。
|
|
21
|
+
|
|
22
|
+
### 指定输出路径
|
|
23
|
+
|
|
24
|
+
```shell
|
|
25
|
+
rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_FILE --output OUTPUT_PATH
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 对回放进行配置
|
|
29
|
+
|
|
30
|
+
通过编写一个 rrvideo 配置文件再传入 rrvideo CLI 的方式可以对回放进行一定的配置。
|
|
31
|
+
|
|
32
|
+
```shell
|
|
33
|
+
rrvideo --input PATH_TO_YOUR_RRWEB_EVENTS_JSON_FILE --config PATH_TO_YOUR_RRVIDEO_CONFIG_FILE
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
rrvideo 配置文件可参考[示例](./rrvideo.config.example.json)。
|
|
37
|
+
|
|
38
|
+
## Sponsors
|
|
39
|
+
|
|
40
|
+
[Become a sponsor](https://opencollective.com/rrweb#sponsor) and get your logo on our README on Github with a link to your site.
|
|
41
|
+
|
|
42
|
+
### Gold Sponsors 🥇
|
|
43
|
+
|
|
44
|
+
<div dir="auto">
|
|
45
|
+
|
|
46
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/0/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
47
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/1/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
48
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/2/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
49
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/3/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
50
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/4/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
51
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/5/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
52
|
+
<a href="https://opencollective.com/rrweb/tiers/gold-sponsor/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/gold-sponsor/6/avatar.svg?requireActive=false&avatarHeight=225" alt="sponsor"></a>
|
|
53
|
+
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
### Silver Sponsors 🥈
|
|
57
|
+
|
|
58
|
+
<div dir="auto">
|
|
59
|
+
|
|
60
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/0/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
61
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/1/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
62
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/2/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
63
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/3/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
64
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/4/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
65
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/5/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
66
|
+
<a href="https://opencollective.com/rrweb/tiers/silver-sponsor/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/silver-sponsor/6/avatar.svg?requireActive=false&avatarHeight=158" alt="sponsor"></a>
|
|
67
|
+
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
### Bronze Sponsors 🥉
|
|
71
|
+
|
|
72
|
+
<div dir="auto">
|
|
73
|
+
|
|
74
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/0/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/0/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
75
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/1/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/1/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
76
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/2/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/2/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
77
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/3/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/3/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
78
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/4/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/4/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
79
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/5/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/5/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
80
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/6/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/6/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
81
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/7/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/7/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
82
|
+
<a href="https://opencollective.com/rrweb/tiers/sponsors/8/website?requireActive=false" target="_blank"><img src="https://opencollective.com/rrweb/tiers/sponsors/8/avatar.svg?requireActive=false&avatarHeight=70" alt="sponsor"></a>
|
|
83
|
+
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
### Backers
|
|
87
|
+
|
|
88
|
+
<a href="https://opencollective.com/rrweb#sponsor" rel="nofollow"><img src="https://opencollective.com/rrweb/tiers/backers.svg?avatarHeight=36"></a>
|
|
89
|
+
|
|
90
|
+
## Core Team Members
|
|
91
|
+
|
|
92
|
+
<table>
|
|
93
|
+
<tr>
|
|
94
|
+
<td align="center">
|
|
95
|
+
<a href="https://github.com/Yuyz0112">
|
|
96
|
+
<img
|
|
97
|
+
src="https://avatars.githubusercontent.com/u/13651389?s=100"
|
|
98
|
+
width="100px;"
|
|
99
|
+
alt=""
|
|
100
|
+
/>
|
|
101
|
+
<br /><sub><b>Yuyz0112</b></sub>
|
|
102
|
+
<br /><br />
|
|
103
|
+
</a>
|
|
104
|
+
</td>
|
|
105
|
+
<td align="center">
|
|
106
|
+
<a href="https://github.com/YunFeng0817">
|
|
107
|
+
<img
|
|
108
|
+
src="https://avatars.githubusercontent.com/u/27533910?s=100"
|
|
109
|
+
width="100px;"
|
|
110
|
+
alt=""
|
|
111
|
+
/>
|
|
112
|
+
<br /><sub><b>Yun Feng</b></sub>
|
|
113
|
+
<br /><br />
|
|
114
|
+
</a>
|
|
115
|
+
</td>
|
|
116
|
+
<td align="center">
|
|
117
|
+
<a href="https://github.com/eoghanmurray">
|
|
118
|
+
<img
|
|
119
|
+
src="https://avatars.githubusercontent.com/u/156780?s=100"
|
|
120
|
+
width="100px;"
|
|
121
|
+
alt=""
|
|
122
|
+
/>
|
|
123
|
+
<br /><sub><b>eoghanmurray</b></sub>
|
|
124
|
+
<br /><br />
|
|
125
|
+
</a>
|
|
126
|
+
</td>
|
|
127
|
+
<td align="center">
|
|
128
|
+
<a href="https://github.com/Juice10">
|
|
129
|
+
<img
|
|
130
|
+
src="https://avatars.githubusercontent.com/u/4106?s=100"
|
|
131
|
+
width="100px;"
|
|
132
|
+
alt=""
|
|
133
|
+
/>
|
|
134
|
+
<br /><sub><b>Juice10</b></sub>
|
|
135
|
+
<br /><sub>open for rrweb consulting</sub>
|
|
136
|
+
</a>
|
|
137
|
+
</td>
|
|
138
|
+
</tr>
|
|
139
|
+
</table>
|
|
140
|
+
|
|
141
|
+
## Who's using rrweb?
|
|
142
|
+
|
|
143
|
+
<table>
|
|
144
|
+
<tr>
|
|
145
|
+
<td align="center">
|
|
146
|
+
<a href="http://www.smartx.com/" target="_blank">
|
|
147
|
+
<img width="195px" src="https://www.rrweb.io/logos/smartx.png">
|
|
148
|
+
</a>
|
|
149
|
+
</td>
|
|
150
|
+
<td align="center">
|
|
151
|
+
<a href="https://posthog.com?utm_source=rrweb&utm_medium=sponsorship&utm_campaign=open-source-sponsorship" target="_blank">
|
|
152
|
+
<img width="195px" src="https://www.rrweb.io/logos/posthog.png">
|
|
153
|
+
</a>
|
|
154
|
+
</td>
|
|
155
|
+
<td align="center">
|
|
156
|
+
<a href="https://statcounter.com/session-replay/" target="_blank">
|
|
157
|
+
<img width="195px" src="https://statcounter.com/images/logo-statcounter-arc-blue.svg">
|
|
158
|
+
</a>
|
|
159
|
+
</td>
|
|
160
|
+
<td align="center">
|
|
161
|
+
<a href="https://recordonce.com/" target="_blank">
|
|
162
|
+
<img width="195px" alt="Smart screen recording for SaaS" src="https://uploads-ssl.webflow.com/5f3d133183156245630d4446/5f3d1940abe8db8612c23521_Record-Once-logo-554x80px.svg">
|
|
163
|
+
</a>
|
|
164
|
+
</td>
|
|
165
|
+
</tr>
|
|
166
|
+
<tr>
|
|
167
|
+
<td align="center">
|
|
168
|
+
<a href="https://cux.io" target="_blank">
|
|
169
|
+
<img style="padding: 8px" alt="The first ever UX automation tool" width="195px" src="https://cux.io/cux-logo.svg">
|
|
170
|
+
</a>
|
|
171
|
+
</td>
|
|
172
|
+
<td align="center">
|
|
173
|
+
<a href="https://remsupp.com" target="_blank">
|
|
174
|
+
<img style="padding: 8px" alt="Remote Access & Co-Browsing" width="195px" src="https://remsupp.com/images/logo.png">
|
|
175
|
+
</a>
|
|
176
|
+
</td>
|
|
177
|
+
<td align="center">
|
|
178
|
+
<a href="https://highlight.io" target="_blank">
|
|
179
|
+
<img style="padding: 8px" alt="The open source, fullstack Monitoring Platform." width="195px" src="https://github.com/highlight/highlight/raw/main/highlight.io/public/images/logo.png">
|
|
180
|
+
</a>
|
|
181
|
+
</td>
|
|
182
|
+
<td align="center">
|
|
183
|
+
<a href="https://analyzee.io" target="_blank">
|
|
184
|
+
<img style="padding: 8px" alt="Comprehensive data analytics platform that empowers businesses to gain valuable insights and make data-driven decisions." width="195px" src="https://cdn.analyzee.io/assets/analyzee-logo.png">
|
|
185
|
+
</a>
|
|
186
|
+
</td>
|
|
187
|
+
</tr>
|
|
188
|
+
<tr>
|
|
189
|
+
<td align="center">
|
|
190
|
+
<a href="https://requestly.io" target="_blank">
|
|
191
|
+
<img style="padding: 8px" alt="Intercept, Modify, Record & Replay HTTP Requests." width="195px" src="https://github.com/requestly/requestly/assets/16779465/652552db-c867-44cb-9bb5-94a2026e04ca">
|
|
192
|
+
</a>
|
|
193
|
+
</td>
|
|
194
|
+
<td align="center">
|
|
195
|
+
<a href="https://gleap.io" target="_blank">
|
|
196
|
+
<img style="padding: 8px" alt="In-app bug reporting & customer feedback platform." width="195px" src="https://assets-global.website-files.com/6506f3f29c68b1724807619d/6506f56010237164c6306591_GleapLogo.svg">
|
|
197
|
+
</a>
|
|
198
|
+
</td>
|
|
199
|
+
<td align="center">
|
|
200
|
+
<a href="https://uxwizz.com" target="_blank">
|
|
201
|
+
<img style="padding: 8px" alt="Self-hosted website analytics with heatmaps and session recordings." width="195px" src="https://github.com/UXWizz/public-files/raw/main/assets/logo.png">
|
|
202
|
+
</a>
|
|
203
|
+
</td>
|
|
204
|
+
<td align="center">
|
|
205
|
+
<a href="https://www.howdygo.com" target="_blank">
|
|
206
|
+
<img style="padding: 8px" alt="Interactive product demos for small marketing teams" width="195px" src="https://assets-global.website-files.com/650afb446f1dd5bd410f00cc/650b2cec6188ff54dd9b01e1_Logo.svg">
|
|
207
|
+
</a>
|
|
208
|
+
</td>
|
|
209
|
+
</tr>
|
|
210
|
+
</table>
|
package/build/cli.d.ts
ADDED
package/build/cli.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const path = __importStar(require("path"));
|
|
32
|
+
const minimist_1 = __importDefault(require("minimist"));
|
|
33
|
+
const cli_progress_bar_1 = require("@open-tech-world/cli-progress-bar");
|
|
34
|
+
const index_1 = require("./index");
|
|
35
|
+
const argv = (0, minimist_1.default)(process.argv.slice(2));
|
|
36
|
+
if (!argv.input) {
|
|
37
|
+
throw new Error('please pass --input to your rrweb events file');
|
|
38
|
+
}
|
|
39
|
+
let config = {};
|
|
40
|
+
if (argv.config) {
|
|
41
|
+
const configPathStr = argv.config;
|
|
42
|
+
const configPath = path.isAbsolute(configPathStr)
|
|
43
|
+
? configPathStr
|
|
44
|
+
: path.resolve(process.cwd(), configPathStr);
|
|
45
|
+
config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
46
|
+
}
|
|
47
|
+
const pBar = new cli_progress_bar_1.ProgressBar({ prefix: 'Transforming' });
|
|
48
|
+
const onProgressUpdate = (percent) => {
|
|
49
|
+
if (percent < 1)
|
|
50
|
+
pBar.run({ value: percent * 100, total: 100 });
|
|
51
|
+
else
|
|
52
|
+
pBar.run({ value: 100, total: 100, prefix: 'Transformation Completed!' });
|
|
53
|
+
};
|
|
54
|
+
(0, index_1.transformToVideo)({
|
|
55
|
+
input: argv.input,
|
|
56
|
+
output: argv.output,
|
|
57
|
+
rrwebPlayer: config,
|
|
58
|
+
onProgressUpdate,
|
|
59
|
+
})
|
|
60
|
+
.then((file) => {
|
|
61
|
+
console.log(`Successfully transformed into "${file}".`);
|
|
62
|
+
})
|
|
63
|
+
.catch((error) => {
|
|
64
|
+
console.log('Failed to transform this session.');
|
|
65
|
+
console.error(error);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
});
|
|
68
|
+
//# sourceMappingURL=cli.js.map
|
package/build/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,uCAAyB;AACzB,2CAA6B;AAC7B,wDAAgC;AAChC,wEAAgE;AAEhE,mCAA2C;AAE3C,MAAM,IAAI,GAAG,IAAA,kBAAQ,EAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAE7C,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAChB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;AACnE,CAAC;AAED,IAAI,MAAM,GAAG,EAAE,CAAC;AAEhB,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,MAAM,aAAa,GAAG,IAAI,CAAC,MAAgB,CAAC;IAC5C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC;QAC/C,CAAC,CAAC,aAAa;QACf,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;IAC/C,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAGvD,CAAC;AACJ,CAAC;AAED,MAAM,IAAI,GAAG,IAAI,8BAAW,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;AACzD,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAE,EAAE;IAC3C,IAAI,OAAO,GAAG,CAAC;QAAE,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;;QAE9D,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC;AAC9E,CAAC,CAAC;AAEF,IAAA,wBAAgB,EAAC;IACf,KAAK,EAAE,IAAI,CAAC,KAAe;IAC3B,MAAM,EAAE,IAAI,CAAC,MAAgB;IAC7B,WAAW,EAAE,MAAM;IACnB,gBAAgB;CACjB,CAAC;KACC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE;IACb,OAAO,CAAC,GAAG,CAAC,kCAAkC,IAAI,IAAI,CAAC,CAAC;AAC1D,CAAC,CAAC;KACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACf,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type Player from '@betterbugs/rrweb-player';
|
|
2
|
+
type RRvideoConfig = {
|
|
3
|
+
input: string;
|
|
4
|
+
output?: string;
|
|
5
|
+
headless?: boolean;
|
|
6
|
+
resolutionRatio?: number;
|
|
7
|
+
onProgressUpdate?: (percent: number) => void;
|
|
8
|
+
rrwebPlayer?: Omit<ConstructorParameters<typeof Player>[0]['props'], 'events'>;
|
|
9
|
+
};
|
|
10
|
+
export declare function transformToVideo(options: RRvideoConfig): Promise<string>;
|
|
11
|
+
export {};
|
package/build/index.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.transformToVideo = void 0;
|
|
36
|
+
const fs = __importStar(require("fs-extra"));
|
|
37
|
+
const path = __importStar(require("path"));
|
|
38
|
+
const playwright_1 = require("playwright");
|
|
39
|
+
const types_1 = require("@betterbugs/types");
|
|
40
|
+
const rrwebScriptPath = path.resolve(require.resolve('@betterbugs/rrweb-player'), '../../dist/rrweb-player.umd.cjs');
|
|
41
|
+
const rrwebStylePath = path.resolve(rrwebScriptPath, '../style.css');
|
|
42
|
+
const rrwebRaw = fs.readFileSync(rrwebScriptPath, 'utf-8');
|
|
43
|
+
const rrwebStyle = fs.readFileSync(rrwebStylePath, 'utf-8');
|
|
44
|
+
// The max valid scale value for the scaling method which can improve the video quality.
|
|
45
|
+
const MaxScaleValue = 2.5;
|
|
46
|
+
const defaultConfig = {
|
|
47
|
+
input: '',
|
|
48
|
+
output: 'rrvideo-output.webm',
|
|
49
|
+
headless: true,
|
|
50
|
+
// A good trade-off value between quality and file size.
|
|
51
|
+
resolutionRatio: 0.8,
|
|
52
|
+
onProgressUpdate: () => {
|
|
53
|
+
//
|
|
54
|
+
},
|
|
55
|
+
rrwebPlayer: {},
|
|
56
|
+
};
|
|
57
|
+
function getHtml(events, config) {
|
|
58
|
+
var _a;
|
|
59
|
+
return `
|
|
60
|
+
<html>
|
|
61
|
+
<head>
|
|
62
|
+
<style>${rrwebStyle}</style>
|
|
63
|
+
<style>html, body {padding: 0; border: none; margin: 0;}</style>
|
|
64
|
+
</head>
|
|
65
|
+
<body>
|
|
66
|
+
<script>
|
|
67
|
+
${rrwebRaw};
|
|
68
|
+
/*<!--*/
|
|
69
|
+
const events = ${JSON.stringify(events).replace(/<\/script>/g, '<\\/script>')};
|
|
70
|
+
/*-->*/
|
|
71
|
+
const userConfig = ${JSON.stringify((config === null || config === void 0 ? void 0 : config.rrwebPlayer) || {})};
|
|
72
|
+
window.replayer = new rrwebPlayer.Player({
|
|
73
|
+
target: document.body,
|
|
74
|
+
width: userConfig.width,
|
|
75
|
+
height: userConfig.height,
|
|
76
|
+
props: {
|
|
77
|
+
...userConfig,
|
|
78
|
+
events,
|
|
79
|
+
showController: false,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
window.replayer.addEventListener('finish', () => window.onReplayFinish());
|
|
83
|
+
window.replayer.addEventListener('ui-update-progress', (payload)=> window.onReplayProgressUpdate
|
|
84
|
+
(payload));
|
|
85
|
+
window.replayer.addEventListener('resize',()=>document.querySelector('.replayer-wrapper').style.transform = 'scale(${((_a = config === null || config === void 0 ? void 0 : config.resolutionRatio) !== null && _a !== void 0 ? _a : 1) * MaxScaleValue}) translate(-50%, -50%)');
|
|
86
|
+
</script>
|
|
87
|
+
</body>
|
|
88
|
+
</html>
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Preprocess all events to get a maximum view port size.
|
|
93
|
+
*/
|
|
94
|
+
function getMaxViewport(events) {
|
|
95
|
+
let maxWidth = 0, maxHeight = 0;
|
|
96
|
+
events.forEach((event) => {
|
|
97
|
+
if (event.type !== types_1.EventType.Meta)
|
|
98
|
+
return;
|
|
99
|
+
if (event.data.width > maxWidth)
|
|
100
|
+
maxWidth = event.data.width;
|
|
101
|
+
if (event.data.height > maxHeight)
|
|
102
|
+
maxHeight = event.data.height;
|
|
103
|
+
});
|
|
104
|
+
return {
|
|
105
|
+
width: maxWidth,
|
|
106
|
+
height: maxHeight,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function transformToVideo(options) {
|
|
110
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
111
|
+
var _a, _b, _c;
|
|
112
|
+
const defaultVideoDir = '__rrvideo__temp__';
|
|
113
|
+
const config = Object.assign({}, defaultConfig);
|
|
114
|
+
if (!options.input)
|
|
115
|
+
throw new Error('input is required');
|
|
116
|
+
// If the output is not specified or undefined, use the default value.
|
|
117
|
+
if (!options.output)
|
|
118
|
+
delete options.output;
|
|
119
|
+
Object.assign(config, options);
|
|
120
|
+
if (config.resolutionRatio > 1)
|
|
121
|
+
config.resolutionRatio = 1; // The max value is 1.
|
|
122
|
+
const eventsPath = path.isAbsolute(config.input)
|
|
123
|
+
? config.input
|
|
124
|
+
: path.resolve(process.cwd(), config.input);
|
|
125
|
+
const outputPath = path.isAbsolute(config.output)
|
|
126
|
+
? config.output
|
|
127
|
+
: path.resolve(process.cwd(), config.output);
|
|
128
|
+
const events = JSON.parse(fs.readFileSync(eventsPath, 'utf-8'));
|
|
129
|
+
// Make the browser viewport fit the player size.
|
|
130
|
+
const maxViewport = getMaxViewport(events);
|
|
131
|
+
// Use the scaling method to improve the video quality.
|
|
132
|
+
const scaledViewport = {
|
|
133
|
+
width: Math.round(maxViewport.width * ((_a = config.resolutionRatio) !== null && _a !== void 0 ? _a : 1) * MaxScaleValue),
|
|
134
|
+
height: Math.round(maxViewport.height * ((_b = config.resolutionRatio) !== null && _b !== void 0 ? _b : 1) * MaxScaleValue),
|
|
135
|
+
};
|
|
136
|
+
Object.assign(config.rrwebPlayer, scaledViewport);
|
|
137
|
+
const browser = yield playwright_1.chromium.launch({
|
|
138
|
+
headless: config.headless,
|
|
139
|
+
});
|
|
140
|
+
const context = yield browser.newContext({
|
|
141
|
+
viewport: scaledViewport,
|
|
142
|
+
recordVideo: {
|
|
143
|
+
dir: defaultVideoDir,
|
|
144
|
+
size: scaledViewport,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
const page = yield context.newPage();
|
|
148
|
+
yield page.goto('about:blank');
|
|
149
|
+
yield page.exposeFunction('onReplayProgressUpdate', (data) => {
|
|
150
|
+
config.onProgressUpdate(data.payload);
|
|
151
|
+
});
|
|
152
|
+
// Wait for the replay to finish
|
|
153
|
+
yield new Promise((resolve) => void page
|
|
154
|
+
.exposeFunction('onReplayFinish', () => resolve())
|
|
155
|
+
.then(() => page.setContent(getHtml(events, config))));
|
|
156
|
+
const videoPath = (yield ((_c = page.video()) === null || _c === void 0 ? void 0 : _c.path())) || '';
|
|
157
|
+
const cleanFiles = (videoPath) => __awaiter(this, void 0, void 0, function* () {
|
|
158
|
+
yield fs.remove(videoPath);
|
|
159
|
+
if ((yield fs.readdir(defaultVideoDir)).length === 0) {
|
|
160
|
+
yield fs.remove(defaultVideoDir);
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
yield context.close();
|
|
164
|
+
yield Promise.all([
|
|
165
|
+
fs
|
|
166
|
+
.move(videoPath, outputPath, { overwrite: true })
|
|
167
|
+
.catch((e) => {
|
|
168
|
+
console.error("Can't create video file. Please check the output path.", e);
|
|
169
|
+
})
|
|
170
|
+
.finally(() => void cleanFiles(videoPath)),
|
|
171
|
+
browser.close(),
|
|
172
|
+
]);
|
|
173
|
+
return outputPath;
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
exports.transformToVideo = transformToVideo;
|
|
177
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@betterbugs/rrvideo",
|
|
3
|
+
"version": "2.0.0-alpha.19",
|
|
4
|
+
"publishConfig": {
|
|
5
|
+
"access": "public"
|
|
6
|
+
},
|
|
7
|
+
"description": "transform rrweb session into video",
|
|
8
|
+
"main": "build/index.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"rrvideo": "build/cli.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"build",
|
|
14
|
+
"package.json"
|
|
15
|
+
],
|
|
16
|
+
"types": "build/index.d.ts",
|
|
17
|
+
"scripts": {
|
|
18
|
+
"install": "playwright install",
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "jest",
|
|
21
|
+
"check-types": "tsc -noEmit",
|
|
22
|
+
"prepublish": "yarn build"
|
|
23
|
+
},
|
|
24
|
+
"author": "BetterBugs-Team",
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/BetterBugs-Team/rrweb.git"
|
|
29
|
+
},
|
|
30
|
+
"homepage": "https://github.com/BetterBugs-Team/rrweb/tree/main/packages/rrvideo#readme",
|
|
31
|
+
"bugs": {
|
|
32
|
+
"url": "https://github.com/BetterBugs-Team/rrweb/issues"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/fs-extra": "11.0.1",
|
|
36
|
+
"@types/jest": "^27.4.1",
|
|
37
|
+
"@types/minimist": "^1.2.1",
|
|
38
|
+
"@types/node": "^18.15.11",
|
|
39
|
+
"jest": "^27.5.1",
|
|
40
|
+
"ts-jest": "^27.1.3",
|
|
41
|
+
"@betterbugs/types": "^2.0.0-alpha.19"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@open-tech-world/cli-progress-bar": "^2.0.2",
|
|
45
|
+
"fs-extra": "^11.1.1",
|
|
46
|
+
"minimist": "^1.2.5",
|
|
47
|
+
"playwright": "^1.32.1",
|
|
48
|
+
"@betterbugs/rrweb-player": "^2.0.0-alpha.19"
|
|
49
|
+
}
|
|
50
|
+
}
|