@hyperframes/engine 0.6.14 → 0.6.16
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/services/parallelCoordinator.d.ts +10 -1
- package/dist/services/parallelCoordinator.d.ts.map +1 -1
- package/dist/services/parallelCoordinator.js +27 -8
- package/dist/services/parallelCoordinator.js.map +1 -1
- package/dist/utils/readWebGlVendorInfoFromCanvas.d.ts +20 -0
- package/dist/utils/readWebGlVendorInfoFromCanvas.d.ts.map +1 -0
- package/dist/utils/readWebGlVendorInfoFromCanvas.js +45 -0
- package/dist/utils/readWebGlVendorInfoFromCanvas.js.map +1 -0
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/services/parallelCoordinator.ts +36 -7
- package/src/utils/readWebGlVendorInfoFromCanvas.ts +52 -0
package/dist/index.d.ts
CHANGED
|
@@ -45,6 +45,7 @@ export { calculateOptimalWorkers, distributeFrames, executeParallelCapture, merg
|
|
|
45
45
|
export { createFileServer, type FileServerOptions, type FileServerHandle, } from "./services/fileServer.js";
|
|
46
46
|
export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes/core";
|
|
47
47
|
export { assertSwiftShader, readWebGlVendorInfo, SwiftShaderAssertionError, BROWSER_GPU_NOT_SOFTWARE, } from "./utils/assertSwiftShader.js";
|
|
48
|
+
export { readWebGlVendorInfoFromCanvas } from "./utils/readWebGlVendorInfoFromCanvas.js";
|
|
48
49
|
export { extractMediaMetadata, extractVideoMetadata, extractAudioMetadata, analyzeKeyframeIntervals, type VideoMetadata, type AudioMetadata, type KeyframeAnalysis, } from "./utils/ffprobe.js";
|
|
49
50
|
export { downloadToTemp, isHttpUrl } from "./utils/urlDownloader.js";
|
|
50
51
|
export { runFfmpeg, formatFfmpegError, type RunFfmpegOptions, type RunFfmpegResult, } from "./utils/runFfmpeg.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -51,6 +51,7 @@ export { createFileServer, } from "./services/fileServer.js";
|
|
|
51
51
|
// ── Utilities ──────────────────────────────────────────────────────────────────
|
|
52
52
|
export { quantizeTimeToFrame, MEDIA_VISUAL_STYLE_PROPERTIES } from "@hyperframes/core";
|
|
53
53
|
export { assertSwiftShader, readWebGlVendorInfo, SwiftShaderAssertionError, BROWSER_GPU_NOT_SOFTWARE, } from "./utils/assertSwiftShader.js";
|
|
54
|
+
export { readWebGlVendorInfoFromCanvas } from "./utils/readWebGlVendorInfoFromCanvas.js";
|
|
54
55
|
export { extractMediaMetadata, extractVideoMetadata, extractAudioMetadata, analyzeKeyframeIntervals, } from "./utils/ffprobe.js";
|
|
55
56
|
export { downloadToTemp, isHttpUrl } from "./utils/urlDownloader.js";
|
|
56
57
|
export { runFfmpeg, formatFfmpegError, } from "./utils/runFfmpeg.js";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,6 +11,15 @@ export interface WorkerTask {
|
|
|
11
11
|
startFrame: number;
|
|
12
12
|
endFrame: number;
|
|
13
13
|
outputDir: string;
|
|
14
|
+
/**
|
|
15
|
+
* Offset subtracted from the absolute frame index when naming the captured
|
|
16
|
+
* file (`frame_<i - outputFrameOffset>.{ext}`). Default 0. Distributed
|
|
17
|
+
* chunks set this to the chunk's absolute startFrame so file names land
|
|
18
|
+
* 0-indexed within the chunk's range — the encoder reads frames
|
|
19
|
+
* sequentially without an `-start_number` override. The per-frame TIME
|
|
20
|
+
* calculation still uses the absolute frame index.
|
|
21
|
+
*/
|
|
22
|
+
outputFrameOffset?: number;
|
|
14
23
|
}
|
|
15
24
|
export interface WorkerResult {
|
|
16
25
|
workerId: number;
|
|
@@ -36,7 +45,7 @@ export interface WorkerSizingConfig extends Partial<Pick<EngineConfig, "concurre
|
|
|
36
45
|
captureCostMultiplier?: number;
|
|
37
46
|
}
|
|
38
47
|
export declare function calculateOptimalWorkers(totalFrames: number, requested?: number, config?: WorkerSizingConfig): number;
|
|
39
|
-
export declare function distributeFrames(totalFrames: number, workerCount: number, workDir: string): WorkerTask[];
|
|
48
|
+
export declare function distributeFrames(totalFrames: number, workerCount: number, workDir: string, rangeStart?: number): WorkerTask[];
|
|
40
49
|
export declare function executeParallelCapture(serverUrl: string, workDir: string, tasks: WorkerTask[], captureOptions: CaptureOptions, createBeforeCaptureHook: () => BeforeCaptureHook | null, signal?: AbortSignal, onProgress?: (progress: ParallelProgress) => void, onFrameBuffer?: (frameIndex: number, buffer: Buffer) => Promise<void>, config?: Partial<EngineConfig>): Promise<WorkerResult[]>;
|
|
41
50
|
export declare function mergeWorkerFrames(workDir: string, tasks: WorkerTask[], outputDir: string): Promise<number>;
|
|
42
51
|
export declare function getSystemResources(): {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallelCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/parallelCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAQL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"parallelCoordinator.d.ts","sourceRoot":"","sources":["../../src/services/parallelCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,EAQL,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,kBAAmB,SAAQ,OAAO,CACjD,IAAI,CACF,YAAY,EACZ,aAAa,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,sBAAsB,CAChF,CACF;IACC;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAuBD,wBAAgB,uBAAuB,CACrC,WAAW,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,kBAAkB,GAC1B,MAAM,CAuDR;AAED,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,MAAM,EACf,UAAU,GAAE,MAAU,GACrB,UAAU,EAAE,CAmBd;AA6FD,wBAAsB,sBAAsB,CAC1C,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,EAAE,EACnB,cAAc,EAAE,cAAc,EAC9B,uBAAuB,EAAE,MAAM,iBAAiB,GAAG,IAAI,EACvD,MAAM,CAAC,EAAE,WAAW,EACpB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,EACjD,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACrE,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAC7B,OAAO,CAAC,YAAY,EAAE,CAAC,CA2CzB;AAED,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,MAAM,CAAC,CA4BjB;AAED,wBAAgB,kBAAkB,IAAI;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;CAC5B,CAOA"}
|
|
@@ -10,6 +10,8 @@ import { copyFile, rename } from "fs/promises";
|
|
|
10
10
|
import { join } from "path";
|
|
11
11
|
import { createCaptureSession, initializeSession, closeCaptureSession, captureFrame, captureFrameToBuffer, getCapturePerfSummary, } from "./frameCapture.js";
|
|
12
12
|
import { DEFAULT_CONFIG } from "../config.js";
|
|
13
|
+
import { assertSwiftShader } from "../utils/assertSwiftShader.js";
|
|
14
|
+
import { readWebGlVendorInfoFromCanvas } from "../utils/readWebGlVendorInfoFromCanvas.js";
|
|
13
15
|
const MEMORY_PER_WORKER_MB = 256;
|
|
14
16
|
const MIN_WORKERS = 1;
|
|
15
17
|
// Hard ceiling on explicit `--workers N` requests. Above this, the cost of
|
|
@@ -75,19 +77,20 @@ export function calculateOptimalWorkers(totalFrames, requested, config) {
|
|
|
75
77
|
}
|
|
76
78
|
return finalWorkers;
|
|
77
79
|
}
|
|
78
|
-
export function distributeFrames(totalFrames, workerCount, workDir) {
|
|
80
|
+
export function distributeFrames(totalFrames, workerCount, workDir, rangeStart = 0) {
|
|
79
81
|
const tasks = [];
|
|
80
82
|
const framesPerWorker = Math.ceil(totalFrames / workerCount);
|
|
81
83
|
for (let i = 0; i < workerCount; i++) {
|
|
82
|
-
const startFrame = i * framesPerWorker;
|
|
83
|
-
const endFrame = Math.min((i + 1) * framesPerWorker, totalFrames);
|
|
84
|
-
if (startFrame >= totalFrames)
|
|
84
|
+
const startFrame = rangeStart + i * framesPerWorker;
|
|
85
|
+
const endFrame = Math.min(rangeStart + (i + 1) * framesPerWorker, rangeStart + totalFrames);
|
|
86
|
+
if (startFrame >= rangeStart + totalFrames)
|
|
85
87
|
break;
|
|
86
88
|
tasks.push({
|
|
87
89
|
workerId: i,
|
|
88
90
|
startFrame,
|
|
89
91
|
endFrame,
|
|
90
92
|
outputDir: join(workDir, `worker-${i}`),
|
|
93
|
+
outputFrameOffset: rangeStart,
|
|
91
94
|
});
|
|
92
95
|
}
|
|
93
96
|
return tasks;
|
|
@@ -101,7 +104,21 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
|
|
|
101
104
|
let perf;
|
|
102
105
|
try {
|
|
103
106
|
session = await createCaptureSession(serverUrl, task.outputDir, captureOptions, createBeforeCaptureHook(), config);
|
|
107
|
+
// Per-worker SwiftShader assertion: when the caller declares
|
|
108
|
+
// `browserGpuMode: "software"`, every worker session must verify Chrome's
|
|
109
|
+
// WebGL backend is actually SwiftShader before the first frame. Hosts
|
|
110
|
+
// that fall back to a hardware GL backend (or silently fail to load
|
|
111
|
+
// SwiftShader) would otherwise produce non-deterministic pixels and
|
|
112
|
+
// break the distributed byte-identical-retry contract — the parallel
|
|
113
|
+
// branch wouldn't catch it via the pre-warmup probe (renderChunk now
|
|
114
|
+
// skips that when chunkWorkerCount > 1). The canvas-based reader works
|
|
115
|
+
// on both regular Chrome and chrome-headless-shell (which serves
|
|
116
|
+
// `chrome://gpu` as an empty document).
|
|
117
|
+
if (config?.browserGpuMode === "software") {
|
|
118
|
+
await assertSwiftShader(session.page, readWebGlVendorInfoFromCanvas);
|
|
119
|
+
}
|
|
104
120
|
await initializeSession(session);
|
|
121
|
+
const outputOffset = task.outputFrameOffset ?? 0;
|
|
105
122
|
for (let i = task.startFrame; i < task.endFrame; i++) {
|
|
106
123
|
if (signal?.aborted) {
|
|
107
124
|
throw new Error("Parallel worker cancelled");
|
|
@@ -110,14 +127,16 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
|
|
|
110
127
|
// frame-index → time math. The 1-in-1001 ULP loss for NTSC is invisible
|
|
111
128
|
// at our scales (frame count tops out at single-digit thousands).
|
|
112
129
|
const time = (i * captureOptions.fps.den) / captureOptions.fps.num;
|
|
130
|
+
const fileFrameIdx = i - outputOffset;
|
|
113
131
|
if (onFrameBuffer) {
|
|
114
|
-
//
|
|
115
|
-
|
|
132
|
+
// The streaming-encode callback receives the absolute index `i`
|
|
133
|
+
// (not `fileFrameIdx`) so the encoder sequences frames against the
|
|
134
|
+
// composition's timeline.
|
|
135
|
+
const { buffer } = await captureFrameToBuffer(session, fileFrameIdx, time);
|
|
116
136
|
await onFrameBuffer(i, buffer);
|
|
117
137
|
}
|
|
118
138
|
else {
|
|
119
|
-
|
|
120
|
-
await captureFrame(session, i, time);
|
|
139
|
+
await captureFrame(session, fileFrameIdx, time);
|
|
121
140
|
}
|
|
122
141
|
framesCaptured++;
|
|
123
142
|
if (onFrameCaptured)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parallelCoordinator.js","sourceRoot":"","sources":["../../src/services/parallelCoordinator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EACL,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,GAKtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,cAAc,EAAqB,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"parallelCoordinator.js","sourceRoot":"","sources":["../../src/services/parallelCoordinator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read SwiftShader vendor/renderer via a 1×1 WebGL canvas + the
|
|
3
|
+
* `WEBGL_debug_renderer_info` extension. Used as the `readInfo` override
|
|
4
|
+
* for {@link assertSwiftShader} when the worker is running on
|
|
5
|
+
* `chrome-headless-shell` — that build serves `chrome://gpu` as an empty
|
|
6
|
+
* document so the default `chrome://gpu`-based info reader trips
|
|
7
|
+
* `net::ERR_FAILED` even when the GL backend is in fact SwiftShader.
|
|
8
|
+
*
|
|
9
|
+
* The canvas-based probe runs against whatever page the caller hands in
|
|
10
|
+
* (we use a fresh `about:blank` so it doesn't depend on the composition
|
|
11
|
+
* URL being navigated yet). The renderer string returned matches the
|
|
12
|
+
* format `assertSwiftShader` expects (substring match against
|
|
13
|
+
* `"swiftshader"`).
|
|
14
|
+
*/
|
|
15
|
+
import type { Page } from "puppeteer-core";
|
|
16
|
+
export declare function readWebGlVendorInfoFromCanvas(page: Page): Promise<{
|
|
17
|
+
vendor: string;
|
|
18
|
+
renderer: string;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=readWebGlVendorInfoFromCanvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readWebGlVendorInfoFromCanvas.d.ts","sourceRoot":"","sources":["../../src/utils/readWebGlVendorInfoFromCanvas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAE3C,wBAAsB,6BAA6B,CACjD,IAAI,EAAE,IAAI,GACT,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgC/C"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read SwiftShader vendor/renderer via a 1×1 WebGL canvas + the
|
|
3
|
+
* `WEBGL_debug_renderer_info` extension. Used as the `readInfo` override
|
|
4
|
+
* for {@link assertSwiftShader} when the worker is running on
|
|
5
|
+
* `chrome-headless-shell` — that build serves `chrome://gpu` as an empty
|
|
6
|
+
* document so the default `chrome://gpu`-based info reader trips
|
|
7
|
+
* `net::ERR_FAILED` even when the GL backend is in fact SwiftShader.
|
|
8
|
+
*
|
|
9
|
+
* The canvas-based probe runs against whatever page the caller hands in
|
|
10
|
+
* (we use a fresh `about:blank` so it doesn't depend on the composition
|
|
11
|
+
* URL being navigated yet). The renderer string returned matches the
|
|
12
|
+
* format `assertSwiftShader` expects (substring match against
|
|
13
|
+
* `"swiftshader"`).
|
|
14
|
+
*/
|
|
15
|
+
export async function readWebGlVendorInfoFromCanvas(page) {
|
|
16
|
+
await page.goto("about:blank", { waitUntil: "domcontentloaded", timeout: 30_000 });
|
|
17
|
+
return page.evaluate(() => {
|
|
18
|
+
try {
|
|
19
|
+
const canvas = document.createElement("canvas");
|
|
20
|
+
const gl = canvas.getContext("webgl") ??
|
|
21
|
+
canvas.getContext("experimental-webgl");
|
|
22
|
+
if (!gl) {
|
|
23
|
+
return { vendor: "", renderer: "" };
|
|
24
|
+
}
|
|
25
|
+
const ext = gl.getExtension("WEBGL_debug_renderer_info");
|
|
26
|
+
if (!ext) {
|
|
27
|
+
return {
|
|
28
|
+
vendor: String(gl.getParameter(gl.VENDOR) ?? ""),
|
|
29
|
+
renderer: String(gl.getParameter(gl.RENDERER) ?? ""),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Older Chrome builds expose the unmasked strings under the literal
|
|
33
|
+
// numeric constants 0x9245 / 0x9246. The extension surface above is
|
|
34
|
+
// identical across builds — read through it.
|
|
35
|
+
return {
|
|
36
|
+
vendor: String(gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) ?? ""),
|
|
37
|
+
renderer: String(gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) ?? ""),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return { vendor: "", renderer: "" };
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=readWebGlVendorInfoFromCanvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readWebGlVendorInfoFromCanvas.js","sourceRoot":"","sources":["../../src/utils/readWebGlVendorInfoFromCanvas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,IAAU;IAEV,MAAM,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE,SAAS,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;IACnF,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAyC,EAAE;QAC9D,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAChD,MAAM,EAAE,GACL,MAAM,CAAC,UAAU,CAAC,OAAO,CAAkC;gBAC3D,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAkC,CAAC;YAC5E,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;YACtC,CAAC;YACD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,2BAA2B,CAG/C,CAAC;YACT,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,OAAO;oBACL,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;oBAChD,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;iBACrD,CAAC;YACJ,CAAC;YACD,oEAAoE;YACpE,oEAAoE;YACpE,6CAA6C;YAC7C,OAAO;gBACL,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC;gBAChE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC;aACrE,CAAC;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QACtC,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/engine",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.16",
|
|
4
4
|
"description": "Seekable web page to video rendering engine (Puppeteer + FFmpeg)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"linkedom": "^0.18.12",
|
|
22
22
|
"puppeteer": "^24.0.0",
|
|
23
23
|
"puppeteer-core": "^24.39.1",
|
|
24
|
-
"@hyperframes/core": "^0.6.
|
|
24
|
+
"@hyperframes/core": "^0.6.16"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^25.0.10",
|
package/src/index.ts
CHANGED
|
@@ -23,12 +23,23 @@ import {
|
|
|
23
23
|
type BeforeCaptureHook,
|
|
24
24
|
} from "./frameCapture.js";
|
|
25
25
|
import { DEFAULT_CONFIG, type EngineConfig } from "../config.js";
|
|
26
|
+
import { assertSwiftShader } from "../utils/assertSwiftShader.js";
|
|
27
|
+
import { readWebGlVendorInfoFromCanvas } from "../utils/readWebGlVendorInfoFromCanvas.js";
|
|
26
28
|
|
|
27
29
|
export interface WorkerTask {
|
|
28
30
|
workerId: number;
|
|
29
31
|
startFrame: number;
|
|
30
32
|
endFrame: number;
|
|
31
33
|
outputDir: string;
|
|
34
|
+
/**
|
|
35
|
+
* Offset subtracted from the absolute frame index when naming the captured
|
|
36
|
+
* file (`frame_<i - outputFrameOffset>.{ext}`). Default 0. Distributed
|
|
37
|
+
* chunks set this to the chunk's absolute startFrame so file names land
|
|
38
|
+
* 0-indexed within the chunk's range — the encoder reads frames
|
|
39
|
+
* sequentially without an `-start_number` override. The per-frame TIME
|
|
40
|
+
* calculation still uses the absolute frame index.
|
|
41
|
+
*/
|
|
42
|
+
outputFrameOffset?: number;
|
|
32
43
|
}
|
|
33
44
|
|
|
34
45
|
export interface WorkerResult {
|
|
@@ -148,20 +159,22 @@ export function distributeFrames(
|
|
|
148
159
|
totalFrames: number,
|
|
149
160
|
workerCount: number,
|
|
150
161
|
workDir: string,
|
|
162
|
+
rangeStart: number = 0,
|
|
151
163
|
): WorkerTask[] {
|
|
152
164
|
const tasks: WorkerTask[] = [];
|
|
153
165
|
const framesPerWorker = Math.ceil(totalFrames / workerCount);
|
|
154
166
|
|
|
155
167
|
for (let i = 0; i < workerCount; i++) {
|
|
156
|
-
const startFrame = i * framesPerWorker;
|
|
157
|
-
const endFrame = Math.min((i + 1) * framesPerWorker, totalFrames);
|
|
158
|
-
if (startFrame >= totalFrames) break;
|
|
168
|
+
const startFrame = rangeStart + i * framesPerWorker;
|
|
169
|
+
const endFrame = Math.min(rangeStart + (i + 1) * framesPerWorker, rangeStart + totalFrames);
|
|
170
|
+
if (startFrame >= rangeStart + totalFrames) break;
|
|
159
171
|
|
|
160
172
|
tasks.push({
|
|
161
173
|
workerId: i,
|
|
162
174
|
startFrame,
|
|
163
175
|
endFrame,
|
|
164
176
|
outputDir: join(workDir, `worker-${i}`),
|
|
177
|
+
outputFrameOffset: rangeStart,
|
|
165
178
|
});
|
|
166
179
|
}
|
|
167
180
|
|
|
@@ -194,8 +207,22 @@ async function executeWorkerTask(
|
|
|
194
207
|
createBeforeCaptureHook(),
|
|
195
208
|
config,
|
|
196
209
|
);
|
|
210
|
+
// Per-worker SwiftShader assertion: when the caller declares
|
|
211
|
+
// `browserGpuMode: "software"`, every worker session must verify Chrome's
|
|
212
|
+
// WebGL backend is actually SwiftShader before the first frame. Hosts
|
|
213
|
+
// that fall back to a hardware GL backend (or silently fail to load
|
|
214
|
+
// SwiftShader) would otherwise produce non-deterministic pixels and
|
|
215
|
+
// break the distributed byte-identical-retry contract — the parallel
|
|
216
|
+
// branch wouldn't catch it via the pre-warmup probe (renderChunk now
|
|
217
|
+
// skips that when chunkWorkerCount > 1). The canvas-based reader works
|
|
218
|
+
// on both regular Chrome and chrome-headless-shell (which serves
|
|
219
|
+
// `chrome://gpu` as an empty document).
|
|
220
|
+
if (config?.browserGpuMode === "software") {
|
|
221
|
+
await assertSwiftShader(session.page, readWebGlVendorInfoFromCanvas);
|
|
222
|
+
}
|
|
197
223
|
await initializeSession(session);
|
|
198
224
|
|
|
225
|
+
const outputOffset = task.outputFrameOffset ?? 0;
|
|
199
226
|
for (let i = task.startFrame; i < task.endFrame; i++) {
|
|
200
227
|
if (signal?.aborted) {
|
|
201
228
|
throw new Error("Parallel worker cancelled");
|
|
@@ -204,14 +231,16 @@ async function executeWorkerTask(
|
|
|
204
231
|
// frame-index → time math. The 1-in-1001 ULP loss for NTSC is invisible
|
|
205
232
|
// at our scales (frame count tops out at single-digit thousands).
|
|
206
233
|
const time = (i * captureOptions.fps.den) / captureOptions.fps.num;
|
|
234
|
+
const fileFrameIdx = i - outputOffset;
|
|
207
235
|
|
|
208
236
|
if (onFrameBuffer) {
|
|
209
|
-
//
|
|
210
|
-
|
|
237
|
+
// The streaming-encode callback receives the absolute index `i`
|
|
238
|
+
// (not `fileFrameIdx`) so the encoder sequences frames against the
|
|
239
|
+
// composition's timeline.
|
|
240
|
+
const { buffer } = await captureFrameToBuffer(session, fileFrameIdx, time);
|
|
211
241
|
await onFrameBuffer(i, buffer);
|
|
212
242
|
} else {
|
|
213
|
-
|
|
214
|
-
await captureFrame(session, i, time);
|
|
243
|
+
await captureFrame(session, fileFrameIdx, time);
|
|
215
244
|
}
|
|
216
245
|
framesCaptured++;
|
|
217
246
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read SwiftShader vendor/renderer via a 1×1 WebGL canvas + the
|
|
3
|
+
* `WEBGL_debug_renderer_info` extension. Used as the `readInfo` override
|
|
4
|
+
* for {@link assertSwiftShader} when the worker is running on
|
|
5
|
+
* `chrome-headless-shell` — that build serves `chrome://gpu` as an empty
|
|
6
|
+
* document so the default `chrome://gpu`-based info reader trips
|
|
7
|
+
* `net::ERR_FAILED` even when the GL backend is in fact SwiftShader.
|
|
8
|
+
*
|
|
9
|
+
* The canvas-based probe runs against whatever page the caller hands in
|
|
10
|
+
* (we use a fresh `about:blank` so it doesn't depend on the composition
|
|
11
|
+
* URL being navigated yet). The renderer string returned matches the
|
|
12
|
+
* format `assertSwiftShader` expects (substring match against
|
|
13
|
+
* `"swiftshader"`).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import type { Page } from "puppeteer-core";
|
|
17
|
+
|
|
18
|
+
export async function readWebGlVendorInfoFromCanvas(
|
|
19
|
+
page: Page,
|
|
20
|
+
): Promise<{ vendor: string; renderer: string }> {
|
|
21
|
+
await page.goto("about:blank", { waitUntil: "domcontentloaded", timeout: 30_000 });
|
|
22
|
+
return page.evaluate((): { vendor: string; renderer: string } => {
|
|
23
|
+
try {
|
|
24
|
+
const canvas = document.createElement("canvas");
|
|
25
|
+
const gl =
|
|
26
|
+
(canvas.getContext("webgl") as WebGLRenderingContext | null) ??
|
|
27
|
+
(canvas.getContext("experimental-webgl") as WebGLRenderingContext | null);
|
|
28
|
+
if (!gl) {
|
|
29
|
+
return { vendor: "", renderer: "" };
|
|
30
|
+
}
|
|
31
|
+
const ext = gl.getExtension("WEBGL_debug_renderer_info") as {
|
|
32
|
+
UNMASKED_VENDOR_WEBGL: number;
|
|
33
|
+
UNMASKED_RENDERER_WEBGL: number;
|
|
34
|
+
} | null;
|
|
35
|
+
if (!ext) {
|
|
36
|
+
return {
|
|
37
|
+
vendor: String(gl.getParameter(gl.VENDOR) ?? ""),
|
|
38
|
+
renderer: String(gl.getParameter(gl.RENDERER) ?? ""),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
// Older Chrome builds expose the unmasked strings under the literal
|
|
42
|
+
// numeric constants 0x9245 / 0x9246. The extension surface above is
|
|
43
|
+
// identical across builds — read through it.
|
|
44
|
+
return {
|
|
45
|
+
vendor: String(gl.getParameter(ext.UNMASKED_VENDOR_WEBGL) ?? ""),
|
|
46
|
+
renderer: String(gl.getParameter(ext.UNMASKED_RENDERER_WEBGL) ?? ""),
|
|
47
|
+
};
|
|
48
|
+
} catch {
|
|
49
|
+
return { vendor: "", renderer: "" };
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|