pup-recorder 0.2.3 → 0.2.5

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/Cargo.lock ADDED
@@ -0,0 +1,281 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "aho-corasick"
7
+ version = "1.1.4"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
10
+ dependencies = [
11
+ "memchr",
12
+ ]
13
+
14
+ [[package]]
15
+ name = "bitflags"
16
+ version = "2.10.0"
17
+ source = "registry+https://github.com/rust-lang/crates.io-index"
18
+ checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
19
+
20
+ [[package]]
21
+ name = "cfg-if"
22
+ version = "1.0.4"
23
+ source = "registry+https://github.com/rust-lang/crates.io-index"
24
+ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
25
+
26
+ [[package]]
27
+ name = "convert_case"
28
+ version = "0.6.0"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca"
31
+ dependencies = [
32
+ "unicode-segmentation",
33
+ ]
34
+
35
+ [[package]]
36
+ name = "crossbeam-deque"
37
+ version = "0.8.6"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
40
+ dependencies = [
41
+ "crossbeam-epoch",
42
+ "crossbeam-utils",
43
+ ]
44
+
45
+ [[package]]
46
+ name = "crossbeam-epoch"
47
+ version = "0.9.18"
48
+ source = "registry+https://github.com/rust-lang/crates.io-index"
49
+ checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
50
+ dependencies = [
51
+ "crossbeam-utils",
52
+ ]
53
+
54
+ [[package]]
55
+ name = "crossbeam-utils"
56
+ version = "0.8.21"
57
+ source = "registry+https://github.com/rust-lang/crates.io-index"
58
+ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
59
+
60
+ [[package]]
61
+ name = "ctor"
62
+ version = "0.2.9"
63
+ source = "registry+https://github.com/rust-lang/crates.io-index"
64
+ checksum = "32a2785755761f3ddc1492979ce1e48d2c00d09311c39e4466429188f3dd6501"
65
+ dependencies = [
66
+ "quote",
67
+ "syn",
68
+ ]
69
+
70
+ [[package]]
71
+ name = "either"
72
+ version = "1.15.0"
73
+ source = "registry+https://github.com/rust-lang/crates.io-index"
74
+ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
75
+
76
+ [[package]]
77
+ name = "libloading"
78
+ version = "0.8.9"
79
+ source = "registry+https://github.com/rust-lang/crates.io-index"
80
+ checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55"
81
+ dependencies = [
82
+ "cfg-if",
83
+ "windows-link",
84
+ ]
85
+
86
+ [[package]]
87
+ name = "memchr"
88
+ version = "2.7.6"
89
+ source = "registry+https://github.com/rust-lang/crates.io-index"
90
+ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
91
+
92
+ [[package]]
93
+ name = "napi"
94
+ version = "2.16.17"
95
+ source = "registry+https://github.com/rust-lang/crates.io-index"
96
+ checksum = "55740c4ae1d8696773c78fdafd5d0e5fe9bc9f1b071c7ba493ba5c413a9184f3"
97
+ dependencies = [
98
+ "bitflags",
99
+ "ctor",
100
+ "napi-derive",
101
+ "napi-sys",
102
+ "once_cell",
103
+ "tokio",
104
+ ]
105
+
106
+ [[package]]
107
+ name = "napi-build"
108
+ version = "2.3.1"
109
+ source = "registry+https://github.com/rust-lang/crates.io-index"
110
+ checksum = "d376940fd5b723c6893cd1ee3f33abbfd86acb1cd1ec079f3ab04a2a3bc4d3b1"
111
+
112
+ [[package]]
113
+ name = "napi-derive"
114
+ version = "2.16.13"
115
+ source = "registry+https://github.com/rust-lang/crates.io-index"
116
+ checksum = "7cbe2585d8ac223f7d34f13701434b9d5f4eb9c332cccce8dee57ea18ab8ab0c"
117
+ dependencies = [
118
+ "cfg-if",
119
+ "convert_case",
120
+ "napi-derive-backend",
121
+ "proc-macro2",
122
+ "quote",
123
+ "syn",
124
+ ]
125
+
126
+ [[package]]
127
+ name = "napi-derive-backend"
128
+ version = "1.0.75"
129
+ source = "registry+https://github.com/rust-lang/crates.io-index"
130
+ checksum = "1639aaa9eeb76e91c6ae66da8ce3e89e921cd3885e99ec85f4abacae72fc91bf"
131
+ dependencies = [
132
+ "convert_case",
133
+ "once_cell",
134
+ "proc-macro2",
135
+ "quote",
136
+ "regex",
137
+ "semver",
138
+ "syn",
139
+ ]
140
+
141
+ [[package]]
142
+ name = "napi-sys"
143
+ version = "2.4.0"
144
+ source = "registry+https://github.com/rust-lang/crates.io-index"
145
+ checksum = "427802e8ec3a734331fec1035594a210ce1ff4dc5bc1950530920ab717964ea3"
146
+ dependencies = [
147
+ "libloading",
148
+ ]
149
+
150
+ [[package]]
151
+ name = "native"
152
+ version = "0.1.0"
153
+ dependencies = [
154
+ "napi",
155
+ "napi-build",
156
+ "napi-derive",
157
+ "rayon",
158
+ ]
159
+
160
+ [[package]]
161
+ name = "once_cell"
162
+ version = "1.21.3"
163
+ source = "registry+https://github.com/rust-lang/crates.io-index"
164
+ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
165
+
166
+ [[package]]
167
+ name = "pin-project-lite"
168
+ version = "0.2.17"
169
+ source = "registry+https://github.com/rust-lang/crates.io-index"
170
+ checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
171
+
172
+ [[package]]
173
+ name = "proc-macro2"
174
+ version = "1.0.106"
175
+ source = "registry+https://github.com/rust-lang/crates.io-index"
176
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
177
+ dependencies = [
178
+ "unicode-ident",
179
+ ]
180
+
181
+ [[package]]
182
+ name = "quote"
183
+ version = "1.0.44"
184
+ source = "registry+https://github.com/rust-lang/crates.io-index"
185
+ checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
186
+ dependencies = [
187
+ "proc-macro2",
188
+ ]
189
+
190
+ [[package]]
191
+ name = "rayon"
192
+ version = "1.11.0"
193
+ source = "registry+https://github.com/rust-lang/crates.io-index"
194
+ checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
195
+ dependencies = [
196
+ "either",
197
+ "rayon-core",
198
+ ]
199
+
200
+ [[package]]
201
+ name = "rayon-core"
202
+ version = "1.13.0"
203
+ source = "registry+https://github.com/rust-lang/crates.io-index"
204
+ checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
205
+ dependencies = [
206
+ "crossbeam-deque",
207
+ "crossbeam-utils",
208
+ ]
209
+
210
+ [[package]]
211
+ name = "regex"
212
+ version = "1.12.2"
213
+ source = "registry+https://github.com/rust-lang/crates.io-index"
214
+ checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
215
+ dependencies = [
216
+ "aho-corasick",
217
+ "memchr",
218
+ "regex-automata",
219
+ "regex-syntax",
220
+ ]
221
+
222
+ [[package]]
223
+ name = "regex-automata"
224
+ version = "0.4.13"
225
+ source = "registry+https://github.com/rust-lang/crates.io-index"
226
+ checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
227
+ dependencies = [
228
+ "aho-corasick",
229
+ "memchr",
230
+ "regex-syntax",
231
+ ]
232
+
233
+ [[package]]
234
+ name = "regex-syntax"
235
+ version = "0.8.8"
236
+ source = "registry+https://github.com/rust-lang/crates.io-index"
237
+ checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
238
+
239
+ [[package]]
240
+ name = "semver"
241
+ version = "1.0.27"
242
+ source = "registry+https://github.com/rust-lang/crates.io-index"
243
+ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
244
+
245
+ [[package]]
246
+ name = "syn"
247
+ version = "2.0.114"
248
+ source = "registry+https://github.com/rust-lang/crates.io-index"
249
+ checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
250
+ dependencies = [
251
+ "proc-macro2",
252
+ "quote",
253
+ "unicode-ident",
254
+ ]
255
+
256
+ [[package]]
257
+ name = "tokio"
258
+ version = "1.50.0"
259
+ source = "registry+https://github.com/rust-lang/crates.io-index"
260
+ checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d"
261
+ dependencies = [
262
+ "pin-project-lite",
263
+ ]
264
+
265
+ [[package]]
266
+ name = "unicode-ident"
267
+ version = "1.0.22"
268
+ source = "registry+https://github.com/rust-lang/crates.io-index"
269
+ checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
270
+
271
+ [[package]]
272
+ name = "unicode-segmentation"
273
+ version = "1.12.0"
274
+ source = "registry+https://github.com/rust-lang/crates.io-index"
275
+ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
276
+
277
+ [[package]]
278
+ name = "windows-link"
279
+ version = "0.2.1"
280
+ source = "registry+https://github.com/rust-lang/crates.io-index"
281
+ checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
package/Cargo.toml ADDED
@@ -0,0 +1,23 @@
1
+ [package]
2
+ name = "native"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+
6
+ [lib]
7
+ path = "src/rust/lib.rs"
8
+ crate-type = ["cdylib"]
9
+
10
+ [profile.release]
11
+ opt-level = 3
12
+ lto = true
13
+ codegen-units = 1
14
+ panic = "abort"
15
+ strip = true
16
+
17
+ [build-dependencies]
18
+ napi-build = "2"
19
+
20
+ [dependencies]
21
+ napi = { version = "2", features = ["napi4", "tokio_rt"] }
22
+ napi-derive = "2"
23
+ rayon = "1"
package/README.md CHANGED
@@ -7,82 +7,66 @@ pup-recorder - record web pages as video
7
7
  ## SYNOPSIS
