@hyperframes/producer 0.8.189 → 0.8.190-hdr.1
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/distributed.js +34 -16
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +62 -62
- package/dist/index.js +35 -20
- package/dist/public-server.js +9 -4
- package/dist/services/distributed/chunkFrames.d.ts +2 -2
- package/dist/services/distributed/renderChunk.d.ts +7 -1
- package/dist/services/render/frameCacheBudget.d.ts +3 -0
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -1188,6 +1188,14 @@ function materializeExtractedFramesForCompiledDir(extracted, compiledDir, option
|
|
|
1188
1188
|
}
|
|
1189
1189
|
}
|
|
1190
1190
|
|
|
1191
|
+
// src/services/render/frameCacheBudget.ts
|
|
1192
|
+
function frameCacheOptions(cfg, workers) {
|
|
1193
|
+
return {
|
|
1194
|
+
frameDataUriCacheLimit: cfg.frameDataUriCacheLimit,
|
|
1195
|
+
frameDataUriCacheBytesLimitMb: Math.floor(cfg.frameDataUriCacheBytesLimitMb / (workers || 1))
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1191
1199
|
// src/services/render/cleanup.ts
|
|
1192
1200
|
import { freemem } from "node:os";
|
|
1193
1201
|
|
|
@@ -12515,10 +12523,7 @@ async function executeRenderPipeline(input) {
|
|
|
12515
12523
|
});
|
|
12516
12524
|
}
|
|
12517
12525
|
});
|
|
12518
|
-
const createRenderVideoFrameInjector = () => createVideoFrameInjector(frameLookup,
|
|
12519
|
-
frameDataUriCacheLimit: cfg.frameDataUriCacheLimit,
|
|
12520
|
-
frameDataUriCacheBytesLimitMb: cfg.frameDataUriCacheBytesLimitMb
|
|
12521
|
-
});
|
|
12526
|
+
const createRenderVideoFrameInjector = () => createVideoFrameInjector(frameLookup, frameCacheOptions(cfg, workerCount));
|
|
12522
12527
|
let captureCalibration;
|
|
12523
12528
|
const htmlInCanvasDetected = compiled.renderModeHints.reasons.some(
|
|
12524
12529
|
(r) => r.code === "htmlInCanvas"
|
|
@@ -14172,12 +14177,13 @@ var RenderChunkValidationError = class extends Error {
|
|
|
14172
14177
|
this.code = code;
|
|
14173
14178
|
}
|
|
14174
14179
|
};
|
|
14175
|
-
function createChunkVideoFrameInjectorFactory(frameLookup) {
|
|
14176
|
-
if (!(frameLookup instanceof Promise))
|
|
14180
|
+
function createChunkVideoFrameInjectorFactory(frameLookup, options) {
|
|
14181
|
+
if (!(frameLookup instanceof Promise))
|
|
14182
|
+
return () => createVideoFrameInjector2(frameLookup, options);
|
|
14177
14183
|
return () => {
|
|
14178
14184
|
let hook;
|
|
14179
14185
|
return async (page, time, heldVideoTime) => {
|
|
14180
|
-
hook ??= createVideoFrameInjector2(await frameLookup);
|
|
14186
|
+
hook ??= createVideoFrameInjector2(await frameLookup, options);
|
|
14181
14187
|
await hook?.(page, time, heldVideoTime);
|
|
14182
14188
|
};
|
|
14183
14189
|
};
|
|
@@ -18719,7 +18725,7 @@ function cfrEncodeArgs(inputArgs, encoder, fpsArg) {
|
|
|
18719
18725
|
"-r",
|
|
18720
18726
|
fpsArg
|
|
18721
18727
|
];
|
|
18722
|
-
appendSoftwareEncoderThreadsArg(args);
|
|
18728
|
+
appendSoftwareEncoderThreadsArg(args, "libx264");
|
|
18723
18729
|
return args;
|
|
18724
18730
|
}
|
|
18725
18731
|
async function reencodeCfr(ctx, chunkPaths, encoder) {
|
|
@@ -18975,6 +18981,22 @@ async function createVerifiedDistributedCaptureSession(serverUrl, framesDir, cap
|
|
|
18975
18981
|
function isCaptureMode(value) {
|
|
18976
18982
|
return value === "beginframe" || value === "screenshot" || value === "drawelement";
|
|
18977
18983
|
}
|
|
18984
|
+
var MixedCaptureModesError = class extends Error {
|
|
18985
|
+
constructor(modes) {
|
|
18986
|
+
super(`[renderChunk] capture workers reported inconsistent modes: ${modes.join(",")}`);
|
|
18987
|
+
this.modes = modes;
|
|
18988
|
+
this.name = "MixedCaptureModesError";
|
|
18989
|
+
}
|
|
18990
|
+
};
|
|
18991
|
+
function observedChunkCaptureMode(perfs) {
|
|
18992
|
+
const modes = [...new Set(perfs.map((perf) => perf.captureMode))];
|
|
18993
|
+
if (modes.length > 1) throw new MixedCaptureModesError(modes);
|
|
18994
|
+
const [mode] = modes;
|
|
18995
|
+
if (!mode || !isCaptureMode(mode)) {
|
|
18996
|
+
throw new Error(`[renderChunk] capture workers reported an invalid mode: ${mode ?? "<none>"}`);
|
|
18997
|
+
}
|
|
18998
|
+
return mode;
|
|
18999
|
+
}
|
|
18978
19000
|
function shouldRetryChunkCaptureWithScreenshot(error) {
|
|
18979
19001
|
const failure = classifyCaptureFailure4(error);
|
|
18980
19002
|
if (failure.kind === "cancelled" || failure.kind === "memory_exhaustion") return false;
|
|
@@ -19272,7 +19294,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
19272
19294
|
) : null;
|
|
19273
19295
|
videoFrameLookup?.catch(() => {
|
|
19274
19296
|
});
|
|
19275
|
-
const createChunkVideoFrameInjector = createChunkVideoFrameInjectorFactory(
|
|
19297
|
+
const createChunkVideoFrameInjector = createChunkVideoFrameInjectorFactory(
|
|
19298
|
+
videoFrameLookup,
|
|
19299
|
+
frameCacheOptions(cfg, chunkWorkerCount)
|
|
19300
|
+
);
|
|
19276
19301
|
const captureStarted = Date.now();
|
|
19277
19302
|
captureMode = await runCaptureWithScreenshotFallback({
|
|
19278
19303
|
forceScreenshot: forceScreenshotForChunk,
|
|
@@ -19326,17 +19351,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
19326
19351
|
},
|
|
19327
19352
|
frameRange: range
|
|
19328
19353
|
});
|
|
19329
|
-
|
|
19330
|
-
if (observedModes.size !== 1 || ![...observedModes].every(isCaptureMode)) {
|
|
19331
|
-
throw new Error(
|
|
19332
|
-
`[renderChunk] capture workers reported invalid or inconsistent modes: ${[...observedModes].join(",") || "<none>"}`
|
|
19333
|
-
);
|
|
19334
|
-
}
|
|
19335
|
-
const [observedMode] = observedModes;
|
|
19336
|
-
if (!observedMode || !isCaptureMode(observedMode)) {
|
|
19337
|
-
throw new Error("[renderChunk] capture completed without an observed mode");
|
|
19338
|
-
}
|
|
19339
|
-
return observedMode;
|
|
19354
|
+
return observedChunkCaptureMode(capturePerfs);
|
|
19340
19355
|
},
|
|
19341
19356
|
resetForScreenshotRetry: () => {
|
|
19342
19357
|
rmSync17(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
package/dist/public-server.js
CHANGED
|
@@ -1208,6 +1208,14 @@ function materializeExtractedFramesForCompiledDir(extracted, compiledDir, option
|
|
|
1208
1208
|
}
|
|
1209
1209
|
}
|
|
1210
1210
|
|
|
1211
|
+
// src/services/render/frameCacheBudget.ts
|
|
1212
|
+
function frameCacheOptions(cfg, workers) {
|
|
1213
|
+
return {
|
|
1214
|
+
frameDataUriCacheLimit: cfg.frameDataUriCacheLimit,
|
|
1215
|
+
frameDataUriCacheBytesLimitMb: Math.floor(cfg.frameDataUriCacheBytesLimitMb / (workers || 1))
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1211
1219
|
// src/services/render/cleanup.ts
|
|
1212
1220
|
import { freemem } from "node:os";
|
|
1213
1221
|
|
|
@@ -12498,10 +12506,7 @@ async function executeRenderPipeline(input) {
|
|
|
12498
12506
|
});
|
|
12499
12507
|
}
|
|
12500
12508
|
});
|
|
12501
|
-
const createRenderVideoFrameInjector = () => createVideoFrameInjector(frameLookup,
|
|
12502
|
-
frameDataUriCacheLimit: cfg.frameDataUriCacheLimit,
|
|
12503
|
-
frameDataUriCacheBytesLimitMb: cfg.frameDataUriCacheBytesLimitMb
|
|
12504
|
-
});
|
|
12509
|
+
const createRenderVideoFrameInjector = () => createVideoFrameInjector(frameLookup, frameCacheOptions(cfg, workerCount));
|
|
12505
12510
|
let captureCalibration;
|
|
12506
12511
|
const htmlInCanvasDetected = compiled.renderModeHints.reasons.some(
|
|
12507
12512
|
(r) => r.code === "htmlInCanvas"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type BeforeCaptureHook, BROWSER_GPU_NOT_SOFTWARE, type CaptureOptions, type EngineConfig, type ExtractedFrames, type FrameLookupTable, type ShownBox } from "@hyperframes/engine";
|
|
1
|
+
import { type BeforeCaptureHook, BROWSER_GPU_NOT_SOFTWARE, type CaptureOptions, createVideoFrameInjector, type EngineConfig, type ExtractedFrames, type FrameLookupTable, type ShownBox } from "@hyperframes/engine";
|
|
2
2
|
import type { LockedRenderConfig } from "../render/stages/freezePlan.js";
|
|
3
3
|
import type { PlanV2RemoteSources } from "./planV2.js";
|
|
4
4
|
import { type DistributedFormat, INVALID_VIDEO_METADATA, type PlanVideosJson } from "./shared.js";
|
|
@@ -17,7 +17,7 @@ export declare class RenderChunkValidationError extends Error {
|
|
|
17
17
|
constructor(code: RenderChunkValidationCode, message: string);
|
|
18
18
|
}
|
|
19
19
|
/** One injector per browser session: a hook reused on a fresh page can skip its first injection. */
|
|
20
|
-
export declare function createChunkVideoFrameInjectorFactory(frameLookup: FrameLookupTable | Promise<FrameLookupTable> | null): () => BeforeCaptureHook | null;
|
|
20
|
+
export declare function createChunkVideoFrameInjectorFactory(frameLookup: FrameLookupTable | Promise<FrameLookupTable> | null, options?: Parameters<typeof createVideoFrameInjector>[1]): () => BeforeCaptureHook | null;
|
|
21
21
|
/**
|
|
22
22
|
* Rebuilds `ExtractedFrames[]` from `<planDir>/video-frames/<videoId>/`. `framePaths` keys are 0-based
|
|
23
23
|
* frame indexes (what `getFrameAtTime` reads); any other key drops every video's first-paint frame.
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
* Every determinism toggle above is opt-in — only this primitive enables them.
|
|
34
34
|
* In-process renders (`executeRenderJob`) leave them off.
|
|
35
35
|
*/
|
|
36
|
-
import { assertSwiftShader, type CaptureOptions, type CaptureMode, type CaptureSession, closeCaptureSession, createCaptureSession, type EngineConfig, initializeSession, probeBeginFrameLiveness, readWebGlVendorInfoFromCanvas } from "@hyperframes/engine";
|
|
36
|
+
import { assertSwiftShader, type CaptureOptions, type CaptureMode, type CapturePerfSummary, type CaptureSession, closeCaptureSession, createCaptureSession, type EngineConfig, initializeSession, probeBeginFrameLiveness, readWebGlVendorInfoFromCanvas } from "@hyperframes/engine";
|
|
37
37
|
import { type ChunkSliceJson, type LockedRenderConfig } from "../render/stages/freezePlan.js";
|
|
38
38
|
import { type PlanVideosJson } from "./shared.js";
|
|
39
39
|
export { CHUNK_FRAME_RANGE_INVALID, CHUNK_INDEX_OUT_OF_RANGE, createChunkVideoFrameInjectorFactory, extractDeferredVideoFramesForChunk, FFMPEG_VERSION_MISMATCH, INVALID_VIDEO_METADATA, MISSING_PLAN_ARTIFACT, MISSING_RUNTIME_ENV_SNAPSHOT, PLAN_HASH_MISMATCH, rebuildExtractedFramesFromPlanDir, RenderChunkValidationError, } from "./chunkFrames.js";
|
|
@@ -136,6 +136,12 @@ export declare const distributedCaptureSessionDependencies: DistributedCaptureSe
|
|
|
136
136
|
* assertion, including fresh screenshot browsers created after a fallback.
|
|
137
137
|
*/
|
|
138
138
|
export declare function createVerifiedDistributedCaptureSession(serverUrl: string, framesDir: string, captureOptions: CaptureOptions, cfg: EngineConfig, dependencies?: DistributedCaptureSessionDependencies): Promise<CaptureSession>;
|
|
139
|
+
/** Workers of one chunk launched in different modes: one worker's BeginFrame check failed and it fell back alone. */
|
|
140
|
+
export declare class MixedCaptureModesError extends Error {
|
|
141
|
+
readonly modes: readonly string[];
|
|
142
|
+
constructor(modes: readonly string[]);
|
|
143
|
+
}
|
|
144
|
+
export declare function observedChunkCaptureMode(perfs: readonly Pick<CapturePerfSummary, "captureMode">[]): CaptureMode;
|
|
139
145
|
/**
|
|
140
146
|
* Only BeginFrame-specific failures are safe to retry in screenshot mode.
|
|
141
147
|
* Cancellation, memory exhaustion, and unrelated authoring/IO failures must
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { EngineConfig } from "@hyperframes/engine";
|
|
2
|
+
/** Cache options for one of `workers` injectors that share the configured budget on the one Node heap. */
|
|
3
|
+
export declare function frameCacheOptions(cfg: Pick<EngineConfig, "frameDataUriCacheLimit" | "frameDataUriCacheBytesLimitMb">, workers: number | undefined): Pick<EngineConfig, "frameDataUriCacheLimit" | "frameDataUriCacheBytesLimitMb">;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.190-hdr.1",
|
|
4
4
|
"description": "HTML-to-video rendering engine using Chrome's BeginFrame API",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
"postcss": "^8.4.0",
|
|
36
36
|
"puppeteer": "^25.2.1",
|
|
37
37
|
"puppeteer-core": "^25.2.1",
|
|
38
|
-
"@hyperframes/
|
|
39
|
-
"@hyperframes/parsers": "0.8.
|
|
40
|
-
"@hyperframes/lint": "0.8.
|
|
41
|
-
"@hyperframes/studio-server": "0.8.
|
|
42
|
-
"@hyperframes/
|
|
38
|
+
"@hyperframes/core": "0.8.190-hdr.1",
|
|
39
|
+
"@hyperframes/parsers": "0.8.190-hdr.1",
|
|
40
|
+
"@hyperframes/lint": "0.8.190-hdr.1",
|
|
41
|
+
"@hyperframes/studio-server": "0.8.190-hdr.1",
|
|
42
|
+
"@hyperframes/engine": "0.8.190-hdr.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^25.0.10",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"tsx": "^4.21.0",
|
|
49
49
|
"typescript": "^5.7.2",
|
|
50
50
|
"vitest": "^4.1.11",
|
|
51
|
-
"@hyperframes/aws-lambda": "0.8.
|
|
51
|
+
"@hyperframes/aws-lambda": "0.8.190-hdr.1"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|