@hyperframes/producer 0.8.214 → 0.8.217
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 +58 -19
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +71 -71
- package/dist/index.d.ts +1 -0
- package/dist/index.js +114 -42
- package/dist/public-server.js +91 -20
- package/dist/server.d.ts +2 -6
- package/dist/services/render/observability.d.ts +4 -0
- package/dist/services/render/stages/probeStage.d.ts +13 -1
- package/dist/services/renderOrchestrator.d.ts +3 -2
- package/dist/services/safeRenderErrorCode.d.ts +5 -0
- package/package.json +7 -7
package/dist/public-server.js
CHANGED
|
@@ -3707,6 +3707,10 @@ function resolveCaptureStallTimeoutMs() {
|
|
|
3707
3707
|
const parsed = raw ? Number(raw) : Number.NaN;
|
|
3708
3708
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_CAPTURE_STALL_MS;
|
|
3709
3709
|
}
|
|
3710
|
+
function stallBudgetMs(stallTimeoutMs, framesDone, beginFrame, cfg) {
|
|
3711
|
+
const deadline = cfg.beginFrameFirstFrameDeadlineMs;
|
|
3712
|
+
return beginFrame && framesDone === 0 && deadline ? Math.min(stallTimeoutMs, deadline) : stallTimeoutMs;
|
|
3713
|
+
}
|
|
3710
3714
|
function captureModeLabel(mode) {
|
|
3711
3715
|
if (mode === "drawelement") return "drawElement";
|
|
3712
3716
|
if (mode === "beginframe") return "BeginFrame";
|
|
@@ -4079,14 +4083,20 @@ async function runCaptureStreamingStage(input) {
|
|
|
4079
4083
|
const phaseDetail = (phase) => `phase=${phase.phase} frame=${phase.frameIndex ?? "n/a"} step=${phase.readStep?.() ?? "n/a"} browser=${phase.browserExecutable} version=${phase.browserVersion} CanvasDrawElement=${phase.canvasDrawElement} gpu=${phase.gpuBackend}`;
|
|
4080
4084
|
const phaseSummary = () => [...workerPhases.entries()].sort(([left], [right]) => left - right).map(([workerId, detail]) => `worker=${workerId} ${detail}`).join("; ");
|
|
4081
4085
|
let stalled = false;
|
|
4086
|
+
const budget = () => stallBudgetMs(
|
|
4087
|
+
stallTimeoutMs,
|
|
4088
|
+
resumeFrom + lastCapturedFrames,
|
|
4089
|
+
captureLabel === "BeginFrame",
|
|
4090
|
+
cfg
|
|
4091
|
+
);
|
|
4082
4092
|
const stallTimer = setInterval(
|
|
4083
4093
|
() => {
|
|
4084
|
-
if (!watchdogArmed || Date.now() - lastProgressAt <=
|
|
4094
|
+
if (!watchdogArmed || Date.now() - lastProgressAt <= budget()) return;
|
|
4085
4095
|
stalled = true;
|
|
4086
4096
|
const stallErr = new ParallelCaptureStallError({
|
|
4087
4097
|
variant: "drain",
|
|
4088
4098
|
captureLabel,
|
|
4089
|
-
stallTimeoutMs,
|
|
4099
|
+
stallTimeoutMs: budget(),
|
|
4090
4100
|
lastCapturedFrames: resumeFrom + lastCapturedFrames,
|
|
4091
4101
|
totalFrames,
|
|
4092
4102
|
phaseSummary: phaseSummary()
|
|
@@ -4094,7 +4104,7 @@ async function runCaptureStreamingStage(input) {
|
|
|
4094
4104
|
parallelReorder.abort(stallErr);
|
|
4095
4105
|
stallController.abort();
|
|
4096
4106
|
},
|
|
4097
|
-
Math.min(
|
|
4107
|
+
Math.min(budget(), DE_STALL_POLL_MS)
|
|
4098
4108
|
);
|
|
4099
4109
|
try {
|
|
4100
4110
|
workerResults = await executeParallelCapture(
|
|
@@ -4175,7 +4185,7 @@ async function runCaptureStreamingStage(input) {
|
|
|
4175
4185
|
throw new ParallelCaptureStallError({
|
|
4176
4186
|
variant: "pool",
|
|
4177
4187
|
captureLabel,
|
|
4178
|
-
stallTimeoutMs,
|
|
4188
|
+
stallTimeoutMs: budget(),
|
|
4179
4189
|
lastCapturedFrames: resumeFrom + lastCapturedFrames,
|
|
4180
4190
|
totalFrames,
|
|
4181
4191
|
phaseSummary: phaseSummary()
|
|
@@ -4276,10 +4286,16 @@ async function runCaptureStreamingStage(input) {
|
|
|
4276
4286
|
for (let i = 0; i < totalFrames; i++) {
|
|
4277
4287
|
assertNotAborted();
|
|
4278
4288
|
const time = i * job.config.fps.den / job.config.fps.num;
|
|
4289
|
+
const budget = stallBudgetMs(
|
|
4290
|
+
stallTimeoutMs,
|
|
4291
|
+
i,
|
|
4292
|
+
session.captureMode === "beginframe",
|
|
4293
|
+
cfg
|
|
4294
|
+
);
|
|
4279
4295
|
const { buffer } = await raceAgainstStall(
|
|
4280
4296
|
captureFrameToBuffer(session, i, time),
|
|
4281
|
-
|
|
4282
|
-
{ session, frameIndex: i, totalFrames, stallTimeoutMs },
|
|
4297
|
+
budget - (Date.now() - lastProgressAt),
|
|
4298
|
+
{ session, frameIndex: i, totalFrames, stallTimeoutMs: budget },
|
|
4283
4299
|
abortSignal
|
|
4284
4300
|
);
|
|
4285
4301
|
await reorderBuffer.waitForFrame(i);
|
|
@@ -5497,6 +5513,7 @@ function watchStall(phase, rule) {
|
|
|
5497
5513
|
let lastChangeAt = Date.now();
|
|
5498
5514
|
let attempt;
|
|
5499
5515
|
let timer;
|
|
5516
|
+
let inTail = false;
|
|
5500
5517
|
const restartWindow = (ms) => {
|
|
5501
5518
|
last = rule.progress();
|
|
5502
5519
|
budgetMs = ms;
|
|
@@ -5506,6 +5523,10 @@ function watchStall(phase, rule) {
|
|
|
5506
5523
|
timer = setInterval(
|
|
5507
5524
|
() => {
|
|
5508
5525
|
const current = rule.progress();
|
|
5526
|
+
if (rule.complete?.() && !inTail) {
|
|
5527
|
+
inTail = true;
|
|
5528
|
+
return restartWindow(rule.tailMs ?? rule.noProgressMs);
|
|
5529
|
+
}
|
|
5509
5530
|
if (current !== last) return restartWindow(rule.noProgressMs);
|
|
5510
5531
|
if (Date.now() - lastChangeAt < budgetMs) return;
|
|
5511
5532
|
const error = new RenderStageStalledError(phase, budgetMs, current);
|
|
@@ -5521,6 +5542,7 @@ function watchStall(phase, rule) {
|
|
|
5521
5542
|
});
|
|
5522
5543
|
const openAttempt = (parent) => {
|
|
5523
5544
|
attempt = new AbortController();
|
|
5545
|
+
inTail = false;
|
|
5524
5546
|
restartWindow(rule.firstProgressMs);
|
|
5525
5547
|
return parent ? AbortSignal.any([parent, attempt.signal]) : attempt.signal;
|
|
5526
5548
|
};
|
|
@@ -8512,7 +8534,8 @@ async function runCompileStage(input) {
|
|
|
8512
8534
|
}
|
|
8513
8535
|
|
|
8514
8536
|
// src/services/render/stages/probeStage.ts
|
|
8515
|
-
import {
|
|
8537
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
8538
|
+
import { basename as basename5, join as join17 } from "node:path";
|
|
8516
8539
|
import { parseHTML as parseHTML6 } from "linkedom";
|
|
8517
8540
|
import {
|
|
8518
8541
|
closeCaptureSession as closeCaptureSession4,
|
|
@@ -8520,6 +8543,7 @@ import {
|
|
|
8520
8543
|
createCaptureSession as createCaptureSession4,
|
|
8521
8544
|
deriveBeginFrameProbeTimeTicks,
|
|
8522
8545
|
getCompositionDuration,
|
|
8546
|
+
getCompositionLengthSource,
|
|
8523
8547
|
initializeSession as initializeSession4,
|
|
8524
8548
|
isTransientBrowserError,
|
|
8525
8549
|
probeBeginFrameLiveness,
|
|
@@ -8658,6 +8682,13 @@ function hasRuntimeMediaChanges(html) {
|
|
|
8658
8682
|
function probeRequiresBrowser(args) {
|
|
8659
8683
|
return args.durationSeconds <= 0 || args.unresolvedCompositionCount > 0 || args.hasAutoStart || args.hasScriptedAudio || args.hasVariableMedia || args.hasInsertedMedia;
|
|
8660
8684
|
}
|
|
8685
|
+
function reportedLengthSource(source) {
|
|
8686
|
+
if (!source) return null;
|
|
8687
|
+
if (source.from !== "media") return { from: source.from };
|
|
8688
|
+
const name = basename5(source.src.split(/[?#]/, 1)[0] ?? "");
|
|
8689
|
+
const srcHash = createHash7("sha256").update(name).digest("hex").slice(0, 12);
|
|
8690
|
+
return { from: "media", tag: source.tag, trimmed: source.trimmed, srcHash };
|
|
8691
|
+
}
|
|
8661
8692
|
async function runProbeStage(input) {
|
|
8662
8693
|
const {
|
|
8663
8694
|
projectDir,
|
|
@@ -8679,6 +8710,7 @@ async function runProbeStage(input) {
|
|
|
8679
8710
|
const probeCfg = cfg.forceScreenshot === forceScreenshot ? cfg : { ...cfg, forceScreenshot };
|
|
8680
8711
|
let fileServer = null;
|
|
8681
8712
|
let probeSession = null;
|
|
8713
|
+
let lengthSource = input.composition.duration > 0 ? { from: "declared" } : null;
|
|
8682
8714
|
let beginFrameStalled = false;
|
|
8683
8715
|
let lastBrowserConsole = [];
|
|
8684
8716
|
const probeStart = Date.now();
|
|
@@ -8840,10 +8872,12 @@ async function runProbeStage(input) {
|
|
|
8840
8872
|
if (composition.duration <= 0) {
|
|
8841
8873
|
log.info("Discovering composition duration...");
|
|
8842
8874
|
const discoveredDuration = await getCompositionDuration(session);
|
|
8875
|
+
lengthSource = reportedLengthSource(await getCompositionLengthSource(session));
|
|
8843
8876
|
assertNotAborted();
|
|
8844
8877
|
log.info("Probed composition duration from browser", {
|
|
8845
8878
|
discoveredDuration,
|
|
8846
|
-
staticDuration: compiled.staticDuration
|
|
8879
|
+
staticDuration: compiled.staticDuration,
|
|
8880
|
+
lengthSource
|
|
8847
8881
|
});
|
|
8848
8882
|
composition.duration = discoveredDuration;
|
|
8849
8883
|
} else {
|
|
@@ -9132,6 +9166,7 @@ async function runProbeStage(input) {
|
|
|
9132
9166
|
probeSession,
|
|
9133
9167
|
lastBrowserConsole,
|
|
9134
9168
|
duration,
|
|
9169
|
+
lengthSource,
|
|
9135
9170
|
totalFrames,
|
|
9136
9171
|
browserProbeMs,
|
|
9137
9172
|
beginFrameStalled
|
|
@@ -9619,7 +9654,7 @@ function checkedDbfs(value) {
|
|
|
9619
9654
|
}
|
|
9620
9655
|
return value;
|
|
9621
9656
|
}
|
|
9622
|
-
async function scanTruePeak(audioPath, trim, timeoutMs, signal) {
|
|
9657
|
+
async function scanTruePeak(audioPath, trim, timeoutMs, signal, seekSeconds = 0) {
|
|
9623
9658
|
let firstBlock;
|
|
9624
9659
|
let laterBlocks = Number.NEGATIVE_INFINITY;
|
|
9625
9660
|
let partialLine = "";
|
|
@@ -9635,7 +9670,21 @@ async function scanTruePeak(audioPath, trim, timeoutMs, signal) {
|
|
|
9635
9670
|
}
|
|
9636
9671
|
};
|
|
9637
9672
|
const result = await runFfmpeg4(
|
|
9638
|
-
[
|
|
9673
|
+
[
|
|
9674
|
+
...seekSeconds > 0 ? ["-ss", String(seekSeconds)] : [],
|
|
9675
|
+
...[
|
|
9676
|
+
"-i",
|
|
9677
|
+
audioPath,
|
|
9678
|
+
"-map",
|
|
9679
|
+
"0:a:0",
|
|
9680
|
+
"-vn",
|
|
9681
|
+
"-af",
|
|
9682
|
+
`${trim}ebur128=peak=true`,
|
|
9683
|
+
"-f",
|
|
9684
|
+
"null",
|
|
9685
|
+
"-"
|
|
9686
|
+
]
|
|
9687
|
+
],
|
|
9639
9688
|
{ signal, timeout: timeoutMs, onStderr: readLines }
|
|
9640
9689
|
);
|
|
9641
9690
|
if (!result.success) {
|
|
@@ -9661,12 +9710,15 @@ async function measureTruePeakDbfs(audioPath, options) {
|
|
|
9661
9710
|
const scans = await Promise.all(
|
|
9662
9711
|
Array.from({ length: count }, (_, k) => {
|
|
9663
9712
|
const start = k === 0 ? 0 : cut(k) - block;
|
|
9664
|
-
const
|
|
9713
|
+
const seekSeconds = Math.max(0, Math.floor(start / sampleRate) - 1);
|
|
9714
|
+
const skipped = seekSeconds * sampleRate;
|
|
9715
|
+
const end = k === count - 1 ? "" : `:end_sample=${cut(k + 1) - skipped}`;
|
|
9665
9716
|
return scanTruePeak(
|
|
9666
9717
|
audioPath,
|
|
9667
|
-
`atrim=start_sample=${start}${end},`,
|
|
9718
|
+
`atrim=start_sample=${start - skipped}${end},`,
|
|
9668
9719
|
timeoutMs,
|
|
9669
|
-
segmentSignal
|
|
9720
|
+
segmentSignal,
|
|
9721
|
+
seekSeconds
|
|
9670
9722
|
);
|
|
9671
9723
|
})
|
|
9672
9724
|
).catch((error) => {
|
|
@@ -12295,12 +12347,15 @@ function resetCaptureAttemptProgress(job) {
|
|
|
12295
12347
|
job.framesRendered = 0;
|
|
12296
12348
|
}
|
|
12297
12349
|
var FIRST_FRAME_STALL_MS = 3e5;
|
|
12298
|
-
|
|
12350
|
+
var TAIL_STALL_MS = FIRST_FRAME_STALL_MS;
|
|
12351
|
+
function frameStallRule(job, totalFrames) {
|
|
12299
12352
|
const noProgressMs = resolveCaptureStallTimeoutMs();
|
|
12300
12353
|
return {
|
|
12301
12354
|
progress: () => job.framesRendered ?? 0,
|
|
12302
12355
|
noProgressMs,
|
|
12303
|
-
firstProgressMs: Math.max(FIRST_FRAME_STALL_MS, noProgressMs)
|
|
12356
|
+
firstProgressMs: Math.max(FIRST_FRAME_STALL_MS, noProgressMs),
|
|
12357
|
+
complete: () => (job.framesRendered ?? 0) >= totalFrames,
|
|
12358
|
+
tailMs: Math.max(TAIL_STALL_MS, noProgressMs)
|
|
12304
12359
|
};
|
|
12305
12360
|
}
|
|
12306
12361
|
function isRecoverableParallelCaptureError(error) {
|
|
@@ -13317,6 +13372,12 @@ async function executeRenderPipeline(input) {
|
|
|
13317
13372
|
}
|
|
13318
13373
|
observability.checkpoint("browser_probe", "duration resolved", {
|
|
13319
13374
|
durationSeconds: probeResult.duration,
|
|
13375
|
+
lengthFrom: probeResult.lengthSource?.from ?? null,
|
|
13376
|
+
...probeResult.lengthSource?.from === "media" ? {
|
|
13377
|
+
lengthTag: probeResult.lengthSource.tag,
|
|
13378
|
+
lengthTrimmed: probeResult.lengthSource.trimmed,
|
|
13379
|
+
lengthSrcHash: probeResult.lengthSource.srcHash
|
|
13380
|
+
} : {},
|
|
13320
13381
|
totalFrames,
|
|
13321
13382
|
compositionHash,
|
|
13322
13383
|
beginFrameStalled: probeResult.beginFrameStalled
|
|
@@ -13502,6 +13563,14 @@ async function executeRenderPipeline(input) {
|
|
|
13502
13563
|
// sample frame indices from this so they land inside the drained range.
|
|
13503
13564
|
compositionDurationSeconds: job.duration,
|
|
13504
13565
|
deFrameFallback: true,
|
|
13566
|
+
// A line per scanned chunk, so a long effect scan reads as preparing, not as a stall.
|
|
13567
|
+
onEffectScanProgress: (scanned, total) => updateJobStatus(
|
|
13568
|
+
job,
|
|
13569
|
+
"rendering",
|
|
13570
|
+
`Checking effects, ${scanned} of ${total} frames`,
|
|
13571
|
+
25,
|
|
13572
|
+
onProgress
|
|
13573
|
+
),
|
|
13505
13574
|
requiresWebGpu: compositionRequiresWebGpu2(compiled.html),
|
|
13506
13575
|
// Live route for Chrome memory (spec §5 Phase −1). The aggregate route
|
|
13507
13576
|
// through CapturePerfSummary only exists on success; a mid-capture
|
|
@@ -14186,7 +14255,7 @@ async function executeRenderPipeline(input) {
|
|
|
14186
14255
|
onProgress
|
|
14187
14256
|
});
|
|
14188
14257
|
},
|
|
14189
|
-
{ stall: frameStallRule(job) }
|
|
14258
|
+
{ stall: frameStallRule(job, totalFrames) }
|
|
14190
14259
|
);
|
|
14191
14260
|
lastBrowserConsole = hdrRes.lastBrowserConsole;
|
|
14192
14261
|
layeredCaptureWarnings.push(...hdrRes.warnings);
|
|
@@ -14631,7 +14700,7 @@ async function executeRenderPipeline(input) {
|
|
|
14631
14700
|
interleaveFrames: overlap !== null,
|
|
14632
14701
|
openAttempt
|
|
14633
14702
|
}),
|
|
14634
|
-
{ stall: frameStallRule(job) }
|
|
14703
|
+
{ stall: frameStallRule(job, totalFrames) }
|
|
14635
14704
|
);
|
|
14636
14705
|
let captureRes;
|
|
14637
14706
|
try {
|
|
@@ -15524,9 +15593,7 @@ function renderConfigFromRequest(request, runtime = {}) {
|
|
|
15524
15593
|
};
|
|
15525
15594
|
}
|
|
15526
15595
|
|
|
15527
|
-
// src/
|
|
15528
|
-
var DEFAULT_SERVER_FPS = { num: 30, den: 1 };
|
|
15529
|
-
var SSE_KEEPALIVE_MS = 3e4;
|
|
15596
|
+
// src/services/safeRenderErrorCode.ts
|
|
15530
15597
|
var SAFE_RENDER_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
15531
15598
|
"ASSET_MEDIA_TYPE_MISMATCH",
|
|
15532
15599
|
"HEIF_IMAGE_CONVERSION_FAILED",
|
|
@@ -15544,6 +15611,10 @@ function extractSafeRenderErrorCode(error) {
|
|
|
15544
15611
|
const code = error.code;
|
|
15545
15612
|
return typeof code === "string" && SAFE_RENDER_ERROR_CODES.has(code) ? code : void 0;
|
|
15546
15613
|
}
|
|
15614
|
+
|
|
15615
|
+
// src/server.ts
|
|
15616
|
+
var DEFAULT_SERVER_FPS = { num: 30, den: 1 };
|
|
15617
|
+
var SSE_KEEPALIVE_MS = 3e4;
|
|
15547
15618
|
function extractSafeRenderErrorMetadata(error) {
|
|
15548
15619
|
const errorCode = extractSafeRenderErrorCode(error);
|
|
15549
15620
|
if (!errorCode || typeof error !== "object" || error === null) return void 0;
|
package/dist/server.d.ts
CHANGED
|
@@ -16,6 +16,8 @@ import { Hono, type Context } from "hono";
|
|
|
16
16
|
import { type RenderConfig } from "./services/renderOrchestrator.js";
|
|
17
17
|
import { type ProducerLogger } from "./logger.js";
|
|
18
18
|
import { type CanvasResolution } from "@hyperframes/core";
|
|
19
|
+
import { extractSafeRenderErrorCode } from "./services/safeRenderErrorCode.js";
|
|
20
|
+
export { extractSafeRenderErrorCode };
|
|
19
21
|
export interface HandlerOptions {
|
|
20
22
|
/** Custom logger. Defaults to console-based defaultLogger. */
|
|
21
23
|
logger?: ProducerLogger;
|
|
@@ -80,11 +82,6 @@ interface PreparedRenderInput {
|
|
|
80
82
|
input: RenderInput;
|
|
81
83
|
cleanupProjectDir?: string;
|
|
82
84
|
}
|
|
83
|
-
/**
|
|
84
|
-
* Preserve only bounded producer error codes across JSON/SSE. Never derive a
|
|
85
|
-
* code from the message: it may contain local paths or signed source URLs.
|
|
86
|
-
*/
|
|
87
|
-
export declare function extractSafeRenderErrorCode(error: unknown): string | undefined;
|
|
88
85
|
export interface SafeRenderErrorMetadata {
|
|
89
86
|
errorCode: string;
|
|
90
87
|
errorOwner?: "system" | "user";
|
|
@@ -126,4 +123,3 @@ export declare function createProducerApp(options?: HandlerOptions): Hono;
|
|
|
126
123
|
* Start the producer HTTP server with graceful shutdown.
|
|
127
124
|
*/
|
|
128
125
|
export declare function startServer(options?: ServerOptions): import("@hono/node-server").ServerType;
|
|
129
|
-
export {};
|
|
@@ -333,6 +333,10 @@ export interface StageStallRule {
|
|
|
333
333
|
noProgressMs: number;
|
|
334
334
|
/** Allowed silence before the current attempt's first change. */
|
|
335
335
|
firstProgressMs: number;
|
|
336
|
+
/** True once every unit of work has landed: nothing more can change `progress()`, only the tail work runs. */
|
|
337
|
+
complete?: () => boolean;
|
|
338
|
+
/** Allowed silence once `complete()` holds; defaults to `noProgressMs`. */
|
|
339
|
+
tailMs?: number;
|
|
336
340
|
}
|
|
337
341
|
/**
|
|
338
342
|
* Classified like the per-call protocol timeout it replaces, so the capture retry ladder retries it.
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* regex, the same first-10/first-5 slicing, and the same `console.warn`
|
|
27
27
|
* prefix.
|
|
28
28
|
*/
|
|
29
|
-
import { type CaptureSession, type EngineConfig, type SubTimelineWaitMemo } from "@hyperframes/engine";
|
|
29
|
+
import { type CaptureSession, type CompositionLengthSource, type EngineConfig, type SubTimelineWaitMemo } from "@hyperframes/engine";
|
|
30
30
|
import type { CompiledComposition } from "../../htmlCompiler.js";
|
|
31
31
|
import { type FileServerHandle } from "../../fileServer.js";
|
|
32
32
|
import type { ProducerLogger } from "../../../logger.js";
|
|
@@ -67,6 +67,8 @@ export interface ProbeStageResult {
|
|
|
67
67
|
lastBrowserConsole: string[];
|
|
68
68
|
/** Composition duration (post-probe). Guaranteed > 0 — the stage throws on <= 0. */
|
|
69
69
|
duration: number;
|
|
70
|
+
/** Which input set `duration`; null when the runtime did not say. */
|
|
71
|
+
lengthSource: ReportedLengthSource | null;
|
|
70
72
|
totalFrames: number;
|
|
71
73
|
/** Wall-clock ms for the entire probe phase (near-zero when `needsBrowser` was false). */
|
|
72
74
|
browserProbeMs: number;
|
|
@@ -113,6 +115,16 @@ export declare function probeRequiresBrowser(args: {
|
|
|
113
115
|
hasVariableMedia: boolean;
|
|
114
116
|
hasInsertedMedia: boolean;
|
|
115
117
|
}): boolean;
|
|
118
|
+
export type ReportedLengthSource = {
|
|
119
|
+
from: Exclude<CompositionLengthSource["from"], "media">;
|
|
120
|
+
} | {
|
|
121
|
+
from: "media";
|
|
122
|
+
tag: string;
|
|
123
|
+
trimmed: boolean;
|
|
124
|
+
srcHash: string;
|
|
125
|
+
};
|
|
126
|
+
/** The length source with a media clip's src reduced to a hash of its file name, so no path leaves the render. */
|
|
127
|
+
export declare function reportedLengthSource(source: CompositionLengthSource | null): ReportedLengthSource | null;
|
|
116
128
|
export declare function runProbeStage(input: ProbeStageInput): Promise<ProbeStageResult>;
|
|
117
129
|
/**
|
|
118
130
|
* Preview/render parity for `muted` media: the runtime keeps muted elements
|
|
@@ -567,10 +567,11 @@ export declare function captureAttemptMadeProgress(attemptTargetFrameCount: numb
|
|
|
567
567
|
export declare function resetCaptureAttemptProgress(job: {
|
|
568
568
|
framesRendered?: number;
|
|
569
569
|
}): void;
|
|
570
|
-
/** The no-progress rule for capture stages that have no watchdog of their own: disk, HDR, chunk.
|
|
570
|
+
/** The no-progress rule for capture stages that have no watchdog of their own: disk, HDR, chunk. Once
|
|
571
|
+
* `totalFrames` have landed the frame count can no longer change, so the stage is judged on the tail budget. */
|
|
571
572
|
export declare function frameStallRule(job: {
|
|
572
573
|
framesRendered?: number;
|
|
573
|
-
}): StageStallRule;
|
|
574
|
+
}, totalFrames: number): StageStallRule;
|
|
574
575
|
export declare function isRecoverableParallelCaptureError(error: unknown): boolean;
|
|
575
576
|
/**
|
|
576
577
|
* Turn a cryptic memory-exhaustion failure (V8 `Set maximum size exceeded`,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hyperframes/producer",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.217",
|
|
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/core": "0.8.
|
|
40
|
-
"@hyperframes/
|
|
41
|
-
"@hyperframes/parsers": "0.8.
|
|
42
|
-
"@hyperframes/studio-server": "0.8.
|
|
38
|
+
"@hyperframes/engine": "0.8.217",
|
|
39
|
+
"@hyperframes/core": "0.8.217",
|
|
40
|
+
"@hyperframes/lint": "0.8.217",
|
|
41
|
+
"@hyperframes/parsers": "0.8.217",
|
|
42
|
+
"@hyperframes/studio-server": "0.8.217"
|
|
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.217"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=22"
|