8
8
 
9
9
  ```
10
- pup source [-W width] [-H height] [-f fps] [-t duration] [-o dir] [-F formats] [-a] [--use-inner-proxy]
10
+ pup source [-W width] [-H height] [-f fps] [-t duration] [-o file] [-a] [-d] [--use-inner-proxy]
11
11
  ```
12
12
 
13
- ## DESCRIPTION
14
-
15
- Renders a web page offscreen via Electron and encodes the result to one or
16
- more video formats. Both mp4 and webm support alpha transparency and
17
- optional audio.
18
-
19
13
  ## OPTIONS
20
14
 
21
15
  ```
22
- source
23
- file://, http(s)://, or data: URI of the page to record.
24
-
25
- -W width, --width=width
26
- Frame width in pixels. Default: 1920.
27
-
28
- -H height, --height=height
29
- Frame height in pixels. Default: 1080.
30
-
31
- -f fps, --fps=fps
32
- Frames per second. Default: 30.
33
-
34
- -t duration, --duration=duration
35
- Recording duration in seconds. Default: 5.
36
-
37
- -o dir, --out-dir=dir
38
- Output directory. Default: out.
39
-
40
- -F formats, --formats=formats
41
- Comma-separated list of output formats. Allowed values: mp4, webm.
42
- Default: mp4.
16
+ source file://, http(s)://, or data: URI
43
17
 
18
+ -W, --width <number> default: 1920
19
+ -H, --height <number> default: 1080
20
+ -f, --fps <number> default: 30
21
+ -t, --duration <number> default: 5
22
+ -o, --out-file <path> default: output.mp4
44
23
  -a, --with-audio
45
- Capture and encode system audio.
46
-
47
- --use-inner-proxy
48
- Route resource requests through the Bilibili inner proxy.
24
+ -d, --deterministic frame-by-frame rendering mode
25
+ --use-inner-proxy use Bilibili inner proxy
49
26
  ```
