@hyperframes/producer 0.8.150 → 0.8.152
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 +9 -3
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +54 -54
- package/dist/index.js +14 -6
- package/dist/public-server.js +13 -5
- package/dist/services/render/captureImageFormat.d.ts +6 -1
- package/dist/services/render/segmentManifest.d.ts +1 -0
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -4304,7 +4304,8 @@ function computeSegmentPlanHash(input) {
|
|
|
4304
4304
|
input.imageFormat,
|
|
4305
4305
|
input.useGpu ? "gpu" : "cpu",
|
|
4306
4306
|
`${input.outputWidth}x${input.outputHeight}`,
|
|
4307
|
-
input.motionBlur
|
|
4307
|
+
input.motionBlur,
|
|
4308
|
+
input.captureQuality === void 0 ? "" : String(input.captureQuality)
|
|
4308
4309
|
].join(" ");
|
|
4309
4310
|
return createHash2("sha256").update(ordered).digest("hex").slice(0, 16);
|
|
4310
4311
|
}
|
|
@@ -7617,6 +7618,9 @@ function isActionableProbeFailure(line) {
|
|
|
7617
7618
|
function resolveCaptureImageFormat(input) {
|
|
7618
7619
|
return input.needsAlpha || input.motionBlur ? "png" : "jpeg";
|
|
7619
7620
|
}
|
|
7621
|
+
function resolveCaptureJpegQuality(quality) {
|
|
7622
|
+
return quality === "draft" ? 80 : 100;
|
|
7623
|
+
}
|
|
7620
7624
|
|
|
7621
7625
|
// src/services/render/stages/probeStage.ts
|
|
7622
7626
|
var FRAME_BOUNDARY_EPSILON = 1e-3;
|
|
@@ -7772,7 +7776,7 @@ async function runProbeStage(input) {
|
|
|
7772
7776
|
height,
|
|
7773
7777
|
fps: job.config.fps,
|
|
7774
7778
|
format: captureFormat,
|
|
7775
|
-
quality: captureFormat === "png" ? void 0 :
|
|
7779
|
+
quality: captureFormat === "png" ? void 0 : resolveCaptureJpegQuality(job.config.quality),
|
|
7776
7780
|
variables: job.config.variables,
|
|
7777
7781
|
deviceScaleFactor,
|
|
7778
7782
|
motionBlur,
|
|
@@ -8756,13 +8760,16 @@ function shouldAllowAdaptiveCaptureRetry(workerCount, _explicitlyConfigured) {
|
|
|
8756
8760
|
return workerCount > 1;
|
|
8757
8761
|
}
|
|
8758
8762
|
var JPEG_RAW_RGBA_DIVISOR = 8;
|
|
8763
|
+
var HIGH_QUALITY_JPEG_RAW_RGBA_DIVISOR = 4;
|
|
8759
8764
|
var DISK_PROJECTION_SAMPLE_FRAMES = 10;
|
|
8760
8765
|
function estimateDiskCaptureBytes(totalFrames, captureOptions) {
|
|
8761
8766
|
const scale = captureOptions.deviceScaleFactor ?? 1;
|
|
8762
8767
|
const outputWidth = Math.ceil(captureOptions.width * scale);
|
|
8763
8768
|
const outputHeight = Math.ceil(captureOptions.height * scale);
|
|
8764
8769
|
const rawBytes = Math.ceil(totalFrames) * outputWidth * outputHeight * 4;
|
|
8765
|
-
return frameFileExtension(captureOptions.format) === "jpg" ? Math.ceil(
|
|
8770
|
+
return frameFileExtension(captureOptions.format) === "jpg" ? Math.ceil(
|
|
8771
|
+
rawBytes / ((captureOptions.quality ?? 80) > 80 ? HIGH_QUALITY_JPEG_RAW_RGBA_DIVISOR : JPEG_RAW_RGBA_DIVISOR)
|
|
8772
|
+
) : rawBytes;
|
|
8766
8773
|
}
|
|
8767
8774
|
function freeDiskBytesAt(path) {
|
|
8768
8775
|
try {
|
|
@@ -12224,7 +12231,7 @@ async function executeRenderPipeline(input) {
|
|
|
12224
12231
|
height,
|
|
12225
12232
|
fps: job.config.fps,
|
|
12226
12233
|
format: captureImageFormat,
|
|
12227
|
-
quality: captureImageFormat === "png" ? void 0 : job.config.quality
|
|
12234
|
+
quality: captureImageFormat === "png" ? void 0 : resolveCaptureJpegQuality(job.config.quality),
|
|
12228
12235
|
variables: job.config.variables,
|
|
12229
12236
|
deviceScaleFactor,
|
|
12230
12237
|
motionBlur: job.config.motionBlur,
|
|
@@ -12852,7 +12859,8 @@ async function executeRenderPipeline(input) {
|
|
|
12852
12859
|
// Device-scaled: the capture buffer, not the CSS composition size.
|
|
12853
12860
|
outputWidth: captureCompositionWidth ?? width,
|
|
12854
12861
|
outputHeight: captureCompositionHeight ?? height,
|
|
12855
|
-
motionBlur: job.config.motionBlur ? JSON.stringify(job.config.motionBlur) : ""
|
|
12862
|
+
motionBlur: job.config.motionBlur ? JSON.stringify(job.config.motionBlur) : "",
|
|
12863
|
+
captureQuality: captureOptions.quality
|
|
12856
12864
|
});
|
|
12857
12865
|
const segmentDir = segmentDirFor(join26(projectDir, "renders"), segmentPlanHash);
|
|
12858
12866
|
let completedSegments = /* @__PURE__ */ new Set();
|
|
@@ -17724,7 +17732,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
|
|
|
17724
17732
|
height: plan2.dimensions.height,
|
|
17725
17733
|
fps: { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen },
|
|
17726
17734
|
format: plan2.dimensions.format === "mp4" ? "jpeg" : "png",
|
|
17727
|
-
quality: plan2.dimensions.format === "mp4" ?
|
|
17735
|
+
quality: plan2.dimensions.format === "mp4" ? resolveCaptureJpegQuality(job.config.quality) : void 0,
|
|
17728
17736
|
deviceScaleFactor: encoder.deviceScaleFactor,
|
|
17729
17737
|
// Re-inject the controller's snapshotted variables so the chunk's
|
|
17730
17738
|
// first capture sees the same `window.__hfVariables` the in-process
|
package/dist/public-server.js
CHANGED
|
@@ -4323,7 +4323,8 @@ function computeSegmentPlanHash(input) {
|
|
|
4323
4323
|
input.imageFormat,
|
|
4324
4324
|
input.useGpu ? "gpu" : "cpu",
|
|
4325
4325
|
`${input.outputWidth}x${input.outputHeight}`,
|
|
4326
|
-
input.motionBlur
|
|
4326
|
+
input.motionBlur,
|
|
4327
|
+
input.captureQuality === void 0 ? "" : String(input.captureQuality)
|
|
4327
4328
|
].join(" ");
|
|
4328
4329
|
return createHash2("sha256").update(ordered).digest("hex").slice(0, 16);
|
|
4329
4330
|
}
|
|
@@ -7636,6 +7637,9 @@ function isActionableProbeFailure(line) {
|
|
|
7636
7637
|
function resolveCaptureImageFormat(input) {
|
|
7637
7638
|
return input.needsAlpha || input.motionBlur ? "png" : "jpeg";
|
|
7638
7639
|
}
|
|
7640
|
+
function resolveCaptureJpegQuality(quality) {
|
|
7641
|
+
return quality === "draft" ? 80 : 100;
|
|
7642
|
+
}
|
|
7639
7643
|
|
|
7640
7644
|
// src/services/render/stages/probeStage.ts
|
|
7641
7645
|
var FRAME_BOUNDARY_EPSILON = 1e-3;
|
|
@@ -7791,7 +7795,7 @@ async function runProbeStage(input) {
|
|
|
7791
7795
|
height,
|
|
7792
7796
|
fps: job.config.fps,
|
|
7793
7797
|
format: captureFormat,
|
|
7794
|
-
quality: captureFormat === "png" ? void 0 :
|
|
7798
|
+
quality: captureFormat === "png" ? void 0 : resolveCaptureJpegQuality(job.config.quality),
|
|
7795
7799
|
variables: job.config.variables,
|
|
7796
7800
|
deviceScaleFactor,
|
|
7797
7801
|
motionBlur,
|
|
@@ -8739,13 +8743,16 @@ function shouldAllowAdaptiveCaptureRetry(workerCount, _explicitlyConfigured) {
|
|
|
8739
8743
|
return workerCount > 1;
|
|
8740
8744
|
}
|
|
8741
8745
|
var JPEG_RAW_RGBA_DIVISOR = 8;
|
|
8746
|
+
var HIGH_QUALITY_JPEG_RAW_RGBA_DIVISOR = 4;
|
|
8742
8747
|
var DISK_PROJECTION_SAMPLE_FRAMES = 10;
|
|
8743
8748
|
function estimateDiskCaptureBytes(totalFrames, captureOptions) {
|
|
8744
8749
|
const scale = captureOptions.deviceScaleFactor ?? 1;
|
|
8745
8750
|
const outputWidth = Math.ceil(captureOptions.width * scale);
|
|
8746
8751
|
const outputHeight = Math.ceil(captureOptions.height * scale);
|
|
8747
8752
|
const rawBytes = Math.ceil(totalFrames) * outputWidth * outputHeight * 4;
|
|
8748
|
-
return frameFileExtension(captureOptions.format) === "jpg" ? Math.ceil(
|
|
8753
|
+
return frameFileExtension(captureOptions.format) === "jpg" ? Math.ceil(
|
|
8754
|
+
rawBytes / ((captureOptions.quality ?? 80) > 80 ? HIGH_QUALITY_JPEG_RAW_RGBA_DIVISOR : JPEG_RAW_RGBA_DIVISOR)
|
|
8755
|
+
) : rawBytes;
|
|
8749
8756
|
}
|
|
8750
8757
|
function freeDiskBytesAt(path) {
|
|
8751
8758
|
try {
|
|
@@ -12207,7 +12214,7 @@ async function executeRenderPipeline(input) {
|
|
|
12207
12214
|
height,
|
|
12208
12215
|
fps: job.config.fps,
|
|
12209
12216
|
format: captureImageFormat,
|
|
12210
|
-
quality: captureImageFormat === "png" ? void 0 : job.config.quality
|
|
12217
|
+
quality: captureImageFormat === "png" ? void 0 : resolveCaptureJpegQuality(job.config.quality),
|
|
12211
12218
|
variables: job.config.variables,
|
|
12212
12219
|
deviceScaleFactor,
|
|
12213
12220
|
motionBlur: job.config.motionBlur,
|
|
@@ -12835,7 +12842,8 @@ async function executeRenderPipeline(input) {
|
|
|
12835
12842
|
// Device-scaled: the capture buffer, not the CSS composition size.
|
|
12836
12843
|
outputWidth: captureCompositionWidth ?? width,
|
|
12837
12844
|
outputHeight: captureCompositionHeight ?? height,
|
|
12838
|
-
motionBlur: job.config.motionBlur ? JSON.stringify(job.config.motionBlur) : ""
|
|
12845
|
+
motionBlur: job.config.motionBlur ? JSON.stringify(job.config.motionBlur) : "",
|
|
12846
|
+
captureQuality: captureOptions.quality
|
|
12839
12847
|
});
|
|
12840
12848
|
const segmentDir = segmentDirFor(join26(projectDir, "renders"), segmentPlanHash);
|
|
12841
12849
|
let completedSegments = /* @__PURE__ */ new Set();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MotionBlurOptions } from "@hyperframes/engine";
|
|
1
|
+
import type { EngineConfig, MotionBlurOptions } from "@hyperframes/engine";
|
|
2
2
|
/**
|
|
3
3
|
* The format a render captures its frames in.
|
|
4
4
|
*
|
|
@@ -16,3 +16,8 @@ export declare function resolveCaptureImageFormat(input: {
|
|
|
16
16
|
needsAlpha: boolean;
|
|
17
17
|
motionBlur: MotionBlurOptions | undefined;
|
|
18
18
|
}): "jpeg" | "png";
|
|
19
|
+
/**
|
|
20
|
+
* Below 100, Chrome's JPEG turns graded colour and grain into 8x8 chroma blotches that survive
|
|
21
|
+
* the final encode. Draft keeps the smaller, faster frames.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveCaptureJpegQuality(quality: EngineConfig["quality"]): number;
|
|
@@ -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
|
+
captureQuality: number | undefined;
|
|
40
41
|
}
|
|
41
42
|
/** Everything that determines segment bytes. Key order is fixed by construction. */
|
|
42
43
|
export declare function computeSegmentPlanHash(input: SegmentPlanHashInput): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.152",
|
|
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/
|
|
40
|
-
"@hyperframes/
|
|
41
|
-
"@hyperframes/studio-server": "0.8.
|
|
42
|
-
"@hyperframes/
|
|
38
|
+
"@hyperframes/core": "0.8.152",
|
|
39
|
+
"@hyperframes/parsers": "0.8.152",
|
|
40
|
+
"@hyperframes/engine": "0.8.152",
|
|
41
|
+
"@hyperframes/studio-server": "0.8.152",
|
|
42
|
+
"@hyperframes/lint": "0.8.152"
|
|
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.152"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|