@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/distributed.js
CHANGED
|
@@ -1770,6 +1770,7 @@ function watchStall(phase, rule) {
|
|
|
1770
1770
|
let lastChangeAt = Date.now();
|
|
1771
1771
|
let attempt;
|
|
1772
1772
|
let timer;
|
|
1773
|
+
let inTail = false;
|
|
1773
1774
|
const restartWindow = (ms) => {
|
|
1774
1775
|
last = rule.progress();
|
|
1775
1776
|
budgetMs = ms;
|
|
@@ -1779,6 +1780,10 @@ function watchStall(phase, rule) {
|
|
|
1779
1780
|
timer = setInterval(
|
|
1780
1781
|
() => {
|
|
1781
1782
|
const current = rule.progress();
|
|
1783
|
+
if (rule.complete?.() && !inTail) {
|
|
1784
|
+
inTail = true;
|
|
1785
|
+
return restartWindow(rule.tailMs ?? rule.noProgressMs);
|
|
1786
|
+
}
|
|
1782
1787
|
if (current !== last) return restartWindow(rule.noProgressMs);
|
|
1783
1788
|
if (Date.now() - lastChangeAt < budgetMs) return;
|
|
1784
1789
|
const error = new RenderStageStalledError(phase, budgetMs, current);
|
|
@@ -1794,6 +1799,7 @@ function watchStall(phase, rule) {
|
|
|
1794
1799
|
});
|
|
1795
1800
|
const openAttempt = (parent) => {
|
|
1796
1801
|
attempt = new AbortController();
|
|
1802
|
+
inTail = false;
|
|
1797
1803
|
restartWindow(rule.firstProgressMs);
|
|
1798
1804
|
return parent ? AbortSignal.any([parent, attempt.signal]) : attempt.signal;
|
|
1799
1805
|
};
|
|
@@ -4668,7 +4674,8 @@ async function runCompileStage(input) {
|
|
|
4668
4674
|
}
|
|
4669
4675
|
|
|
4670
4676
|
// src/services/render/stages/probeStage.ts
|
|
4671
|
-
import {
|
|
4677
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
4678
|
+
import { basename as basename4, join as join8 } from "node:path";
|
|
4672
4679
|
import { parseHTML as parseHTML6 } from "linkedom";
|
|
4673
4680
|
import {
|
|
4674
4681
|
closeCaptureSession as closeCaptureSession4,
|
|
@@ -4676,6 +4683,7 @@ import {
|
|
|
4676
4683
|
createCaptureSession as createCaptureSession4,
|
|
4677
4684
|
deriveBeginFrameProbeTimeTicks,
|
|
4678
4685
|
getCompositionDuration,
|
|
4686
|
+
getCompositionLengthSource,
|
|
4679
4687
|
initializeSession as initializeSession4,
|
|
4680
4688
|
isTransientBrowserError,
|
|
4681
4689
|
probeBeginFrameLiveness,
|
|
@@ -4814,6 +4822,13 @@ function hasRuntimeMediaChanges(html) {
|
|
|
4814
4822
|
function probeRequiresBrowser(args) {
|
|
4815
4823
|
return args.durationSeconds <= 0 || args.unresolvedCompositionCount > 0 || args.hasAutoStart || args.hasScriptedAudio || args.hasVariableMedia || args.hasInsertedMedia;
|
|
4816
4824
|
}
|
|
4825
|
+
function reportedLengthSource(source) {
|
|
4826
|
+
if (!source) return null;
|
|
4827
|
+
if (source.from !== "media") return { from: source.from };
|
|
4828
|
+
const name = basename4(source.src.split(/[?#]/, 1)[0] ?? "");
|
|
4829
|
+
const srcHash = createHash5("sha256").update(name).digest("hex").slice(0, 12);
|
|
4830
|
+
return { from: "media", tag: source.tag, trimmed: source.trimmed, srcHash };
|
|
4831
|
+
}
|
|
4817
4832
|
async function runProbeStage(input) {
|
|
4818
4833
|
const {
|
|
4819
4834
|
projectDir,
|
|
@@ -4835,6 +4850,7 @@ async function runProbeStage(input) {
|
|
|
4835
4850
|
const probeCfg = cfg.forceScreenshot === forceScreenshot ? cfg : { ...cfg, forceScreenshot };
|
|
4836
4851
|
let fileServer = null;
|
|
4837
4852
|
let probeSession = null;
|
|
4853
|
+
let lengthSource = input.composition.duration > 0 ? { from: "declared" } : null;
|
|
4838
4854
|
let beginFrameStalled = false;
|
|
4839
4855
|
let lastBrowserConsole = [];
|
|
4840
4856
|
const probeStart = Date.now();
|
|
@@ -4996,10 +5012,12 @@ async function runProbeStage(input) {
|
|
|
4996
5012
|
if (composition.duration <= 0) {
|
|
4997
5013
|
log.info("Discovering composition duration...");
|
|
4998
5014
|
const discoveredDuration = await getCompositionDuration(session);
|
|
5015
|
+
lengthSource = reportedLengthSource(await getCompositionLengthSource(session));
|
|
4999
5016
|
assertNotAborted();
|
|
5000
5017
|
log.info("Probed composition duration from browser", {
|
|
5001
5018
|
discoveredDuration,
|
|
5002
|
-
staticDuration: compiled.staticDuration
|
|
5019
|
+
staticDuration: compiled.staticDuration,
|
|
5020
|
+
lengthSource
|
|
5003
5021
|
});
|
|
5004
5022
|
composition.duration = discoveredDuration;
|
|
5005
5023
|
} else {
|
|
@@ -5288,6 +5306,7 @@ async function runProbeStage(input) {
|
|
|
5288
5306
|
probeSession,
|
|
5289
5307
|
lastBrowserConsole,
|
|
5290
5308
|
duration,
|
|
5309
|
+
lengthSource,
|
|
5291
5310
|
totalFrames,
|
|
5292
5311
|
browserProbeMs,
|
|
5293
5312
|
beginFrameStalled
|
|
@@ -5839,7 +5858,7 @@ function checkedDbfs(value) {
|
|
|
5839
5858
|
}
|
|
5840
5859
|
return value;
|
|
5841
5860
|
}
|
|
5842
|
-
async function scanTruePeak(audioPath, trim, timeoutMs, signal) {
|
|
5861
|
+
async function scanTruePeak(audioPath, trim, timeoutMs, signal, seekSeconds = 0) {
|
|
5843
5862
|
let firstBlock;
|
|
5844
5863
|
let laterBlocks = Number.NEGATIVE_INFINITY;
|
|
5845
5864
|
let partialLine = "";
|
|
@@ -5855,7 +5874,21 @@ async function scanTruePeak(audioPath, trim, timeoutMs, signal) {
|
|
|
5855
5874
|
}
|
|
5856
5875
|
};
|
|
5857
5876
|
const result = await runFfmpeg4(
|
|
5858
|
-
[
|
|
5877
|
+
[
|
|
5878
|
+
...seekSeconds > 0 ? ["-ss", String(seekSeconds)] : [],
|
|
5879
|
+
...[
|
|
5880
|
+
"-i",
|
|
5881
|
+
audioPath,
|
|
5882
|
+
"-map",
|
|
5883
|
+
"0:a:0",
|
|
5884
|
+
"-vn",
|
|
5885
|
+
"-af",
|
|
5886
|
+
`${trim}ebur128=peak=true`,
|
|
5887
|
+
"-f",
|
|
5888
|
+
"null",
|
|
5889
|
+
"-"
|
|
5890
|
+
]
|
|
5891
|
+
],
|
|
5859
5892
|
{ signal, timeout: timeoutMs, onStderr: readLines }
|
|
5860
5893
|
);
|
|
5861
5894
|
if (!result.success) {
|
|
@@ -5881,12 +5914,15 @@ async function measureTruePeakDbfs(audioPath, options) {
|
|
|
5881
5914
|
const scans = await Promise.all(
|
|
5882
5915
|
Array.from({ length: count }, (_, k) => {
|
|
5883
5916
|
const start = k === 0 ? 0 : cut(k) - block;
|
|
5884
|
-
const
|
|
5917
|
+
const seekSeconds = Math.max(0, Math.floor(start / sampleRate) - 1);
|
|
5918
|
+
const skipped = seekSeconds * sampleRate;
|
|
5919
|
+
const end = k === count - 1 ? "" : `:end_sample=${cut(k + 1) - skipped}`;
|
|
5885
5920
|
return scanTruePeak(
|
|
5886
5921
|
audioPath,
|
|
5887
|
-
`atrim=start_sample=${start}${end},`,
|
|
5922
|
+
`atrim=start_sample=${start - skipped}${end},`,
|
|
5888
5923
|
timeoutMs,
|
|
5889
|
-
segmentSignal
|
|
5924
|
+
segmentSignal,
|
|
5925
|
+
seekSeconds
|
|
5890
5926
|
);
|
|
5891
5927
|
})
|
|
5892
5928
|
).catch((error) => {
|
|
@@ -7318,12 +7354,15 @@ function captureAttemptMadeProgress(attemptTargetFrameCount, remainingFrameCount
|
|
|
7318
7354
|
return remainingFrameCount < attemptTargetFrameCount;
|
|
7319
7355
|
}
|
|
7320
7356
|
var FIRST_FRAME_STALL_MS = 3e5;
|
|
7321
|
-
|
|
7357
|
+
var TAIL_STALL_MS = FIRST_FRAME_STALL_MS;
|
|
7358
|
+
function frameStallRule(job, totalFrames) {
|
|
7322
7359
|
const noProgressMs = resolveCaptureStallTimeoutMs();
|
|
7323
7360
|
return {
|
|
7324
7361
|
progress: () => job.framesRendered ?? 0,
|
|
7325
7362
|
noProgressMs,
|
|
7326
|
-
firstProgressMs: Math.max(FIRST_FRAME_STALL_MS, noProgressMs)
|
|
7363
|
+
firstProgressMs: Math.max(FIRST_FRAME_STALL_MS, noProgressMs),
|
|
7364
|
+
complete: () => (job.framesRendered ?? 0) >= totalFrames,
|
|
7365
|
+
tailMs: Math.max(TAIL_STALL_MS, noProgressMs)
|
|
7327
7366
|
};
|
|
7328
7367
|
}
|
|
7329
7368
|
function isRecoverableParallelCaptureError(error) {
|
|
@@ -8283,12 +8322,12 @@ function readPlanProtocolV1(planJson, capabilities = DISTRIBUTED_RENDER_CAPABILI
|
|
|
8283
8322
|
}
|
|
8284
8323
|
|
|
8285
8324
|
// src/services/render/stages/planHash.ts
|
|
8286
|
-
import { createHash as
|
|
8325
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
8287
8326
|
import { closeSync as closeSync3, createReadStream as createReadStream3, openSync as openSync3, readSync as readSync2 } from "node:fs";
|
|
8288
8327
|
var PLAN_HASH_SCHEMA_PREFIX = "hyperframes-plan-hash-v1\0";
|
|
8289
8328
|
var FIELD_DELIMITER = Buffer.from([0]);
|
|
8290
8329
|
function computePlanHash(input) {
|
|
8291
|
-
const hash =
|
|
8330
|
+
const hash = createHash6("sha256");
|
|
8292
8331
|
hash.update(PLAN_HASH_SCHEMA_PREFIX, "utf8");
|
|
8293
8332
|
hash.update(input.compositionHtml);
|
|
8294
8333
|
hash.update(FIELD_DELIMITER);
|
|
@@ -8335,12 +8374,12 @@ function canonicalJsonStringify(value) {
|
|
|
8335
8374
|
throw new TypeError(`canonicalJsonStringify: unsupported value type ${typeof value}`);
|
|
8336
8375
|
}
|
|
8337
8376
|
function sha256Hex(bytes) {
|
|
8338
|
-
const h =
|
|
8377
|
+
const h = createHash6("sha256");
|
|
8339
8378
|
h.update(bytes);
|
|
8340
8379
|
return h.digest("hex");
|
|
8341
8380
|
}
|
|
8342
8381
|
function sha256File(path) {
|
|
8343
|
-
const hash =
|
|
8382
|
+
const hash = createHash6("sha256");
|
|
8344
8383
|
const buffer = Buffer.allocUnsafe(1024 * 1024);
|
|
8345
8384
|
const fd = openSync3(path, "r");
|
|
8346
8385
|
try {
|
|
@@ -8355,7 +8394,7 @@ function sha256File(path) {
|
|
|
8355
8394
|
return hash.digest("hex");
|
|
8356
8395
|
}
|
|
8357
8396
|
async function sha256FileAsync(path) {
|
|
8358
|
-
const hash =
|
|
8397
|
+
const hash = createHash6("sha256");
|
|
8359
8398
|
for await (const chunk of createReadStream3(path, { highWaterMark: 1024 * 1024 })) {
|
|
8360
8399
|
hash.update(chunk);
|
|
8361
8400
|
}
|
|
@@ -9126,7 +9165,7 @@ async function muxChunkWithAudio(input) {
|
|
|
9126
9165
|
}
|
|
9127
9166
|
|
|
9128
9167
|
// src/services/distributed/planSize.ts
|
|
9129
|
-
import { createHash as
|
|
9168
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
9130
9169
|
import { lstatSync, readdirSync as readdirSync6 } from "node:fs";
|
|
9131
9170
|
import { extname as extname3, join as join21, relative as relative4 } from "node:path";
|
|
9132
9171
|
var MAX_TOP_COMPONENTS = 10;
|
|
@@ -9156,7 +9195,7 @@ var PLAN_ROOT_CATEGORY = {
|
|
|
9156
9195
|
"plan.json": "metadata"
|
|
9157
9196
|
};
|
|
9158
9197
|
function hashComponent(value) {
|
|
9159
|
-
return
|
|
9198
|
+
return createHash7("sha256").update(value).digest("hex").slice(0, 12);
|
|
9160
9199
|
}
|
|
9161
9200
|
function classifyFile(segments, rootKind) {
|
|
9162
9201
|
const rootName = segments[0] ?? "";
|
|
@@ -11945,7 +11984,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11945
11984
|
openAttempt,
|
|
11946
11985
|
verifyFirstSession: forceScreenshot || !verifyInWorker ? void 0 : verifyFirstWorker
|
|
11947
11986
|
}),
|
|
11948
|
-
{ stall: frameStallRule(job) }
|
|
11987
|
+
{ stall: frameStallRule(job, framesInChunk) }
|
|
11949
11988
|
).catch(async (captureError) => {
|
|
11950
11989
|
await overlap.current?.abort();
|
|
11951
11990
|
overlap.current = null;
|
|
@@ -12383,7 +12422,7 @@ function validateIntDimension(field, value) {
|
|
|
12383
12422
|
|
|
12384
12423
|
// src/services/distributed/projectHash.ts
|
|
12385
12424
|
import { closeSync as closeSync5, openSync as openSync5, readdirSync as readdirSync10, readSync as readSync4, realpathSync as realpathSync2, statSync as statSync9 } from "node:fs";
|
|
12386
|
-
import { createHash as
|
|
12425
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
12387
12426
|
import { join as join29 } from "node:path";
|
|
12388
12427
|
var SITE_ID_SCHEME = "site-v2\0";
|
|
12389
12428
|
var READ_CHUNK_BYTES = 256 * 1024;
|
|
@@ -12418,7 +12457,7 @@ function listSiteFiles(projectDir) {
|
|
|
12418
12457
|
return files;
|
|
12419
12458
|
}
|
|
12420
12459
|
function hashProjectDir(projectDir, files = listSiteFiles(projectDir)) {
|
|
12421
|
-
const hash =
|
|
12460
|
+
const hash = createHash8("sha256").update(SITE_ID_SCHEME);
|
|
12422
12461
|
const chunk = Buffer.allocUnsafe(READ_CHUNK_BYTES);
|
|
12423
12462
|
for (const rel of files) {
|
|
12424
12463
|
hash.update(rel);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.1.0",
|
|
3
3
|
"buildId": "dev",
|
|
4
|
-
"sha256": "
|
|
4
|
+
"sha256": "0d41a8caf8d45a36e83ff7218b7543020591d67d12e033e6142f2d54de8bd055",
|
|
5
5
|
"artifacts": {
|
|
6
6
|
"iife": "hyperframe.runtime.iife.js",
|
|
7
7
|
"esm": "hyperframe.runtime.mjs"
|