50
27
 
51
28
  ## ENVIRONMENT
52
29
 
53
30
  ```
54
- PUP_LOG_LEVEL Verbosity: 0=error 1=warn 2=info 3=debug. Default: 2.
55
- PUP_USE_INNER_PROXY Set to 1 to enable the inner proxy globally.
56
- PUP_DISABLE_GPU Set to 1 to disable GPU acceleration.
31
+ PUP_LOG_LEVEL 0=error 1=warn 2=info 3=debug. default: 2
32
+ PUP_USE_INNER_PROXY 1=on
33
+ PUP_DISABLE_GPU 1=on
34
+ PUP_DETERMINISTIC 1=on
57
35
  ```
58
36
 
59
37
  ## API
60
38
 
61
39
  ```typescript
62
- import { pup, type VideoFormat } from "pup-recorder";
63
-
64
- const { options, files } = await pup(source, {
65
- width?, height?, fps?, duration?, outDir?,
66
- formats?: VideoFormat[],
67
- withAudio?, useInnerProxy?,
68
- cancelQuery?, onProgress?,
40
+ import { pup } from "pup-recorder";
41
+
42
+ const result = await pup(source, {
43
+ width?: number,
44
+ height?: number,
45
+ fps?: number,
46
+ duration?: number,
47
+ outFile?: string,
48
+ withAudio?: boolean,
49
+ deterministic?: boolean,
50
+ useInnerProxy?: boolean,
51
+ signal?: AbortSignal,
52
+ onProgress?: (progress: number) => void,
69
53
  });
70
- // files: { mp4?, webm?, cover }
54
+ // result: { options, written, jank, outFile, audio? }
71
55
  ```
