@hyperframes/producer 0.9.20 → 0.9.22
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 +103 -12
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +74 -74
- package/dist/index.js +106 -12
- package/dist/public-server.js +79 -7
- package/dist/renderRequest.d.ts +1 -0
- package/dist/services/distributed/chunkFrames.d.ts +3 -0
- package/dist/services/distributed/plan.d.ts +7 -5
- package/dist/services/fileServer.d.ts +3 -3
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -331,7 +331,7 @@ function buildVirtualTimeShim(options) {
|
|
|
331
331
|
} catch (e) {}
|
|
332
332
|
}
|
|
333
333
|
` : "";
|
|
334
|
-
const seekToTimeReseedCall = seedRandomFromFrame ? "reseedRngFromTime(safeTimeMs);\n
|
|
334
|
+
const seekToTimeReseedCall = seedRandomFromFrame ? "reseedRngFromTime(safeTimeMs);\n " : "";
|
|
335
335
|
return String.raw`(function() {
|
|
336
336
|
if (window.__HF_VIRTUAL_TIME__) return;
|
|
337
337
|
|
|
@@ -410,6 +410,82 @@ ${seededRandomBlock}
|
|
|
410
410
|
}
|
|
411
411
|
};
|
|
412
412
|
|
|
413
|
+
// Timers set once rendering has started run on film time: each seek fires every timer due by then, in
|
|
414
|
+
// due order. Until a seek after the page reports ready, timers keep the wall clock: setup code waits on
|
|
415
|
+
// them while the renderer may already be seeking.
|
|
416
|
+
var rendering = false;
|
|
417
|
+
var timerQueue = [];
|
|
418
|
+
var nextTimerId = 1000000000;
|
|
419
|
+
var firingDepth = 0;
|
|
420
|
+
function addTimer(callback, delay, args, repeats) {
|
|
421
|
+
// A timer set from a firing timer waits at least 1 ms, so a zero-delay chain cannot stall a seek.
|
|
422
|
+
var ms = Math.max(firingDepth > 0 ? 1 : 0, Number(delay) || 0);
|
|
423
|
+
var entry = { id: nextTimerId++, callback: callback, args: args, due: virtualNowMs + ms, every: repeats ? Math.max(1, ms) : 0, cancelled: false };
|
|
424
|
+
timerQueue.push(entry);
|
|
425
|
+
return entry.id;
|
|
426
|
+
}
|
|
427
|
+
function cancelTimer(id) {
|
|
428
|
+
for (var i = 0; i < timerQueue.length; i++) {
|
|
429
|
+
if (timerQueue[i].id === id) {
|
|
430
|
+
timerQueue[i].cancelled = true;
|
|
431
|
+
return true;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
function fireDueTimers(untilMs) {
|
|
437
|
+
// Frame times are fractional, so a timer due on a frame lands a rounding error past it; it still fires on it.
|
|
438
|
+
untilMs += 0.000001;
|
|
439
|
+
while (true) {
|
|
440
|
+
var next = null;
|
|
441
|
+
for (var i = 0; i < timerQueue.length; i++) {
|
|
442
|
+
var candidate = timerQueue[i];
|
|
443
|
+
if (!candidate.cancelled && candidate.due <= untilMs && (next === null || candidate.due < next.due)) next = candidate;
|
|
444
|
+
}
|
|
445
|
+
if (next === null) break;
|
|
446
|
+
var dueMs = next.due;
|
|
447
|
+
if (next.every) next.due += next.every;
|
|
448
|
+
else next.cancelled = true;
|
|
449
|
+
virtualNowMs = dueMs;
|
|
450
|
+
firingDepth++;
|
|
451
|
+
try {
|
|
452
|
+
next.callback.apply(window, next.args);
|
|
453
|
+
} catch (err) {
|
|
454
|
+
originalSetTimeout(function() { throw err; }, 0);
|
|
455
|
+
}
|
|
456
|
+
firingDepth--;
|
|
457
|
+
}
|
|
458
|
+
timerQueue = timerQueue.filter(function(entry) { return !entry.cancelled; });
|
|
459
|
+
}
|
|
460
|
+
window.setTimeout = function(callback, delay) {
|
|
461
|
+
if (!rendering || typeof callback !== "function") return originalSetTimeout.apply(null, arguments);
|
|
462
|
+
return addTimer(callback, delay, Array.prototype.slice.call(arguments, 2), false);
|
|
463
|
+
};
|
|
464
|
+
window.setInterval = function(callback, delay) {
|
|
465
|
+
if (!rendering || typeof callback !== "function") return originalSetInterval.apply(null, arguments);
|
|
466
|
+
return addTimer(callback, delay, Array.prototype.slice.call(arguments, 2), true);
|
|
467
|
+
};
|
|
468
|
+
window.clearTimeout = function(id) {
|
|
469
|
+
if (!cancelTimer(id)) originalClearTimeout(id);
|
|
470
|
+
};
|
|
471
|
+
window.clearInterval = function(id) {
|
|
472
|
+
if (!cancelTimer(id)) originalClearInterval(id);
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
function seekToTime(nextTimeMs) {
|
|
476
|
+
var safeTimeMs = Math.max(0, Number(nextTimeMs) || 0);
|
|
477
|
+
if (!rendering && window.__renderReady === true) {
|
|
478
|
+
rendering = true;
|
|
479
|
+
// A worker whose first frame is past the start plays the film's first frame first, so timers the
|
|
480
|
+
// page starts there keep the schedule a one-worker render gives them.
|
|
481
|
+
if (safeTimeMs > 0) seekToTime(0);
|
|
482
|
+
}
|
|
483
|
+
${seekToTimeReseedCall}fireDueTimers(safeTimeMs);
|
|
484
|
+
virtualNowMs = safeTimeMs;
|
|
485
|
+
flushAnimationFrame();
|
|
486
|
+
return virtualNowMs;
|
|
487
|
+
}
|
|
488
|
+
|
|
413
489
|
window.__HF_VIRTUAL_TIME__ = {
|
|
414
490
|
originalSetTimeout: originalSetTimeout,
|
|
415
491
|
originalClearTimeout: originalClearTimeout,
|
|
@@ -417,12 +493,7 @@ ${seededRandomBlock}
|
|
|
417
493
|
originalClearInterval: originalClearInterval,
|
|
418
494
|
originalRequestAnimationFrame: originalRequestAnimationFrame,
|
|
419
495
|
originalCancelAnimationFrame: originalCancelAnimationFrame,
|
|
420
|
-
seekToTime:
|
|
421
|
-
var safeTimeMs = Math.max(0, Number(nextTimeMs) || 0);
|
|
422
|
-
virtualNowMs = safeTimeMs;
|
|
423
|
-
${seekToTimeReseedCall}flushAnimationFrame();
|
|
424
|
-
return virtualNowMs;
|
|
425
|
-
},
|
|
496
|
+
seekToTime: seekToTime,
|
|
426
497
|
getTime: function() {
|
|
427
498
|
return virtualNowMs;
|
|
428
499
|
},
|
|
@@ -16828,13 +16899,14 @@ var RenderChunkValidationError = class extends Error {
|
|
|
16828
16899
|
this.code = code;
|
|
16829
16900
|
}
|
|
16830
16901
|
};
|
|
16902
|
+
var chunkFrameInjectorDependencies = { createVideoFrameInjector: createVideoFrameInjector3 };
|
|
16831
16903
|
function createChunkVideoFrameInjectorFactory(frameLookup, options) {
|
|
16832
16904
|
if (!(frameLookup instanceof Promise))
|
|
16833
|
-
return () =>
|
|
16905
|
+
return () => chunkFrameInjectorDependencies.createVideoFrameInjector(frameLookup, options);
|
|
16834
16906
|
return () => {
|
|
16835
16907
|
let hook;
|
|
16836
16908
|
return async (page, time, heldVideoTime) => {
|
|
16837
|
-
hook ??=
|
|
16909
|
+
hook ??= chunkFrameInjectorDependencies.createVideoFrameInjector(await frameLookup, options);
|
|
16838
16910
|
await hook?.(page, time, heldVideoTime);
|
|
16839
16911
|
};
|
|
16840
16912
|
};
|
|
@@ -18006,7 +18078,7 @@ function assertPlanSizeWithinLimit(input) {
|
|
|
18006
18078
|
});
|
|
18007
18079
|
throw new PlanTooLargeError(breakdown.totalBytes, input.limitBytes, breakdown, input.observedAt);
|
|
18008
18080
|
}
|
|
18009
|
-
function resolveChunkPlan(totalFrames, configChunkSize, maxParallelChunks, targetChunkFrames) {
|
|
18081
|
+
function resolveChunkPlan(totalFrames, configChunkSize, maxParallelChunks, targetChunkFrames, minParallelChunks = 1) {
|
|
18010
18082
|
assertPositiveInteger2("totalFrames", totalFrames);
|
|
18011
18083
|
assertPositiveInteger2("maxParallelChunks", maxParallelChunks);
|
|
18012
18084
|
if (configChunkSize !== void 0) {
|
|
@@ -18015,7 +18087,11 @@ function resolveChunkPlan(totalFrames, configChunkSize, maxParallelChunks, targe
|
|
|
18015
18087
|
if (targetChunkFrames !== void 0) {
|
|
18016
18088
|
assertPositiveInteger2("targetChunkFrames", targetChunkFrames);
|
|
18017
18089
|
}
|
|
18018
|
-
|
|
18090
|
+
assertPositiveInteger2("minParallelChunks", minParallelChunks);
|
|
18091
|
+
const autoSizeParallel = targetChunkFrames === void 0 ? maxParallelChunks : Math.min(
|
|
18092
|
+
maxParallelChunks,
|
|
18093
|
+
Math.max(minParallelChunks, Math.ceil(totalFrames / targetChunkFrames))
|
|
18094
|
+
);
|
|
18019
18095
|
const resolvedChunkSize = configChunkSize ?? Math.max(MIN_CHUNK_SIZE, Math.ceil(totalFrames / autoSizeParallel));
|
|
18020
18096
|
const naiveCount = Math.ceil(totalFrames / resolvedChunkSize);
|
|
18021
18097
|
const chunkCount = Math.min(maxParallelChunks, Math.max(1, naiveCount));
|
|
@@ -18594,7 +18670,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
|
|
|
18594
18670
|
totalFrames,
|
|
18595
18671
|
config.chunkSize,
|
|
18596
18672
|
maxParallel,
|
|
18597
|
-
config.targetChunkFrames
|
|
18673
|
+
config.targetChunkFrames,
|
|
18674
|
+
config.minParallelChunks
|
|
18598
18675
|
);
|
|
18599
18676
|
const chunks = buildPlanChunkSlices(
|
|
18600
18677
|
frameWeights,
|
|
@@ -20598,6 +20675,20 @@ function validateDistributedRenderConfig(config) {
|
|
|
20598
20675
|
);
|
|
20599
20676
|
}
|
|
20600
20677
|
}
|
|
20678
|
+
if (config.minParallelChunks !== void 0) {
|
|
20679
|
+
if (!Number.isInteger(config.minParallelChunks) || config.minParallelChunks < 1) {
|
|
20680
|
+
throw new InvalidConfigError(
|
|
20681
|
+
"config.minParallelChunks",
|
|
20682
|
+
`must be a positive integer; got ${config.minParallelChunks}`
|
|
20683
|
+
);
|
|
20684
|
+
}
|
|
20685
|
+
if (config.minParallelChunks > MAX_PARALLEL_CHUNKS_CEILING) {
|
|
20686
|
+
throw new InvalidConfigError(
|
|
20687
|
+
"config.minParallelChunks",
|
|
20688
|
+
`must be <= ${MAX_PARALLEL_CHUNKS_CEILING}; got ${config.minParallelChunks}`
|
|
20689
|
+
);
|
|
20690
|
+
}
|
|
20691
|
+
}
|
|
20601
20692
|
for (const field of ["workerTimeoutSeconds", "workerConcurrency"]) {
|
|
20602
20693
|
const value = config[field];
|
|
20603
20694
|
if (value !== void 0 && (!Number.isInteger(value) || value < 1)) {
|
|
@@ -20767,6 +20858,7 @@ function assertDistributedOptions(value) {
|
|
|
20767
20858
|
"chunkSize",
|
|
20768
20859
|
"maxParallelChunks",
|
|
20769
20860
|
"targetChunkFrames",
|
|
20861
|
+
"minParallelChunks",
|
|
20770
20862
|
"planDirSizeLimitBytes"
|
|
20771
20863
|
]) {
|
|
20772
20864
|
assertOptionalInteger(value, field, 1);
|
|
@@ -20906,6 +20998,7 @@ function distributedConfigFromRequest(request, runtime = {}) {
|
|
|
20906
20998
|
chunkSize: distributed.chunkSize,
|
|
20907
20999
|
maxParallelChunks: distributed.maxParallelChunks,
|
|
20908
21000
|
targetChunkFrames: distributed.targetChunkFrames,
|
|
21001
|
+
minParallelChunks: distributed.minParallelChunks,
|
|
20909
21002
|
runtimeCap: distributed.runtimeCap,
|
|
20910
21003
|
rejectOnSystemFonts: distributed.rejectOnSystemFonts,
|
|
20911
21004
|
failClosedFontFetch: distributed.failClosedFontFetch,
|
|
@@ -20933,6 +21026,7 @@ function renderRequestFromDistributedConfig(input) {
|
|
|
20933
21026
|
...optionalProperty("chunkSize", config.chunkSize),
|
|
20934
21027
|
...optionalProperty("maxParallelChunks", config.maxParallelChunks),
|
|
20935
21028
|
...optionalProperty("targetChunkFrames", config.targetChunkFrames),
|
|
21029
|
+
...optionalProperty("minParallelChunks", config.minParallelChunks),
|
|
20936
21030
|
...optionalProperty("runtimeCap", config.runtimeCap),
|
|
20937
21031
|
...optionalProperty("rejectOnSystemFonts", config.rejectOnSystemFonts),
|
|
20938
21032
|
...optionalProperty("failClosedFontFetch", config.failClosedFontFetch),
|
package/dist/public-server.js
CHANGED
|
@@ -348,7 +348,7 @@ function buildVirtualTimeShim(options) {
|
|
|
348
348
|
} catch (e) {}
|
|
349
349
|
}
|
|
350
350
|
` : "";
|
|
351
|
-
const seekToTimeReseedCall = seedRandomFromFrame ? "reseedRngFromTime(safeTimeMs);\n
|
|
351
|
+
const seekToTimeReseedCall = seedRandomFromFrame ? "reseedRngFromTime(safeTimeMs);\n " : "";
|
|
352
352
|
return String.raw`(function() {
|
|
353
353
|
if (window.__HF_VIRTUAL_TIME__) return;
|
|
354
354
|
|
|
@@ -427,6 +427,82 @@ ${seededRandomBlock}
|
|
|
427
427
|
}
|
|
428
428
|
};
|
|
429
429
|
|
|
430
|
+
// Timers set once rendering has started run on film time: each seek fires every timer due by then, in
|
|
431
|
+
// due order. Until a seek after the page reports ready, timers keep the wall clock: setup code waits on
|
|
432
|
+
// them while the renderer may already be seeking.
|
|
433
|
+
var rendering = false;
|
|
434
|
+
var timerQueue = [];
|
|
435
|
+
var nextTimerId = 1000000000;
|
|
436
|
+
var firingDepth = 0;
|
|
437
|
+
function addTimer(callback, delay, args, repeats) {
|
|
438
|
+
// A timer set from a firing timer waits at least 1 ms, so a zero-delay chain cannot stall a seek.
|
|
439
|
+
var ms = Math.max(firingDepth > 0 ? 1 : 0, Number(delay) || 0);
|
|
440
|
+
var entry = { id: nextTimerId++, callback: callback, args: args, due: virtualNowMs + ms, every: repeats ? Math.max(1, ms) : 0, cancelled: false };
|
|
441
|
+
timerQueue.push(entry);
|
|
442
|
+
return entry.id;
|
|
443
|
+
}
|
|
444
|
+
function cancelTimer(id) {
|
|
445
|
+
for (var i = 0; i < timerQueue.length; i++) {
|
|
446
|
+
if (timerQueue[i].id === id) {
|
|
447
|
+
timerQueue[i].cancelled = true;
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
function fireDueTimers(untilMs) {
|
|
454
|
+
// Frame times are fractional, so a timer due on a frame lands a rounding error past it; it still fires on it.
|
|
455
|
+
untilMs += 0.000001;
|
|
456
|
+
while (true) {
|
|
457
|
+
var next = null;
|
|
458
|
+
for (var i = 0; i < timerQueue.length; i++) {
|
|
459
|
+
var candidate = timerQueue[i];
|
|
460
|
+
if (!candidate.cancelled && candidate.due <= untilMs && (next === null || candidate.due < next.due)) next = candidate;
|
|
461
|
+
}
|
|
462
|
+
if (next === null) break;
|
|
463
|
+
var dueMs = next.due;
|
|
464
|
+
if (next.every) next.due += next.every;
|
|
465
|
+
else next.cancelled = true;
|
|
466
|
+
virtualNowMs = dueMs;
|
|
467
|
+
firingDepth++;
|
|
468
|
+
try {
|
|
469
|
+
next.callback.apply(window, next.args);
|
|
470
|
+
} catch (err) {
|
|
471
|
+
originalSetTimeout(function() { throw err; }, 0);
|
|
472
|
+
}
|
|
473
|
+
firingDepth--;
|
|
474
|
+
}
|
|
475
|
+
timerQueue = timerQueue.filter(function(entry) { return !entry.cancelled; });
|
|
476
|
+
}
|
|
477
|
+
window.setTimeout = function(callback, delay) {
|
|
478
|
+
if (!rendering || typeof callback !== "function") return originalSetTimeout.apply(null, arguments);
|
|
479
|
+
return addTimer(callback, delay, Array.prototype.slice.call(arguments, 2), false);
|
|
480
|
+
};
|
|
481
|
+
window.setInterval = function(callback, delay) {
|
|
482
|
+
if (!rendering || typeof callback !== "function") return originalSetInterval.apply(null, arguments);
|
|
483
|
+
return addTimer(callback, delay, Array.prototype.slice.call(arguments, 2), true);
|
|
484
|
+
};
|
|
485
|
+
window.clearTimeout = function(id) {
|
|
486
|
+
if (!cancelTimer(id)) originalClearTimeout(id);
|
|
487
|
+
};
|
|
488
|
+
window.clearInterval = function(id) {
|
|
489
|
+
if (!cancelTimer(id)) originalClearInterval(id);
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
function seekToTime(nextTimeMs) {
|
|
493
|
+
var safeTimeMs = Math.max(0, Number(nextTimeMs) || 0);
|
|
494
|
+
if (!rendering && window.__renderReady === true) {
|
|
495
|
+
rendering = true;
|
|
496
|
+
// A worker whose first frame is past the start plays the film's first frame first, so timers the
|
|
497
|
+
// page starts there keep the schedule a one-worker render gives them.
|
|
498
|
+
if (safeTimeMs > 0) seekToTime(0);
|
|
499
|
+
}
|
|
500
|
+
${seekToTimeReseedCall}fireDueTimers(safeTimeMs);
|
|
501
|
+
virtualNowMs = safeTimeMs;
|
|
502
|
+
flushAnimationFrame();
|
|
503
|
+
return virtualNowMs;
|
|
504
|
+
}
|
|
505
|
+
|
|
430
506
|
window.__HF_VIRTUAL_TIME__ = {
|
|
431
507
|
originalSetTimeout: originalSetTimeout,
|
|
432
508
|
originalClearTimeout: originalClearTimeout,
|
|
@@ -434,12 +510,7 @@ ${seededRandomBlock}
|
|
|
434
510
|
originalClearInterval: originalClearInterval,
|
|
435
511
|
originalRequestAnimationFrame: originalRequestAnimationFrame,
|
|
436
512
|
originalCancelAnimationFrame: originalCancelAnimationFrame,
|
|
437
|
-
seekToTime:
|
|
438
|
-
var safeTimeMs = Math.max(0, Number(nextTimeMs) || 0);
|
|
439
|
-
virtualNowMs = safeTimeMs;
|
|
440
|
-
${seekToTimeReseedCall}flushAnimationFrame();
|
|
441
|
-
return virtualNowMs;
|
|
442
|
-
},
|
|
513
|
+
seekToTime: seekToTime,
|
|
443
514
|
getTime: function() {
|
|
444
515
|
return virtualNowMs;
|
|
445
516
|
},
|
|
@@ -16537,6 +16608,7 @@ function assertDistributedOptions(value) {
|
|
|
16537
16608
|
"chunkSize",
|
|
16538
16609
|
"maxParallelChunks",
|
|
16539
16610
|
"targetChunkFrames",
|
|
16611
|
+
"minParallelChunks",
|
|
16540
16612
|
"planDirSizeLimitBytes"
|
|
16541
16613
|
]) {
|
|
16542
16614
|
assertOptionalInteger(value, field, 1);
|
package/dist/renderRequest.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export interface DistributedRenderOptions {
|
|
|
12
12
|
chunkSize?: number;
|
|
13
13
|
maxParallelChunks?: number;
|
|
14
14
|
targetChunkFrames?: number;
|
|
15
|
+
minParallelChunks?: number;
|
|
15
16
|
runtimeCap?: DistributedRenderConfig["runtimeCap"];
|
|
16
17
|
rejectOnSystemFonts?: boolean;
|
|
17
18
|
failClosedFontFetch?: boolean;
|
|
@@ -16,6 +16,9 @@ export declare class RenderChunkValidationError extends Error {
|
|
|
16
16
|
readonly code: RenderChunkValidationCode;
|
|
17
17
|
constructor(code: RenderChunkValidationCode, message: string);
|
|
18
18
|
}
|
|
19
|
+
export declare const chunkFrameInjectorDependencies: {
|
|
20
|
+
createVideoFrameInjector: typeof createVideoFrameInjector;
|
|
21
|
+
};
|
|
19
22
|
/** One injector per browser session: a hook reused on a fresh page can skip its first injection. */
|
|
20
23
|
export declare function createChunkVideoFrameInjectorFactory(frameLookup: FrameLookupTable | Promise<FrameLookupTable> | null, options?: Parameters<typeof createVideoFrameInjector>[1]): () => BeforeCaptureHook | null;
|
|
21
24
|
/**
|
|
@@ -104,17 +104,19 @@ export interface DistributedRenderConfig extends Pick<RenderRequestOptions, "pag
|
|
|
104
104
|
* chunks whose per-chunk frame count stays at or below this bound, still
|
|
105
105
|
* capped by `maxParallelChunks`:
|
|
106
106
|
*
|
|
107
|
-
* chunkCount = clamp(ceil(totalFrames / targetChunkFrames),
|
|
107
|
+
* chunkCount = clamp(ceil(totalFrames / targetChunkFrames), minParallelChunks, maxParallelChunks)
|
|
108
108
|
*
|
|
109
109
|
* This bounds per-chunk render *time* (which scales with frames-per-chunk) so
|
|
110
110
|
* a single chunk can't exceed a downstream per-chunk timeout on a long video,
|
|
111
|
-
* while short videos
|
|
111
|
+
* while short videos drop to `minParallelChunks` (default 1). It is a ceiling, not a
|
|
112
112
|
* fixed size: a video short enough to fit in fewer chunks gets fewer. Ignored
|
|
113
113
|
* when `chunkSize` is set (an explicit fixed size already pins per-chunk
|
|
114
114
|
* frames). Mutually exclusive with `chunkSize` in intent; if both are passed,
|
|
115
115
|
* `chunkSize` wins and `targetChunkFrames` is a no-op.
|
|
116
116
|
*/
|
|
117
117
|
targetChunkFrames?: number;
|
|
118
|
+
/** Fewest chunks a `targetChunkFrames`-sized plan uses, so a short video keeps this fan-out. */
|
|
119
|
+
minParallelChunks?: number;
|
|
118
120
|
/** Runtime hint; consumed by future per-runtime budget checks. The current implementation records the value but does not enforce. */
|
|
119
121
|
runtimeCap?: "lambda" | "temporal" | "cloud-run-job" | "k8s-job" | "none";
|
|
120
122
|
/**
|
|
@@ -397,12 +399,12 @@ export declare function measurePlanDirBytes(planDir: string): number;
|
|
|
397
399
|
* on tiny renders). Explicit numbers, including `240`, take precedence.
|
|
398
400
|
*
|
|
399
401
|
* Optional `targetChunkFrames` caps per-chunk frames in the auto-sized path:
|
|
400
|
-
* the auto-sizer then targets `clamp(ceil(totalFrames / targetChunkFrames),
|
|
401
|
-
* maxParallelChunks)` chunks, so short videos
|
|
402
|
+
* the auto-sizer then targets `clamp(ceil(totalFrames / targetChunkFrames), minParallelChunks,
|
|
403
|
+
* maxParallelChunks)` chunks, so short videos drop to `minParallelChunks` and long
|
|
402
404
|
* videos add chunks (up to the cap) to keep each one under the bound. It is a
|
|
403
405
|
* no-op when omitted, and ignored when `configChunkSize` is set.
|
|
404
406
|
*/
|
|
405
|
-
export declare function resolveChunkPlan(totalFrames: number, configChunkSize: number | undefined, maxParallelChunks: number, targetChunkFrames?: number): {
|
|
407
|
+
export declare function resolveChunkPlan(totalFrames: number, configChunkSize: number | undefined, maxParallelChunks: number, targetChunkFrames?: number, minParallelChunks?: number): {
|
|
406
408
|
chunkCount: number;
|
|
407
409
|
effectiveChunkSize: number;
|
|
408
410
|
};
|
|
@@ -95,9 +95,9 @@ export interface VirtualTimeShimOptions {
|
|
|
95
95
|
/**
|
|
96
96
|
* Build the page-side virtual-time shim script.
|
|
97
97
|
*
|
|
98
|
-
* The shim freezes `Date.now`, `performance.now`, and the
|
|
99
|
-
*
|
|
100
|
-
* notion of "now". The renderer issues `__HF_VIRTUAL_TIME__.seekToTime(ms)`
|
|
98
|
+
* The shim freezes `Date.now`, `performance.now`, rAF, and the timers set
|
|
99
|
+
* after the first seek, so a render seek can deterministically advance the
|
|
100
|
+
* page's notion of "now". The renderer issues `__HF_VIRTUAL_TIME__.seekToTime(ms)`
|
|
101
101
|
* before every frame capture; everything timing-related on the page sees
|
|
102
102
|
* exactly `ms` until the next seek.
|
|
103
103
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.22",
|
|
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.11.0",
|
|
37
37
|
"puppeteer-core": "^25.11.0",
|
|
38
|
-
"@hyperframes/
|
|
39
|
-
"@hyperframes/
|
|
40
|
-
"@hyperframes/
|
|
41
|
-
"@hyperframes/
|
|
42
|
-
"@hyperframes/
|
|
38
|
+
"@hyperframes/core": "0.9.22",
|
|
39
|
+
"@hyperframes/parsers": "0.9.22",
|
|
40
|
+
"@hyperframes/lint": "0.9.22",
|
|
41
|
+
"@hyperframes/engine": "0.9.22",
|
|
42
|
+
"@hyperframes/studio-server": "0.9.22"
|
|
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.9.
|
|
51
|
+
"@hyperframes/aws-lambda": "0.9.22"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|