@hyperframes/producer 0.8.199 → 0.8.200
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 +42 -21
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +65 -62
- package/dist/index.js +109 -30
- package/dist/public-server.js +77 -26
- package/dist/services/distributed/chunkWeights.d.ts +2 -0
- package/dist/services/htmlCompiler.d.ts +0 -2
- package/dist/services/render/audioPadTrim.d.ts +2 -0
- package/dist/services/render/stages/compileStage.d.ts +1 -1
- package/dist/services/render/stages/freezePlan.d.ts +1 -0
- package/dist/services/renderOrchestrator.d.ts +2 -1
- package/package.json +7 -7
package/dist/distributed.js
CHANGED
|
@@ -2311,10 +2311,6 @@ var THREE_D_CONTEXT_PATTERN = /transform-style\s*:\s*preserve-3d|backface-visibi
|
|
|
2311
2311
|
function detectThreeDTransformUsage(html) {
|
|
2312
2312
|
return THREE_D_CONTEXT_PATTERN.test(html);
|
|
2313
2313
|
}
|
|
2314
|
-
var MIX_BLEND_MODE_PATTERN = /mix-blend-mode\s*:/i;
|
|
2315
|
-
function detectMixBlendModeUsage(html) {
|
|
2316
|
-
return MIX_BLEND_MODE_PATTERN.test(html);
|
|
2317
|
-
}
|
|
2318
2314
|
var BACKGROUND_IMAGE_DECL_PATTERN = /(?:^|;|\{)\s*background(?:-image)?\s*:[^;}]*(?:\bgradient\s*\(|url\s*\()/i;
|
|
2319
2315
|
function detectAncestorBackgroundImage(html) {
|
|
2320
2316
|
const { document: document2 } = parseHTML4(html);
|
|
@@ -3327,7 +3323,6 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
|
|
|
3327
3323
|
const renderModeHints = detectRenderModeHints(sanitizedHtml, options.pageMotionBlur);
|
|
3328
3324
|
const hasShaderTransitions = detectShaderTransitionUsage(sanitizedHtml);
|
|
3329
3325
|
const usesThreeDTransforms = detectThreeDTransformUsage(sanitizedHtml);
|
|
3330
|
-
const usesMixBlendMode = detectMixBlendModeUsage(sanitizedHtml);
|
|
3331
3326
|
const hasAncestorBackgroundImage = detectAncestorBackgroundImage(sanitizedHtml);
|
|
3332
3327
|
const normalizedFontHtml = normalizeSystemFontPrimaryFamilies(
|
|
3333
3328
|
injectTextRenderingRule(
|
|
@@ -3441,7 +3436,6 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
|
|
|
3441
3436
|
renderModeHints,
|
|
3442
3437
|
hasShaderTransitions,
|
|
3443
3438
|
usesThreeDTransforms,
|
|
3444
|
-
usesMixBlendMode,
|
|
3445
3439
|
hasAncestorBackgroundImage
|
|
3446
3440
|
};
|
|
3447
3441
|
}
|
|
@@ -3848,13 +3842,6 @@ async function runCompileStage(input) {
|
|
|
3848
3842
|
"[Render] Fast capture: composition uses a CSS 3D rendering context (perspective / preserve-3d / backface-visibility), so disabling drawElementImage for this render. Capture uses the platform's baseline route."
|
|
3849
3843
|
);
|
|
3850
3844
|
}
|
|
3851
|
-
if (cfg.useDrawElement && process.env.HF_FAST_CAPTURE_BLEND !== "true" && compiled.usesMixBlendMode) {
|
|
3852
|
-
cfg.useDrawElement = false;
|
|
3853
|
-
deCompileGate = "mix_blend_mode";
|
|
3854
|
-
log.info(
|
|
3855
|
-
"[Render] Fast capture: composition uses mix-blend-mode, so disabling drawElementImage for this render. Capture uses the platform's baseline route."
|
|
3856
|
-
);
|
|
3857
|
-
}
|
|
3858
3845
|
if (cfg.useDrawElement && process.env.HF_FAST_CAPTURE_ANCESTOR_BG !== "true" && compiled.hasAncestorBackgroundImage) {
|
|
3859
3846
|
cfg.useDrawElement = false;
|
|
3860
3847
|
deCompileGate = "ancestor_background_image";
|
|
@@ -5312,10 +5299,11 @@ async function constrainAacTruePeak(input) {
|
|
|
5312
5299
|
const timeoutMs = input.timeoutMs ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
|
|
5313
5300
|
return enforceAacTruePeak({
|
|
5314
5301
|
audioPath: input.audioPath,
|
|
5302
|
+
sourcePath: input.sourcePath,
|
|
5315
5303
|
targetDurationSeconds: input.targetDurationSeconds,
|
|
5316
5304
|
signal: input.signal,
|
|
5317
|
-
probeTruePeak: (audioPath, signal) => measureTruePeakDbfs(audioPath, { timeoutMs, signal }),
|
|
5318
|
-
encode: defaultAacEncoder(timeoutMs, input.signal, input.sourcePath)
|
|
5305
|
+
probeTruePeak: input.probeTruePeakDbfs ?? ((audioPath, signal) => measureTruePeakDbfs(audioPath, { timeoutMs, signal })),
|
|
5306
|
+
encode: input.encodeAac ?? defaultAacEncoder(timeoutMs, input.signal, input.sourcePath)
|
|
5319
5307
|
});
|
|
5320
5308
|
}
|
|
5321
5309
|
async function enforceAacTruePeak(input) {
|
|
@@ -5325,6 +5313,7 @@ async function enforceAacTruePeak(input) {
|
|
|
5325
5313
|
const correctedPath = join9(scratchDir, "audio.m4a");
|
|
5326
5314
|
const measurements = [];
|
|
5327
5315
|
let attenuationDb = 0;
|
|
5316
|
+
let sourcePeakDbfs;
|
|
5328
5317
|
let measuredPath = input.audioPath;
|
|
5329
5318
|
for (let pass = 0; pass <= MAX_TRUE_PEAK_CORRECTION_PASSES; pass += 1) {
|
|
5330
5319
|
const truePeakDbfs = await input.probeTruePeak(measuredPath, input.signal);
|
|
@@ -5341,7 +5330,11 @@ async function enforceAacTruePeak(input) {
|
|
|
5341
5330
|
}
|
|
5342
5331
|
if (pass === MAX_TRUE_PEAK_CORRECTION_PASSES) break;
|
|
5343
5332
|
const headroomDb = AAC_TRUE_PEAK_CORRECTION_HEADROOM_DB * 2 ** pass;
|
|
5344
|
-
|
|
5333
|
+
if (input.sourcePath && sourcePeakDbfs === void 0) {
|
|
5334
|
+
sourcePeakDbfs = await input.probeTruePeak(input.sourcePath, input.signal);
|
|
5335
|
+
}
|
|
5336
|
+
const referenceDbfs = Math.max(truePeakDbfs, (sourcePeakDbfs ?? -Infinity) + attenuationDb);
|
|
5337
|
+
attenuationDb += AAC_DELIVERY_TRUE_PEAK_DBFS - headroomDb - referenceDbfs;
|
|
5345
5338
|
const result = await input.encode(
|
|
5346
5339
|
input.audioPath,
|
|
5347
5340
|
correctedPath,
|
|
@@ -5758,7 +5751,7 @@ async function runCaptureStage(input) {
|
|
|
5758
5751
|
);
|
|
5759
5752
|
}
|
|
5760
5753
|
}
|
|
5761
|
-
const captureOptions = buildCaptureOptions();
|
|
5754
|
+
const captureOptions = { ...buildCaptureOptions(), deFrameFallback: false };
|
|
5762
5755
|
const remedy = diskCaptureRemedy(cfg, job.config.format ?? "mp4", job.duration ?? 0, workerCount);
|
|
5763
5756
|
const checkDiskProjection = createDiskCaptureProjection({
|
|
5764
5757
|
framesDir,
|
|
@@ -7336,6 +7329,18 @@ function planFrameWeights(input) {
|
|
|
7336
7329
|
}
|
|
7337
7330
|
return weights;
|
|
7338
7331
|
}
|
|
7332
|
+
function withChunkCaptureCost(slices, weights) {
|
|
7333
|
+
const lightest = weights.reduce((least, weight) => Math.min(least, weight), Infinity);
|
|
7334
|
+
return slices.map((slice) => {
|
|
7335
|
+
let sum2 = 0;
|
|
7336
|
+
for (let frame = slice.startFrame; frame < slice.endFrame; frame++) sum2 += weights[frame];
|
|
7337
|
+
const cost = Math.round(sum2 / (slice.endFrame - slice.startFrame) / lightest * 100) / 100;
|
|
7338
|
+
return cost > 1 ? { ...slice, captureCost: cost } : slice;
|
|
7339
|
+
});
|
|
7340
|
+
}
|
|
7341
|
+
function effectiveChunkFrames(frames, captureCost = 1) {
|
|
7342
|
+
return Math.round(frames * captureCost);
|
|
7343
|
+
}
|
|
7339
7344
|
function buildWeightedChunkSlices(weights, chunkCount, minFrames, maxFrames) {
|
|
7340
7345
|
if (isUniformFrameCost(weights)) return null;
|
|
7341
7346
|
const totalFrames = weights.length;
|
|
@@ -8660,7 +8665,10 @@ function buildPlanChunkSlices(frameWeights, config, chunkCount, effectiveChunkSi
|
|
|
8660
8665
|
MIN_CHUNK_SIZE,
|
|
8661
8666
|
Math.min(config.targetChunkFrames ?? MAX_CHUNK_SIZE, MAX_CHUNK_SIZE, maxFramesPerChunk)
|
|
8662
8667
|
) : null;
|
|
8663
|
-
return
|
|
8668
|
+
return withChunkCaptureCost(
|
|
8669
|
+
weighted ?? buildChunkSlices(frameWeights.length, chunkCount, effectiveChunkSize),
|
|
8670
|
+
frameWeights
|
|
8671
|
+
);
|
|
8664
8672
|
}
|
|
8665
8673
|
async function readFontSnapshotSha() {
|
|
8666
8674
|
const module = await import("@hyperframes/core/fonts/embedded-data");
|
|
@@ -9651,7 +9659,12 @@ function parseChunkSlices(value) {
|
|
|
9651
9659
|
throw new PlanV2IntegrityError(`meta/chunks.json contains duplicate chunk index ${index}`);
|
|
9652
9660
|
}
|
|
9653
9661
|
indexes.add(index);
|
|
9654
|
-
return { index, startFrame, endFrame };
|
|
9662
|
+
if (chunk.captureCost === void 0) return { index, startFrame, endFrame };
|
|
9663
|
+
const captureCost = chunk.captureCost;
|
|
9664
|
+
if (typeof captureCost !== "number" || !Number.isFinite(captureCost) || captureCost <= 1) {
|
|
9665
|
+
throw new PlanV2IntegrityError(`${field}.captureCost must be a number above 1`);
|
|
9666
|
+
}
|
|
9667
|
+
return { index, startFrame, endFrame, captureCost };
|
|
9655
9668
|
});
|
|
9656
9669
|
}
|
|
9657
9670
|
function buildVideoChunkDependencies(executionPlanDir, dimensions) {
|
|
@@ -10828,15 +10841,17 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
10828
10841
|
deferredVideos.filter((video) => remoteVideoIds.has(video.videoId))
|
|
10829
10842
|
)
|
|
10830
10843
|
});
|
|
10844
|
+
const captureFrames = effectiveChunkFrames(framesInChunk, slice.captureCost);
|
|
10831
10845
|
const chunkWorkerCount = resolveChunkCaptureWorkers(
|
|
10832
|
-
|
|
10833
|
-
calculateOptimalWorkers2(
|
|
10846
|
+
captureFrames,
|
|
10847
|
+
calculateOptimalWorkers2(captureFrames, void 0, cfg),
|
|
10834
10848
|
options?.maxCaptureWorkers
|
|
10835
10849
|
);
|
|
10836
10850
|
let session = null;
|
|
10837
10851
|
let outputKind;
|
|
10838
10852
|
let framesEncoded = 0;
|
|
10839
10853
|
let sessionBootMs = 0;
|
|
10854
|
+
let videoExtractMs = 0;
|
|
10840
10855
|
let captureStageMs = 0;
|
|
10841
10856
|
let encodeStageMs = 0;
|
|
10842
10857
|
let captureMode;
|
|
@@ -10902,6 +10917,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
10902
10917
|
session = null;
|
|
10903
10918
|
}
|
|
10904
10919
|
}
|
|
10920
|
+
const extractStarted = Date.now();
|
|
10905
10921
|
const deferredVideoFrames = planVideos ? extractDeferredVideoFramesForChunk({
|
|
10906
10922
|
planDir,
|
|
10907
10923
|
planVideos,
|
|
@@ -10911,6 +10927,9 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
10911
10927
|
cfg,
|
|
10912
10928
|
remoteSources,
|
|
10913
10929
|
shownBoxes
|
|
10930
|
+
}).then((frames) => {
|
|
10931
|
+
videoExtractMs = Date.now() - extractStarted;
|
|
10932
|
+
return frames;
|
|
10914
10933
|
}) : Promise.resolve([]);
|
|
10915
10934
|
extraction = deferredVideoFrames;
|
|
10916
10935
|
const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? deferredVideoFrames.then(
|
|
@@ -11128,6 +11147,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11128
11147
|
sessionBootMs,
|
|
11129
11148
|
captureStageMs,
|
|
11130
11149
|
encodeStageMs,
|
|
11150
|
+
// Wall time of the chunk's own video frame extraction; it overlaps captureStageMs, so do not add them.
|
|
11151
|
+
videoExtractMs,
|
|
11131
11152
|
workers: chunkWorkerCount,
|
|
11132
11153
|
captureMode,
|
|
11133
11154
|
// Device-pixel box each video's frames were extracted to cover; a video not listed kept full size.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.1.0",
|
|
3
3
|
"buildId": "dev",
|
|
4
|
-
"sha256": "
|
|
4
|
+
"sha256": "72ff9fd22c5222e47fb7ec1b9bb2e3643440846a146df5ced666c818e2027d86",
|
|
5
5
|
"artifacts": {
|
|
6
6
|
"iife": "hyperframe.runtime.iife.js",
|
|
7
7
|
"esm": "hyperframe.runtime.mjs"
|