72
56
 
73
57
  ## FILES
74
58
 
75
59
  ```
76
- dist/cli.js CLI entry point
77
- dist/index.js library entry point
60
+ dist/cli.cjs
61
+ dist/index.js
78
62
  ```
79
63
 
80
64
  ## EXAMPLES
81
65
 
82
66
  ```sh
83
67
  pup https://example.com -t 5
84
- pup file:///path/to/page.html -F webm -t 10
85
- pup https://example.com -F mp4,webm -a -W 1280 -H 720 -f 60 -t 10 -o /tmp/out
68
+ pup file:///path/to/page.html -d -t 10
69
+ pup https://example.com -a -W 1280 -H 720 -f 60 -t 10
86
70
  ```
87
71
 
88
72
  ## SEE ALSO
package/build.ts CHANGED
@@ -3,12 +3,15 @@ import { rm } from "fs/promises";
3
3
  import { createRequire } from "module";
4
4
  import { join } from "path";
5
5
  import { build, type Options } from "tsup";
6
+ import { buildRust } from "./build_rust";
6
7
  import { dependencies } from "./package.json";
7
8
 
8
9
  const require = createRequire(import.meta.url);
9
10
  const tsPath = require.resolve("@typescript/native-preview/package.json");
10
11
  const tsgo = join(tsPath, "..", "bin", "tsgo.js");
11
12
 
13
+ await buildRust();
14
+
12
15
  await $`${tsgo}`;
13
16
  await rm("dist", { recursive: true, force: true });
14
17
 
@@ -21,20 +24,20 @@ const common: Options = {
21
24
  minify: true,
22
25
  treeshake: true,
23
26
  banner: { js: `import "source-map-support/register.js";` },
27
+ loader: { ".zip": "binary" },
24
28
  };
25
29
 
