hyperframes 0.8.34 → 0.8.35
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/cli.js +174 -96
- package/dist/commands/layout-audit.browser.js +7 -1
- package/dist/fontLocalizeCli.js +131 -76
- package/dist/hyperframes-player.global.js +1 -1
- package/dist/skills/hyperframes-cli/SKILL.md +2 -2
- package/dist/studio/assets/{hyperframes-player-D4aSRr_M.js → hyperframes-player-lPOqAC3l.js} +1 -1
- package/dist/studio/assets/{index-CkxPQxLJ.js → index-BRr1JoHX.js} +80 -80
- package/dist/studio/assets/{index-hch4ktcC.js → index-RPEcu_bT.js} +1 -1
- package/dist/studio/assets/{index-aNyQBoJv.js → index-ywAULfGT.js} +1 -1
- package/dist/studio/index.html +1 -1
- package/dist/studio/index.js +15 -14
- package/dist/studio/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50,7 +50,7 @@ var VERSION;
|
|
|
50
50
|
var init_version = __esm({
|
|
51
51
|
"src/version.ts"() {
|
|
52
52
|
"use strict";
|
|
53
|
-
VERSION = true ? "0.8.
|
|
53
|
+
VERSION = true ? "0.8.35" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -65353,6 +65353,34 @@ var init_pageNavigationTimeoutErrorHint = __esm({
|
|
|
65353
65353
|
}
|
|
65354
65354
|
});
|
|
65355
65355
|
|
|
65356
|
+
// ../engine/src/services/drawElementCaptureError.ts
|
|
65357
|
+
function isDrawElementCaptureError(error) {
|
|
65358
|
+
let current2 = error;
|
|
65359
|
+
for (let depth = 0; depth < 5 && typeof current2 === "object" && current2 !== null; depth++) {
|
|
65360
|
+
if ("deCaptureFailure" in current2 && current2.deCaptureFailure === true) return true;
|
|
65361
|
+
current2 = "cause" in current2 ? current2.cause : void 0;
|
|
65362
|
+
}
|
|
65363
|
+
return false;
|
|
65364
|
+
}
|
|
65365
|
+
var DrawElementCaptureError;
|
|
65366
|
+
var init_drawElementCaptureError = __esm({
|
|
65367
|
+
"../engine/src/services/drawElementCaptureError.ts"() {
|
|
65368
|
+
"use strict";
|
|
65369
|
+
DrawElementCaptureError = class extends Error {
|
|
65370
|
+
frameIndex;
|
|
65371
|
+
constructor(frameIndex, reason, cause) {
|
|
65372
|
+
super(
|
|
65373
|
+
`drawElement capture failed at frame ${frameIndex}: ${reason}; fresh screenshot capture required`,
|
|
65374
|
+
{ cause }
|
|
65375
|
+
);
|
|
65376
|
+
this.name = "DrawElementCaptureError";
|
|
65377
|
+
Object.defineProperty(this, "deCaptureFailure", { value: true, enumerable: true });
|
|
65378
|
+
this.frameIndex = frameIndex;
|
|
65379
|
+
}
|
|
65380
|
+
};
|
|
65381
|
+
}
|
|
65382
|
+
});
|
|
65383
|
+
|
|
65356
65384
|
// ../engine/src/services/screenshotService.ts
|
|
65357
65385
|
async function getCdpSession(page) {
|
|
65358
65386
|
let client = cdpSessionCache.get(page);
|
|
@@ -69417,7 +69445,10 @@ async function captureFrameCore(session, frameIndex, time) {
|
|
|
69417
69445
|
else session.beginFrameNoDamageCount++;
|
|
69418
69446
|
screenshotBuffer = result.buffer;
|
|
69419
69447
|
} else if (session.captureMode === "drawelement" && session.clipBoundaryFrames?.has(frameIndex) && process.env.HF_FAST_CAPTURE_BOUNDARY_SS === "true") {
|
|
69420
|
-
|
|
69448
|
+
throw new DrawElementCaptureError(
|
|
69449
|
+
frameIndex,
|
|
69450
|
+
"boundary screenshot requested on an injected canvas page"
|
|
69451
|
+
);
|
|
69421
69452
|
} else if (session.captureMode === "drawelement") {
|
|
69422
69453
|
if (session.beginFrameTimeTicks > 0) {
|
|
69423
69454
|
const client = await getCdpSession(page);
|
|
@@ -69446,10 +69477,10 @@ async function captureFrameCore(session, frameIndex, time) {
|
|
|
69446
69477
|
const median3 = sorted ? sorted[sorted.length >> 1] ?? 0 : 0;
|
|
69447
69478
|
const floor = Math.max(2e4, median3 * 0.12);
|
|
69448
69479
|
if (screenshotBuffer.length < floor) {
|
|
69449
|
-
|
|
69450
|
-
|
|
69480
|
+
throw new DrawElementCaptureError(
|
|
69481
|
+
frameIndex,
|
|
69482
|
+
`suspect small frame (${screenshotBuffer.length}B < ${Math.round(floor)}B)`
|
|
69451
69483
|
);
|
|
69452
|
-
screenshotBuffer = await pageScreenshotCapture(page, options);
|
|
69453
69484
|
} else {
|
|
69454
69485
|
if (sizes.length >= 60) sizes.shift();
|
|
69455
69486
|
sizes.push(screenshotBuffer.length);
|
|
@@ -69459,10 +69490,7 @@ async function captureFrameCore(session, frameIndex, time) {
|
|
|
69459
69490
|
if (isRecoverableDrawElementError(err)) {
|
|
69460
69491
|
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
69461
69492
|
const reason = isCanvasNotInitializedError(err) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
69462
|
-
|
|
69463
|
-
`[engine] fast capture: frame ${frameIndex} \u2014 ${reason}; screenshot fallback for this frame (see fast-capture-limitations.md)`
|
|
69464
|
-
);
|
|
69465
|
-
screenshotBuffer = await pageScreenshotCapture(page, options);
|
|
69493
|
+
throw new DrawElementCaptureError(frameIndex, reason, err);
|
|
69466
69494
|
} else {
|
|
69467
69495
|
throw err;
|
|
69468
69496
|
}
|
|
@@ -69551,21 +69579,10 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
69551
69579
|
);
|
|
69552
69580
|
void quantizedTime;
|
|
69553
69581
|
if (session.clipBoundaryFrames?.has(frameIndex) && process.env.HF_FAST_CAPTURE_BOUNDARY_SS === "true") {
|
|
69554
|
-
|
|
69555
|
-
|
|
69556
|
-
|
|
69557
|
-
|
|
69558
|
-
{
|
|
69559
|
-
const boundaryMs = Date.now() - startTime;
|
|
69560
|
-
session.capturePerf.totalMs += boundaryMs;
|
|
69561
|
-
session.capturePerf.frameMs.push(boundaryMs);
|
|
69562
|
-
}
|
|
69563
|
-
const boundaryResult = Promise.resolve(buffer);
|
|
69564
|
-
if (session.staticFrames) {
|
|
69565
|
-
session.lastEncodeResult = boundaryResult;
|
|
69566
|
-
session.lastEncodeResultFrame = frameIndex;
|
|
69567
|
-
}
|
|
69568
|
-
return { encodeResult: boundaryResult, captureTimeMs: Date.now() - startTime };
|
|
69582
|
+
throw new DrawElementCaptureError(
|
|
69583
|
+
frameIndex,
|
|
69584
|
+
"boundary screenshot requested on an injected canvas page"
|
|
69585
|
+
);
|
|
69569
69586
|
}
|
|
69570
69587
|
const { encodeResult } = await produceDrawElementFrame(
|
|
69571
69588
|
page,
|
|
@@ -69587,15 +69604,6 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
69587
69604
|
}
|
|
69588
69605
|
return { encodeResult, captureTimeMs };
|
|
69589
69606
|
} catch (captureError) {
|
|
69590
|
-
if (isRecoverableDrawElementError(captureError)) {
|
|
69591
|
-
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
69592
|
-
const reason = isCanvasNotInitializedError(captureError) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
69593
|
-
console.log(
|
|
69594
|
-
`[engine] fast capture: frame ${frameIndex} \u2014 ${reason}; screenshot fallback for this frame (see fast-capture-limitations.md)`
|
|
69595
|
-
);
|
|
69596
|
-
const buffer = await pageScreenshotCapture(page, options);
|
|
69597
|
-
return { encodeResult: Promise.resolve(buffer), captureTimeMs: Date.now() - startTime };
|
|
69598
|
-
}
|
|
69599
69607
|
if (session.isInitialized) {
|
|
69600
69608
|
await captureFrameErrorDiagnostics(
|
|
69601
69609
|
session,
|
|
@@ -69604,6 +69612,11 @@ async function captureFrameToBufferPipelined(session, frameIndex, time) {
|
|
|
69604
69612
|
captureError instanceof Error ? captureError : new Error(String(captureError))
|
|
69605
69613
|
);
|
|
69606
69614
|
}
|
|
69615
|
+
if (isRecoverableDrawElementError(captureError)) {
|
|
69616
|
+
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
69617
|
+
const reason = isCanvasNotInitializedError(captureError) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
69618
|
+
throw new DrawElementCaptureError(frameIndex, reason, captureError);
|
|
69619
|
+
}
|
|
69607
69620
|
throw captureError;
|
|
69608
69621
|
}
|
|
69609
69622
|
}
|
|
@@ -69637,6 +69650,8 @@ async function captureFramesBatchPipelined(session, frameIndices, times) {
|
|
|
69637
69650
|
options.height,
|
|
69638
69651
|
options.quality ?? 80
|
|
69639
69652
|
);
|
|
69653
|
+
for (const result of encodeResults) void result.catch(() => {
|
|
69654
|
+
});
|
|
69640
69655
|
const okCount = failedAt === null ? frameIndices.length : failedAt;
|
|
69641
69656
|
const elapsed = Date.now() - startTime;
|
|
69642
69657
|
session.capturePerf.frames += okCount;
|
|
@@ -69656,23 +69671,8 @@ async function captureFramesBatchPipelined(session, frameIndices, times) {
|
|
|
69656
69671
|
if (failedAt !== null) {
|
|
69657
69672
|
if (isRecoverableDrawElementError(error)) {
|
|
69658
69673
|
const reason = isCanvasNotInitializedError(error) ? "drawElement canvas not initialized" : "No cached paint record";
|
|
69659
|
-
|
|
69660
|
-
|
|
69661
|
-
);
|
|
69662
|
-
for (let i2 = failedAt; i2 < frameIndices.length; i2++) {
|
|
69663
|
-
const frameIndex = frameIndices[i2];
|
|
69664
|
-
const time = times[i2];
|
|
69665
|
-
if (frameIndex === void 0 || time === void 0) break;
|
|
69666
|
-
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
69667
|
-
await prepareFrameForCapture(session, frameIndex, time);
|
|
69668
|
-
const buffer = await pageScreenshotCapture(page, options);
|
|
69669
|
-
const encodeResult = Promise.resolve(buffer);
|
|
69670
|
-
if (session.staticFrames) {
|
|
69671
|
-
session.lastEncodeResult = encodeResult;
|
|
69672
|
-
session.lastEncodeResultFrame = frameIndex;
|
|
69673
|
-
}
|
|
69674
|
-
results.push({ frameIndex, encodeResult });
|
|
69675
|
-
}
|
|
69674
|
+
session.deNcprFallbacks = (session.deNcprFallbacks ?? 0) + 1;
|
|
69675
|
+
throw new DrawElementCaptureError(frameIndices[failedAt] ?? failedAt, reason, error);
|
|
69676
69676
|
} else {
|
|
69677
69677
|
console.log(
|
|
69678
69678
|
`[engine] fast capture: batch produce failed at frame ${frameIndices[failedAt] ?? "?"} (${error ?? "?"}); re-capturing ${frameIndices.length - failedAt} frame(s) per-frame`
|
|
@@ -69845,7 +69845,7 @@ function getCapturePerfSummary(session) {
|
|
|
69845
69845
|
if (frames > 0 && ncprFallbacks / frames > DE_FALLBACK_RATIO_WARN_THRESHOLD) {
|
|
69846
69846
|
const pct = Math.round(ncprFallbacks / frames * 100);
|
|
69847
69847
|
console.warn(
|
|
69848
|
-
`[engine] fast capture: ${ncprFallbacks}/${frames} frame(s) (${pct}%)
|
|
69848
|
+
`[engine] fast capture: ${ncprFallbacks}/${frames} frame(s) (${pct}%) rejected due to missing canvas/paint records; fresh screenshot capture required.`
|
|
69849
69849
|
);
|
|
69850
69850
|
}
|
|
69851
69851
|
return {
|
|
@@ -69895,6 +69895,7 @@ var init_frameCapture = __esm({
|
|
|
69895
69895
|
"../engine/src/services/frameCapture.ts"() {
|
|
69896
69896
|
"use strict";
|
|
69897
69897
|
init_dist3();
|
|
69898
|
+
init_drawElementCaptureError();
|
|
69898
69899
|
init_browserManager();
|
|
69899
69900
|
init_screenshotService();
|
|
69900
69901
|
init_drawElementService();
|
|
@@ -79752,6 +79753,21 @@ function findRootTag(source, parsedTags) {
|
|
|
79752
79753
|
}
|
|
79753
79754
|
return null;
|
|
79754
79755
|
}
|
|
79756
|
+
function hasUnquotedLessThan(attrs2) {
|
|
79757
|
+
let quote = null;
|
|
79758
|
+
for (const ch of attrs2) {
|
|
79759
|
+
if (quote) {
|
|
79760
|
+
if (ch === quote) quote = null;
|
|
79761
|
+
continue;
|
|
79762
|
+
}
|
|
79763
|
+
if (ch === '"' || ch === "'") {
|
|
79764
|
+
quote = ch;
|
|
79765
|
+
} else if (ch === "<") {
|
|
79766
|
+
return true;
|
|
79767
|
+
}
|
|
79768
|
+
}
|
|
79769
|
+
return false;
|
|
79770
|
+
}
|
|
79755
79771
|
function readAttr(tagSource, attr2) {
|
|
79756
79772
|
if (!tagSource) return null;
|
|
79757
79773
|
const escaped = attr2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -82765,6 +82781,21 @@ var init_dist4 = __esm({
|
|
|
82765
82781
|
}
|
|
82766
82782
|
return findings;
|
|
82767
82783
|
},
|
|
82784
|
+
// unclosed_tag_swallowed_element
|
|
82785
|
+
({ tags }) => {
|
|
82786
|
+
const findings = [];
|
|
82787
|
+
for (const tag of tags) {
|
|
82788
|
+
if (!hasUnquotedLessThan(tag.attrs)) continue;
|
|
82789
|
+
findings.push({
|
|
82790
|
+
code: "unclosed_tag_swallowed_element",
|
|
82791
|
+
severity: "error",
|
|
82792
|
+
message: `<${tag.name}> is missing its closing \`>\` before the next \`<\` \u2014 the following element is swallowed as bogus attribute text and never becomes a real node.`,
|
|
82793
|
+
fixHint: "Close the previous tag's `>` before opening the next element.",
|
|
82794
|
+
snippet: truncateSnippet(tag.raw)
|
|
82795
|
+
});
|
|
82796
|
+
}
|
|
82797
|
+
return findings;
|
|
82798
|
+
},
|
|
82768
82799
|
// invalid_inline_script_syntax (malformed close tag)
|
|
82769
82800
|
({ source }) => {
|
|
82770
82801
|
if (!INVALID_SCRIPT_CLOSE_PATTERN.test(source)) return [];
|
|
@@ -94476,6 +94507,7 @@ __export(src_exports, {
|
|
|
94476
94507
|
DEFAULT_HDR10_MASTERING: () => DEFAULT_HDR10_MASTERING,
|
|
94477
94508
|
DEFAULT_VP9_CPU_USED: () => DEFAULT_VP9_CPU_USED,
|
|
94478
94509
|
DOM_LAYER_MASK_STYLE_ID: () => DOM_LAYER_MASK_STYLE_ID,
|
|
94510
|
+
DrawElementCaptureError: () => DrawElementCaptureError,
|
|
94479
94511
|
DrawElementVerificationError: () => DrawElementVerificationError,
|
|
94480
94512
|
ENABLE_BROWSER_POOL: () => ENABLE_BROWSER_POOL,
|
|
94481
94513
|
ENCODER_PRESETS: () => ENCODER_PRESETS,
|
|
@@ -94590,6 +94622,7 @@ __export(src_exports, {
|
|
|
94590
94622
|
initializeSession: () => initializeSession,
|
|
94591
94623
|
injectVideoFramesBatch: () => injectVideoFramesBatch,
|
|
94592
94624
|
isBlockedNetworkHost: () => isBlockedNetworkHost,
|
|
94625
|
+
isDrawElementCaptureError: () => isDrawElementCaptureError,
|
|
94593
94626
|
isDrawElementVerificationError: () => isDrawElementVerificationError,
|
|
94594
94627
|
isExternalFfmpegInterruption: () => isExternalFfmpegInterruption,
|
|
94595
94628
|
isFatalCaptureFailure: () => isFatalCaptureFailure,
|
|
@@ -94705,6 +94738,7 @@ var init_src = __esm({
|
|
|
94705
94738
|
init_videoFrameInjector();
|
|
94706
94739
|
init_hdr();
|
|
94707
94740
|
init_renderProvenance();
|
|
94741
|
+
init_drawElementCaptureError();
|
|
94708
94742
|
}
|
|
94709
94743
|
});
|
|
94710
94744
|
|
|
@@ -126935,7 +126969,7 @@ function revertedRouting(routing) {
|
|
|
126935
126969
|
return freezeRouting({ ...routing, state: "reverted" });
|
|
126936
126970
|
}
|
|
126937
126971
|
function replanAfterFailure(plan2, failure) {
|
|
126938
|
-
if (plan2.kind === "sdr_disk" && failure.kind === "draw_element_verification") {
|
|
126972
|
+
if (plan2.kind === "sdr_disk" && (failure.kind === "draw_element_verification" || failure.kind === "draw_element_capture")) {
|
|
126939
126973
|
return createCapturePlan({
|
|
126940
126974
|
...plan2,
|
|
126941
126975
|
forceScreenshot: true,
|
|
@@ -139692,7 +139726,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
|
|
|
139692
139726
|
if (failure.kind === "cancelled") {
|
|
139693
139727
|
throw error;
|
|
139694
139728
|
}
|
|
139695
|
-
if (isDrawElementVerificationError(error)) {
|
|
139729
|
+
if (isDrawElementVerificationError(error) || isDrawElementCaptureError(error)) {
|
|
139696
139730
|
throw error;
|
|
139697
139731
|
}
|
|
139698
139732
|
const remaining = findMissingFrameRanges(
|
|
@@ -139920,7 +139954,7 @@ function resolveParallelRouterRetryPlan(args) {
|
|
|
139920
139954
|
}
|
|
139921
139955
|
function shouldRetryViaPinnedFallback(args) {
|
|
139922
139956
|
if (args.isCancellation || args.isEncoderInterrupted) return false;
|
|
139923
|
-
if (args.isVerifyError) return true;
|
|
139957
|
+
if (args.isVerifyError || args.isDeCaptureError) return true;
|
|
139924
139958
|
if (args.isDeRendererStall === true || args.isSequentialCaptureStall === true) return true;
|
|
139925
139959
|
return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
|
|
139926
139960
|
}
|
|
@@ -139946,6 +139980,9 @@ async function closeOrphanedProbeForRetry(probe2, closer, log2, retryContext) {
|
|
|
139946
139980
|
function shouldStreamParallelCapture(args) {
|
|
139947
139981
|
return args.routerEnabled && args.workerCount > 1 && !args.useDrawElement && args.outputFormat === "mp4" && args.streamingOk && !args.layeredOrEffectRoute;
|
|
139948
139982
|
}
|
|
139983
|
+
function shouldClampDefaultDrawElement(args) {
|
|
139984
|
+
return args.useDrawElement && !args.fastCaptureExplicitOptIn && (!args.useStreamingEncode || args.workerCount > 1) && !args.deParallelStreamVerified;
|
|
139985
|
+
}
|
|
139949
139986
|
function resolveCaptureForceScreenshotForPageSideCompositing(args) {
|
|
139950
139987
|
return args.usePageSideCompositing ? true : args.forceScreenshot;
|
|
139951
139988
|
}
|
|
@@ -140688,6 +140725,32 @@ async function executeRenderPipeline(input2) {
|
|
|
140688
140725
|
deWorkerInversion: deWorkerInversion ?? "none",
|
|
140689
140726
|
deParallelRouter: deParallelRouter ?? "none"
|
|
140690
140727
|
});
|
|
140728
|
+
let useStreamingEncode = shouldUseStreamingEncode(
|
|
140729
|
+
cfg,
|
|
140730
|
+
outputFormat,
|
|
140731
|
+
workerCount,
|
|
140732
|
+
job.duration,
|
|
140733
|
+
deParallelStreamForced
|
|
140734
|
+
);
|
|
140735
|
+
const deParallelStreamVerified = (deParallelStreamForced || process.env.HF_DE_PARALLEL_STREAM === "true") && useStreamingEncode && workerCount > 1;
|
|
140736
|
+
if (shouldClampDefaultDrawElement({
|
|
140737
|
+
useDrawElement: cfg.useDrawElement,
|
|
140738
|
+
fastCaptureExplicitOptIn: process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE === "true",
|
|
140739
|
+
useStreamingEncode,
|
|
140740
|
+
workerCount,
|
|
140741
|
+
deParallelStreamVerified
|
|
140742
|
+
})) {
|
|
140743
|
+
cfg.useDrawElement = false;
|
|
140744
|
+
deClampReason = workerCount > 1 ? "parallel" : "disk_path";
|
|
140745
|
+
log2.info(
|
|
140746
|
+
"[Render] Fast capture: default-on drawElement disabled for this render \u2014 " + (workerCount > 1 ? "parallel capture" : "the disk capture path") + " has no runtime self-verification. Set PRODUCER_EXPERIMENTAL_FAST_CAPTURE=true to override."
|
|
140747
|
+
);
|
|
140748
|
+
if (probeSession && probeSession.captureMode === "drawelement") {
|
|
140749
|
+
lastBrowserConsole = probeSession.browserConsoleBuffer;
|
|
140750
|
+
await closeCaptureSession(probeSession);
|
|
140751
|
+
probeSession = null;
|
|
140752
|
+
}
|
|
140753
|
+
}
|
|
140691
140754
|
const captureParallelStreamRouterEnabled = process.env.HF_CAPTURE_PARALLEL_STREAM === "true";
|
|
140692
140755
|
const captureParallelStreamArgs = {
|
|
140693
140756
|
workerCount,
|
|
@@ -140719,7 +140782,7 @@ async function executeRenderPipeline(input2) {
|
|
|
140719
140782
|
await closeCaptureSession(probeSession);
|
|
140720
140783
|
probeSession = null;
|
|
140721
140784
|
}
|
|
140722
|
-
|
|
140785
|
+
useStreamingEncode = shouldUseStreamingEncode(
|
|
140723
140786
|
cfg,
|
|
140724
140787
|
outputFormat,
|
|
140725
140788
|
workerCount,
|
|
@@ -140734,18 +140797,6 @@ async function executeRenderPipeline(input2) {
|
|
|
140734
140797
|
durationSeconds: job.duration,
|
|
140735
140798
|
maxDurationSeconds: cfg.streamingEncodeMaxDurationSeconds
|
|
140736
140799
|
});
|
|
140737
|
-
const deParallelStreamVerified = (deParallelStreamForced || process.env.HF_DE_PARALLEL_STREAM === "true") && useStreamingEncode && workerCount > 1;
|
|
140738
|
-
if (cfg.useDrawElement && process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE !== "true" && (!useStreamingEncode || workerCount > 1) && !deParallelStreamVerified) {
|
|
140739
|
-
cfg.useDrawElement = false;
|
|
140740
|
-
deClampReason = workerCount > 1 ? "parallel" : "disk_path";
|
|
140741
|
-
log2.info(
|
|
140742
|
-
"[Render] Fast capture: default-on drawElement disabled for this render \u2014 " + (workerCount > 1 ? "parallel capture" : "the disk capture path") + " has no runtime self-verification. Set PRODUCER_EXPERIMENTAL_FAST_CAPTURE=true to override."
|
|
140743
|
-
);
|
|
140744
|
-
if (probeSession && probeSession.captureMode === "drawelement") {
|
|
140745
|
-
await closeCaptureSession(probeSession);
|
|
140746
|
-
probeSession = null;
|
|
140747
|
-
}
|
|
140748
|
-
}
|
|
140749
140800
|
const FORMAT_EXT3 = {
|
|
140750
140801
|
mp4: ".mp4",
|
|
140751
140802
|
webm: ".webm",
|
|
@@ -141006,11 +141057,13 @@ async function executeRenderPipeline(input2) {
|
|
|
141006
141057
|
streamingRes = await invokeStreaming();
|
|
141007
141058
|
} catch (err) {
|
|
141008
141059
|
const isVerifyError = isDrawElementVerificationError(err);
|
|
141060
|
+
const isDeCaptureError = isDrawElementCaptureError(err);
|
|
141009
141061
|
const isDeStall = isDeRendererStallError(err);
|
|
141010
141062
|
const isSequentialStall = isSequentialCaptureStallError(err);
|
|
141011
141063
|
const isCancellation = err instanceof RenderCancelledError || executionSignal?.aborted === true;
|
|
141012
141064
|
if (!shouldRetryViaPinnedFallback({
|
|
141013
141065
|
isVerifyError,
|
|
141066
|
+
isDeCaptureError,
|
|
141014
141067
|
isCancellation,
|
|
141015
141068
|
isEncoderInterrupted: err instanceof EncoderInterruptedError,
|
|
141016
141069
|
deWorkerInversion,
|
|
@@ -141031,12 +141084,12 @@ async function executeRenderPipeline(input2) {
|
|
|
141031
141084
|
deFallbackReason = isMemoryExhaustion ? "oom" : isDeStall ? "de_renderer_stall" : "capture_error";
|
|
141032
141085
|
}
|
|
141033
141086
|
log2.warn(
|
|
141034
|
-
isVerifyError ? "[Render] drawElement self-verification failed; re-rendering via screenshot" : isDeStall ? "[Render] drawElement renderer stalled; re-rendering via screenshot" : isSequentialStall ? "[Render] sequential capture stalled; retrying on a fresh screenshot session" : "[Render] capture failed
|
|
141087
|
+
isVerifyError ? "[Render] drawElement self-verification failed; re-rendering via screenshot" : isDeStall ? "[Render] drawElement renderer stalled; re-rendering via screenshot" : isSequentialStall ? "[Render] sequential capture stalled; retrying on a fresh screenshot session" : "[Render] capture failed; re-rendering via a fresh screenshot session",
|
|
141035
141088
|
{ error: err instanceof Error ? err.message : String(err) }
|
|
141036
141089
|
);
|
|
141037
141090
|
observability.checkpoint(
|
|
141038
141091
|
"capture_streaming",
|
|
141039
|
-
isVerifyError ? "drawElement self-verify failed; retrying with forceScreenshot" : isDeStall ? "drawElement renderer stalled; retrying with forceScreenshot" : isSequentialStall ? "sequential capture stalled; retrying with a fresh screenshot session" : "capture failed
|
|
141092
|
+
isVerifyError ? "drawElement self-verify failed; retrying with forceScreenshot" : isDeStall ? "drawElement renderer stalled; retrying with forceScreenshot" : isSequentialStall ? "sequential capture stalled; retrying with a fresh screenshot session" : "capture failed; retrying with a fresh screenshot session"
|
|
141040
141093
|
);
|
|
141041
141094
|
const failedRouting = capturePlan.routing.kind;
|
|
141042
141095
|
capturePlan = replanAfterFailure(
|
|
@@ -141149,22 +141202,22 @@ async function executeRenderPipeline(input2) {
|
|
|
141149
141202
|
try {
|
|
141150
141203
|
captureRes = await invokeDiskCapture(capturePlan);
|
|
141151
141204
|
} catch (err) {
|
|
141152
|
-
if (!isDrawElementVerificationError(err) || err instanceof RenderCancelledError || executionSignal?.aborted === true) {
|
|
141205
|
+
if (!isDrawElementVerificationError(err) && !isDrawElementCaptureError(err) || err instanceof RenderCancelledError || executionSignal?.aborted === true) {
|
|
141153
141206
|
throw err;
|
|
141154
141207
|
}
|
|
141155
|
-
deSelfVerifyFallback =
|
|
141208
|
+
deSelfVerifyFallback = isDrawElementVerificationError(err);
|
|
141156
141209
|
const t2 = deVerifyFallbackTelemetry(err);
|
|
141157
|
-
deFallbackReason = t2.reason;
|
|
141210
|
+
deFallbackReason = deSelfVerifyFallback ? t2.reason : "capture_error";
|
|
141158
141211
|
deFallbackFailedDb = t2.failedDb;
|
|
141159
141212
|
deFallbackFrameIndex = t2.frameIndex;
|
|
141160
141213
|
deFallbackThresholdDb = t2.thresholdDb;
|
|
141161
141214
|
log2.warn(
|
|
141162
|
-
"[Render] drawElement
|
|
141215
|
+
"[Render] drawElement capture failed on the parallel disk path; re-rendering via screenshot",
|
|
141163
141216
|
{ error: err instanceof Error ? err.message : String(err) }
|
|
141164
141217
|
);
|
|
141165
141218
|
observability.checkpoint(
|
|
141166
141219
|
"capture_disk",
|
|
141167
|
-
"drawElement
|
|
141220
|
+
"drawElement capture failed; retrying with a fresh screenshot session"
|
|
141168
141221
|
);
|
|
141169
141222
|
rmSync23(framesDir, { recursive: true, force: true });
|
|
141170
141223
|
mkdirSync27(framesDir, { recursive: true });
|
|
@@ -141177,7 +141230,9 @@ async function executeRenderPipeline(input2) {
|
|
|
141177
141230
|
probeSession = null;
|
|
141178
141231
|
await closeOrphanedProbeForRetry(orphaned, closeCaptureSession, log2, "disk verify");
|
|
141179
141232
|
}
|
|
141180
|
-
capturePlan = replanAfterFailure(capturePlan, {
|
|
141233
|
+
capturePlan = replanAfterFailure(capturePlan, {
|
|
141234
|
+
kind: deSelfVerifyFallback ? "draw_element_verification" : "draw_element_capture"
|
|
141235
|
+
});
|
|
141181
141236
|
syncCapturePlan();
|
|
141182
141237
|
updateCaptureObservability({
|
|
141183
141238
|
forceScreenshot: capturePlan.forceScreenshot,
|
|
@@ -150848,10 +150903,10 @@ function searchMissCommand(query2, tier) {
|
|
|
150848
150903
|
const quoted = query2.replace(/(["\\$`])/g, "\\$1");
|
|
150849
150904
|
return `npx hyperframes feedback --search-miss "${quoted}" --wanted "<the move you needed>" --tier ${tier}`;
|
|
150850
150905
|
}
|
|
150851
|
-
function
|
|
150852
|
-
if (!json && process.stdout.isTTY) return;
|
|
150853
|
-
if (
|
|
150854
|
-
|
|
150906
|
+
function localModelHint(json, status) {
|
|
150907
|
+
if (!json && process.stdout.isTTY) return null;
|
|
150908
|
+
if (status?.status !== "not-asked") return null;
|
|
150909
|
+
return nonInteractiveConsentMessage();
|
|
150855
150910
|
}
|
|
150856
150911
|
async function offerLocalModel(matchCount, json, registryBaseUrl, artifactRevision) {
|
|
150857
150912
|
if (json || !process.stdout.isTTY) return;
|
|
@@ -150982,6 +151037,11 @@ var init_catalog = __esm({
|
|
|
150982
151037
|
const matching = searched ? searched.items : tagged;
|
|
150983
151038
|
if (matching.length === 0) {
|
|
150984
151039
|
const unsearchable = Boolean(query2) && searched?.localMode === "words" && hasNoSearchableTokens(query2);
|
|
151040
|
+
const tierHint = query2 && !unsearchable && warnings.length === 0 ? localModelHint(json, effectiveStatus) : null;
|
|
151041
|
+
if (tierHint) {
|
|
151042
|
+
warnings.push(tierHint);
|
|
151043
|
+
console.error(tierHint);
|
|
151044
|
+
}
|
|
150985
151045
|
if (json && query2) {
|
|
150986
151046
|
console.log(
|
|
150987
151047
|
JSON.stringify(
|
|
@@ -151087,7 +151147,8 @@ var init_catalog = __esm({
|
|
|
151087
151147
|
}
|
|
151088
151148
|
if (searched.localMode === "words") {
|
|
151089
151149
|
if (warnings.length === 0) {
|
|
151090
|
-
|
|
151150
|
+
const hint2 = localModelHint(json, effectiveStatus);
|
|
151151
|
+
if (hint2) console.error(hint2);
|
|
151091
151152
|
await offerLocalModel(matching.length, json, config.registry, artifactRevision);
|
|
151092
151153
|
}
|
|
151093
151154
|
}
|
|
@@ -153388,7 +153449,7 @@ function uploadTimeoutMs(byteLength) {
|
|
|
153388
153449
|
);
|
|
153389
153450
|
}
|
|
153390
153451
|
function shouldIgnoreSegment(segment) {
|
|
153391
|
-
return
|
|
153452
|
+
return IGNORED_DIRS.has(segment) || IGNORED_FILES.has(segment);
|
|
153392
153453
|
}
|
|
153393
153454
|
function createProjectIgnore(rootDir) {
|
|
153394
153455
|
const matcher = ignore2().add(DEFAULT_PROJECT_IGNORE);
|
|
@@ -153714,7 +153775,7 @@ var init_publishProject = __esm({
|
|
|
153714
153775
|
IGNORED_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", ".next", "coverage"]);
|
|
153715
153776
|
IGNORED_FILES = /* @__PURE__ */ new Set([".DS_Store", "Thumbs.db"]);
|
|
153716
153777
|
HYPERFRAMES_IGNORE_FILE = ".hyperframesignore";
|
|
153717
|
-
DEFAULT_PROJECT_IGNORE = ["/renders/", "/snapshots/"];
|
|
153778
|
+
DEFAULT_PROJECT_IGNORE = ["/renders/", "/snapshots/", ".*"];
|
|
153718
153779
|
PUBLISH_CONTENT_TYPE = "application/zip";
|
|
153719
153780
|
PUBLISH_METADATA_TIMEOUT_MS = 3e4;
|
|
153720
153781
|
PUBLISH_UPLOAD_MIN_TIMEOUT_MS = 12e4;
|
|
@@ -164939,7 +165000,7 @@ function createKeyframesCommand(options = {}) {
|
|
|
164939
165000
|
},
|
|
164940
165001
|
layout: {
|
|
164941
165002
|
type: "string",
|
|
164942
|
-
description: "--shot layout: 'path' (ghosts at real positions + path, default) or 'strip' (
|
|
165003
|
+
description: "--shot layout: 'path' (ghosts at real positions + path, default) or 'strip' (for in-place/overlapping motion). 'strip' captures a real per-time pixel filmstrip only when --selector targets an SVG element; any other selector (e.g. a DOM/sub-composition host) instead gets one live frame plus vector position markers."
|
|
164943
165004
|
},
|
|
164944
165005
|
from: { type: "string", description: "--shot: sample only from this time (seconds)." },
|
|
164945
165006
|
to: { type: "string", description: "--shot: sample only up to this time (seconds)." },
|
|
@@ -166446,19 +166507,25 @@ var init_manager4 = __esm({
|
|
|
166446
166507
|
|
|
166447
166508
|
// src/tts/python.ts
|
|
166448
166509
|
import { execFileSync as execFileSync14 } from "child_process";
|
|
166510
|
+
function validatePythonOverride(override) {
|
|
166511
|
+
try {
|
|
166512
|
+
const version2 = execFileSync14(override, ["--version"], {
|
|
166513
|
+
encoding: "utf-8",
|
|
166514
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
166515
|
+
timeout: 5e3
|
|
166516
|
+
});
|
|
166517
|
+
if (/Python 3/.test(version2)) return { ok: true };
|
|
166518
|
+
return {
|
|
166519
|
+
ok: false,
|
|
166520
|
+
reason: `did not report a Python 3 version (got ${JSON.stringify(version2.trim())})`
|
|
166521
|
+
};
|
|
166522
|
+
} catch (error) {
|
|
166523
|
+
return { ok: false, reason: error instanceof Error ? error.message : String(error) };
|
|
166524
|
+
}
|
|
166525
|
+
}
|
|
166449
166526
|
function findPython() {
|
|
166450
166527
|
const override = process.env.HYPERFRAMES_PYTHON;
|
|
166451
|
-
if (override)
|
|
166452
|
-
try {
|
|
166453
|
-
const version2 = execFileSync14(override, ["--version"], {
|
|
166454
|
-
encoding: "utf-8",
|
|
166455
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
166456
|
-
timeout: 5e3
|
|
166457
|
-
});
|
|
166458
|
-
if (/Python 3/.test(version2)) return override;
|
|
166459
|
-
} catch {
|
|
166460
|
-
}
|
|
166461
|
-
}
|
|
166528
|
+
if (override && validatePythonOverride(override).ok) return override;
|
|
166462
166529
|
for (const name of ["python3", "python"]) {
|
|
166463
166530
|
try {
|
|
166464
166531
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -166480,6 +166547,13 @@ function findPython() {
|
|
|
166480
166547
|
}
|
|
166481
166548
|
return void 0;
|
|
166482
166549
|
}
|
|
166550
|
+
function describeRejectedPythonOverride() {
|
|
166551
|
+
const override = process.env.HYPERFRAMES_PYTHON;
|
|
166552
|
+
if (!override) return null;
|
|
166553
|
+
const validation = validatePythonOverride(override);
|
|
166554
|
+
if (validation.ok) return null;
|
|
166555
|
+
return `HYPERFRAMES_PYTHON="${override}" was rejected: ${validation.reason}`;
|
|
166556
|
+
}
|
|
166483
166557
|
function hasPythonPackage(python, pkg) {
|
|
166484
166558
|
try {
|
|
166485
166559
|
execFileSync14(python, ["-c", `import ${pkg}`], {
|
|
@@ -167260,11 +167334,15 @@ async function checkWhisper() {
|
|
|
167260
167334
|
hint: getInstallInstructions2()
|
|
167261
167335
|
};
|
|
167262
167336
|
}
|
|
167337
|
+
function notInstalledDetail(base2) {
|
|
167338
|
+
const overrideRejection = describeRejectedPythonOverride();
|
|
167339
|
+
return overrideRejection ? `${base2}. ${overrideRejection}` : base2;
|
|
167340
|
+
}
|
|
167263
167341
|
function checkLocalVoice() {
|
|
167264
167342
|
if (hasPythonModules(KOKORO_MODULES)) return { ok: true, detail: "Kokoro deps installed" };
|
|
167265
167343
|
return {
|
|
167266
167344
|
ok: false,
|
|
167267
|
-
detail: "Not installed (optional \u2014 local voice fallback)",
|
|
167345
|
+
detail: notInstalledDetail("Not installed (optional \u2014 local voice fallback)"),
|
|
167268
167346
|
hint: KOKORO_PIP
|
|
167269
167347
|
};
|
|
167270
167348
|
}
|
|
@@ -167272,7 +167350,7 @@ function checkLocalMusic() {
|
|
|
167272
167350
|
if (hasPythonModules(MUSICGEN_MODULES)) return { ok: true, detail: "MusicGen deps installed" };
|
|
167273
167351
|
return {
|
|
167274
167352
|
ok: false,
|
|
167275
|
-
detail: "Not installed (optional \u2014 local music fallback)",
|
|
167353
|
+
detail: notInstalledDetail("Not installed (optional \u2014 local music fallback)"),
|
|
167276
167354
|
hint: MUSICGEN_PIP
|
|
167277
167355
|
};
|
|
167278
167356
|
}
|
|
@@ -1689,7 +1689,13 @@
|
|
|
1689
1689
|
axes && axes !== "normal" ? axes : ""
|
|
1690
1690
|
}`;
|
|
1691
1691
|
});
|
|
1692
|
-
|
|
1692
|
+
// img shares the same pixel-only-motion blind spot as canvas/video: an
|
|
1693
|
+
// equal-size, equal-position opaque src/visibility swap moves no
|
|
1694
|
+
// geometry and no opacity. mediaPixelHash already handles it generically
|
|
1695
|
+
// (drawImage accepts any CanvasImageSource; width/height fall back to
|
|
1696
|
+
// rect.width/height same as canvas/video), so only the element selector
|
|
1697
|
+
// needed widening.
|
|
1698
|
+
for (const media of root.querySelectorAll("canvas, video, img")) {
|
|
1693
1699
|
if (!isVisibleElement(media)) continue;
|
|
1694
1700
|
parts.push(`p:${mediaPixelHash(media)}`);
|
|
1695
1701
|
}
|