hyperframes 0.8.8 → 0.8.10

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 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.8" : "0.0.0-dev";
53
+ VERSION = true ? "0.8.10" : "0.0.0-dev";
54
54
  }
55
55
  });
56
56
 
@@ -58829,17 +58829,17 @@ function isSafePath(base2, resolved2) {
58829
58829
  }
58830
58830
  const target = resolve4(resolved2);
58831
58831
  const trailing = [];
58832
- let probe = target;
58832
+ let probe2 = target;
58833
58833
  for (; ; ) {
58834
58834
  let ancestorReal;
58835
58835
  try {
58836
- ancestorReal = realpathSync(probe);
58836
+ ancestorReal = realpathSync(probe2);
58837
58837
  } catch {
58838
- const parent = dirname3(probe);
58839
- if (parent === probe)
58838
+ const parent = dirname3(probe2);
58839
+ if (parent === probe2)
58840
58840
  return false;
58841
- trailing.push(basename(probe));
58842
- probe = parent;
58841
+ trailing.push(basename(probe2));
58842
+ probe2 = parent;
58843
58843
  continue;
58844
58844
  }
58845
58845
  const targetReal = trailing.length ? join2(ancestorReal, ...[...trailing].reverse()) : ancestorReal;
@@ -63261,9 +63261,9 @@ function createRuntimeStartTimeResolver(params) {
63261
63261
  return typeof HTMLMediaElement !== "undefined" && el instanceof HTMLMediaElement;
63262
63262
  };
63263
63263
  const resolveDurationForElement = (element) => {
63264
- const cached2 = durationCache.get(element);
63265
- if (cached2 !== void 0)
63266
- return cached2;
63264
+ const cached3 = durationCache.get(element);
63265
+ if (cached3 !== void 0)
63266
+ return cached3;
63267
63267
  let resolved2 = null;
63268
63268
  const durationAttr = parseDurationAttr(element) ?? (includeAuthoredTimingAttrs ? parseAuthoredDurationAttr(element) : null);
63269
63269
  if (durationAttr != null && durationAttr > 0) {
@@ -63321,9 +63321,9 @@ function createRuntimeStartTimeResolver(params) {
63321
63321
  return resolveStartForElementInternal(compositionRoot2, fallback);
63322
63322
  };
63323
63323
  const resolveStartForElementInternal = (element, fallback) => {
63324
- const cached2 = startCache.get(element);
63325
- if (cached2 !== void 0) {
63326
- return cached2 == null ? fallback : cached2;
63324
+ const cached3 = startCache.get(element);
63325
+ if (cached3 !== void 0) {
63326
+ return cached3 == null ? fallback : cached3;
63327
63327
  }
63328
63328
  if (visiting.has(element)) {
63329
63329
  return fallback;
@@ -65570,16 +65570,16 @@ async function launchBrowser(fingerprint) {
65570
65570
  `[BrowserManager] Browser launched (${browserVersion}, ${captureMode}, gl=${gpuFlags.join(" ") || "default"}, headlessShell=${!!fingerprint.executablePath}, platform=${process.platform})`
65571
65571
  );
65572
65572
  if (captureMode === "beginframe") {
65573
- const probe = await probeBeginFrameSupport(browser).catch((error) => ({
65573
+ const probe2 = await probeBeginFrameSupport(browser).catch((error) => ({
65574
65574
  supported: true,
65575
65575
  detail: `probe harness error ignored: ${error instanceof Error ? error.message : String(error)}`,
65576
65576
  durationMs: 0
65577
65577
  }));
65578
- if (!probe.supported) {
65578
+ if (!probe2.supported) {
65579
65579
  await closeBrowserAfterFailedProbe(browser);
65580
65580
  browser = void 0;
65581
65581
  console.warn(
65582
- `[BrowserManager] HeadlessExperimental.beginFrame probe failed after ${probe.durationMs}ms: ${probe.detail}; falling back to screenshot mode.`
65582
+ `[BrowserManager] HeadlessExperimental.beginFrame probe failed after ${probe2.durationMs}ms: ${probe2.detail}; falling back to screenshot mode.`
65583
65583
  );
65584
65584
  captureMode = "screenshot";
65585
65585
  browser = await ppt.launch({
@@ -65935,9 +65935,9 @@ async function beginFrameCapture(page, options, frameTimeTicks, interval) {
65935
65935
  buffer = Buffer.from(result.screenshotData, "base64");
65936
65936
  lastFrameCache.set(page, buffer);
65937
65937
  } else {
65938
- const cached2 = lastFrameCache.get(page);
65939
- if (cached2) {
65940
- buffer = cached2;
65938
+ const cached3 = lastFrameCache.get(page);
65939
+ if (cached3) {
65940
+ buffer = cached3;
65941
65941
  } else {
65942
65942
  const fallback = await sendBeginFrame(client, {
65943
65943
  frameTimeTicks: frameTimeTicks + 1e-3,
@@ -67726,6 +67726,169 @@ var init_threeDProjection = __esm({
67726
67726
  }
67727
67727
  });
67728
67728
 
67729
+ // ../parsers/dist/ffBinaries.js
67730
+ import { execFileSync } from "child_process";
67731
+ import { accessSync, constants, existsSync as existsSync4 } from "fs";
67732
+ import { delimiter, join as join6, resolve as resolve5 } from "path";
67733
+ function candidateFileName(candidate) {
67734
+ return candidate.split(/[\\/]/).at(-1)?.toLowerCase() ?? candidate.toLowerCase();
67735
+ }
67736
+ function chooseBestPathCandidate(name, candidates) {
67737
+ const normalized2 = candidates.map((candidate) => candidate.trim()).filter(Boolean);
67738
+ return normalized2.find((candidate) => candidateFileName(candidate) === `${name}.exe`) ?? normalized2.find((candidate) => candidateFileName(candidate) === name) ?? normalized2.find((candidate) => !candidateFileName(candidate).match(/\.(cmd|bat)$/i)) ?? normalized2[0];
67739
+ }
67740
+ function isExecutablePathCandidate(candidate) {
67741
+ if (process.platform === "win32") return existsSync4(candidate);
67742
+ try {
67743
+ accessSync(candidate, constants.X_OK);
67744
+ return true;
67745
+ } catch {
67746
+ return false;
67747
+ }
67748
+ }
67749
+ function scanPath(name) {
67750
+ const pathValue = process.env.PATH;
67751
+ const searchDirs = [
67752
+ ...process.platform === "win32" ? [process.cwd()] : [],
67753
+ ...pathValue ? pathValue.split(delimiter) : []
67754
+ ].filter(Boolean);
67755
+ if (searchDirs.length === 0) return void 0;
67756
+ const extensions = process.platform === "win32" ? [
67757
+ ".exe",
67758
+ ...new Set(
67759
+ (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((ext) => ext.trim().toLowerCase()).filter(Boolean)
67760
+ ),
67761
+ ""
67762
+ ] : [""];
67763
+ const candidates = [];
67764
+ for (const dir of new Set(searchDirs)) {
67765
+ for (const ext of extensions) {
67766
+ const candidate = join6(dir, `${name}${ext}`);
67767
+ if (isExecutablePathCandidate(candidate)) candidates.push(candidate);
67768
+ }
67769
+ }
67770
+ return chooseBestPathCandidate(name, candidates);
67771
+ }
67772
+ function findInCommonDirs(name) {
67773
+ for (const dir of COMMON_BIN_DIRS) {
67774
+ const candidate = `${dir}/${name}`;
67775
+ if (existsSync4(candidate)) return candidate;
67776
+ }
67777
+ return void 0;
67778
+ }
67779
+ function findInProjectLocalBin(name) {
67780
+ const extension2 = process.platform === "win32" ? ".exe" : "";
67781
+ const candidate = resolve5(".hyperframes", "bin", `${name}${extension2}`);
67782
+ return existsSync4(candidate) ? candidate : void 0;
67783
+ }
67784
+ function lookupOnSystem(name) {
67785
+ if (pathLookupCache.has(name)) return pathLookupCache.get(name);
67786
+ let found;
67787
+ if (process.platform === "win32") {
67788
+ found = scanPath(name);
67789
+ } else {
67790
+ try {
67791
+ const output = execFileSync("which", [name], {
67792
+ encoding: "utf-8",
67793
+ stdio: ["pipe", "pipe", "pipe"],
67794
+ timeout: 5e3
67795
+ });
67796
+ const candidate = chooseBestPathCandidate(name, output.split(/\r?\n/));
67797
+ found = candidate && isExecutablePathCandidate(candidate) ? candidate : scanPath(name);
67798
+ } catch {
67799
+ found = scanPath(name);
67800
+ }
67801
+ }
67802
+ found ??= findInProjectLocalBin(name);
67803
+ found ??= findInCommonDirs(name);
67804
+ const resolved2 = found ? resolve5(found) : void 0;
67805
+ pathLookupCache.set(name, resolved2);
67806
+ return resolved2;
67807
+ }
67808
+ function findFfBinary(name, options = {}) {
67809
+ const configured = process.env[ENV_BY_NAME[name]]?.trim();
67810
+ if (configured) {
67811
+ if (options.configuredMustExist && !existsSync4(configured)) return void 0;
67812
+ return resolve5(configured);
67813
+ }
67814
+ return lookupOnSystem(name);
67815
+ }
67816
+ var FFMPEG_PATH_ENV, FFPROBE_PATH_ENV, ENV_BY_NAME, pathLookupCache, COMMON_BIN_DIRS;
67817
+ var init_ffBinaries = __esm({
67818
+ "../parsers/dist/ffBinaries.js"() {
67819
+ "use strict";
67820
+ FFMPEG_PATH_ENV = "HYPERFRAMES_FFMPEG_PATH";
67821
+ FFPROBE_PATH_ENV = "HYPERFRAMES_FFPROBE_PATH";
67822
+ ENV_BY_NAME = {
67823
+ ffmpeg: FFMPEG_PATH_ENV,
67824
+ ffprobe: FFPROBE_PATH_ENV
67825
+ };
67826
+ pathLookupCache = /* @__PURE__ */ new Map();
67827
+ COMMON_BIN_DIRS = process.platform === "win32" ? [] : ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin", "/snap/bin"];
67828
+ }
67829
+ });
67830
+
67831
+ // ../engine/src/utils/ffmpegBinaries.ts
67832
+ import { existsSync as existsSync5 } from "fs";
67833
+ function getFfmpegBinary() {
67834
+ return findFfBinary("ffmpeg") ?? "ffmpeg";
67835
+ }
67836
+ function getFfprobeBinary() {
67837
+ return findFfBinary("ffprobe") ?? "ffprobe";
67838
+ }
67839
+ function assertConfiguredFfmpegBinariesExist() {
67840
+ const ffmpegPath = process.env[FFMPEG_PATH_ENV]?.trim();
67841
+ if (ffmpegPath && !existsSync5(ffmpegPath)) {
67842
+ throw new Error(
67843
+ `[FFmpeg] FFmpeg binary not found at ${FFMPEG_PATH_ENV}="${ffmpegPath}". Install FFmpeg or unset the override.${pathEncodingHint(ffmpegPath)}`
67844
+ );
67845
+ }
67846
+ const ffprobePath = process.env[FFPROBE_PATH_ENV]?.trim();
67847
+ if (ffprobePath && !existsSync5(ffprobePath)) {
67848
+ throw new Error(
67849
+ `[FFmpeg] FFprobe binary not found at ${FFPROBE_PATH_ENV}="${ffprobePath}". Install FFmpeg or unset the override.${pathEncodingHint(ffprobePath)}`
67850
+ );
67851
+ }
67852
+ }
67853
+ function pathEncodingHint(configuredPath) {
67854
+ if (!configuredPath.includes("\uFFFD")) return "";
67855
+ return " The path contains a Unicode replacement character, which usually means it was mangled while being copied or decoded.";
67856
+ }
67857
+ var init_ffmpegBinaries = __esm({
67858
+ "../engine/src/utils/ffmpegBinaries.ts"() {
67859
+ "use strict";
67860
+ init_ffBinaries();
67861
+ }
67862
+ });
67863
+
67864
+ // ../engine/src/utils/psnrFilterAvailability.ts
67865
+ import { execFile } from "child_process";
67866
+ import { promisify } from "util";
67867
+ function isPsnrFilterAvailable() {
67868
+ if (cached === null) cached = probe();
67869
+ return cached;
67870
+ }
67871
+ async function probe() {
67872
+ const execFileP = promisify(execFile);
67873
+ try {
67874
+ const { stdout: stdout2 } = await execFileP(getFfmpegBinary(), ["-hide_banner", "-filters"], {
67875
+ maxBuffer: 4 * 1024 * 1024,
67876
+ timeout: 5e3
67877
+ });
67878
+ return /(^|\s)psnr(\s|$)/m.test(stdout2);
67879
+ } catch {
67880
+ return false;
67881
+ }
67882
+ }
67883
+ var cached;
67884
+ var init_psnrFilterAvailability = __esm({
67885
+ "../engine/src/utils/psnrFilterAvailability.ts"() {
67886
+ "use strict";
67887
+ init_ffmpegBinaries();
67888
+ cached = null;
67889
+ }
67890
+ });
67891
+
67729
67892
  // ../engine/src/services/captureWarning.ts
67730
67893
  function cloneCaptureWarning(warning) {
67731
67894
  return {
@@ -67897,8 +68060,8 @@ var init_captureFailure = __esm({
67897
68060
  });
67898
68061
 
67899
68062
  // ../engine/src/services/frameCapture.ts
67900
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
67901
- import { join as join6 } from "path";
68063
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
68064
+ import { join as join7 } from "path";
67902
68065
  function isDrawElementVerificationError(err) {
67903
68066
  let e3 = err;
67904
68067
  for (let depth = 0; depth < 5 && typeof e3 === "object" && e3 !== null; depth++) {
@@ -68219,6 +68382,15 @@ async function initDrawElementOrTransparentBackground(session, page, logInitPhas
68219
68382
  await routeToFallback();
68220
68383
  return;
68221
68384
  }
68385
+ if (!forceDE && !await isPsnrFilterAvailable()) {
68386
+ session.deGateReason = "ffmpeg_no_psnr_filter";
68387
+ session.deFallbackTrigger = "ffmpeg_no_psnr_filter";
68388
+ console.warn(
68389
+ `[engine] fast capture: falling back to ${session.launchCaptureMode} capture \u2014 host ffmpeg is missing or was built without the \`psnr\` filter (libpostproc), so drawElement self-verification cannot run. Install an ffmpeg build that includes libpostproc (or set HYPERFRAMES_FFMPEG_PATH to one) to re-enable fast capture.`
68390
+ );
68391
+ await routeToFallback();
68392
+ return;
68393
+ }
68222
68394
  const mode = resolveDrawElementCaptureMode(session.isSwiftShader, transparent);
68223
68395
  if (mode === "screenshot") {
68224
68396
  session.deGateReason = "swiftshader";
@@ -68329,7 +68501,7 @@ async function completeDeferredDrawElementInit(session) {
68329
68501
  session.deInitDeferred = false;
68330
68502
  }
68331
68503
  async function createCaptureSession(serverUrl, outputDir, options, onBeforeCapture = null, config) {
68332
- if (!existsSync4(outputDir)) mkdirSync2(outputDir, { recursive: true });
68504
+ if (!existsSync6(outputDir)) mkdirSync2(outputDir, { recursive: true });
68333
68505
  const headlessShell = resolveHeadlessShellPath(config);
68334
68506
  const isLinux = process.platform === "linux";
68335
68507
  const forceScreenshot = config?.forceScreenshot ?? DEFAULT_CONFIG2.forceScreenshot;
@@ -69092,9 +69264,9 @@ async function initializeSession(session) {
69092
69264
  }
69093
69265
  async function captureFrameErrorDiagnostics(session, frameIndex, time, error) {
69094
69266
  try {
69095
- const diagnosticsDir = join6(session.outputDir, "diagnostics");
69096
- if (!existsSync4(diagnosticsDir)) mkdirSync2(diagnosticsDir, { recursive: true });
69097
- const base2 = join6(diagnosticsDir, `frame-error-${frameIndex}`);
69267
+ const diagnosticsDir = join7(session.outputDir, "diagnostics");
69268
+ if (!existsSync6(diagnosticsDir)) mkdirSync2(diagnosticsDir, { recursive: true });
69269
+ const base2 = join7(diagnosticsDir, `frame-error-${frameIndex}`);
69098
69270
  await session.page.screenshot({ path: `${base2}.png`, type: "png", fullPage: true });
69099
69271
  const html = await session.page.content();
69100
69272
  writeFileSync2(`${base2}.html`, html, "utf-8");
@@ -69593,7 +69765,7 @@ async function captureFrame(session, frameIndex, time) {
69593
69765
  }
69594
69766
  function writeCapturedFrame(session, fileIndex, buffer) {
69595
69767
  const ext = session.options.format === "png" ? "png" : "jpg";
69596
- const framePath = join6(session.outputDir, `frame_${String(fileIndex).padStart(6, "0")}.${ext}`);
69768
+ const framePath = join7(session.outputDir, `frame_${String(fileIndex).padStart(6, "0")}.${ext}`);
69597
69769
  writeFileSync2(framePath, buffer);
69598
69770
  return framePath;
69599
69771
  }
@@ -69800,7 +69972,7 @@ async function closeCaptureSession(session) {
69800
69972
  session.isInitialized = false;
69801
69973
  }
69802
69974
  function prepareCaptureSessionForReuse(session, outputDir, onBeforeCapture) {
69803
- if (!existsSync4(outputDir)) {
69975
+ if (!existsSync6(outputDir)) {
69804
69976
  mkdirSync2(outputDir, { recursive: true });
69805
69977
  }
69806
69978
  session.outputDir = outputDir;
@@ -69935,6 +70107,7 @@ var init_frameCapture = __esm({
69935
70107
  init_screenshotService();
69936
70108
  init_drawElementService();
69937
70109
  init_threeDProjection();
70110
+ init_psnrFilterAvailability();
69938
70111
  init_config2();
69939
70112
  init_captureWarning();
69940
70113
  init_mediaRenderIdBridge();
@@ -69993,141 +70166,6 @@ var init_frameCapture = __esm({
69993
70166
  }
69994
70167
  });
69995
70168
 
69996
- // ../parsers/dist/ffBinaries.js
69997
- import { execFileSync } from "child_process";
69998
- import { accessSync, constants, existsSync as existsSync5 } from "fs";
69999
- import { delimiter, join as join7, resolve as resolve5 } from "path";
70000
- function candidateFileName(candidate) {
70001
- return candidate.split(/[\\/]/).at(-1)?.toLowerCase() ?? candidate.toLowerCase();
70002
- }
70003
- function chooseBestPathCandidate(name, candidates) {
70004
- const normalized2 = candidates.map((candidate) => candidate.trim()).filter(Boolean);
70005
- return normalized2.find((candidate) => candidateFileName(candidate) === `${name}.exe`) ?? normalized2.find((candidate) => candidateFileName(candidate) === name) ?? normalized2.find((candidate) => !candidateFileName(candidate).match(/\.(cmd|bat)$/i)) ?? normalized2[0];
70006
- }
70007
- function isExecutablePathCandidate(candidate) {
70008
- if (process.platform === "win32") return existsSync5(candidate);
70009
- try {
70010
- accessSync(candidate, constants.X_OK);
70011
- return true;
70012
- } catch {
70013
- return false;
70014
- }
70015
- }
70016
- function scanPath(name) {
70017
- const pathValue = process.env.PATH;
70018
- const searchDirs = [
70019
- ...process.platform === "win32" ? [process.cwd()] : [],
70020
- ...pathValue ? pathValue.split(delimiter) : []
70021
- ].filter(Boolean);
70022
- if (searchDirs.length === 0) return void 0;
70023
- const extensions = process.platform === "win32" ? [
70024
- ".exe",
70025
- ...new Set(
70026
- (process.env.PATHEXT ?? ".COM;.EXE;.BAT;.CMD").split(";").map((ext) => ext.trim().toLowerCase()).filter(Boolean)
70027
- ),
70028
- ""
70029
- ] : [""];
70030
- const candidates = [];
70031
- for (const dir of new Set(searchDirs)) {
70032
- for (const ext of extensions) {
70033
- const candidate = join7(dir, `${name}${ext}`);
70034
- if (isExecutablePathCandidate(candidate)) candidates.push(candidate);
70035
- }
70036
- }
70037
- return chooseBestPathCandidate(name, candidates);
70038
- }
70039
- function findInCommonDirs(name) {
70040
- for (const dir of COMMON_BIN_DIRS) {
70041
- const candidate = `${dir}/${name}`;
70042
- if (existsSync5(candidate)) return candidate;
70043
- }
70044
- return void 0;
70045
- }
70046
- function findInProjectLocalBin(name) {
70047
- const extension2 = process.platform === "win32" ? ".exe" : "";
70048
- const candidate = resolve5(".hyperframes", "bin", `${name}${extension2}`);
70049
- return existsSync5(candidate) ? candidate : void 0;
70050
- }
70051
- function lookupOnSystem(name) {
70052
- if (pathLookupCache.has(name)) return pathLookupCache.get(name);
70053
- let found;
70054
- if (process.platform === "win32") {
70055
- found = scanPath(name);
70056
- } else {
70057
- try {
70058
- const output = execFileSync("which", [name], {
70059
- encoding: "utf-8",
70060
- stdio: ["pipe", "pipe", "pipe"],
70061
- timeout: 5e3
70062
- });
70063
- const candidate = chooseBestPathCandidate(name, output.split(/\r?\n/));
70064
- found = candidate && isExecutablePathCandidate(candidate) ? candidate : scanPath(name);
70065
- } catch {
70066
- found = scanPath(name);
70067
- }
70068
- }
70069
- found ??= findInProjectLocalBin(name);
70070
- found ??= findInCommonDirs(name);
70071
- const resolved2 = found ? resolve5(found) : void 0;
70072
- pathLookupCache.set(name, resolved2);
70073
- return resolved2;
70074
- }
70075
- function findFfBinary(name, options = {}) {
70076
- const configured = process.env[ENV_BY_NAME[name]]?.trim();
70077
- if (configured) {
70078
- if (options.configuredMustExist && !existsSync5(configured)) return void 0;
70079
- return resolve5(configured);
70080
- }
70081
- return lookupOnSystem(name);
70082
- }
70083
- var FFMPEG_PATH_ENV, FFPROBE_PATH_ENV, ENV_BY_NAME, pathLookupCache, COMMON_BIN_DIRS;
70084
- var init_ffBinaries = __esm({
70085
- "../parsers/dist/ffBinaries.js"() {
70086
- "use strict";
70087
- FFMPEG_PATH_ENV = "HYPERFRAMES_FFMPEG_PATH";
70088
- FFPROBE_PATH_ENV = "HYPERFRAMES_FFPROBE_PATH";
70089
- ENV_BY_NAME = {
70090
- ffmpeg: FFMPEG_PATH_ENV,
70091
- ffprobe: FFPROBE_PATH_ENV
70092
- };
70093
- pathLookupCache = /* @__PURE__ */ new Map();
70094
- COMMON_BIN_DIRS = process.platform === "win32" ? [] : ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin", "/snap/bin"];
70095
- }
70096
- });
70097
-
70098
- // ../engine/src/utils/ffmpegBinaries.ts
70099
- import { existsSync as existsSync6 } from "fs";
70100
- function getFfmpegBinary() {
70101
- return findFfBinary("ffmpeg") ?? "ffmpeg";
70102
- }
70103
- function getFfprobeBinary() {
70104
- return findFfBinary("ffprobe") ?? "ffprobe";
70105
- }
70106
- function assertConfiguredFfmpegBinariesExist() {
70107
- const ffmpegPath = process.env[FFMPEG_PATH_ENV]?.trim();
70108
- if (ffmpegPath && !existsSync6(ffmpegPath)) {
70109
- throw new Error(
70110
- `[FFmpeg] FFmpeg binary not found at ${FFMPEG_PATH_ENV}="${ffmpegPath}". Install FFmpeg or unset the override.${pathEncodingHint(ffmpegPath)}`
70111
- );
70112
- }
70113
- const ffprobePath = process.env[FFPROBE_PATH_ENV]?.trim();
70114
- if (ffprobePath && !existsSync6(ffprobePath)) {
70115
- throw new Error(
70116
- `[FFmpeg] FFprobe binary not found at ${FFPROBE_PATH_ENV}="${ffprobePath}". Install FFmpeg or unset the override.${pathEncodingHint(ffprobePath)}`
70117
- );
70118
- }
70119
- }
70120
- function pathEncodingHint(configuredPath) {
70121
- if (!configuredPath.includes("\uFFFD")) return "";
70122
- return " The path contains a Unicode replacement character, which usually means it was mangled while being copied or decoded.";
70123
- }
70124
- var init_ffmpegBinaries = __esm({
70125
- "../engine/src/utils/ffmpegBinaries.ts"() {
70126
- "use strict";
70127
- init_ffBinaries();
70128
- }
70129
- });
70130
-
70131
70169
  // ../engine/src/utils/managedChildProcess.ts
70132
70170
  var DEFAULT_TERMINATION_GRACE_MS, DEFAULT_STDERR_MAX_BYTES, ManagedChildProcess;
70133
70171
  var init_managedChildProcess = __esm({
@@ -70754,13 +70792,13 @@ async function probeMediaOutput(filePath, signal) {
70754
70792
  mediaProbeOutputSignalCaches.set(signal, cache2);
70755
70793
  }
70756
70794
  const identity = mediaFileIdentity(filePath);
70757
- const cached2 = cache2.get(filePath);
70758
- if (identity !== null && cached2?.identity === identity) {
70795
+ const cached3 = cache2.get(filePath);
70796
+ if (identity !== null && cached3?.identity === identity) {
70759
70797
  if (!signal) {
70760
70798
  cache2.delete(filePath);
70761
- cache2.set(filePath, cached2);
70799
+ cache2.set(filePath, cached3);
70762
70800
  }
70763
- return cached2.promise;
70801
+ return cached3.promise;
70764
70802
  }
70765
70803
  const promise = runFfprobe(
70766
70804
  filePath,
@@ -70943,8 +70981,8 @@ function parseFrameRate(frameRateStr) {
70943
70981
  return rounded > 0 ? rounded : 0.01;
70944
70982
  }
70945
70983
  async function extractMediaMetadata(filePath) {
70946
- const cached2 = videoMetadataCache.get(filePath);
70947
- if (cached2) return cached2;
70984
+ const cached3 = videoMetadataCache.get(filePath);
70985
+ if (cached3) return cached3;
70948
70986
  const probePromise = (async () => {
70949
70987
  let stillImageMetaMemo;
70950
70988
  const stillImage = () => {
@@ -71030,8 +71068,8 @@ async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
71030
71068
  probeCache = finalVideoFrameTimestampSignalCaches.get(signal) ?? /* @__PURE__ */ new Map();
71031
71069
  finalVideoFrameTimestampSignalCaches.set(signal, probeCache);
71032
71070
  }
71033
- const cached2 = probeCache.get(cacheKey);
71034
- if (cached2) return cached2;
71071
+ const cached3 = probeCache.get(cacheKey);
71072
+ if (cached3) return cached3;
71035
71073
  const probePromise = (async () => {
71036
71074
  if (!(videoDurationSeconds > 0) || !Number.isFinite(videoDurationSeconds)) {
71037
71075
  throw new Error(
@@ -71041,7 +71079,7 @@ async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
71041
71079
  const streamEnd = videoStreamStartSeconds + videoDurationSeconds;
71042
71080
  const intervalStart = Math.max(videoStreamStartSeconds, streamEnd - 1);
71043
71081
  const parseFinalTimestamp = (stdout2) => stdout2.split("\n").map((line2) => line2.trim().split(",")[0]?.trim() ?? "").filter((value) => value.length > 0).map((value) => Number(value)).filter((timestamp2) => Number.isFinite(timestamp2)).at(-1);
71044
- const probe = async (readInterval) => {
71082
+ const probe2 = async (readInterval) => {
71045
71083
  const args = [
71046
71084
  "-select_streams",
71047
71085
  "v:0",
@@ -71057,7 +71095,7 @@ async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
71057
71095
  });
71058
71096
  return parseFinalTimestamp(stdout2);
71059
71097
  };
71060
- const timestamp = await probe(`${intervalStart}%${streamEnd}`) ?? await probe(
71098
+ const timestamp = await probe2(`${intervalStart}%${streamEnd}`) ?? await probe2(
71061
71099
  /* full scan */
71062
71100
  );
71063
71101
  if (timestamp === void 0) {
@@ -71074,8 +71112,8 @@ async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
71074
71112
  return probePromise;
71075
71113
  }
71076
71114
  async function extractAudioMetadata(filePath, options) {
71077
- const cached2 = options?.signal ? void 0 : audioMetadataCache.get(filePath);
71078
- if (cached2) return cached2;
71115
+ const cached3 = options?.signal ? void 0 : audioMetadataCache.get(filePath);
71116
+ if (cached3) return cached3;
71079
71117
  const probePromise = (async () => {
71080
71118
  const output = await probeMediaOutput(filePath, options?.signal);
71081
71119
  const audioStream = output.streams.find((s2) => s2.codec_type === "audio");
@@ -71128,8 +71166,8 @@ async function extractAudioMetadata(filePath, options) {
71128
71166
  return probePromise;
71129
71167
  }
71130
71168
  async function analyzeKeyframeIntervals(filePath) {
71131
- const cached2 = keyframeCache.get(filePath);
71132
- if (cached2) return cached2;
71169
+ const cached3 = keyframeCache.get(filePath);
71170
+ if (cached3) return cached3;
71133
71171
  const promise = analyzeKeyframeIntervalsUncached(filePath);
71134
71172
  keyframeCache.set(filePath, promise);
71135
71173
  promise.catch(() => {
@@ -72148,8 +72186,8 @@ function findReferenceTargetEl(doc, refId) {
72148
72186
  return doc.getElementById(refId) ?? doc.querySelector(`[data-composition-id="${refId}"]`);
72149
72187
  }
72150
72188
  function resolveReferencedStart(doc, el, startCache, visiting) {
72151
- const cached2 = startCache.get(el);
72152
- if (cached2 !== void 0) return cached2;
72189
+ const cached3 = startCache.get(el);
72190
+ if (cached3 !== void 0) return cached3;
72153
72191
  if (visiting.has(el)) return 0;
72154
72192
  visiting.add(el);
72155
72193
  try {
@@ -79632,7 +79670,7 @@ import postcss22 from "postcss";
79632
79670
  import { createHash as createHash2 } from "crypto";
79633
79671
  import { existsSync as existsSync22, readFileSync as readFileSync4, readdirSync as readdirSync4 } from "fs";
79634
79672
  import { dirname as dirname7, extname as extname3, join as join22, relative as relative3, resolve as resolve8 } from "path";
79635
- import { execFile } from "child_process";
79673
+ import { execFile as execFile2 } from "child_process";
79636
79674
  import { existsSync as existsSync11 } from "fs";
79637
79675
  import { join as join10 } from "path";
79638
79676
  function parseHtmlStructure(source) {
@@ -80372,8 +80410,8 @@ function synthesizeWindowRaw(timelineVar, anim) {
80372
80410
  return `${timelineVar}.${anim.method}("${anim.targetSelector}", { ${entries2.join(", ")} }, ${pos})`;
80373
80411
  }
80374
80412
  async function cachedExtractGsapWindows(scriptContent) {
80375
- const cached2 = gsapWindowsCache.get(scriptContent);
80376
- if (cached2) return cached2;
80413
+ const cached3 = gsapWindowsCache.get(scriptContent);
80414
+ if (cached3) return cached3;
80377
80415
  const windows = await extractGsapWindows(scriptContent);
80378
80416
  gsapWindowsCache.set(scriptContent, windows);
80379
80417
  return windows;
@@ -81493,7 +81531,7 @@ function shouldBlockRender(strictErrors, strictAll, totalErrors, totalWarnings)
81493
81531
  }
81494
81532
  function execFileAsync(file, args) {
81495
81533
  return new Promise((resolvePromise, reject2) => {
81496
- execFile(file, args, { timeout: PROBE_TIMEOUT_MS }, (error, stdout2) => {
81534
+ execFile2(file, args, { timeout: PROBE_TIMEOUT_MS }, (error, stdout2) => {
81497
81535
  if (error) reject2(error);
81498
81536
  else resolvePromise(stdout2.toString());
81499
81537
  });
@@ -88080,10 +88118,10 @@ function createFrameSourceCache(entryLimit, bytesLimit, frameSrcResolver) {
88080
88118
  async function get(framePath) {
88081
88119
  const servedSrc = frameSrcResolver?.(framePath);
88082
88120
  if (servedSrc) return servedSrc;
88083
- const cached2 = cache2.get(framePath);
88084
- if (cached2) {
88085
- remember(framePath, cached2);
88086
- return cached2;
88121
+ const cached3 = cache2.get(framePath);
88122
+ if (cached3) {
88123
+ remember(framePath, cached3);
88124
+ return cached3;
88087
88125
  }
88088
88126
  const existing = inFlight2.get(framePath);
88089
88127
  if (existing) {
@@ -89986,13 +90024,13 @@ var init_audioMixer = __esm({
89986
90024
  });
89987
90025
 
89988
90026
  // ../engine/src/utils/psnr.ts
89989
- import { execFile as execFile2 } from "child_process";
90027
+ import { execFile as execFile3 } from "child_process";
89990
90028
  import { mkdtemp, rm, writeFile } from "fs/promises";
89991
90029
  import { tmpdir as tmpdir3 } from "os";
89992
90030
  import { join as join15 } from "path";
89993
- import { promisify } from "util";
90031
+ import { promisify as promisify2 } from "util";
89994
90032
  async function psnrDb(a, b2) {
89995
- const execFileP = promisify(execFile2);
90033
+ const execFileP = promisify2(execFile3);
89996
90034
  const dir = await mkdtemp(join15(tmpdir3(), "hf-de-verify-"));
89997
90035
  try {
89998
90036
  const pa = join15(dir, "a.jpg");
@@ -90347,10 +90385,27 @@ function assertDiskSampleAboveFloor(db, verifyMinDb, idx, workerId) {
90347
90385
  `[Parallel] drawElement disk self-verify passed (worker ${workerId}, frame ${idx}, ${db === Infinity ? "inf" : db.toFixed(1)}dB)`
90348
90386
  );
90349
90387
  }
90388
+ function isFfmpegInfrastructureFailure(err) {
90389
+ if (!err || typeof err !== "object") return false;
90390
+ const record = err;
90391
+ if (record.code === "ENOENT") return true;
90392
+ const message = typeof record.message === "string" ? record.message : "";
90393
+ const stderr = typeof record.stderr === "string" ? record.stderr : "";
90394
+ const text2 = `${message}
90395
+ ${stderr}`;
90396
+ return /\bENOENT\b|No such filter|Unknown filter/i.test(text2);
90397
+ }
90350
90398
  async function psnrForDiskSample(framePath, truth, workerId, idx) {
90351
90399
  try {
90352
90400
  return await psnrDb(await readFile(framePath), truth);
90353
90401
  } catch (err) {
90402
+ if (isFfmpegInfrastructureFailure(err)) {
90403
+ const detail = err instanceof Error ? err.message : String(err);
90404
+ throw new Error(
90405
+ `[Parallel] drawElement disk self-verify aborted (worker ${workerId}, frame ${idx}): ffmpeg or the \`psnr\` filter is unavailable \u2014 ${detail}. The preflight in initDrawElementOrTransparentBackground normally catches this at bootstrap; if you hit this after a successful preflight, ffmpeg was replaced mid-render or HYPERFRAMES_FFMPEG_PATH now points at a different binary.`,
90406
+ { cause: err }
90407
+ );
90408
+ }
90354
90409
  console.warn(
90355
90410
  `[Parallel] drawElement disk self-verify sample skipped (worker ${workerId}, frame ${idx}): ${err instanceof Error ? err.message : String(err)}`
90356
90411
  );
@@ -92792,12 +92847,12 @@ function bytesToMb(bytes) {
92792
92847
  return Math.trunc(bytes / (1024 * 1024));
92793
92848
  }
92794
92849
  function getSystemMeta() {
92795
- if (cached) return cached;
92850
+ if (cached2) return cached2;
92796
92851
  const cpuInfo = cpus2();
92797
92852
  const firstCpu = cpuInfo[0] ?? null;
92798
92853
  const agent_runtime = detectAgentRuntime();
92799
92854
  const hints = agent_runtime === null ? detectAgentHints() : { agent_hint: null, term_program: null, agent_env_hints: null };
92800
- cached = {
92855
+ cached2 = {
92801
92856
  os_release: release3(),
92802
92857
  cpu_count: cpuInfo.length,
92803
92858
  cpu_model: firstCpu?.model?.trim() ?? null,
@@ -92814,7 +92869,7 @@ function getSystemMeta() {
92814
92869
  term_program: hints.term_program,
92815
92870
  agent_env_hints: hints.agent_env_hints
92816
92871
  };
92817
- return cached;
92872
+ return cached2;
92818
92873
  }
92819
92874
  function detectDocker() {
92820
92875
  try {
@@ -92911,14 +92966,14 @@ function getAvailableMemoryMb() {
92911
92966
  }
92912
92967
  return fallback;
92913
92968
  }
92914
- var cached, CI_PROVIDERS;
92969
+ var cached2, CI_PROVIDERS;
92915
92970
  var init_system = __esm({
92916
92971
  "src/telemetry/system.ts"() {
92917
92972
  "use strict";
92918
92973
  init_src();
92919
92974
  init_agent_runtime();
92920
92975
  init_platform();
92921
- cached = null;
92976
+ cached2 = null;
92922
92977
  CI_PROVIDERS = [
92923
92978
  { name: "github_actions", envVar: "GITHUB_ACTIONS", mode: "truthy" },
92924
92979
  { name: "gitlab_ci", envVar: "GITLAB_CI", mode: "truthy" },
@@ -92968,8 +93023,8 @@ function resolveCanary(name) {
92968
93023
  decisions.clear();
92969
93024
  decisionsTelemetryPosture = posture;
92970
93025
  }
92971
- const cached2 = decisions.get(name);
92972
- if (cached2) return cached2;
93026
+ const cached3 = decisions.get(name);
93027
+ if (cached3) return cached3;
92973
93028
  const decision = decideCanary(name);
92974
93029
  decisions.set(name, decision);
92975
93030
  return decision;
@@ -95946,28 +96001,28 @@ async function fetchJson(url) {
95946
96001
  }
95947
96002
  async function fetchRegistryManifest(baseUrl = DEFAULT_REGISTRY_URL, options) {
95948
96003
  const cacheFile = cachePath(baseUrl, "registry");
95949
- const cached2 = readCacheEntry(cacheFile);
95950
- if (!options?.skipCache && cached2 && isFresh(cached2)) return cached2.data;
96004
+ const cached3 = readCacheEntry(cacheFile);
96005
+ if (!options?.skipCache && cached3 && isFresh(cached3)) return cached3.data;
95951
96006
  try {
95952
96007
  const manifest = await fetchJson(`${baseUrl}/registry.json`);
95953
96008
  writeCache(cacheFile, manifest);
95954
96009
  return manifest;
95955
96010
  } catch {
95956
- return cached2?.data;
96011
+ return cached3?.data;
95957
96012
  }
95958
96013
  }
95959
96014
  async function fetchItemManifest(name, type, baseUrl = DEFAULT_REGISTRY_URL) {
95960
96015
  const dir = ITEM_TYPE_DIRS[type];
95961
96016
  const cacheFile = cachePath(baseUrl, `${dir}__${name}`);
95962
- const cached2 = readCacheEntry(cacheFile);
95963
- if (cached2 && isFresh(cached2)) return cached2.data;
96017
+ const cached3 = readCacheEntry(cacheFile);
96018
+ if (cached3 && isFresh(cached3)) return cached3.data;
95964
96019
  const url = `${baseUrl}/${dir}/${name}/registry-item.json`;
95965
96020
  try {
95966
96021
  const item = await fetchJson(url);
95967
96022
  writeCache(cacheFile, item);
95968
96023
  return item;
95969
96024
  } catch (err) {
95970
- if (cached2) return cached2.data;
96025
+ if (cached3) return cached3.data;
95971
96026
  throw err;
95972
96027
  }
95973
96028
  }
@@ -98244,7 +98299,7 @@ var init_updateCheck = __esm({
98244
98299
  });
98245
98300
 
98246
98301
  // src/utils/skillsManifest.ts
98247
- import { execFile as execFile3 } from "child_process";
98302
+ import { execFile as execFile4 } from "child_process";
98248
98303
  import { createHash as createHash6 } from "crypto";
98249
98304
  import {
98250
98305
  existsSync as existsSync29,
@@ -98256,7 +98311,7 @@ import {
98256
98311
  } from "fs";
98257
98312
  import { homedir as homedir6 } from "os";
98258
98313
  import { isAbsolute as isAbsolute6, join as join27, relative as relative6, resolve as resolve13, sep as sep4 } from "path";
98259
- import { promisify as promisify2 } from "util";
98314
+ import { promisify as promisify3 } from "util";
98260
98315
  function isCoreSkill(name) {
98261
98316
  return name === ENTRY_SKILL || name.startsWith("hyperframes-") || name === "media-use";
98262
98317
  }
@@ -98549,7 +98604,7 @@ var execFileAsync2, TEXT_EXT, DEFAULT_REPO_SLUG, MANIFEST_FILE, FETCH_TIMEOUT_MS
98549
98604
  var init_skillsManifest = __esm({
98550
98605
  "src/utils/skillsManifest.ts"() {
98551
98606
  "use strict";
98552
- execFileAsync2 = promisify2(execFile3);
98607
+ execFileAsync2 = promisify3(execFile4);
98553
98608
  TEXT_EXT = /* @__PURE__ */ new Set([
98554
98609
  ".md",
98555
98610
  ".txt",
@@ -99668,29 +99723,29 @@ var init_lintFormat = __esm({
99668
99723
  // src/server/portUtils.ts
99669
99724
  import net from "net";
99670
99725
  import http from "http";
99671
- import { execFile as execFile4 } from "child_process";
99672
- import { promisify as promisify3 } from "util";
99726
+ import { execFile as execFile5 } from "child_process";
99727
+ import { promisify as promisify4 } from "util";
99673
99728
  import { resolve as resolve14 } from "path";
99674
99729
  async function isPortAvailableOnHost(port, host) {
99675
- const probe = net.createServer();
99676
- probe.unref();
99730
+ const probe2 = net.createServer();
99731
+ probe2.unref();
99677
99732
  const bindError = await new Promise((settle) => {
99678
99733
  const handleError = (err) => settle(err);
99679
- probe.once("error", handleError);
99680
- probe.listen({ port, host }, () => {
99681
- probe.removeListener("error", handleError);
99734
+ probe2.once("error", handleError);
99735
+ probe2.listen({ port, host }, () => {
99736
+ probe2.removeListener("error", handleError);
99682
99737
  settle(null);
99683
99738
  });
99684
99739
  });
99685
99740
  if (bindError !== null) {
99686
99741
  return bindError.code !== "EADDRINUSE";
99687
99742
  }
99688
- await new Promise((done) => probe.close(() => done()));
99743
+ await new Promise((done) => probe2.close(() => done()));
99689
99744
  return true;
99690
99745
  }
99691
- async function testPortOnAllHosts(port, probe = isPortAvailableOnHost) {
99746
+ async function testPortOnAllHosts(port, probe2 = isPortAvailableOnHost) {
99692
99747
  for (const host of PORT_PROBE_HOSTS) {
99693
- const available = await probe(port, host);
99748
+ const available = await probe2(port, host);
99694
99749
  if (!available) return false;
99695
99750
  }
99696
99751
  return true;
@@ -99927,7 +99982,7 @@ var execFileAsync3, MAX_PORT_SCAN, PROBE_TIMEOUT_MS2, PROBE_MAX_BYTES, PORT_PROB
99927
99982
  var init_portUtils = __esm({
99928
99983
  "src/server/portUtils.ts"() {
99929
99984
  "use strict";
99930
- execFileAsync3 = promisify3(execFile4);
99985
+ execFileAsync3 = promisify4(execFile5);
99931
99986
  MAX_PORT_SCAN = 100;
99932
99987
  PROBE_TIMEOUT_MS2 = 300;
99933
99988
  PROBE_MAX_BYTES = 4096;
@@ -101614,7 +101669,7 @@ var init_chunk_W2SBTCO2 = __esm({
101614
101669
  // ../studio-server/dist/chunk-6H3V3WGJ.js
101615
101670
  import { existsSync as existsSync34, statSync as statSync10 } from "fs";
101616
101671
  import { relative as relative8, resolve as resolve18, sep as sep5 } from "path";
101617
- import { execFile as execFile5 } from "child_process";
101672
+ import { execFile as execFile6 } from "child_process";
101618
101673
  import { extname as extname7 } from "path";
101619
101674
  function lower(value) {
101620
101675
  return value?.toLowerCase() ?? "";
@@ -101752,10 +101807,10 @@ async function probeAssetCodecCached(filePath, cache2, runner) {
101752
101807
  } catch {
101753
101808
  return null;
101754
101809
  }
101755
- const cached2 = cache2.get(filePath);
101756
- if (cached2 && cached2.mtimeMs === stat3.mtimeMs && cached2.size === stat3.size) {
101757
- rememberProbeResult(cache2, filePath, cached2);
101758
- return cached2.facts;
101810
+ const cached3 = cache2.get(filePath);
101811
+ if (cached3 && cached3.mtimeMs === stat3.mtimeMs && cached3.size === stat3.size) {
101812
+ rememberProbeResult(cache2, filePath, cached3);
101813
+ return cached3.facts;
101759
101814
  }
101760
101815
  const facts = await probeAssetCodec(filePath, runner);
101761
101816
  rememberProbeResult(cache2, filePath, { mtimeMs: stat3.mtimeMs, size: stat3.size, facts });
@@ -101822,7 +101877,7 @@ var init_chunk_6H3V3WGJ = __esm({
101822
101877
  init_assetResolution();
101823
101878
  init_ffBinaries();
101824
101879
  execFileRunner = (command2, args, options) => new Promise((resolvePromise) => {
101825
- execFile5(
101880
+ execFile6(
101826
101881
  command2,
101827
101882
  args,
101828
101883
  { timeout: options?.timeout, maxBuffer: options?.maxBuffer },
@@ -106262,9 +106317,9 @@ function locateSystemFont(family) {
106262
106317
  const normalized2 = normalizeName(family);
106263
106318
  if (!normalized2)
106264
106319
  return null;
106265
- const cached2 = cache.get(normalized2);
106266
- if (cached2 !== void 0)
106267
- return cached2;
106320
+ const cached3 = cache.get(normalized2);
106321
+ if (cached3 !== void 0)
106322
+ return cached3;
106268
106323
  let result = null;
106269
106324
  result = locateViaSystemProfiler(normalized2);
106270
106325
  if (!result) {
@@ -109280,8 +109335,8 @@ function createProjectSignature(projectDir) {
109280
109335
  collectProjectSignatureManifestFiles(normalizedProjectDir, files);
109281
109336
  files.sort((a, b2) => a.file.localeCompare(b2.file));
109282
109337
  const fingerprint = createProjectFingerprint(normalizedProjectDir, files);
109283
- const cached2 = projectSignatureCache.get(normalizedProjectDir);
109284
- if (cached2?.fingerprint === fingerprint) return cached2.signature;
109338
+ const cached3 = projectSignatureCache.get(normalizedProjectDir);
109339
+ if (cached3?.fingerprint === fingerprint) return cached3.signature;
109285
109340
  const hash2 = createHash9("sha256");
109286
109341
  for (const entry of files) {
109287
109342
  const relativePath = relative10(normalizedProjectDir, entry.file);
@@ -115339,20 +115394,15 @@ import { existsSync as existsSync41, readFileSync as readFileSync27 } from "fs";
115339
115394
  import { dirname as dirname16, resolve as resolve26 } from "path";
115340
115395
  import { fileURLToPath as fileURLToPath2 } from "url";
115341
115396
  function resolveHyperframeManifestPath() {
115342
- if (process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH) {
115343
- return process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH;
115397
+ const envOverride = process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH;
115398
+ if (envOverride) {
115399
+ return envOverride;
115344
115400
  }
115345
- const candidates = [
115346
- SIBLING_MANIFEST_PATH,
115347
- ...CWD_RELATIVE_MANIFEST_PATHS,
115348
- MODULE_RELATIVE_MANIFEST_PATH
115349
- ];
115350
- for (const candidate of candidates) {
115351
- if (existsSync41(candidate)) {
115352
- return candidate;
115353
- }
115354
- }
115355
- return MODULE_RELATIVE_MANIFEST_PATH;
115401
+ const found = MANIFEST_CANDIDATES.find((candidate) => existsSync41(candidate));
115402
+ return found ?? MODULE_RELATIVE_MANIFEST_PATH;
115403
+ }
115404
+ function triedManifestPaths() {
115405
+ return process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH ? [process.env.PRODUCER_HYPERFRAME_MANIFEST_PATH] : MANIFEST_CANDIDATES;
115356
115406
  }
115357
115407
  function getVerifiedHyperframeRuntimeSource() {
115358
115408
  return resolveVerifiedHyperframeRuntime().runtimeSource;
@@ -115360,8 +115410,9 @@ function getVerifiedHyperframeRuntimeSource() {
115360
115410
  function resolveVerifiedHyperframeRuntime() {
115361
115411
  const manifestPath2 = resolveHyperframeManifestPath();
115362
115412
  if (!existsSync41(manifestPath2)) {
115413
+ const tried = triedManifestPaths().join(", ");
115363
115414
  throw new Error(
115364
- `[HyperframeRuntimeLoader] Missing manifest at ${manifestPath2}. Build core runtime artifacts before rendering.`
115415
+ `[HyperframeRuntimeLoader] Missing manifest. Tried: ${tried}. Searched from cwd=${process.cwd()}. Build core runtime artifacts before rendering.`
115365
115416
  );
115366
115417
  }
115367
115418
  const manifestRaw = readFileSync27(manifestPath2, "utf8");
@@ -115391,7 +115442,7 @@ function resolveVerifiedHyperframeRuntime() {
115391
115442
  runtimeSource
115392
115443
  };
115393
115444
  }
115394
- var PRODUCER_DIR, SIBLING_MANIFEST_PATH, MODULE_RELATIVE_MANIFEST_PATH, CWD_RELATIVE_MANIFEST_PATHS;
115445
+ var PRODUCER_DIR, SIBLING_MANIFEST_PATH, MODULE_RELATIVE_MANIFEST_PATH, MANIFEST_CANDIDATES;
115395
115446
  var init_hyperframeRuntimeLoader = __esm({
115396
115447
  "../producer/src/services/hyperframeRuntimeLoader.ts"() {
115397
115448
  "use strict";
@@ -115401,13 +115452,12 @@ var init_hyperframeRuntimeLoader = __esm({
115401
115452
  PRODUCER_DIR,
115402
115453
  "../../../core/dist/hyperframe.manifest.json"
115403
115454
  );
115404
- CWD_RELATIVE_MANIFEST_PATHS = [
115405
- // When bundled to a single file (dist/public-server.js), the manifest
115406
- // is copied as a sibling by build.mjs
115407
- resolve26(PRODUCER_DIR, "hyperframe.manifest.json"),
115455
+ MANIFEST_CANDIDATES = [
115456
+ SIBLING_MANIFEST_PATH,
115408
115457
  resolve26(process.cwd(), "packages/core/dist/hyperframe.manifest.json"),
115409
115458
  resolve26(process.cwd(), "../core/dist/hyperframe.manifest.json"),
115410
- resolve26(process.cwd(), "core/dist/hyperframe.manifest.json")
115459
+ resolve26(process.cwd(), "core/dist/hyperframe.manifest.json"),
115460
+ MODULE_RELATIVE_MANIFEST_PATH
115411
115461
  ];
115412
115462
  }
115413
115463
  });
@@ -121119,8 +121169,8 @@ function cachedCompressionPath(input2, originalFormat, cacheDir) {
121119
121169
  function readCachedCompression(path2) {
121120
121170
  try {
121121
121171
  if (!existsSync46(path2)) return null;
121122
- const cached2 = readFileSync28(path2);
121123
- return cached2.length > 0 ? cached2 : null;
121172
+ const cached3 = readFileSync28(path2);
121173
+ return cached3.length > 0 ? cached3 : null;
121124
121174
  } catch {
121125
121175
  return null;
121126
121176
  }
@@ -121152,8 +121202,8 @@ async function fontToDataUri(input2, originalFormat, options = {}) {
121152
121202
  originalFormat,
121153
121203
  options.cacheDir ?? defaultCacheDir()
121154
121204
  );
121155
- const cached2 = readCachedCompression(cachePath2);
121156
- if (cached2) return `data:font/woff2;base64,${cached2.toString("base64")}`;
121205
+ const cached3 = readCachedCompression(cachePath2);
121206
+ if (cached3) return `data:font/woff2;base64,${cached3.toString("base64")}`;
121157
121207
  const compressed = await (options.compressImpl ?? compressToWoff2)(input2);
121158
121208
  cacheCompression(cachePath2, compressed);
121159
121209
  return `data:font/woff2;base64,${compressed.toString("base64")}`;
@@ -123733,8 +123783,8 @@ async function discoverAudioVolumeAutomationFromTimeline(page, audioIds, composi
123733
123783
  const volumeDescriptor = typeof HTMLMediaElement === "undefined" ? void 0 : Object.getOwnPropertyDescriptor(HTMLMediaElement.prototype, "volume");
123734
123784
  const nativeVolumeGet = volumeDescriptor?.get;
123735
123785
  const nativeVolumeSet = volumeDescriptor?.set;
123736
- const withUnclampedVolume2 = (el, probe) => {
123737
- if (!nativeVolumeGet || !nativeVolumeSet) return probe();
123786
+ const withUnclampedVolume2 = (el, probe2) => {
123787
+ if (!nativeVolumeGet || !nativeVolumeSet) return probe2();
123738
123788
  let authored = Number(nativeVolumeGet.call(el));
123739
123789
  Object.defineProperty(el, "volume", {
123740
123790
  configurable: true,
@@ -123745,7 +123795,7 @@ async function discoverAudioVolumeAutomationFromTimeline(page, audioIds, composi
123745
123795
  }
123746
123796
  });
123747
123797
  try {
123748
- return probe();
123798
+ return probe2();
123749
123799
  } finally {
123750
123800
  delete el.volume;
123751
123801
  nativeVolumeSet.call(el, Math.max(0, Math.min(1, authored)));
@@ -129046,9 +129096,9 @@ function shouldRetryViaPinnedFallback(args) {
129046
129096
  if (args.isVerifyError) return true;
129047
129097
  return args.deWorkerInversion === "inverted" || args.deParallelRouter === "routed";
129048
129098
  }
129049
- async function closeOrphanedProbeForRetry(probe, closer, log2, retryContext) {
129099
+ async function closeOrphanedProbeForRetry(probe2, closer, log2, retryContext) {
129050
129100
  try {
129051
- await closer(probe);
129101
+ await closer(probe2);
129052
129102
  } catch (closeErr) {
129053
129103
  log2.warn(`[Render] probe close before ${retryContext} retry failed; continuing with retry`, {
129054
129104
  error: closeErr instanceof Error ? closeErr.message : String(closeErr)
@@ -132324,7 +132374,7 @@ import { execFile as execFileCallback } from "child_process";
132324
132374
  import { dirname as dirname28, join as join67 } from "path";
132325
132375
  import { existsSync as existsSync61, readFileSync as readFileSync37 } from "fs";
132326
132376
  import { fileURLToPath as fileURLToPath7 } from "url";
132327
- import { promisify as promisify4 } from "util";
132377
+ import { promisify as promisify5 } from "util";
132328
132378
  function isPlanAudioArtifactPath(path2) {
132329
132379
  return path2 === PLAN_AUDIO_RELATIVE_PATH || path2 === PLAN_AUDIO_LEGACY_RELATIVE_PATH;
132330
132380
  }
@@ -132482,7 +132532,7 @@ function buildPlanVideosJson(input2) {
132482
132532
  }
132483
132533
  async function readFfmpegVersion() {
132484
132534
  if (cachedFfmpegVersion !== null) return cachedFfmpegVersion;
132485
- const { stdout: stdout2 } = await execFile6("ffmpeg", ["-version"], {
132535
+ const { stdout: stdout2 } = await execFile7("ffmpeg", ["-version"], {
132486
132536
  maxBuffer: 1024 * 1024,
132487
132537
  // See runFfmpeg.ts: keeps a console window off the user's desktop on Windows.
132488
132538
  windowsHide: true
@@ -132540,7 +132590,7 @@ function readProducerVersion() {
132540
132590
  cachedProducerVersion = "0.0.0-unknown";
132541
132591
  return cachedProducerVersion;
132542
132592
  }
132543
- var PLAN_VIDEOS_META_RELATIVE_PATH, PLAN_AUDIO_RELATIVE_PATH, PLAN_AUDIO_LEGACY_RELATIVE_PATH, INVALID_VIDEO_METADATA, PlanVideosMetadataError, execFile6, cachedFfmpegVersion, cachedProducerVersion;
132593
+ var PLAN_VIDEOS_META_RELATIVE_PATH, PLAN_AUDIO_RELATIVE_PATH, PLAN_AUDIO_LEGACY_RELATIVE_PATH, INVALID_VIDEO_METADATA, PlanVideosMetadataError, execFile7, cachedFfmpegVersion, cachedProducerVersion;
132544
132594
  var init_shared2 = __esm({
132545
132595
  "../producer/src/services/distributed/shared.ts"() {
132546
132596
  "use strict";
@@ -132560,7 +132610,7 @@ var init_shared2 = __esm({
132560
132610
  this.name = "PlanVideosMetadataError";
132561
132611
  }
132562
132612
  };
132563
- execFile6 = promisify4(execFileCallback);
132613
+ execFile7 = promisify5(execFileCallback);
132564
132614
  cachedFfmpegVersion = null;
132565
132615
  cachedProducerVersion = null;
132566
132616
  }
@@ -134397,14 +134447,14 @@ async function runCaptureWithScreenshotFallback(input2) {
134397
134447
  return await input2.run(true);
134398
134448
  }
134399
134449
  }
134400
- async function beginFrameSessionNeedsScreenshotFallback(session, probe = probeBeginFrameLiveness) {
134450
+ async function beginFrameSessionNeedsScreenshotFallback(session, probe2 = probeBeginFrameLiveness) {
134401
134451
  if (session.launchCaptureMode !== "beginframe") return false;
134402
134452
  const timeoutMs = Number(process.env.PRODUCER_BEGINFRAME_PROBE_TIMEOUT_MS) > 0 ? Number(process.env.PRODUCER_BEGINFRAME_PROBE_TIMEOUT_MS) : 3e4;
134403
134453
  const probeTick = deriveBeginFrameProbeTimeTicks(
134404
134454
  session.beginFrameTimeTicks,
134405
134455
  session.beginFrameIntervalMs
134406
134456
  );
134407
- return !await probe(session.page, timeoutMs, probeTick, session.beginFrameIntervalMs);
134457
+ return !await probe2(session.page, timeoutMs, probeTick, session.beginFrameIntervalMs);
134408
134458
  }
134409
134459
  function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v1") {
134410
134460
  const result = [];
@@ -135766,15 +135816,15 @@ function checkFFprobe() {
135766
135816
  }
135767
135817
  function chromeSharedLibOutcome(executablePath, found) {
135768
135818
  if (process.platform !== "linux") return found;
135769
- const probe = probeChromeSharedLibs(executablePath);
135770
- if (probe.probeUnavailable || probe.ok) return found;
135819
+ const probe2 = probeChromeSharedLibs(executablePath);
135820
+ if (probe2.probeUnavailable || probe2.ok) return found;
135771
135821
  const distro = detectLinuxDistro();
135772
135822
  return {
135773
135823
  name: "Chrome",
135774
135824
  ok: false,
135775
135825
  level: "error",
135776
135826
  title: "Chrome cannot launch (missing system libraries)",
135777
- detail: `Chrome at ${executablePath} is missing shared libraries on ${distroLabel(distro)}: ${probe.missing.join(", ")}`,
135827
+ detail: `Chrome at ${executablePath} is missing shared libraries on ${distroLabel(distro)}: ${probe2.missing.join(", ")}`,
135778
135828
  hint: chromeDepsInstallCommand(distro.family),
135779
135829
  path: executablePath
135780
135830
  };
@@ -144104,13 +144154,13 @@ var init_producer = __esm({
144104
144154
 
144105
144155
  // src/utils/webmAlphaCheck.ts
144106
144156
  import { execFileSync as execFileSync11 } from "child_process";
144107
- function webmAlphaAdvisory(format, probe) {
144157
+ function webmAlphaAdvisory(format, probe2) {
144108
144158
  if (format !== "webm") return void 0;
144109
- if (!probe.probed) return void 0;
144110
- if (!probe.alphaMode) {
144159
+ if (!probe2.probed) return void 0;
144160
+ if (!probe2.alphaMode) {
144111
144161
  return "The WebM output has no VP9 alpha sidecar (the ALPHA_MODE stream tag is absent), so transparency was flattened to opaque. Your ffmpeg/libvpx-vp9 build cannot emit the alpha plane on this platform. For guaranteed transparency, re-render with --format mov (ProRes 4444).";
144112
144162
  }
144113
- if (probe.sampledAlphaFullyOpaque) {
144163
+ if (probe2.sampledAlphaFullyOpaque) {
144114
144164
  return "The WebM declares alpha (ALPHA_MODE=1) but every sampled decoded pixel reads alpha=255. This may be intentional (the composition has no transparent regions in the samples) OR your ffmpeg/libvpx-vp9 build wrote the tag without emitting the alpha side data \u2014 a known Windows-build quirk. To rule it out, re-render with --format mov (ProRes 4444), or with --format png-sequence and encode the frames yourself: ffmpeg -framerate <fps> -i frame_%06d.png -c:v prores_ks -profile:v 4444 -pix_fmt yuva444p10le out.mov";
144115
144165
  }
144116
144166
  return void 0;
@@ -144144,12 +144194,12 @@ function probeWebmAlpha(filePath) {
144144
144194
  const alphaMode = Object.entries(tags).some(
144145
144195
  ([k2, v2]) => k2.toLowerCase() === "alpha_mode" && String(v2) === "1"
144146
144196
  );
144147
- const probe = { probed: true, alphaMode };
144197
+ const probe2 = { probed: true, alphaMode };
144148
144198
  if (alphaMode) {
144149
144199
  const opaque = sampledAlphaIsFullyOpaque(filePath);
144150
- if (opaque === true) probe.sampledAlphaFullyOpaque = true;
144200
+ if (opaque === true) probe2.sampledAlphaFullyOpaque = true;
144151
144201
  }
144152
- return probe;
144202
+ return probe2;
144153
144203
  } catch {
144154
144204
  return { probed: false, alphaMode: false };
144155
144205
  }
@@ -144803,12 +144853,13 @@ async function renderLocal(projectDir, outputPath, options) {
144803
144853
  await producer.executeRenderJob(job, projectDir, outputPath, onProgress);
144804
144854
  } catch (error) {
144805
144855
  maybeConsumeDeParallelRouterTrial(deParallelRouterActive, job, options.quiet);
144856
+ const inContainer = process.env.CONTAINER === "true";
144806
144857
  handleRenderError(
144807
144858
  error,
144808
144859
  options,
144809
144860
  startTime,
144810
144861
  false,
144811
- "Try --docker for containerized rendering",
144862
+ inContainer ? "" : "Try --docker for containerized rendering",
144812
144863
  job.failedStage,
144813
144864
  job
144814
144865
  );
@@ -150177,10 +150228,10 @@ __export(normalize_audio_exports, {
150177
150228
  resolveLocalAudioPath: () => resolveLocalAudioPath,
150178
150229
  updateAudioVolume: () => updateAudioVolume
150179
150230
  });
150180
- import { execFile as execFile7 } from "child_process";
150231
+ import { execFile as execFile8 } from "child_process";
150181
150232
  import { existsSync as existsSync91, readFileSync as readFileSync66, renameSync as renameSync15, writeFileSync as writeFileSync38 } from "fs";
150182
150233
  import { isAbsolute as isAbsolute14, relative as relative23, resolve as resolve58 } from "path";
150183
- import { promisify as promisify5 } from "util";
150234
+ import { promisify as promisify6 } from "util";
150184
150235
  function authoredNumber(raw, fallback, attribute2, id, strictlyPositive = false) {
150185
150236
  if (raw === void 0) return fallback;
150186
150237
  const value = Number(raw);
@@ -150536,7 +150587,7 @@ var init_normalize_audio = __esm({
150536
150587
  init_colors();
150537
150588
  init_project();
150538
150589
  init_commandResult();
150539
- execFileAsync4 = promisify5(execFile7);
150590
+ execFileAsync4 = promisify6(execFile8);
150540
150591
  FFMPEG_TIMEOUT_MS = 12e4;
150541
150592
  DEFAULT_TOLERANCE_LU = 0.5;
150542
150593
  examples14 = [
@@ -152773,7 +152824,7 @@ function timelineDuration(page) {
152773
152824
  });
152774
152825
  }
152775
152826
  async function resolveScopeInBrowser(page, scope, candidates) {
152776
- const probe = await page.evaluate(
152827
+ const probe2 = await page.evaluate(
152777
152828
  (scopeSel, cands) => {
152778
152829
  let root = null;
152779
152830
  try {
@@ -152799,9 +152850,9 @@ async function resolveScopeInBrowser(page, scope, candidates) {
152799
152850
  const selectors = resolveShotSelectors(
152800
152851
  scope,
152801
152852
  candidates,
152802
- (_s, target) => probe.descendant[candidates.indexOf(target)] === true
152853
+ (_s, target) => probe2.descendant[candidates.indexOf(target)] === true
152803
152854
  );
152804
- return { selectors, scopeExists: probe.scopeExists };
152855
+ return { selectors, scopeExists: probe2.scopeExists };
152805
152856
  }
152806
152857
  async function resolveScopedRequests(page, requests, scopeSelector2) {
152807
152858
  const resolved2 = await resolveScopeInBrowser(
@@ -153862,8 +153913,8 @@ function findReferenceTargetEl2(doc, refId) {
153862
153913
  return doc.getElementById(refId) ?? doc.querySelector(`[data-composition-id="${refId}"]`);
153863
153914
  }
153864
153915
  function resolveStart3(doc, el, startCache, visiting) {
153865
- const cached2 = startCache.get(el);
153866
- if (cached2 !== void 0) return cached2;
153916
+ const cached3 = startCache.get(el);
153917
+ if (cached3 !== void 0) return cached3;
153867
153918
  if (visiting.has(el)) return 0;
153868
153919
  visiting.add(el);
153869
153920
  try {
@@ -154435,12 +154486,12 @@ async function showInfo(json) {
154435
154486
  const { selectProviders: selectProviders2, listAvailableProviders: listAvailableProviders2, DEFAULT_MODEL: DEFAULT_MODEL5, MODEL_MEMORY_MB: MODEL_MEMORY_MB2, modelPath: modelPath2 } = await Promise.resolve().then(() => (init_manager3(), manager_exports3));
154436
154487
  const providers = listAvailableProviders2();
154437
154488
  const auto = selectProviders2("auto");
154438
- const cached2 = existsSync96(modelPath2());
154489
+ const cached3 = existsSync96(modelPath2());
154439
154490
  if (json) {
154440
154491
  console.log(
154441
154492
  JSON.stringify({
154442
154493
  defaultModel: DEFAULT_MODEL5,
154443
- modelCached: cached2,
154494
+ modelCached: cached3,
154444
154495
  modelPath: modelPath2(),
154445
154496
  peakMemoryMb: MODEL_MEMORY_MB2[DEFAULT_MODEL5],
154446
154497
  availableProviders: providers,
@@ -154454,7 +154505,7 @@ async function showInfo(json) {
154454
154505
  console.log(` ${c.dim("Default model:")} ${c.accent(DEFAULT_MODEL5)}`);
154455
154506
  console.log(` ${c.dim("Peak memory:")} ~${MODEL_MEMORY_MB2[DEFAULT_MODEL5]} MB`);
154456
154507
  console.log(
154457
- ` ${c.dim("Weights cached:")} ${cached2 ? c.success("yes") : c.dim("no (will download on first run)")}`
154508
+ ` ${c.dim("Weights cached:")} ${cached3 ? c.success("yes") : c.dim("no (will download on first run)")}`
154458
154509
  );
154459
154510
  console.log(` ${c.dim("Cache path:")} ${modelPath2()}`);
154460
154511
  console.log("");
@@ -154705,11 +154756,11 @@ function transcribeWithParakeet(inputPath, dir, options) {
154705
154756
  );
154706
154757
  }
154707
154758
  const model = options?.model ?? DEFAULT_MODEL3;
154708
- const cached2 = existsSync97(
154759
+ const cached3 = existsSync97(
154709
154760
  join105(homedir20(), ".cache", "huggingface", "hub", `models--${model.replace(/\//g, "--")}`)
154710
154761
  );
154711
154762
  options?.onProgress?.(
154712
- cached2 ? "Transcribing with Parakeet..." : "Downloading Parakeet model (first run, ~600MB)..."
154763
+ cached3 ? "Transcribing with Parakeet..." : "Downloading Parakeet model (first run, ~600MB)..."
154713
154764
  );
154714
154765
  const workDir = mkdtempSync15(join105(tmpdir15(), "hyperframes-parakeet-"));
154715
154766
  try {
@@ -155169,9 +155220,9 @@ function hasPythonModules(modules) {
155169
155220
  const python = findPython();
155170
155221
  if (!python) return false;
155171
155222
  const list = JSON.stringify(modules);
155172
- const probe = `import importlib.util,sys; sys.exit(0 if all(importlib.util.find_spec(m) for m in ${list}) else 1)`;
155223
+ const probe2 = `import importlib.util,sys; sys.exit(0 if all(importlib.util.find_spec(m) for m in ${list}) else 1)`;
155173
155224
  try {
155174
- execFileSync14(python, ["-c", probe], {
155225
+ execFileSync14(python, ["-c", probe2], {
155175
155226
  stdio: ["pipe", "pipe", "pipe"],
155176
155227
  timeout: 1e4
155177
155228
  });
@@ -163588,7 +163639,7 @@ var init_multipart_parser = __esm({
163588
163639
 
163589
163640
  // ../../node_modules/.bun/node-fetch@3.3.2/node_modules/node-fetch/src/body.js
163590
163641
  import Stream, { PassThrough } from "stream";
163591
- import { types as types3, deprecate, promisify as promisify6 } from "util";
163642
+ import { types as types3, deprecate, promisify as promisify7 } from "util";
163592
163643
  import { Buffer as Buffer3 } from "buffer";
163593
163644
  async function consumeBody(data2) {
163594
163645
  if (data2[INTERNALS].disturbed) {
@@ -163643,7 +163694,7 @@ var init_body = __esm({
163643
163694
  init_fetch_error();
163644
163695
  init_base2();
163645
163696
  init_is();
163646
- pipeline3 = promisify6(Stream.pipeline);
163697
+ pipeline3 = promisify7(Stream.pipeline);
163647
163698
  INTERNALS = /* @__PURE__ */ Symbol("Body internals");
163648
163699
  Body = class {
163649
163700
  constructor(body, {
@@ -196932,8 +196983,8 @@ async function captureSnapshots(projectDir, opts) {
196932
196983
  const alphaDecoderCache = /* @__PURE__ */ new Map();
196933
196984
  const shouldUseVp9AlphaDecoder = (filePath) => {
196934
196985
  if (!extractMediaMetadata2) return Promise.resolve(false);
196935
- const cached2 = alphaDecoderCache.get(filePath);
196936
- if (cached2) return cached2;
196986
+ const cached3 = alphaDecoderCache.get(filePath);
196987
+ if (cached3) return cached3;
196937
196988
  const pending = extractMediaMetadata2(filePath).then((meta) => meta.hasAlpha && meta.videoCodec === "vp9").catch(() => false);
196938
196989
  alphaDecoderCache.set(filePath, pending);
196939
196990
  return pending;
@@ -197515,9 +197566,9 @@ function statsToAdjust(stats) {
197515
197566
  }
197516
197567
  };
197517
197568
  }
197518
- function summarizeMediaTreatmentAnalysis(probe, frames) {
197569
+ function summarizeMediaTreatmentAnalysis(probe2, frames) {
197519
197570
  const result = statsToAdjust(summarizeFrames(frames));
197520
- const hdr = ["smpte2084", "arib-std-b67"].includes(probe.transfer);
197571
+ const hdr = ["smpte2084", "arib-std-b67"].includes(probe2.transfer);
197521
197572
  const diagnosis = [];
197522
197573
  if (result.measured.shadowClipRisk > 0) {
197523
197574
  diagnosis.push("sampled frames contain deep or clipped shadows");
@@ -197530,16 +197581,16 @@ function summarizeMediaTreatmentAnalysis(probe, frames) {
197530
197581
  const warnings = [];
197531
197582
  if (hdr)
197532
197583
  warnings.push("HDR transfer detected; the realtime treatment path is SDR/Rec.709.");
197533
- if (probe.colorSpace === "unknown" || probe.transfer === "unknown") {
197584
+ if (probe2.colorSpace === "unknown" || probe2.transfer === "unknown") {
197534
197585
  warnings.push("Source color metadata is incomplete; camera LOG cannot be identified reliably from container metadata alone.");
197535
197586
  }
197536
197587
  return {
197537
197588
  ...result,
197538
197589
  source: {
197539
- colorSpace: probe.colorSpace,
197540
- transfer: probe.transfer,
197541
- primaries: probe.primaries,
197542
- pixelFormat: probe.pixelFormat,
197590
+ colorSpace: probe2.colorSpace,
197591
+ transfer: probe2.transfer,
197592
+ primaries: probe2.primaries,
197593
+ pixelFormat: probe2.pixelFormat,
197543
197594
  hdr,
197544
197595
  log: "unknown"
197545
197596
  },
@@ -197551,9 +197602,9 @@ function analyzeMediaGrade(mediaPath, options = {}) {
197551
197602
  const ffmpegPath = options.ffmpegPath ?? "ffmpeg";
197552
197603
  const ffprobePath = options.ffprobePath ?? "ffprobe";
197553
197604
  try {
197554
- const probe = probeMedia2(mediaPath, ffprobePath);
197605
+ const probe2 = probeMedia2(mediaPath, ffprobePath);
197555
197606
  const isImage = IMAGE_EXTENSIONS3.has(extname20(mediaPath).toLowerCase());
197556
- const fps = !isImage && probe.duration ? Math.max(0.1, Math.min(2, SAMPLE_FRAMES / probe.duration)) : null;
197607
+ const fps = !isImage && probe2.duration ? Math.max(0.1, Math.min(2, SAMPLE_FRAMES / probe2.duration)) : null;
197557
197608
  const filters2 = [
197558
197609
  fps ? `fps=${fps.toFixed(4)}` : null,
197559
197610
  "format=yuv444p",
@@ -197579,7 +197630,7 @@ function analyzeMediaGrade(mediaPath, options = {}) {
197579
197630
  timeout: Number(process.env.HYPERFRAMES_ANALYZE_TIMEOUT_MS) || DEFAULT_TIMEOUT_MS2,
197580
197631
  stdio: ["ignore", "pipe", "pipe"]
197581
197632
  });
197582
- return summarizeMediaTreatmentAnalysis(probe, parseMediaTreatmentSignalStats(raw));
197633
+ return summarizeMediaTreatmentAnalysis(probe2, parseMediaTreatmentSignalStats(raw));
197583
197634
  } catch (error) {
197584
197635
  const message = error instanceof Error ? error.message : String(error);
197585
197636
  throw new Error(`grade analysis failed for ${mediaPath}: ${message}`);
@@ -208691,8 +208742,8 @@ function collectStatusRows(s2) {
208691
208742
  if (s2.credential.type === "oauth") rows.push(...oauthRows(s2.credential));
208692
208743
  if (s2.apiError) {
208693
208744
  rows.push([c.error("API check failed:"), s2.apiError]);
208694
- const cached2 = s2.persistedUser && userDisplayName(s2.persistedUser);
208695
- if (cached2) rows.push(["Account:", `${cached2} ${c.dim("(cached)")}`]);
208745
+ const cached3 = s2.persistedUser && userDisplayName(s2.persistedUser);
208746
+ if (cached3) rows.push(["Account:", `${cached3} ${c.dim("(cached)")}`]);
208696
208747
  return rows;
208697
208748
  }
208698
208749
  if (s2.user) rows.push(...identityRows(s2.user));