26
- await Promise.all([
27
- build({
28
- ...common,
29
- entry: ["src/index.ts", "src/cli.ts"],
30
- format: "esm",
31
- outDir: "dist",
32
- experimentalDts: true,
33
- }),
34
- build({
35
- ...common,
36
- entry: ["src/app.ts"],
37
- format: "cjs",
38
- outDir: "dist",
39
- }),
40
- ]);
30
+ await build({
31
+ ...common,
32
+ entry: ["src/index.ts", "src/cli.ts"],
33
+ format: "esm",
34
+ outDir: "dist",
35
+ experimentalDts: true,
36
+ });
37
+
38
+ await build({
39
+ ...common,
40
+ entry: ["src/app.ts"],
41
+ format: "cjs",
42
+ outDir: "dist",
43
+ });
package/build_rust.ts ADDED
@@ -0,0 +1,86 @@
1
+ // Created by Autokaka (qq1909698494@gmail.com) on 2026/02/10.
2
+
3
+ import { $ } from "bun";
4
+ import { zipSync } from "fflate";
5
+ import { mkdir, readFile, stat, writeFile } from "fs/promises";
6
+ import { join } from "path";
7
+
8
+ function getTriple(platform: string, arch: string) {
9
+ if (platform === "darwin") {
10
+ if (arch === "x64") return "x86_64-apple-darwin";
11
+ if (arch === "arm64") return "aarch64-apple-darwin";
12
+ }
13
+ if (platform === "linux") {
14
+ if (arch === "x64") return "x86_64-unknown-linux-gnu";
15
+ if (arch === "arm64") return "aarch64-unknown-linux-gnu";
16
+ }
17
+ if (platform === "win32") {
18
+ if (arch === "x64") return "x86_64-pc-windows-msvc";
19
+ if (arch === "arm64") return "aarch64-pc-windows-msvc";
20
+ }
21
+ return null;
22
+ }
23
+
24
+ function getArtifactName(platform: string) {
25
+ if (platform === "darwin") return "libnative.dylib";
26
+ if (platform === "linux") return "libnative.so";
27
+ if (platform === "win32") return "native.dll";
28
+ return null;
29
+ }
30
+
31
+ const PLATFORMS = ["darwin", "linux", "win32"];
32
+ const ARCHS = ["x64", "arm64"];
33
+ const RUST_DIR = "rust";
34
+ const ZIP_PATH = join(RUST_DIR, "native.zip");
35
+ const RUST_SOURCES = ["src/rust/lib.rs", "build.rs", "Cargo.toml", "Cargo.lock"];
36
+
37
+ async function needsRebuild(): Promise<boolean> {
38
+ const zipMtime = await stat(ZIP_PATH)
39
+ .then((s) => s.mtimeMs)
40
+ .catch(() => 0);
41
+ const mtimes = await Promise.all(
42
+ RUST_SOURCES.map((f) =>
43
+ stat(f)
44
+ .then((s) => s.mtimeMs)
45
+ .catch(() => Infinity),
46
+ ),
47
+ );
48
+ return mtimes.some((m) => m > zipMtime);
49
+ }
50
+
51
+ async function cargoBuild(platform: string, arch: string): Promise<[string, Uint8Array] | undefined> {
52
+ const triple = getTriple(platform, arch);
53
+ const libName = getArtifactName(platform);
54
+ if (!triple || !libName) return;
55
+
56
+ if (platform === "win32") {
57
+ await $`cargo xwin build --release --quiet --target ${triple}`;
58
+ } else {
59
+ await $`cargo zigbuild --release --quiet --target ${triple}`;
60
+ }
61
+
62
+ const data = await readFile(join(`target/${triple}/release`, libName));
63
+ return [`${platform}-${arch}.node`, new Uint8Array(data)];
64
+ }
65
+
66
+ export async function buildRust() {
67
+ if (!(await needsRebuild())) {
68
+ return;
69
+ }
70
+
71
+ await $`cargo install --quiet cargo-zigbuild cargo-xwin`;
72
+
73
+ const entries: [string, Uint8Array][] = [];
74
+ for (const platform of PLATFORMS) {
75
+ for (const arch of ARCHS) {
76
+ const entry = await cargoBuild(platform, arch);
77
+ if (entry) entries.push(entry);
78
+ }
79
+ }
80
+
81
+ await mkdir(RUST_DIR, { recursive: true });
82
+
83
+ const zip = zipSync(Object.fromEntries(entries));
84
+ await writeFile(ZIP_PATH, zip);
85
+ await writeFile(join(RUST_DIR, "native.zip.d.ts"), `declare const data: Uint8Array;\nexport default data;\n`);
86
+ }