hyperframes 0.7.53 → 0.7.54
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 +316 -38
- package/dist/commands/layout-audit.browser.js +82 -7
- package/dist/studio/assets/{index-Bo8sRL2U.js → index-CMHYjEZ5.js} +1 -1
- package/dist/studio/assets/{index-CJpl5RTK.js → index-pRhCpGPz.js} +3 -3
- package/dist/studio/assets/{index-DHrXh-VF.js → index-uBY329wb.js} +1 -1
- package/dist/studio/index.html +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.7.
|
|
53
|
+
VERSION = true ? "0.7.54" : "0.0.0-dev";
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -64600,8 +64600,13 @@ async function getCompositionDuration(session) {
|
|
|
64600
64600
|
return window.__hf?.duration ?? 0;
|
|
64601
64601
|
});
|
|
64602
64602
|
}
|
|
64603
|
+
function computeDeVerifySampleFractions(k2) {
|
|
64604
|
+
if (k2 <= 0) return [];
|
|
64605
|
+
if (k2 === 1) return [0.95];
|
|
64606
|
+
return [...Array.from({ length: k2 - 1 }, (_, i2) => (i2 + 1) / k2), 0.95];
|
|
64607
|
+
}
|
|
64603
64608
|
async function captureDeVerificationFrames(session, page, logInitPhase) {
|
|
64604
|
-
const kRaw = Number(process.env.HF_DE_VERIFY ?? "4");
|
|
64609
|
+
const kRaw = Number(process.env.HF_DE_VERIFY ?? session.options.deVerifySamples ?? "4");
|
|
64605
64610
|
const k2 = Number.isFinite(kRaw) ? Math.max(0, Math.min(8, Math.floor(kRaw))) : 4;
|
|
64606
64611
|
if (k2 === 0 || process.env.HF_FORCE_DRAWELEMENT === "1") return;
|
|
64607
64612
|
if (session.options.format === "png") return;
|
|
@@ -64623,7 +64628,7 @@ async function captureDeVerificationFrames(session, page, logInitPhase) {
|
|
|
64623
64628
|
}
|
|
64624
64629
|
}
|
|
64625
64630
|
const boundary = await computeClipBoundaryFrames(page, fps);
|
|
64626
|
-
const fractions =
|
|
64631
|
+
const fractions = computeDeVerifySampleFractions(k2);
|
|
64627
64632
|
const seekTo = async (t2) => {
|
|
64628
64633
|
await page.evaluate((tt3) => {
|
|
64629
64634
|
const hf = window.__hf;
|
|
@@ -64672,6 +64677,8 @@ function getCapturePerfSummary(session) {
|
|
|
64672
64677
|
staticDedupArmed: (session.staticFrames?.size ?? 0) > 0,
|
|
64673
64678
|
staticDedupPredicted: session.staticFrames?.size ?? 0,
|
|
64674
64679
|
staticDedupSkipReason: session.staticDedupSkipReason,
|
|
64680
|
+
beginFrameNoDamage: session.beginFrameNoDamageCount,
|
|
64681
|
+
beginFrameHasDamage: session.beginFrameHasDamageCount,
|
|
64675
64682
|
captureMode: session.captureMode,
|
|
64676
64683
|
deGateReason: session.deGateReason,
|
|
64677
64684
|
deWorkerEncode: session.workerEncodeEnabled ?? false,
|
|
@@ -70849,10 +70856,11 @@ var init_dist4 = __esm({
|
|
|
70849
70856
|
];
|
|
70850
70857
|
},
|
|
70851
70858
|
// missing_timeline_registry + timeline_registry_missing_init
|
|
70852
|
-
({ source, rawSource, options }) => {
|
|
70859
|
+
({ source, rawSource, rootTag, options }) => {
|
|
70853
70860
|
if (options.isSubComposition || rawSource.trimStart().toLowerCase().startsWith("<template")) {
|
|
70854
70861
|
return [];
|
|
70855
70862
|
}
|
|
70863
|
+
if (/(?:^|\s)data-no-timeline(?=[\s=/]|$)/i.test(rootTag?.attrs || "")) return [];
|
|
70856
70864
|
const findings = [];
|
|
70857
70865
|
if (!TIMELINE_REGISTRY_INIT_PATTERN.test(source) && !TIMELINE_REGISTRY_ASSIGN_PATTERN.test(source) && !TIMELINE_REGISTRY_OBJECT_LITERAL_PATTERN.test(source)) {
|
|
70858
70866
|
findings.push({
|
|
@@ -76850,6 +76858,11 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
|
|
|
76850
76858
|
});
|
|
76851
76859
|
}
|
|
76852
76860
|
}
|
|
76861
|
+
function resolveParallelDeVerifySamples(callerValue, workerCount) {
|
|
76862
|
+
if (callerValue !== void 0) return callerValue;
|
|
76863
|
+
if (workerCount <= 1) return void 0;
|
|
76864
|
+
return Math.min(8, 4 + 2 * (workerCount - 1));
|
|
76865
|
+
}
|
|
76853
76866
|
async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions, createBeforeCaptureHook, signal, onProgress, onFrameBuffer, config) {
|
|
76854
76867
|
const totalFrames = tasks.reduce(
|
|
76855
76868
|
(sum, t2) => sum + Math.ceil((t2.endFrame - t2.startFrame) / (t2.frameStride ?? 1)),
|
|
@@ -76871,12 +76884,17 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
|
|
|
76871
76884
|
}
|
|
76872
76885
|
};
|
|
76873
76886
|
const parallel = tasks.length > 1;
|
|
76887
|
+
const deVerifySamples = resolveParallelDeVerifySamples(
|
|
76888
|
+
captureOptions.deVerifySamples,
|
|
76889
|
+
tasks.length
|
|
76890
|
+
);
|
|
76891
|
+
const workerCaptureOptions = deVerifySamples === captureOptions.deVerifySamples ? captureOptions : { ...captureOptions, deVerifySamples };
|
|
76874
76892
|
const results = await Promise.all(
|
|
76875
76893
|
tasks.map(
|
|
76876
76894
|
(task) => executeWorkerTask(
|
|
76877
76895
|
task,
|
|
76878
76896
|
serverUrl,
|
|
76879
|
-
|
|
76897
|
+
workerCaptureOptions,
|
|
76880
76898
|
createBeforeCaptureHook,
|
|
76881
76899
|
signal,
|
|
76882
76900
|
onFrameCaptured,
|
|
@@ -79261,6 +79279,7 @@ function renderObservabilityEventProperties(props) {
|
|
|
79261
79279
|
de_pre_router_workers: props.captureDePreRouterWorkers,
|
|
79262
79280
|
de_self_verify_fallback: props.captureDeSelfVerifyFallback,
|
|
79263
79281
|
de_fallback_reason: props.captureDeFallbackReason,
|
|
79282
|
+
capture_parallel_stream: props.captureParallelStream,
|
|
79264
79283
|
observability_extract_video_count: props.observabilityExtractVideoCount,
|
|
79265
79284
|
observability_extracted_video_count: props.observabilityExtractedVideoCount,
|
|
79266
79285
|
observability_extract_total_frames: props.observabilityExtractTotalFrames,
|
|
@@ -79305,6 +79324,8 @@ function trackRenderComplete(props) {
|
|
|
79305
79324
|
static_dedup_skip_reason: props.staticDedupSkipReason,
|
|
79306
79325
|
static_dedup_predicted_frames: props.staticDedupPredictedFrames,
|
|
79307
79326
|
static_dedup_reused_frames: props.staticDedupReusedFrames,
|
|
79327
|
+
begin_frame_no_damage_frames: props.beginFrameNoDamageFrames,
|
|
79328
|
+
begin_frame_has_damage_frames: props.beginFrameHasDamageFrames,
|
|
79308
79329
|
de_capture_mode: props.deCaptureMode,
|
|
79309
79330
|
de_compile_gate: props.deCompileGate,
|
|
79310
79331
|
de_clamp_reason: props.deClampReason,
|
|
@@ -84448,6 +84469,9 @@ function buildBrowserArgs(url, options) {
|
|
|
84448
84469
|
if (options.remoteDebuggingPort !== void 0 && options.userDataDir) {
|
|
84449
84470
|
args.push(`--remote-debugging-port=${options.remoteDebuggingPort}`);
|
|
84450
84471
|
}
|
|
84472
|
+
if (options.disableGpu) {
|
|
84473
|
+
args.push("--disable-gpu");
|
|
84474
|
+
}
|
|
84451
84475
|
args.push(url);
|
|
84452
84476
|
return args;
|
|
84453
84477
|
}
|
|
@@ -85312,6 +85336,7 @@ function renderObservabilityTelemetryPayload(observability) {
|
|
|
85312
85336
|
captureDePreRouterWorkers: capture2.dePreRouterWorkers,
|
|
85313
85337
|
captureDeSelfVerifyFallback: capture2.deSelfVerifyFallback,
|
|
85314
85338
|
captureDeFallbackReason: capture2.deFallbackReason,
|
|
85339
|
+
captureParallelStream: capture2.captureParallelStream,
|
|
85315
85340
|
observabilityExtractVideoCount: extraction?.videoCount,
|
|
85316
85341
|
observabilityExtractedVideoCount: extraction?.extractedVideoCount,
|
|
85317
85342
|
observabilityExtractTotalFrames: extraction?.totalFramesExtracted,
|
|
@@ -101069,6 +101094,12 @@ function aggregateDedup(perfs) {
|
|
|
101069
101094
|
skipReason: skipReasons.length > 0 ? skipReasons.join("|") : void 0
|
|
101070
101095
|
};
|
|
101071
101096
|
}
|
|
101097
|
+
function aggregateBeginFrameReuse(perfs) {
|
|
101098
|
+
const noDamageFrames = perfs.reduce((sum, p2) => sum + (p2.beginFrameNoDamage ?? 0), 0);
|
|
101099
|
+
const hasDamageFrames = perfs.reduce((sum, p2) => sum + (p2.beginFrameHasDamage ?? 0), 0);
|
|
101100
|
+
if (noDamageFrames + hasDamageFrames === 0) return void 0;
|
|
101101
|
+
return { noDamageFrames, hasDamageFrames };
|
|
101102
|
+
}
|
|
101072
101103
|
function buildRenderPerfSummary(input2) {
|
|
101073
101104
|
return {
|
|
101074
101105
|
renderId: input2.job.id,
|
|
@@ -101112,6 +101143,7 @@ function buildRenderPerfSummary(input2) {
|
|
|
101112
101143
|
peakRssMb: Math.round(input2.peakRssBytes / (1024 * 1024)),
|
|
101113
101144
|
peakHeapUsedMb: Math.round(input2.peakHeapUsedBytes / (1024 * 1024)),
|
|
101114
101145
|
staticDedup: aggregateDedup(input2.dedupPerfs),
|
|
101146
|
+
beginFrameReuse: aggregateBeginFrameReuse(input2.dedupPerfs),
|
|
101115
101147
|
drawElement: aggregateDrawElement(
|
|
101116
101148
|
input2.dedupPerfs,
|
|
101117
101149
|
input2.drawElement ?? { selfVerifyFallback: false }
|
|
@@ -106318,6 +106350,39 @@ function detectThreeDTransformUsage(html) {
|
|
|
106318
106350
|
function detectMixBlendModeUsage(html) {
|
|
106319
106351
|
return MIX_BLEND_MODE_PATTERN.test(html);
|
|
106320
106352
|
}
|
|
106353
|
+
function detectAncestorBackgroundImage(html) {
|
|
106354
|
+
const { document: document2 } = parseHTML(html);
|
|
106355
|
+
const root = document2.querySelector("[data-composition-id]");
|
|
106356
|
+
if (!root) return false;
|
|
106357
|
+
const ancestors = [];
|
|
106358
|
+
for (let el = root.parentElement; el; el = el.parentElement) ancestors.push(el);
|
|
106359
|
+
if (document2.documentElement && !ancestors.includes(document2.documentElement)) {
|
|
106360
|
+
ancestors.push(document2.documentElement);
|
|
106361
|
+
}
|
|
106362
|
+
for (const el of ancestors) {
|
|
106363
|
+
const style = el.getAttribute("style");
|
|
106364
|
+
if (style && BACKGROUND_IMAGE_DECL_PATTERN.test(`{${style}}`)) return true;
|
|
106365
|
+
}
|
|
106366
|
+
for (const styleEl of document2.querySelectorAll("style")) {
|
|
106367
|
+
const css = styleEl.textContent ?? "";
|
|
106368
|
+
for (const rule of css.matchAll(/([^{}]+)\{([^}]*)\}/g)) {
|
|
106369
|
+
const [, selectorList = "", declarations = ""] = rule;
|
|
106370
|
+
if (!BACKGROUND_IMAGE_DECL_PATTERN.test(`{${declarations}}`)) continue;
|
|
106371
|
+
for (const selector of selectorList.split(",")) {
|
|
106372
|
+
const sel = selector.trim();
|
|
106373
|
+
if (!sel || sel.startsWith("@")) continue;
|
|
106374
|
+
if (/^(?:html|:root)$/i.test(sel)) return true;
|
|
106375
|
+
try {
|
|
106376
|
+
for (const matched of document2.querySelectorAll(sel)) {
|
|
106377
|
+
if (ancestors.includes(matched)) return true;
|
|
106378
|
+
}
|
|
106379
|
+
} catch {
|
|
106380
|
+
}
|
|
106381
|
+
}
|
|
106382
|
+
}
|
|
106383
|
+
}
|
|
106384
|
+
return false;
|
|
106385
|
+
}
|
|
106321
106386
|
function detectShaderTransitionUsage(html) {
|
|
106322
106387
|
let scriptMatch;
|
|
106323
106388
|
const scriptPattern = new RegExp(INLINE_SCRIPT_PATTERN.source, INLINE_SCRIPT_PATTERN.flags);
|
|
@@ -107150,6 +107215,7 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
|
|
|
107150
107215
|
const hasShaderTransitions = detectShaderTransitionUsage(sanitizedHtml);
|
|
107151
107216
|
const usesThreeDTransforms = detectThreeDTransformUsage(sanitizedHtml);
|
|
107152
107217
|
const usesMixBlendMode = detectMixBlendModeUsage(sanitizedHtml);
|
|
107218
|
+
const hasAncestorBackgroundImage = detectAncestorBackgroundImage(sanitizedHtml);
|
|
107153
107219
|
const normalizedFontHtml = normalizeSystemFontPrimaryFamilies(
|
|
107154
107220
|
injectTextRenderingRule2(
|
|
107155
107221
|
coalesceHeadStylesAndBodyScripts2(promoteCssImportsToLinkTags(sanitizedHtml))
|
|
@@ -107256,7 +107322,8 @@ async function compileForRender(projectDir, htmlPath, downloadDir, options = {})
|
|
|
107256
107322
|
renderModeHints,
|
|
107257
107323
|
hasShaderTransitions,
|
|
107258
107324
|
usesThreeDTransforms,
|
|
107259
|
-
usesMixBlendMode
|
|
107325
|
+
usesMixBlendMode,
|
|
107326
|
+
hasAncestorBackgroundImage
|
|
107260
107327
|
};
|
|
107261
107328
|
}
|
|
107262
107329
|
async function discoverMediaFromBrowser(page) {
|
|
@@ -107495,7 +107562,7 @@ async function recompileWithResolutions(compiled, resolutions, projectDir, downl
|
|
|
107495
107562
|
hasShaderTransitions: compiled.hasShaderTransitions
|
|
107496
107563
|
};
|
|
107497
107564
|
}
|
|
107498
|
-
var EmptyCompositionError, INLINE_SCRIPT_PATTERN, COMPILER_MOUNT_BLOCK_START, COMPILER_MOUNT_BLOCK_END, THREE_D_CONTEXT_PATTERN, MIX_BLEND_MODE_PATTERN, SHADER_TRANSITION_USAGE_PATTERN, REMOTE_MEDIA_SUBDIR, REMOTE_MEDIA_TAG_RE, REMOTE_IMG_TAG_RE, REMOTE_BG_URL_RE, REMOTE_FONTFACE_URL_RE, MAX_STYLESHEET_BYTES, LOCAL_FONTFACE_URL_RE, GSAP_CDN_BASE;
|
|
107565
|
+
var EmptyCompositionError, INLINE_SCRIPT_PATTERN, COMPILER_MOUNT_BLOCK_START, COMPILER_MOUNT_BLOCK_END, THREE_D_CONTEXT_PATTERN, MIX_BLEND_MODE_PATTERN, BACKGROUND_IMAGE_DECL_PATTERN, SHADER_TRANSITION_USAGE_PATTERN, REMOTE_MEDIA_SUBDIR, REMOTE_MEDIA_TAG_RE, REMOTE_IMG_TAG_RE, REMOTE_BG_URL_RE, REMOTE_FONTFACE_URL_RE, MAX_STYLESHEET_BYTES, LOCAL_FONTFACE_URL_RE, GSAP_CDN_BASE;
|
|
107499
107566
|
var init_htmlCompiler2 = __esm({
|
|
107500
107567
|
"../producer/src/services/htmlCompiler.ts"() {
|
|
107501
107568
|
"use strict";
|
|
@@ -107532,6 +107599,7 @@ Check that each file referenced by data-composition-src contains valid HTML with
|
|
|
107532
107599
|
COMPILER_MOUNT_BLOCK_END = "/* __HF_COMPILER_MOUNT_END__ */";
|
|
107533
107600
|
THREE_D_CONTEXT_PATTERN = /transform-style\s*:\s*preserve-3d|backface-visibility\s*:|perspective\s*:\s*[0-9]|perspective\s*\(|matrix3d\s*\(|rotate3d\s*\(|\btransformPerspective\b/i;
|
|
107534
107601
|
MIX_BLEND_MODE_PATTERN = /mix-blend-mode\s*:/i;
|
|
107602
|
+
BACKGROUND_IMAGE_DECL_PATTERN = /(?:^|;|\{)\s*background(?:-image)?\s*:[^;}]*(?:\bgradient\s*\(|url\s*\()/i;
|
|
107535
107603
|
SHADER_TRANSITION_USAGE_PATTERN = /\b(?:(?:window|globalThis)\s*\.\s*)?HyperShader\s*\.\s*init\s*\(|\b__hf\s*\.\s*transitions\s*=/;
|
|
107536
107604
|
REMOTE_MEDIA_SUBDIR = "_remote_media";
|
|
107537
107605
|
REMOTE_MEDIA_TAG_RE = /<(?:video|audio)\b[^>]*?\bsrc\s*=\s*["'](https?:\/\/[^"']+)["'][^>]*>/gi;
|
|
@@ -107586,6 +107654,13 @@ async function runCompileStage(input2) {
|
|
|
107586
107654
|
"[Render] Fast capture: composition uses mix-blend-mode \u2014 disabling drawElementImage for this render. Capture uses the platform's baseline route."
|
|
107587
107655
|
);
|
|
107588
107656
|
}
|
|
107657
|
+
if (cfg.useDrawElement && process.env.HF_FAST_CAPTURE_ANCESTOR_BG !== "true" && compiled.hasAncestorBackgroundImage) {
|
|
107658
|
+
cfg.useDrawElement = false;
|
|
107659
|
+
deCompileGate = "ancestor_background_image";
|
|
107660
|
+
log2.info(
|
|
107661
|
+
"[Render] Fast capture: composition root's ancestors (body/html/wrapper) carry a background-image \u2014 disabling drawElementImage for this render. Capture uses the platform's baseline route."
|
|
107662
|
+
);
|
|
107663
|
+
}
|
|
107589
107664
|
if (cfg.useDrawElement && process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE !== "true" && compiled.hasShaderTransitions) {
|
|
107590
107665
|
cfg.useDrawElement = false;
|
|
107591
107666
|
deCompileGate = "shader_transitions";
|
|
@@ -109632,7 +109707,8 @@ import {
|
|
|
109632
109707
|
mkdirSync as mkdirSync19,
|
|
109633
109708
|
mkdtempSync as mkdtempSync3,
|
|
109634
109709
|
openSync as openSync3,
|
|
109635
|
-
readFileSync as readFileSync25
|
|
109710
|
+
readFileSync as readFileSync25,
|
|
109711
|
+
statfsSync as statfsSync2
|
|
109636
109712
|
} from "fs";
|
|
109637
109713
|
import { join as join43 } from "path";
|
|
109638
109714
|
function tempDirSafePrefix(id) {
|
|
@@ -109715,9 +109791,52 @@ async function probeHdrExtractionDims(args) {
|
|
|
109715
109791
|
}
|
|
109716
109792
|
}
|
|
109717
109793
|
}
|
|
109794
|
+
function estimateHdrExtractionBytes(videos, fps) {
|
|
109795
|
+
let total = 0;
|
|
109796
|
+
for (const v2 of videos) {
|
|
109797
|
+
const frames = Math.ceil(Math.max(0, v2.durationSeconds) * fps);
|
|
109798
|
+
total += frames * v2.width * v2.height * 6;
|
|
109799
|
+
}
|
|
109800
|
+
return total;
|
|
109801
|
+
}
|
|
109802
|
+
function assertHdrExtractionDiskHeadroom(framesDir, plannedVideos, fps, log2) {
|
|
109803
|
+
const estimatedBytes = estimateHdrExtractionBytes(plannedVideos, fps);
|
|
109804
|
+
let freeBytes;
|
|
109805
|
+
try {
|
|
109806
|
+
const stat3 = statfsSync2(framesDir);
|
|
109807
|
+
freeBytes = stat3.bavail * stat3.bsize;
|
|
109808
|
+
} catch {
|
|
109809
|
+
return;
|
|
109810
|
+
}
|
|
109811
|
+
const estimatedGb = (estimatedBytes / 1e9).toFixed(1);
|
|
109812
|
+
if (estimatedBytes > freeBytes * HDR_EXTRACTION_HEADROOM_FRACTION) {
|
|
109813
|
+
throw new Error(
|
|
109814
|
+
`HDR pre-extraction needs ~${estimatedGb} GB of raw 16-bit frames but only ${(freeBytes / 1e9).toFixed(1)} GB is free at ${framesDir}. If the composition doesn't need HDR output, re-run with --sdr; otherwise free up disk space and retry.`
|
|
109815
|
+
);
|
|
109816
|
+
}
|
|
109817
|
+
if (estimatedBytes > HDR_EXTRACTION_WARN_BYTES) {
|
|
109818
|
+
log2.warn(
|
|
109819
|
+
`HDR pre-extraction will write ~${estimatedGb} GB of raw 16-bit frames (pass --sdr to skip if HDR output isn't needed)`,
|
|
109820
|
+
{ estimatedBytes, freeBytes }
|
|
109821
|
+
);
|
|
109822
|
+
}
|
|
109823
|
+
}
|
|
109718
109824
|
async function extractHdrVideoFrames(args) {
|
|
109719
109825
|
const { job, log: log2, framesDir, composition, prep, width, height, abortSignal, hdrDiagnostics } = args;
|
|
109720
109826
|
const out = /* @__PURE__ */ new Map();
|
|
109827
|
+
mkdirSync19(framesDir, { recursive: true });
|
|
109828
|
+
const plannedVideos = [];
|
|
109829
|
+
for (const [videoId] of prep.hdrVideoSrcPaths) {
|
|
109830
|
+
const video = composition.videos.find((v2) => v2.id === videoId);
|
|
109831
|
+
if (!video) continue;
|
|
109832
|
+
const dims = prep.hdrExtractionDims.get(videoId) ?? { width, height };
|
|
109833
|
+
plannedVideos.push({
|
|
109834
|
+
durationSeconds: video.end - video.start,
|
|
109835
|
+
width: dims.width,
|
|
109836
|
+
height: dims.height
|
|
109837
|
+
});
|
|
109838
|
+
}
|
|
109839
|
+
assertHdrExtractionDiskHeadroom(framesDir, plannedVideos, fpsToNumber(job.config.fps), log2);
|
|
109721
109840
|
for (const [videoId, srcPath] of prep.hdrVideoSrcPaths) {
|
|
109722
109841
|
const video = composition.videos.find((v2) => v2.id === videoId);
|
|
109723
109842
|
if (!video) continue;
|
|
@@ -109825,13 +109944,15 @@ function decodeHdrImageBuffers(args) {
|
|
|
109825
109944
|
}
|
|
109826
109945
|
return out;
|
|
109827
109946
|
}
|
|
109828
|
-
var NO_FOLLOW_FLAG;
|
|
109947
|
+
var NO_FOLLOW_FLAG, HDR_EXTRACTION_HEADROOM_FRACTION, HDR_EXTRACTION_WARN_BYTES;
|
|
109829
109948
|
var init_captureHdrResources = __esm({
|
|
109830
109949
|
"../producer/src/services/render/stages/captureHdrResources.ts"() {
|
|
109831
109950
|
"use strict";
|
|
109832
109951
|
init_src();
|
|
109833
109952
|
init_dist3();
|
|
109834
109953
|
NO_FOLLOW_FLAG = constants3.O_NOFOLLOW ?? 0;
|
|
109954
|
+
HDR_EXTRACTION_HEADROOM_FRACTION = 0.9;
|
|
109955
|
+
HDR_EXTRACTION_WARN_BYTES = 1e10;
|
|
109835
109956
|
}
|
|
109836
109957
|
});
|
|
109837
109958
|
|
|
@@ -110940,6 +111061,8 @@ async function runEncodeStage(input2) {
|
|
|
110940
111061
|
return { encodeMs: Date.now() - stage5Start };
|
|
110941
111062
|
}
|
|
110942
111063
|
updateJobStatus(job, "encoding", "Encoding video", 75, onProgress);
|
|
111064
|
+
const scaledEncodeTimeout = Math.ceil((job.duration ?? 0) * 4e3);
|
|
111065
|
+
const videoEngineCfg = scaledEncodeTimeout > engineCfg.ffmpegEncodeTimeout ? { ...engineCfg, ffmpegEncodeTimeout: scaledEncodeTimeout } : engineCfg;
|
|
110943
111066
|
const frameExt = needsAlpha ? "png" : "jpg";
|
|
110944
111067
|
const framePattern = `frame_%06d.${frameExt}`;
|
|
110945
111068
|
const encoderOpts = {
|
|
@@ -110967,14 +111090,14 @@ async function runEncodeStage(input2) {
|
|
|
110967
111090
|
encoderOpts,
|
|
110968
111091
|
chunkedEncodeSize,
|
|
110969
111092
|
abortSignal,
|
|
110970
|
-
|
|
111093
|
+
videoEngineCfg
|
|
110971
111094
|
) : await encodeFramesFromDir(
|
|
110972
111095
|
framesDir,
|
|
110973
111096
|
framePattern,
|
|
110974
111097
|
videoOnlyPath,
|
|
110975
111098
|
encoderOpts,
|
|
110976
111099
|
abortSignal,
|
|
110977
|
-
|
|
111100
|
+
videoEngineCfg
|
|
110978
111101
|
);
|
|
110979
111102
|
assertNotAborted();
|
|
110980
111103
|
if (!encodeResult.success) {
|
|
@@ -111056,6 +111179,7 @@ import {
|
|
|
111056
111179
|
appendFileSync
|
|
111057
111180
|
} from "fs";
|
|
111058
111181
|
import { join as join50, dirname as dirname19, resolve as resolve26 } from "path";
|
|
111182
|
+
import { totalmem as totalmem2 } from "os";
|
|
111059
111183
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
111060
111184
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
111061
111185
|
function sampleDirectoryBytes(dir) {
|
|
@@ -111380,11 +111504,24 @@ function createRenderJob(config) {
|
|
|
111380
111504
|
function normalizeCompositionSrcPath(srcPath) {
|
|
111381
111505
|
return srcPath.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
111382
111506
|
}
|
|
111383
|
-
function
|
|
111507
|
+
function readSceneRootDuration(entryHtml) {
|
|
111508
|
+
if (!entryHtml) return null;
|
|
111509
|
+
const { document: document2 } = parseHTML(entryHtml);
|
|
111510
|
+
const template = document2.querySelector("template");
|
|
111511
|
+
const scope = template ? parseHTML(template.innerHTML).document : document2;
|
|
111512
|
+
const root = scope.querySelector("[data-composition-id]");
|
|
111513
|
+
return root?.getAttribute("data-duration") ?? null;
|
|
111514
|
+
}
|
|
111515
|
+
function createStandaloneEntryRenderClone(root, host, sceneDuration) {
|
|
111384
111516
|
const hostClone = host.cloneNode(true);
|
|
111385
111517
|
hostClone.setAttribute("data-start", "0");
|
|
111386
111518
|
if (root === host) return hostClone;
|
|
111387
111519
|
const rootClone = root.cloneNode(false);
|
|
111520
|
+
if (sceneDuration != null) {
|
|
111521
|
+
rootClone.setAttribute("data-duration", sceneDuration);
|
|
111522
|
+
} else {
|
|
111523
|
+
rootClone.removeAttribute("data-duration");
|
|
111524
|
+
}
|
|
111388
111525
|
rootClone.appendChild(hostClone);
|
|
111389
111526
|
return rootClone;
|
|
111390
111527
|
}
|
|
@@ -111421,7 +111558,13 @@ function resolveInversionRetryPlan(args) {
|
|
|
111421
111558
|
};
|
|
111422
111559
|
}
|
|
111423
111560
|
function shouldPreferParallelDrawElement(args) {
|
|
111424
|
-
return args.routerEnabled && args.workerCount > 1 && typeof args.requestedWorkers !== "number" && args.useDrawElement && !args.deCompileGate && !args.forceScreenshot && args.outputFormat === "mp4" && args.minFrames > 0 && args.totalFrames >= args.minFrames && !args.layeredOrEffectRoute && !args.supersampling && !args.probeDeGated && !args.experimentalParallelDeOptIn
|
|
111561
|
+
return args.routerEnabled && args.workerCount > 1 && typeof args.requestedWorkers !== "number" && args.useDrawElement && !args.deCompileGate && !args.forceScreenshot && args.outputFormat === "mp4" && args.minFrames > 0 && args.totalFrames >= args.minFrames && !args.layeredOrEffectRoute && !args.supersampling && !args.probeDeGated && !args.experimentalParallelDeOptIn && // RAM floor: routed parallel DE runs 3 concurrent hardware-GPU Chrome
|
|
111562
|
+
// instances. On a 16 GB machine that produced vertical black slabs in the
|
|
111563
|
+
// final MP4 (wild report, CLI 0.7.52) — compositor tiles evicted under
|
|
111564
|
+
// GPU/memory pressure, and sampled self-verify can miss partial-frame
|
|
111565
|
+
// damage. Single-worker DE (the inversion) stays available below the
|
|
111566
|
+
// floor; only the parallel bet is withheld.
|
|
111567
|
+
(args.minMemoryMb <= 0 || args.totalMemoryMb >= args.minMemoryMb);
|
|
111425
111568
|
}
|
|
111426
111569
|
function resolveParallelRouterRetryPlan(args) {
|
|
111427
111570
|
if (args.deParallelRouter !== "routed") return null;
|
|
@@ -111442,13 +111585,16 @@ function shouldRetryViaPinnedFallback(args) {
|
|
|
111442
111585
|
if (args.isVerifyError) return true;
|
|
111443
111586
|
return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
|
|
111444
111587
|
}
|
|
111588
|
+
function shouldStreamParallelCapture(args) {
|
|
111589
|
+
return args.routerEnabled && args.workerCount > 1 && !args.useDrawElement && args.outputFormat === "mp4" && args.streamingOk && !args.layeredOrEffectRoute;
|
|
111590
|
+
}
|
|
111445
111591
|
function resolveCaptureForceScreenshotForPageSideCompositing(args) {
|
|
111446
111592
|
return args.usePageSideCompositing ? true : args.forceScreenshot;
|
|
111447
111593
|
}
|
|
111448
111594
|
function shouldDiscardProbeSessionForPageSideCompositing(args) {
|
|
111449
111595
|
return args.hasProbeSession && args.usePageSideCompositing;
|
|
111450
111596
|
}
|
|
111451
|
-
function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
|
|
111597
|
+
function extractStandaloneEntryFromIndex(indexHtml, entryFile, entryHtml) {
|
|
111452
111598
|
const normalizedEntryFile = normalizeCompositionSrcPath(entryFile);
|
|
111453
111599
|
const { document: document2 } = parseHTML(indexHtml);
|
|
111454
111600
|
const body = document2.querySelector("body");
|
|
@@ -111462,7 +111608,8 @@ function extractStandaloneEntryFromIndex(indexHtml, entryFile) {
|
|
|
111462
111608
|
(candidate) => candidate.hasAttribute("data-composition-id")
|
|
111463
111609
|
) ?? null;
|
|
111464
111610
|
if (!root) return null;
|
|
111465
|
-
const
|
|
111611
|
+
const sceneDuration = readSceneRootDuration(entryHtml) ?? host.getAttribute("data-duration");
|
|
111612
|
+
const renderClone = createStandaloneEntryRenderClone(root, host, sceneDuration);
|
|
111466
111613
|
replaceBodyWithRenderClone(body, renderClone);
|
|
111467
111614
|
return document2.toString();
|
|
111468
111615
|
}
|
|
@@ -111582,7 +111729,8 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
111582
111729
|
}
|
|
111583
111730
|
const standaloneHtml = extractStandaloneEntryFromIndex(
|
|
111584
111731
|
readFileSync26(projectIndexPath, "utf-8"),
|
|
111585
|
-
entryFile
|
|
111732
|
+
entryFile,
|
|
111733
|
+
rawEntry
|
|
111586
111734
|
);
|
|
111587
111735
|
if (!standaloneHtml) {
|
|
111588
111736
|
throw new Error(
|
|
@@ -111627,6 +111775,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
111627
111775
|
let deClampReason;
|
|
111628
111776
|
let deWorkerInversion;
|
|
111629
111777
|
let deParallelStreamForced = false;
|
|
111778
|
+
let captureParallelStreamForced = false;
|
|
111630
111779
|
let deSelfVerifyFallback = false;
|
|
111631
111780
|
let deFallbackReason;
|
|
111632
111781
|
let deDrainStats;
|
|
@@ -111882,6 +112031,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
111882
112031
|
const deParallelMinFramesRaw = process.env.HF_DE_PARALLEL_MIN_FRAMES;
|
|
111883
112032
|
const deParallelMinFramesNum = deParallelMinFramesRaw === void 0 || deParallelMinFramesRaw.trim() === "" ? 2e3 : Number(deParallelMinFramesRaw);
|
|
111884
112033
|
const deParallelMinFrames = Number.isFinite(deParallelMinFramesNum) ? deParallelMinFramesNum : 2e3;
|
|
112034
|
+
const deParallelMinMemRaw = process.env.HF_DE_PARALLEL_MIN_MEM_MB;
|
|
112035
|
+
const deParallelMinMemNum = deParallelMinMemRaw === void 0 || deParallelMinMemRaw.trim() === "" ? 24576 : Number(deParallelMinMemRaw);
|
|
112036
|
+
const deParallelMinMemoryMb = Number.isFinite(deParallelMinMemNum) ? deParallelMinMemNum : 24576;
|
|
111885
112037
|
const deParallelRouterEligible = shouldPreferParallelDrawElement({
|
|
111886
112038
|
workerCount: WOULD_RESOLVE_MULTI_WORKER,
|
|
111887
112039
|
requestedWorkers: job.config.workers,
|
|
@@ -111895,7 +112047,9 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
111895
112047
|
supersampling: deviceScaleFactor > 1,
|
|
111896
112048
|
probeDeGated: probeSession !== null && probeSession.captureMode !== "drawelement" && !probeSession.deInitDeferred,
|
|
111897
112049
|
experimentalParallelDeOptIn: process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE === "true" || process.env.HF_DE_PARALLEL_STREAM === "true",
|
|
111898
|
-
routerEnabled: deParallelRouterEnabled
|
|
112050
|
+
routerEnabled: deParallelRouterEnabled,
|
|
112051
|
+
totalMemoryMb: Math.round(totalmem2() / (1024 * 1024)),
|
|
112052
|
+
minMemoryMb: deParallelMinMemoryMb
|
|
111899
112053
|
});
|
|
111900
112054
|
let workerCount;
|
|
111901
112055
|
const captureStageObservationData = (extra = {}) => ({
|
|
@@ -112005,6 +112159,32 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
112005
112159
|
deWorkerInversion: deWorkerInversion ?? "none",
|
|
112006
112160
|
deParallelRouter: deParallelRouter ?? "none"
|
|
112007
112161
|
});
|
|
112162
|
+
const captureParallelStreamRouterEnabled = process.env.HF_CAPTURE_PARALLEL_STREAM === "true";
|
|
112163
|
+
const captureParallelStreamArgs = {
|
|
112164
|
+
workerCount,
|
|
112165
|
+
useDrawElement: cfg.useDrawElement,
|
|
112166
|
+
outputFormat,
|
|
112167
|
+
streamingOk: shouldUseStreamingEncode(cfg, outputFormat, 1, job.duration),
|
|
112168
|
+
layeredOrEffectRoute: hasHdrContent || compiled.hasShaderTransitions
|
|
112169
|
+
};
|
|
112170
|
+
const captureParallelStreamEligible = shouldStreamParallelCapture({
|
|
112171
|
+
routerEnabled: captureParallelStreamRouterEnabled,
|
|
112172
|
+
...captureParallelStreamArgs
|
|
112173
|
+
});
|
|
112174
|
+
if (captureParallelStreamEligible) {
|
|
112175
|
+
captureParallelStreamForced = true;
|
|
112176
|
+
const captureParallelStream = process.platform === "linux" && !captureForceScreenshot ? "beginframe" : "screenshot";
|
|
112177
|
+
log2.info(
|
|
112178
|
+
`[Render] Parallel ${captureParallelStream} capture will stream to the encoder (interleaved, ${workerCount} workers) instead of the disk path. Set HF_CAPTURE_PARALLEL_STREAM=false to disable.`
|
|
112179
|
+
);
|
|
112180
|
+
updateCaptureObservability({ captureParallelStream });
|
|
112181
|
+
observability.checkpoint(
|
|
112182
|
+
"worker_resolution",
|
|
112183
|
+
`parallel ${captureParallelStream} capture routed to streaming`
|
|
112184
|
+
);
|
|
112185
|
+
} else if (shouldStreamParallelCapture({ routerEnabled: true, ...captureParallelStreamArgs })) {
|
|
112186
|
+
updateCaptureObservability({ captureParallelStream: "eligible_off" });
|
|
112187
|
+
}
|
|
112008
112188
|
if (workerCount > 1 && probeSession) {
|
|
112009
112189
|
lastBrowserConsole = probeSession.browserConsoleBuffer;
|
|
112010
112190
|
await closeCaptureSession(probeSession);
|
|
@@ -112015,7 +112195,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
112015
112195
|
outputFormat,
|
|
112016
112196
|
workerCount,
|
|
112017
112197
|
job.duration,
|
|
112018
|
-
deParallelStreamForced
|
|
112198
|
+
deParallelStreamForced || captureParallelStreamForced
|
|
112019
112199
|
);
|
|
112020
112200
|
log2.info("streaming-encode gate", {
|
|
112021
112201
|
enabled: useStreamingEncode,
|
|
@@ -112172,7 +112352,7 @@ async function executeRenderJob(job, projectDir, outputPath, onProgress, abortSi
|
|
|
112172
112352
|
workerCount,
|
|
112173
112353
|
probeSession,
|
|
112174
112354
|
outputFormat,
|
|
112175
|
-
forceParallelStream: deParallelStreamForced,
|
|
112355
|
+
forceParallelStream: deParallelStreamForced || captureParallelStreamForced,
|
|
112176
112356
|
streamingEncoderOptions: {
|
|
112177
112357
|
fps: job.config.fps,
|
|
112178
112358
|
width,
|
|
@@ -115270,6 +115450,7 @@ __export(src_exports2, {
|
|
|
115270
115450
|
getCapturePerfSummary: () => getCapturePerfSummary,
|
|
115271
115451
|
getCompositionDuration: () => getCompositionDuration,
|
|
115272
115452
|
initializeSession: () => initializeSession,
|
|
115453
|
+
injectDeterministicFontFaces: () => injectDeterministicFontFaces,
|
|
115273
115454
|
localizeRemoteFontFaces: () => localizeRemoteFontFaces,
|
|
115274
115455
|
localizeRemoteImageSources: () => localizeRemoteImageSources,
|
|
115275
115456
|
localizeRemoteMediaSources: () => localizeRemoteMediaSources,
|
|
@@ -115296,6 +115477,7 @@ var init_src2 = __esm({
|
|
|
115296
115477
|
init_logger();
|
|
115297
115478
|
init_server();
|
|
115298
115479
|
init_errorMessage2();
|
|
115480
|
+
init_deterministicFonts();
|
|
115299
115481
|
init_parityContract2();
|
|
115300
115482
|
init_paths();
|
|
115301
115483
|
init_hyperframeLint();
|
|
@@ -117206,7 +117388,8 @@ function openStudioBrowser(url, projectName, options) {
|
|
|
117206
117388
|
openBrowser(`${url}#project/${projectName}`, {
|
|
117207
117389
|
browserPath: options?.browserPath,
|
|
117208
117390
|
userDataDir: options?.userDataDir,
|
|
117209
|
-
remoteDebuggingPort: options?.remoteDebuggingPort
|
|
117391
|
+
remoteDebuggingPort: options?.remoteDebuggingPort,
|
|
117392
|
+
disableGpu: options?.browserNoGpu
|
|
117210
117393
|
});
|
|
117211
117394
|
}
|
|
117212
117395
|
function printStudioSummary(projectName, url, opts = {}) {
|
|
@@ -117528,6 +117711,11 @@ var init_preview = __esm({
|
|
|
117528
117711
|
"remote-debugging-port": {
|
|
117529
117712
|
type: "string",
|
|
117530
117713
|
description: "Chromium remote debugging port (requires --browser-path and --user-data-dir)"
|
|
117714
|
+
},
|
|
117715
|
+
"browser-no-gpu": {
|
|
117716
|
+
type: "boolean",
|
|
117717
|
+
default: false,
|
|
117718
|
+
description: "Launch the opened browser with --disable-gpu (requires --browser-path). For hosts where hardware acceleration crashes the graphics driver (e.g. NVIDIA Xid resets); with the system default browser use --no-open instead."
|
|
117531
117719
|
}
|
|
117532
117720
|
},
|
|
117533
117721
|
async run({ args }) {
|
|
@@ -117617,6 +117805,14 @@ var init_preview = __esm({
|
|
|
117617
117805
|
}
|
|
117618
117806
|
const noOpen = !args.open;
|
|
117619
117807
|
const browserPath = args["browser-path"];
|
|
117808
|
+
const browserNoGpu = !!args["browser-no-gpu"];
|
|
117809
|
+
if (browserNoGpu && !browserPath) {
|
|
117810
|
+
R2.error(
|
|
117811
|
+
"--browser-no-gpu requires --browser-path (the system default browser cannot receive Chromium flags \u2014 use --no-open on GPU-unstable hosts)"
|
|
117812
|
+
);
|
|
117813
|
+
process.exitCode = 1;
|
|
117814
|
+
return;
|
|
117815
|
+
}
|
|
117620
117816
|
const userDataDir = args["user-data-dir"];
|
|
117621
117817
|
let remoteDebuggingPort;
|
|
117622
117818
|
try {
|
|
@@ -117634,7 +117830,8 @@ var init_preview = __esm({
|
|
|
117634
117830
|
noOpen,
|
|
117635
117831
|
browserPath,
|
|
117636
117832
|
userDataDir,
|
|
117637
|
-
remoteDebuggingPort
|
|
117833
|
+
remoteDebuggingPort,
|
|
117834
|
+
browserNoGpu
|
|
117638
117835
|
});
|
|
117639
117836
|
}
|
|
117640
117837
|
if (hasLocalStudio(dir)) {
|
|
@@ -117643,7 +117840,8 @@ var init_preview = __esm({
|
|
|
117643
117840
|
noOpen,
|
|
117644
117841
|
browserPath,
|
|
117645
117842
|
userDataDir,
|
|
117646
|
-
remoteDebuggingPort
|
|
117843
|
+
remoteDebuggingPort,
|
|
117844
|
+
browserNoGpu
|
|
117647
117845
|
});
|
|
117648
117846
|
}
|
|
117649
117847
|
const forceNew = !!args["force-new"];
|
|
@@ -117653,7 +117851,8 @@ var init_preview = __esm({
|
|
|
117653
117851
|
noOpen,
|
|
117654
117852
|
browserPath,
|
|
117655
117853
|
userDataDir,
|
|
117656
|
-
remoteDebuggingPort
|
|
117854
|
+
remoteDebuggingPort,
|
|
117855
|
+
browserNoGpu
|
|
117657
117856
|
});
|
|
117658
117857
|
}
|
|
117659
117858
|
});
|
|
@@ -121735,6 +121934,8 @@ function trackRenderMetrics(job, elapsedMs, options, docker) {
|
|
|
121735
121934
|
staticDedupSkipReason: perf?.staticDedup?.skipReason,
|
|
121736
121935
|
staticDedupPredictedFrames: perf?.staticDedup?.predictedFrames,
|
|
121737
121936
|
staticDedupReusedFrames: perf?.staticDedup?.reusedFrames,
|
|
121937
|
+
beginFrameNoDamageFrames: perf?.beginFrameReuse?.noDamageFrames,
|
|
121938
|
+
beginFrameHasDamageFrames: perf?.beginFrameReuse?.hasDamageFrames,
|
|
121738
121939
|
deCaptureMode: perf?.drawElement?.mode,
|
|
121739
121940
|
deCompileGate: perf?.drawElement?.compileGate,
|
|
121740
121941
|
deClampReason: perf?.drawElement?.clampReason,
|
|
@@ -123419,8 +123620,9 @@ async function seekCompositionTimeline(page, timeSeconds, options = {}) {
|
|
|
123419
123620
|
)
|
|
123420
123621
|
);
|
|
123421
123622
|
}
|
|
123422
|
-
|
|
123423
|
-
|
|
123623
|
+
const waitForFontsMs = options.waitForFontsMs ?? DEFAULT_POST_SEEK_FONT_WAIT_MS;
|
|
123624
|
+
if (waitForFontsMs > 0) {
|
|
123625
|
+
await waitForCompositionFonts(page, waitForFontsMs);
|
|
123424
123626
|
}
|
|
123425
123627
|
if (options.settleMs !== void 0) {
|
|
123426
123628
|
const settleMs = Math.max(0, options.settleMs);
|
|
@@ -123447,12 +123649,23 @@ async function waitForCompositionFonts(page, timeoutMs) {
|
|
|
123447
123649
|
await page.evaluate((ms) => {
|
|
123448
123650
|
const fonts = Reflect.get(document, "fonts");
|
|
123449
123651
|
if (typeof fonts !== "object" || fonts === null) return Promise.resolve();
|
|
123450
|
-
|
|
123451
|
-
|
|
123452
|
-
|
|
123453
|
-
|
|
123454
|
-
|
|
123455
|
-
|
|
123652
|
+
void document.body?.offsetHeight;
|
|
123653
|
+
return new Promise((resolveWait) => {
|
|
123654
|
+
const deadline = setTimeout(resolveWait, ms);
|
|
123655
|
+
requestAnimationFrame(() => {
|
|
123656
|
+
const status = Reflect.get(fonts, "status");
|
|
123657
|
+
const ready = Reflect.get(fonts, "ready");
|
|
123658
|
+
if (status !== "loading" || !ready) {
|
|
123659
|
+
clearTimeout(deadline);
|
|
123660
|
+
resolveWait();
|
|
123661
|
+
return;
|
|
123662
|
+
}
|
|
123663
|
+
Promise.resolve(ready).then(() => {
|
|
123664
|
+
clearTimeout(deadline);
|
|
123665
|
+
resolveWait();
|
|
123666
|
+
});
|
|
123667
|
+
});
|
|
123668
|
+
});
|
|
123456
123669
|
}, timeoutMs).catch(() => {
|
|
123457
123670
|
});
|
|
123458
123671
|
}
|
|
@@ -123527,7 +123740,7 @@ async function runFfmpegOnce(ffmpegPath, args, timeoutMs) {
|
|
|
123527
123740
|
});
|
|
123528
123741
|
});
|
|
123529
123742
|
}
|
|
123530
|
-
var SHADER_TRANSITIONS_TIMEOUT_MS, CAPTURE_SETTLE_MS, PREFERRED_SEEK_TARGET_WAIT_MS, AUDIT_SEEK_OPTIONS, ZOOM_REGION_PATTERN, DEFAULT_ZOOM_PADDING_PX, DEFAULT_ZOOM_SCALE, MIN_CROP_REGION_PX;
|
|
123743
|
+
var SHADER_TRANSITIONS_TIMEOUT_MS, CAPTURE_SETTLE_MS, PREFERRED_SEEK_TARGET_WAIT_MS, DEFAULT_POST_SEEK_FONT_WAIT_MS, AUDIT_SEEK_OPTIONS, ZOOM_REGION_PATTERN, DEFAULT_ZOOM_PADDING_PX, DEFAULT_ZOOM_SCALE, MIN_CROP_REGION_PX;
|
|
123531
123744
|
var init_captureCompositionFrame = __esm({
|
|
123532
123745
|
"src/capture/captureCompositionFrame.ts"() {
|
|
123533
123746
|
"use strict";
|
|
@@ -123536,6 +123749,7 @@ var init_captureCompositionFrame = __esm({
|
|
|
123536
123749
|
SHADER_TRANSITIONS_TIMEOUT_MS = 9e4;
|
|
123537
123750
|
CAPTURE_SETTLE_MS = 1500;
|
|
123538
123751
|
PREFERRED_SEEK_TARGET_WAIT_MS = 500;
|
|
123752
|
+
DEFAULT_POST_SEEK_FONT_WAIT_MS = 500;
|
|
123539
123753
|
AUDIT_SEEK_OPTIONS = {
|
|
123540
123754
|
fallbackToBridgeAndTimelines: true,
|
|
123541
123755
|
animationFrameSettle: "double",
|
|
@@ -124512,6 +124726,57 @@ Examples:
|
|
|
124512
124726
|
}
|
|
124513
124727
|
});
|
|
124514
124728
|
|
|
124729
|
+
// src/utils/bundleWithLocalizedFonts.ts
|
|
124730
|
+
var bundleWithLocalizedFonts_exports = {};
|
|
124731
|
+
__export(bundleWithLocalizedFonts_exports, {
|
|
124732
|
+
__resetFontLocalizationWarningsForTests: () => __resetFontLocalizationWarningsForTests,
|
|
124733
|
+
bundleWithLocalizedFonts: () => bundleWithLocalizedFonts,
|
|
124734
|
+
localizeWithProducer: () => localizeWithProducer
|
|
124735
|
+
});
|
|
124736
|
+
async function bundleWithLocalizedFonts(projectDir, localizeFonts = localizeWithProducer) {
|
|
124737
|
+
const { bundleToSingleHtml: bundleToSingleHtml2 } = await Promise.resolve().then(() => (init_compiler(), compiler_exports));
|
|
124738
|
+
const html = await bundleToSingleHtml2(projectDir);
|
|
124739
|
+
return localizeFonts(html);
|
|
124740
|
+
}
|
|
124741
|
+
async function loadFontInjector() {
|
|
124742
|
+
try {
|
|
124743
|
+
const producerSpecifier = "@hyperframes/producer";
|
|
124744
|
+
const mod = await import(
|
|
124745
|
+
/* @vite-ignore */
|
|
124746
|
+
producerSpecifier
|
|
124747
|
+
);
|
|
124748
|
+
return mod.injectDeterministicFontFaces ?? null;
|
|
124749
|
+
} catch {
|
|
124750
|
+
return null;
|
|
124751
|
+
}
|
|
124752
|
+
}
|
|
124753
|
+
function __resetFontLocalizationWarningsForTests() {
|
|
124754
|
+
warnedFontLocalizationFailures.clear();
|
|
124755
|
+
}
|
|
124756
|
+
async function localizeWithProducer(html, loadInjector = loadFontInjector, warn = (m2) => console.warn(` ${c.warn("\u26A0")} ${m2}`)) {
|
|
124757
|
+
const inject = await loadInjector();
|
|
124758
|
+
if (!inject) return html;
|
|
124759
|
+
try {
|
|
124760
|
+
return await inject(html);
|
|
124761
|
+
} catch (err) {
|
|
124762
|
+
const message = `Font localization failed; capturing with remote/fallback fonts instead: ${normalizeErrorMessage(err)}`;
|
|
124763
|
+
if (!warnedFontLocalizationFailures.has(message)) {
|
|
124764
|
+
warnedFontLocalizationFailures.add(message);
|
|
124765
|
+
warn(message);
|
|
124766
|
+
}
|
|
124767
|
+
return html;
|
|
124768
|
+
}
|
|
124769
|
+
}
|
|
124770
|
+
var warnedFontLocalizationFailures;
|
|
124771
|
+
var init_bundleWithLocalizedFonts = __esm({
|
|
124772
|
+
"src/utils/bundleWithLocalizedFonts.ts"() {
|
|
124773
|
+
"use strict";
|
|
124774
|
+
init_errorMessage();
|
|
124775
|
+
init_colors();
|
|
124776
|
+
warnedFontLocalizationFailures = /* @__PURE__ */ new Set();
|
|
124777
|
+
}
|
|
124778
|
+
});
|
|
124779
|
+
|
|
124515
124780
|
// src/utils/checkBrowser.ts
|
|
124516
124781
|
var checkBrowser_exports = {};
|
|
124517
124782
|
__export(checkBrowser_exports, {
|
|
@@ -124522,8 +124787,8 @@ __export(checkBrowser_exports, {
|
|
|
124522
124787
|
import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync26 } from "fs";
|
|
124523
124788
|
import { join as join76 } from "path";
|
|
124524
124789
|
async function runBrowserCheck(project, options, motion, runGrid) {
|
|
124525
|
-
const {
|
|
124526
|
-
const html = await
|
|
124790
|
+
const { bundleWithLocalizedFonts: bundleWithLocalizedFonts2 } = await Promise.resolve().then(() => (init_bundleWithLocalizedFonts(), bundleWithLocalizedFonts_exports));
|
|
124791
|
+
const html = await bundleWithLocalizedFonts2(project.dir);
|
|
124527
124792
|
const server = await serveStaticProjectHtml(project.dir, html, "Failed to bind check server");
|
|
124528
124793
|
const drafts = [];
|
|
124529
124794
|
let currentTime = 0;
|
|
@@ -124561,8 +124826,8 @@ async function runBrowserCheck(project, options, motion, runGrid) {
|
|
|
124561
124826
|
}
|
|
124562
124827
|
async function captureFindingCrops(project, options, requests) {
|
|
124563
124828
|
if (requests.length === 0) return [];
|
|
124564
|
-
const {
|
|
124565
|
-
const html = await
|
|
124829
|
+
const { bundleWithLocalizedFonts: bundleWithLocalizedFonts2 } = await Promise.resolve().then(() => (init_bundleWithLocalizedFonts(), bundleWithLocalizedFonts_exports));
|
|
124830
|
+
const html = await bundleWithLocalizedFonts2(project.dir);
|
|
124566
124831
|
const server = await serveStaticProjectHtml(project.dir, html, "Failed to bind check server");
|
|
124567
124832
|
let chromeBrowser;
|
|
124568
124833
|
const written = [];
|
|
@@ -125245,6 +125510,7 @@ var init_checkBrowser = __esm({
|
|
|
125245
125510
|
"container_overflow",
|
|
125246
125511
|
"content_overlap",
|
|
125247
125512
|
"text_occluded",
|
|
125513
|
+
"text_not_painted",
|
|
125248
125514
|
"caption_zone_collision",
|
|
125249
125515
|
"frame_out_of_frame",
|
|
125250
125516
|
"motion_appears_late",
|
|
@@ -172136,9 +172402,9 @@ function computeSnapshotTimes(duration, opts) {
|
|
|
172136
172402
|
return { times: times.map(round5), appendedTail: false };
|
|
172137
172403
|
}
|
|
172138
172404
|
async function captureSnapshots(projectDir, opts) {
|
|
172139
|
-
const {
|
|
172405
|
+
const { bundleWithLocalizedFonts: bundleWithLocalizedFonts2 } = await Promise.resolve().then(() => (init_bundleWithLocalizedFonts(), bundleWithLocalizedFonts_exports));
|
|
172140
172406
|
const numFrames = opts.frames ?? 5;
|
|
172141
|
-
const html = await
|
|
172407
|
+
const html = await bundleWithLocalizedFonts2(projectDir);
|
|
172142
172408
|
const server = await serveStaticProjectHtml(projectDir, html);
|
|
172143
172409
|
const savedPaths = [];
|
|
172144
172410
|
try {
|
|
@@ -172213,6 +172479,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
172213
172479
|
syncVideoFrameVisibility2 = engine.syncVideoFrameVisibility;
|
|
172214
172480
|
extractMediaMetadata2 = engine.extractMediaMetadata;
|
|
172215
172481
|
} catch {
|
|
172482
|
+
console.warn(
|
|
172483
|
+
` ${c.warn("\u26A0")} @hyperframes/engine unavailable \u2014 <video> elements will appear black in snapshots. Verify media via a draft render's extracted frames instead.`
|
|
172484
|
+
);
|
|
172216
172485
|
}
|
|
172217
172486
|
const alphaDecoderCache = /* @__PURE__ */ new Map();
|
|
172218
172487
|
const shouldUseVp9AlphaDecoder = (filePath) => {
|
|
@@ -172285,6 +172554,12 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
172285
172554
|
dataUri: `data:image/png;base64,${png.toString("base64")}`
|
|
172286
172555
|
});
|
|
172287
172556
|
}
|
|
172557
|
+
if (active.length > 0 && updates.length < active.length) {
|
|
172558
|
+
const missed = active.length - updates.length;
|
|
172559
|
+
console.warn(
|
|
172560
|
+
` ${c.warn("\u26A0")} ${missed}/${active.length} active <video> frame(s) could not be extracted at ${time.toFixed(1)}s \u2014 those videos will appear black/stale in this snapshot`
|
|
172561
|
+
);
|
|
172562
|
+
}
|
|
172288
172563
|
try {
|
|
172289
172564
|
if (updates.length > 0) {
|
|
172290
172565
|
await injectVideoFramesBatch2(page, updates);
|
|
@@ -172294,6 +172569,9 @@ async function captureSnapshots(projectDir, opts) {
|
|
|
172294
172569
|
active.map((a) => a.id)
|
|
172295
172570
|
);
|
|
172296
172571
|
} catch {
|
|
172572
|
+
console.warn(
|
|
172573
|
+
` ${c.warn("\u26A0")} video frame injection failed at ${time.toFixed(1)}s \u2014 <video> elements will appear black/stale in this snapshot`
|
|
172574
|
+
);
|
|
172297
172575
|
}
|
|
172298
172576
|
}
|
|
172299
172577
|
const timeLabel = `${time.toFixed(1)}s`;
|