@hyperframes/producer 0.8.185 → 0.8.188
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 +26 -30
- package/dist/distributed.js +1307 -1328
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +70 -69
- package/dist/index.js +1958 -1935
- package/dist/public-server.js +1566 -1523
- package/dist/renderRequest.d.ts +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/services/distributed/assemble.d.ts +1 -1
- package/dist/services/distributed/chunkFrames.d.ts +1 -1
- package/dist/services/distributed/plan.d.ts +2 -1
- package/dist/services/htmlCompiler.d.ts +3 -2
- package/dist/services/render/motionBlurRoute.d.ts +11 -1
- package/dist/services/render/segmentManifest.d.ts +1 -0
- package/dist/services/render/stages/assembleStage.d.ts +1 -0
- package/dist/services/render/stages/audioStage.d.ts +6 -4
- package/dist/services/render/stages/captureStage.d.ts +3 -8
- package/dist/services/render/stages/compileStage.d.ts +2 -0
- package/dist/services/render/stages/freezePlan.d.ts +2 -1
- package/dist/services/renderOrchestrator.d.ts +1 -0
- package/package.json +7 -7
package/dist/renderRequest.d.ts
CHANGED
|
@@ -38,6 +38,7 @@ export interface RenderRequestOptions {
|
|
|
38
38
|
videoBitrate?: string;
|
|
39
39
|
videoFrameFormat?: VideoFrameFormat;
|
|
40
40
|
hdrMode?: RenderConfig["hdrMode"];
|
|
41
|
+
pageMotionBlur?: RenderConfig["pageMotionBlur"];
|
|
41
42
|
variables?: Record<string, unknown>;
|
|
42
43
|
outputResolution?: CanvasResolution;
|
|
43
44
|
outputResolutionAspectAgnostic?: boolean;
|
package/dist/server.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ interface RenderInput {
|
|
|
41
41
|
quality: "draft" | "standard" | "high";
|
|
42
42
|
format?: "mp4" | "webm" | "mov";
|
|
43
43
|
videoFrameFormat?: RenderConfig["videoFrameFormat"];
|
|
44
|
+
pageMotionBlur?: RenderConfig["pageMotionBlur"];
|
|
44
45
|
outputDynamicRange?: "auto" | "hdr" | "sdr";
|
|
45
46
|
workers?: number;
|
|
46
47
|
crf?: number;
|
|
@@ -68,7 +68,7 @@ export declare function assemble(planDir: string, chunkOutputs: AssembleChunkPat
|
|
|
68
68
|
*/
|
|
69
69
|
cfr?: boolean;
|
|
70
70
|
}): Promise<AssembleResult>;
|
|
71
|
-
/**
|
|
71
|
+
/** Mp4 chunks carrying audio, or with it as a separate file, stitch under one index like S3's. */
|
|
72
72
|
export declare function chunksAreStitchedMp4(planDir: string, cfr: boolean): boolean;
|
|
73
73
|
export declare function stitchesSeparateAudio(planDir: string): boolean;
|
|
74
74
|
export {};
|
|
@@ -32,7 +32,7 @@ export declare function buildChunkCaptureOptions(input: {
|
|
|
32
32
|
fpsDen: number;
|
|
33
33
|
format: DistributedFormat;
|
|
34
34
|
};
|
|
35
|
-
encoder: Pick<LockedRenderConfig, "quality" | "deviceScaleFactor" | "variables">;
|
|
35
|
+
encoder: Pick<LockedRenderConfig, "quality" | "deviceScaleFactor" | "variables" | "pageMotionBlur">;
|
|
36
36
|
videoCount: number;
|
|
37
37
|
html: string;
|
|
38
38
|
skipReadinessVideoIds?: string[];
|
|
@@ -4,6 +4,7 @@ import { type ProducerLogger } from "../../logger.js";
|
|
|
4
4
|
import { type RenderJob, type RenderStrictness } from "../renderOrchestrator.js";
|
|
5
5
|
import { type ChunkSliceJson, type PlanFileDigests } from "../render/stages/freezePlan.js";
|
|
6
6
|
import { type DistributedFormat } from "./shared.js";
|
|
7
|
+
import type { RenderRequestOptions } from "../../renderRequest.js";
|
|
7
8
|
import { type PlanProtocolV1Descriptor } from "./planProtocol.js";
|
|
8
9
|
import { type PlanSizeBreakdown } from "./planSize.js";
|
|
9
10
|
/**
|
|
@@ -11,7 +12,7 @@ import { type PlanSizeBreakdown } from "./planSize.js";
|
|
|
11
12
|
* `height`, and `format` are required; everything else carries a default
|
|
12
13
|
* sensible for AWS Lambda fan-out.
|
|
13
14
|
*/
|
|
14
|
-
export interface DistributedRenderConfig {
|
|
15
|
+
export interface DistributedRenderConfig extends Pick<RenderRequestOptions, "pageMotionBlur"> {
|
|
15
16
|
/** Integer frame rate. Distributed renders only accept integer fps; the in-process renderer's `Fps` rational handles NTSC. */
|
|
16
17
|
fps: DistributedFps;
|
|
17
18
|
width: number;
|
|
@@ -26,7 +26,7 @@ export interface CompiledComposition {
|
|
|
26
26
|
hasAncestorBackgroundImage: boolean;
|
|
27
27
|
}
|
|
28
28
|
export declare function injectSdkPositionEditsRenderScript(html: string): string;
|
|
29
|
-
export type RenderModeHintCode = "iframe" | "requestAnimationFrame" | "htmlInCanvas";
|
|
29
|
+
export type RenderModeHintCode = "iframe" | "requestAnimationFrame" | "htmlInCanvas" | "captureMotionBlur";
|
|
30
30
|
export interface RenderModeHint {
|
|
31
31
|
code: RenderModeHintCode;
|
|
32
32
|
message: string;
|
|
@@ -35,7 +35,7 @@ export interface RenderModeHints {
|
|
|
35
35
|
recommendScreenshot: boolean;
|
|
36
36
|
reasons: RenderModeHint[];
|
|
37
37
|
}
|
|
38
|
-
export declare function detectRenderModeHints(html: string): RenderModeHints;
|
|
38
|
+
export declare function detectRenderModeHints(html: string, pageMotionBlur?: "off"): RenderModeHints;
|
|
39
39
|
export declare function detectThreeDTransformUsage(html: string): boolean;
|
|
40
40
|
/**
|
|
41
41
|
* Background-image signals on ancestors of the composition root.
|
|
@@ -191,6 +191,7 @@ export interface CompileForRenderOptions {
|
|
|
191
191
|
* `window.__hfVariables` injection covers script reads, not var() in CSS.
|
|
192
192
|
*/
|
|
193
193
|
variables?: Record<string, unknown>;
|
|
194
|
+
pageMotionBlur?: "off";
|
|
194
195
|
}
|
|
195
196
|
/**
|
|
196
197
|
* Compile an HTML composition project into a single self-contained HTML string
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
* requested on one. There is nothing to reject, and threading it through the frozen plan
|
|
17
17
|
* is a feature rather than a fix.
|
|
18
18
|
*/
|
|
19
|
-
import type { MotionBlurOptions } from "@hyperframes/engine";
|
|
19
|
+
import type { MotionBlurOptions, PageMotionBlurOff } from "@hyperframes/engine";
|
|
20
20
|
import type { CapturePlan } from "./capturePlan.js";
|
|
21
21
|
/**
|
|
22
22
|
* Throw a named error when motion blur was asked for on a route that cannot deliver it.
|
|
@@ -25,3 +25,13 @@ import type { CapturePlan } from "./capturePlan.js";
|
|
|
25
25
|
* is a render that accepts `motionBlur` and returns frames with no blur in them.
|
|
26
26
|
*/
|
|
27
27
|
export declare function assertMotionBlurSupported(motionBlur: MotionBlurOptions | undefined, route: CapturePlan["kind"]): void;
|
|
28
|
+
/**
|
|
29
|
+
* Why the page's own capture blur (`data-motion-blur="on"`) must stand down on this route, or
|
|
30
|
+
* undefined when it can run. The layered compositor screenshots each DOM layer after hiding the
|
|
31
|
+
* others; blur draws the whole composition into a canvas that those hides do not reach, so a
|
|
32
|
+
* layer comes out wrong (HDR: backgrounds and overlays lost).
|
|
33
|
+
*/
|
|
34
|
+
export declare function pageMotionBlurForRoute(route: {
|
|
35
|
+
hasHdrContent: boolean;
|
|
36
|
+
useLayeredComposite: boolean;
|
|
37
|
+
}): PageMotionBlurOff | undefined;
|
|
@@ -37,6 +37,7 @@ export interface SegmentPlanHashInput {
|
|
|
37
37
|
outputHeight: number;
|
|
38
38
|
/** Serialised motion-blur options, or "" when off; sample count and shutter change every pixel. */
|
|
39
39
|
motionBlur: string;
|
|
40
|
+
pageMotionBlur: "off" | undefined;
|
|
40
41
|
captureQuality: number | undefined;
|
|
41
42
|
}
|
|
42
43
|
/** Everything that determines segment bytes. Key order is fixed by construction. */
|
|
@@ -46,4 +46,5 @@ export interface AssembleStageResult {
|
|
|
46
46
|
/** Wall-clock ms for the assemble phase. */
|
|
47
47
|
assembleMs: number;
|
|
48
48
|
}
|
|
49
|
+
export declare function recordLimiterAttenuation(job: RenderJob, audioLoweredDb: number | undefined): void;
|
|
49
50
|
export declare function runAssembleStage(input: AssembleStageInput): Promise<AssembleStageResult>;
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* `success: false`.
|
|
17
17
|
* - `perfStages.audioProcessMs` is set whether or not the call ran.
|
|
18
18
|
*/
|
|
19
|
+
import type { Fps } from "@hyperframes/core";
|
|
19
20
|
import { type AudioProcessingFailure } from "@hyperframes/engine";
|
|
20
21
|
import type { CompositionMetadata } from "../shared.js";
|
|
21
22
|
import type { ProducerLogger } from "../../../logger.js";
|
|
@@ -24,8 +25,9 @@ export interface AudioStageInput {
|
|
|
24
25
|
workDir: string;
|
|
25
26
|
/** `join(workDir, "compiled")`; passed through to the audio mixer for asset resolution. */
|
|
26
27
|
compiledDir: string;
|
|
27
|
-
/**
|
|
28
|
-
|
|
28
|
+
/** Probed video frame count and exact frame rate define the delivered audio length. */
|
|
29
|
+
totalFrames: number;
|
|
30
|
+
fps: Fps;
|
|
29
31
|
/** Timeout forwarded to ffmpeg subprocesses used by the audio mixer. */
|
|
30
32
|
ffmpegProcessTimeout: number;
|
|
31
33
|
/** Master gain forwarded to the audio mixer. */
|
|
@@ -34,14 +36,14 @@ export interface AudioStageInput {
|
|
|
34
36
|
audios: CompositionMetadata["audios"];
|
|
35
37
|
masterFxChain?: string;
|
|
36
38
|
urlByAbsentLocalPath?: ReadonlyMap<string, string>;
|
|
37
|
-
/** Keep the float mix the AAC was encoded from here, for a later re-encode from it. */
|
|
38
|
-
keepEncoderInputAt?: string;
|
|
39
39
|
abortSignal: AbortSignal | undefined;
|
|
40
40
|
assertNotAborted: () => void;
|
|
41
41
|
/** Where a per-track failure's detail goes. Optional so tests need not pass one. */
|
|
42
42
|
log?: ProducerLogger;
|
|
43
43
|
}
|
|
44
44
|
export interface AudioStageResult {
|
|
45
|
+
/** Actual delivery attenuation, for the render warning and metadata. */
|
|
46
|
+
audioLoweredDb?: number;
|
|
45
47
|
/** Always `join(workDir, MIXED_AUDIO_FILENAME)`. */
|
|
46
48
|
audioOutputPath: string;
|
|
47
49
|
/** True iff the audio mix actually produced a file. False when there are no audio elements. */
|
|
@@ -26,13 +26,9 @@
|
|
|
26
26
|
* - `job.framesRendered` is updated at every per-frame / per-progress
|
|
27
27
|
* point; `Capturing frame N/M` goes through `reportFrameProgress`.
|
|
28
28
|
*
|
|
29
|
-
* Known follow-up: this stage imports `executeDiskCaptureWithAdaptiveRetry`
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* invoked during load. A subsequent PR will consolidate the capture
|
|
33
|
-
* helpers (`executeDiskCaptureWithAdaptiveRetry`, `countFrameRanges`,
|
|
34
|
-
* `safeCleanup`, `sampleDirectoryBytes`, etc.) into a shared module so
|
|
35
|
-
* the stages can import them without reaching back into the orchestrator.
|
|
29
|
+
* Known follow-up: this stage imports `executeDiskCaptureWithAdaptiveRetry` from
|
|
30
|
+
* `renderOrchestrator.ts`, which imports the stage (a cycle that resolves at module init). The
|
|
31
|
+
* capture helpers should move to a shared module so stages stop reaching back into the orchestrator.
|
|
36
32
|
*/
|
|
37
33
|
import { type BeforeCaptureHook, type CaptureOptions, type CapturePerfSummary, type CaptureSession, type EngineConfig, type LandedFrame } from "@hyperframes/engine";
|
|
38
34
|
import type { FileServerHandle } from "../../fileServer.js";
|
|
@@ -128,7 +124,6 @@ export declare function inspectDiskCaptureHeadroom(framesDir: string, totalFrame
|
|
|
128
124
|
*/
|
|
129
125
|
export declare function diskCaptureRemedy(cfg: EngineConfig, outputFormat: NonNullable<RenderConfig["format"]>, durationSeconds: number, workerCount: number): string;
|
|
130
126
|
export declare function diskCaptureShortfallError(needBytes: number, freeBytes: number, framesDir: string, basis: "estimate" | "measured", remedy: string): Error;
|
|
131
|
-
export declare function assertDiskCaptureHeadroom(framesDir: string, totalFrames: number, captureOptions: CaptureOptions, remedy: string, freeDiskBytes?: (path: string) => number | null): void;
|
|
132
127
|
/** Frame bytes written so far: the merged frames dir plus every capture attempt's worker dirs. */
|
|
133
128
|
export declare function measureCaptureFrameBytes(workDir: string, framesDir: string): number;
|
|
134
129
|
/** Per-frame callback: after the sample frames, throws if the projected remainder exceeds 90% of free space. */
|
|
@@ -80,6 +80,8 @@ export interface CompileStageInput {
|
|
|
80
80
|
variables?: Record<string, unknown>;
|
|
81
81
|
/** Absolute project paths not on disk, readable at these URLs instead. */
|
|
82
82
|
urlByAbsentLocalPath?: ReadonlyMap<string, string>;
|
|
83
|
+
/** See RenderConfig.pageMotionBlur; decides whether the page renders through screenshots. */
|
|
84
|
+
pageMotionBlur?: "off";
|
|
83
85
|
}
|
|
84
86
|
export interface CompileStageResult {
|
|
85
87
|
compiled: CompiledComposition;
|
|
@@ -10,11 +10,12 @@
|
|
|
10
10
|
* has in memory.
|
|
11
11
|
*/
|
|
12
12
|
import type { Fps } from "@hyperframes/core";
|
|
13
|
+
import type { RenderRequestOptions } from "../../../renderRequest.js";
|
|
13
14
|
import { type PlanDimensions } from "./planHash.js";
|
|
14
15
|
/**
|
|
15
16
|
* The encoder configuration locked in at plan time.
|
|
16
17
|
*/
|
|
17
|
-
export interface LockedRenderConfig {
|
|
18
|
+
export interface LockedRenderConfig extends Pick<RenderRequestOptions, "pageMotionBlur"> {
|
|
18
19
|
captureMode: "beginframe" | "screenshot";
|
|
19
20
|
forceScreenshot: boolean;
|
|
20
21
|
deviceScaleFactor: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.188",
|
|
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/
|
|
41
|
-
"@hyperframes/
|
|
42
|
-
"@hyperframes/
|
|
38
|
+
"@hyperframes/engine": "0.8.188",
|
|
39
|
+
"@hyperframes/parsers": "0.8.188",
|
|
40
|
+
"@hyperframes/lint": "0.8.188",
|
|
41
|
+
"@hyperframes/core": "0.8.188",
|
|
42
|
+
"@hyperframes/studio-server": "0.8.188"
|
|
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.188"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|