@hyperframes/producer 0.8.207 → 0.8.208
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 +94 -48
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +67 -67
- package/dist/index.js +94 -48
- package/dist/public-server.js +8 -4
- package/dist/services/distributed/renderChunk.d.ts +2 -0
- package/dist/services/render/stages/captureStage.d.ts +1 -0
- package/dist/services/render/stages/extractVideosStage.d.ts +1 -1
- package/dist/services/renderOrchestrator.d.ts +1 -0
- package/package.json +7 -7
package/dist/distributed.js
CHANGED
|
@@ -5446,10 +5446,11 @@ var VideoExtractionStageError = class extends Error {
|
|
|
5446
5446
|
kind: failure.kind,
|
|
5447
5447
|
affectedElementCount: failure.count
|
|
5448
5448
|
}))
|
|
5449
|
-
)) {
|
|
5449
|
+
), ffmpegReason) {
|
|
5450
5450
|
const total = failures.reduce((sum2, failure) => sum2 + failure.count, 0);
|
|
5451
5451
|
const breakdown = failures.map((failure) => `${failure.kind}=${failure.count}`).join(",");
|
|
5452
|
-
|
|
5452
|
+
const reason = ffmpegReason ? `: ffmpeg said: ${ffmpegReason}` : "";
|
|
5453
|
+
super(`Video extraction failed for ${total} source(s) [${code}; ${breakdown}]${reason}`);
|
|
5453
5454
|
this.code = code;
|
|
5454
5455
|
this.retryable = retryable;
|
|
5455
5456
|
this.failures = failures;
|
|
@@ -5496,7 +5497,8 @@ function buildVideoExtractionStageError(result) {
|
|
|
5496
5497
|
retryable ? "VIDEO_EXTRACTION_FAILED" : "VIDEO_SOURCE_UNRENDERABLE",
|
|
5497
5498
|
retryable,
|
|
5498
5499
|
failures,
|
|
5499
|
-
extractionFailureMetadataFromResult(result)
|
|
5500
|
+
extractionFailureMetadataFromResult(result),
|
|
5501
|
+
result.errors.find((failure) => failure.ffmpegReason)?.ffmpegReason
|
|
5500
5502
|
);
|
|
5501
5503
|
}
|
|
5502
5504
|
function buildHdrProbeStageError(failures) {
|
|
@@ -6501,6 +6503,7 @@ async function runCaptureStage(input) {
|
|
|
6501
6503
|
dedupPerfs,
|
|
6502
6504
|
pageErrorLines: workerPageErrors,
|
|
6503
6505
|
openAttempt: input.openAttempt,
|
|
6506
|
+
verifyFirstSession: input.verifyFirstSession,
|
|
6504
6507
|
onProgress: (progress) => {
|
|
6505
6508
|
if (progress.latestWorkerPhase) {
|
|
6506
6509
|
if (progress.capturedFrames === 0) reportWorkerStartup(job, progress, onProgress);
|
|
@@ -7371,7 +7374,8 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
|
|
|
7371
7374
|
});
|
|
7372
7375
|
} : void 0,
|
|
7373
7376
|
void 0,
|
|
7374
|
-
options.cfg
|
|
7377
|
+
options.cfg,
|
|
7378
|
+
{ verifyFirstSession: options.verifyFirstSession }
|
|
7375
7379
|
);
|
|
7376
7380
|
pushWorkerDedupPerfs(workerResults, options.dedupPerfs);
|
|
7377
7381
|
if (options.pageErrorLines) pushWorkerPageErrors(workerResults, options.pageErrorLines);
|
|
@@ -11432,16 +11436,18 @@ function observedChunkCaptureMode(perfs) {
|
|
|
11432
11436
|
}
|
|
11433
11437
|
return mode;
|
|
11434
11438
|
}
|
|
11439
|
+
var PROBE_SELECTED_SCREENSHOT = "[renderChunk] probe selected screenshot capture";
|
|
11435
11440
|
function shouldRetryChunkCaptureWithScreenshot(error) {
|
|
11436
11441
|
const failure = classifyCaptureFailure4(error);
|
|
11437
11442
|
if (failure.kind === "cancelled" || failure.kind === "memory_exhaustion") return false;
|
|
11438
|
-
return /HeadlessExperimental\.beginFrame/i.test(failure.message) || /beginFrame probe timeout/i.test(failure.message) || /Another frame is pending|Frame still pending/i.test(failure.message);
|
|
11443
|
+
return /HeadlessExperimental\.beginFrame/i.test(failure.message) || /beginFrame probe timeout/i.test(failure.message) || failure.message.includes(PROBE_SELECTED_SCREENSHOT) || /Another frame is pending|Frame still pending/i.test(failure.message);
|
|
11439
11444
|
}
|
|
11440
11445
|
async function runCaptureWithScreenshotFallback(input) {
|
|
11441
11446
|
try {
|
|
11442
11447
|
return await input.run(input.forceScreenshot);
|
|
11443
11448
|
} catch (error) {
|
|
11444
|
-
if (input.forceScreenshot ||
|
|
11449
|
+
if (input.forceScreenshot || await input.canRetry?.() === false) throw error;
|
|
11450
|
+
if (!shouldRetryChunkCaptureWithScreenshot(error)) throw error;
|
|
11445
11451
|
input.onFallback?.(error);
|
|
11446
11452
|
await input.resetForScreenshotRetry();
|
|
11447
11453
|
return await input.run(true);
|
|
@@ -11650,7 +11656,24 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11650
11656
|
let extraction;
|
|
11651
11657
|
const overlap = { current: null };
|
|
11652
11658
|
try {
|
|
11653
|
-
|
|
11659
|
+
const verifyInWorker = chunkWorkerCount > 1 && !forceScreenshotForChunk;
|
|
11660
|
+
let boxesMeasured;
|
|
11661
|
+
let boxesFailed;
|
|
11662
|
+
const boxesReady = new Promise((resolve10, reject) => {
|
|
11663
|
+
boxesMeasured = resolve10;
|
|
11664
|
+
boxesFailed = reject;
|
|
11665
|
+
});
|
|
11666
|
+
boxesReady.catch(() => {
|
|
11667
|
+
});
|
|
11668
|
+
const measureBoxes = async (page) => {
|
|
11669
|
+
shownBoxes = await measureVideoShownBoxes(
|
|
11670
|
+
page,
|
|
11671
|
+
[...shownFrames.keys()],
|
|
11672
|
+
chunkFrameNumbers.map((frame) => frame * chunkFps.den / chunkFps.num)
|
|
11673
|
+
);
|
|
11674
|
+
boxesMeasured();
|
|
11675
|
+
};
|
|
11676
|
+
if (chunkWorkerCount === 1) {
|
|
11654
11677
|
const bootStarted = Date.now();
|
|
11655
11678
|
session = await createVerifiedDistributedCaptureSession(
|
|
11656
11679
|
fileServer.url,
|
|
@@ -11659,11 +11682,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11659
11682
|
cfg
|
|
11660
11683
|
);
|
|
11661
11684
|
sessionBootMs = Date.now() - bootStarted;
|
|
11662
|
-
|
|
11663
|
-
session.page,
|
|
11664
|
-
[...shownFrames.keys()],
|
|
11665
|
-
chunkFrameNumbers.map((frame) => frame * chunkFps.den / chunkFps.num)
|
|
11666
|
-
);
|
|
11685
|
+
await measureBoxes(session.page);
|
|
11667
11686
|
const browserSelectedScreenshot = session.launchCaptureMode === "screenshot";
|
|
11668
11687
|
const beginFrameStalled = !browserSelectedScreenshot && await beginFrameSessionNeedsScreenshotFallback(session);
|
|
11669
11688
|
if (browserSelectedScreenshot) {
|
|
@@ -11672,10 +11691,6 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11672
11691
|
"[renderChunk] Browser capability probe selected screenshot capture for the entire chunk",
|
|
11673
11692
|
{ chunkIndex }
|
|
11674
11693
|
);
|
|
11675
|
-
if (chunkWorkerCount > 1) {
|
|
11676
|
-
await closeCaptureSession10(session);
|
|
11677
|
-
session = null;
|
|
11678
|
-
}
|
|
11679
11694
|
} else if (beginFrameStalled) {
|
|
11680
11695
|
forceScreenshotForChunk = true;
|
|
11681
11696
|
log.warn(
|
|
@@ -11685,41 +11700,66 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11685
11700
|
await closeCaptureSession10(session).catch(() => {
|
|
11686
11701
|
});
|
|
11687
11702
|
session = null;
|
|
11688
|
-
|
|
11689
|
-
|
|
11690
|
-
|
|
11691
|
-
|
|
11692
|
-
|
|
11693
|
-
|
|
11694
|
-
|
|
11695
|
-
|
|
11696
|
-
|
|
11697
|
-
|
|
11698
|
-
|
|
11699
|
-
|
|
11703
|
+
const screenshotBootStarted = Date.now();
|
|
11704
|
+
const screenshotCfg = {
|
|
11705
|
+
...cfg,
|
|
11706
|
+
forceScreenshot: true,
|
|
11707
|
+
forceScreenshotExplicitlyOptedOut: false
|
|
11708
|
+
};
|
|
11709
|
+
session = await createVerifiedDistributedCaptureSession(
|
|
11710
|
+
fileServer.url,
|
|
11711
|
+
framesDir,
|
|
11712
|
+
captureOptions,
|
|
11713
|
+
screenshotCfg
|
|
11714
|
+
);
|
|
11715
|
+
sessionBootMs += Date.now() - screenshotBootStarted;
|
|
11716
|
+
}
|
|
11717
|
+
} else if (!verifyInWorker) {
|
|
11718
|
+
boxesMeasured();
|
|
11719
|
+
}
|
|
11720
|
+
let verification;
|
|
11721
|
+
const verifyFirstWorker = (first) => verification ??= (async () => {
|
|
11722
|
+
sessionBootMs = Date.now() - verifyStarted;
|
|
11723
|
+
try {
|
|
11724
|
+
await measureBoxes(first.page);
|
|
11725
|
+
const selectedScreenshot = first.launchCaptureMode === "screenshot";
|
|
11726
|
+
if (selectedScreenshot || await beginFrameSessionNeedsScreenshotFallback(first)) {
|
|
11727
|
+
forceScreenshotForChunk = true;
|
|
11728
|
+
log.warn(
|
|
11729
|
+
selectedScreenshot ? "[renderChunk] Browser capability probe selected screenshot capture for the entire chunk" : "[renderChunk] BeginFrame liveness probe failed; using screenshot capture for the entire chunk",
|
|
11730
|
+
{ chunkIndex }
|
|
11700
11731
|
);
|
|
11701
|
-
|
|
11732
|
+
throw new Error(PROBE_SELECTED_SCREENSHOT);
|
|
11702
11733
|
}
|
|
11703
|
-
}
|
|
11704
|
-
|
|
11705
|
-
|
|
11734
|
+
} catch (error) {
|
|
11735
|
+
if (!forceScreenshotForChunk) {
|
|
11736
|
+
verifyFailure = error;
|
|
11737
|
+
boxesFailed(error);
|
|
11738
|
+
}
|
|
11739
|
+
throw error;
|
|
11706
11740
|
}
|
|
11707
|
-
}
|
|
11708
|
-
|
|
11709
|
-
|
|
11710
|
-
|
|
11711
|
-
|
|
11712
|
-
|
|
11713
|
-
|
|
11714
|
-
|
|
11715
|
-
|
|
11716
|
-
|
|
11717
|
-
|
|
11718
|
-
|
|
11719
|
-
|
|
11720
|
-
|
|
11721
|
-
|
|
11741
|
+
})();
|
|
11742
|
+
let verifyStarted = 0;
|
|
11743
|
+
let verifyFailure;
|
|
11744
|
+
const deferredVideoFrames = planVideos ? boxesReady.then(() => {
|
|
11745
|
+
const extractStarted = Date.now();
|
|
11746
|
+
return extractDeferredVideoFramesForChunk({
|
|
11747
|
+
planDir,
|
|
11748
|
+
planVideos,
|
|
11749
|
+
frames: chunkFrameNumbers,
|
|
11750
|
+
fps: chunkFps,
|
|
11751
|
+
outputRoot: videoFramesDir,
|
|
11752
|
+
cfg,
|
|
11753
|
+
remoteSources,
|
|
11754
|
+
shownBoxes
|
|
11755
|
+
}).then((frames) => {
|
|
11756
|
+
videoExtractMs = Date.now() - extractStarted;
|
|
11757
|
+
return frames;
|
|
11758
|
+
});
|
|
11759
|
+
}) : boxesReady.then(() => []);
|
|
11722
11760
|
extraction = deferredVideoFrames;
|
|
11761
|
+
deferredVideoFrames.catch(() => {
|
|
11762
|
+
});
|
|
11723
11763
|
const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? deferredVideoFrames.then(
|
|
11724
11764
|
(deferred) => createFrameLookupTable5(
|
|
11725
11765
|
planVideos.videos,
|
|
@@ -11798,6 +11838,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11798
11838
|
const captureStarted = Date.now();
|
|
11799
11839
|
captureMode = await runCaptureWithScreenshotFallback({
|
|
11800
11840
|
forceScreenshot: forceScreenshotForChunk,
|
|
11841
|
+
canRetry: () => verifyFailure === void 0,
|
|
11801
11842
|
// fallow-ignore-next-line complexity
|
|
11802
11843
|
run: async (forceScreenshot) => {
|
|
11803
11844
|
const captureCfg = cfg.forceScreenshot === forceScreenshot ? cfg : {
|
|
@@ -11827,6 +11868,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11827
11868
|
}
|
|
11828
11869
|
const captureSession = session;
|
|
11829
11870
|
session = null;
|
|
11871
|
+
verifyStarted = Date.now();
|
|
11830
11872
|
overlap.current = canEncodeWhileCapturing(encodeInput, chunkWorkerCount, cpus().length) ? encodeWhileCapturing(encodeInput, framesInChunk) : null;
|
|
11831
11873
|
await observeRenderStage(
|
|
11832
11874
|
new RenderObservabilityRecorder({ pipelineStartMs: start, log }),
|
|
@@ -11854,7 +11896,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11854
11896
|
frameRange: range,
|
|
11855
11897
|
onFrameLanded: (frame) => overlap.current?.onFrameLanded(frame),
|
|
11856
11898
|
interleaveFrames: interleavesCapture(overlap.current !== null, options),
|
|
11857
|
-
openAttempt
|
|
11899
|
+
openAttempt,
|
|
11900
|
+
verifyFirstSession: forceScreenshot || !verifyInWorker ? void 0 : verifyFirstWorker
|
|
11858
11901
|
}),
|
|
11859
11902
|
{ stall: frameStallRule(job) }
|
|
11860
11903
|
).catch(async (captureError) => {
|
|
@@ -11866,6 +11909,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11866
11909
|
},
|
|
11867
11910
|
resetForScreenshotRetry: () => {
|
|
11868
11911
|
rmSync11(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
|
|
11912
|
+
boxesMeasured();
|
|
11869
11913
|
mkdirSync14(framesDir, { recursive: true });
|
|
11870
11914
|
capturePerfs.length = 0;
|
|
11871
11915
|
captureAttempts.length = 0;
|
|
@@ -11881,6 +11925,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath, options) {
|
|
|
11881
11925
|
);
|
|
11882
11926
|
}
|
|
11883
11927
|
}).catch(async (captureError) => {
|
|
11928
|
+
if (verifyFailure !== void 0) throw verifyFailure;
|
|
11929
|
+
boxesFailed(captureError);
|
|
11884
11930
|
await deferredVideoFrames;
|
|
11885
11931
|
throw captureError;
|
|
11886
11932
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "0.1.0",
|
|
3
3
|
"buildId": "dev",
|
|
4
|
-
"sha256": "
|
|
4
|
+
"sha256": "e7380e2810c1db76b94231462d6756bbd8fd7047ab2014b7428a26dc7105b099",
|
|
5
5
|
"artifacts": {
|
|
6
6
|
"iife": "hyperframe.runtime.iife.js",
|
|
7
7
|
"esm": "hyperframe.runtime.mjs"
|