@hyperframes/engine 0.8.144 → 0.8.146

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.
Files changed (263) hide show
  1. package/dist/config.d.ts +0 -1
  2. package/dist/config.js +1 -2
  3. package/dist/index.d.ts +2 -3
  4. package/dist/index.js +2 -3
  5. package/dist/services/__fixtures__/jpeg.d.ts +0 -1
  6. package/dist/services/__fixtures__/jpeg.js +0 -1
  7. package/dist/services/audioFxRender.d.ts +0 -1
  8. package/dist/services/audioFxRender.js +0 -1
  9. package/dist/services/audioMixer.d.ts +0 -1
  10. package/dist/services/audioMixer.js +0 -1
  11. package/dist/services/audioMixer.types.d.ts +0 -1
  12. package/dist/services/audioMixer.types.js +0 -1
  13. package/dist/services/audioVolumeEnvelope.d.ts +0 -1
  14. package/dist/services/audioVolumeEnvelope.js +0 -1
  15. package/dist/services/browserLeasePool.d.ts +0 -1
  16. package/dist/services/browserLeasePool.js +0 -1
  17. package/dist/services/browserManager.d.ts +0 -1
  18. package/dist/services/browserManager.js +2 -3
  19. package/dist/services/captureFailure.d.ts +0 -1
  20. package/dist/services/captureFailure.js +0 -1
  21. package/dist/services/captureWarning.d.ts +0 -1
  22. package/dist/services/captureWarning.js +0 -1
  23. package/dist/services/chromeHostCeiling.d.ts +0 -1
  24. package/dist/services/chromeHostCeiling.js +0 -1
  25. package/dist/services/chromeMemorySampler.d.ts +0 -1
  26. package/dist/services/chromeMemorySampler.js +0 -1
  27. package/dist/services/chunkEncoder.d.ts +0 -1
  28. package/dist/services/chunkEncoder.js +4 -5
  29. package/dist/services/chunkEncoder.types.d.ts +0 -1
  30. package/dist/services/chunkEncoder.types.js +0 -1
  31. package/dist/services/drawElementCaptureError.d.ts +0 -1
  32. package/dist/services/drawElementCaptureError.js +0 -1
  33. package/dist/services/drawElementService.d.ts +0 -1
  34. package/dist/services/drawElementService.js +1 -2
  35. package/dist/services/extractedFrameIndex.d.ts +0 -1
  36. package/dist/services/extractedFrameIndex.js +0 -1
  37. package/dist/services/extractionCache.d.ts +3 -1
  38. package/dist/services/extractionCache.js +17 -4
  39. package/dist/services/fileServer.d.ts +0 -1
  40. package/dist/services/fileServer.js +0 -1
  41. package/dist/services/frameCapture.d.ts +2 -2
  42. package/dist/services/frameCapture.js +33 -33
  43. package/dist/services/hdrCapture.d.ts +0 -1
  44. package/dist/services/hdrCapture.js +0 -1
  45. package/dist/services/mediaHidden.d.ts +0 -1
  46. package/dist/services/mediaHidden.js +0 -1
  47. package/dist/services/mediaRenderIdBridge.d.ts +0 -1
  48. package/dist/services/mediaRenderIdBridge.js +0 -1
  49. package/dist/services/mediaTimelineWindow.d.ts +0 -1
  50. package/dist/services/mediaTimelineWindow.js +0 -1
  51. package/dist/services/motionBlur.d.ts +0 -1
  52. package/dist/services/motionBlur.js +0 -1
  53. package/dist/services/pageNavigationTimeoutErrorHint.d.ts +0 -1
  54. package/dist/services/pageNavigationTimeoutErrorHint.js +0 -1
  55. package/dist/services/parallelCoordinator.d.ts +0 -1
  56. package/dist/services/parallelCoordinator.js +2 -3
  57. package/dist/services/protocolTimeoutErrorHint.d.ts +0 -1
  58. package/dist/services/protocolTimeoutErrorHint.js +0 -1
  59. package/dist/services/referenceResolver.d.ts +0 -1
  60. package/dist/services/referenceResolver.js +0 -1
  61. package/dist/services/screenshotService.d.ts +0 -1
  62. package/dist/services/screenshotService.js +19 -20
  63. package/dist/services/streamingEncoder.d.ts +0 -1
  64. package/dist/services/streamingEncoder.js +0 -1
  65. package/dist/services/systemMemory.d.ts +0 -1
  66. package/dist/services/systemMemory.js +2 -3
  67. package/dist/services/threeDProjection.d.ts +0 -1
  68. package/dist/services/threeDProjection.js +2 -3
  69. package/dist/services/videoFrameExtractor.d.ts +3 -1
  70. package/dist/services/videoFrameExtractor.js +47 -13
  71. package/dist/services/videoFrameInjector.d.ts +0 -1
  72. package/dist/services/videoFrameInjector.js +0 -1
  73. package/dist/services/vp9Options.d.ts +0 -1
  74. package/dist/services/vp9Options.js +0 -1
  75. package/dist/services/wavChunks.d.ts +0 -1
  76. package/dist/services/wavChunks.js +0 -1
  77. package/dist/types.d.ts +0 -1
  78. package/dist/types.js +0 -1
  79. package/dist/utils/alphaBlit.d.ts +0 -1
  80. package/dist/utils/alphaBlit.js +0 -1
  81. package/dist/utils/alphaPlaneProbe.d.ts +0 -1
  82. package/dist/utils/alphaPlaneProbe.js +0 -1
  83. package/dist/utils/assertSwiftShader.d.ts +0 -1
  84. package/dist/utils/assertSwiftShader.js +0 -1
  85. package/dist/utils/concurrencyLimit.d.ts +5 -0
  86. package/dist/utils/concurrencyLimit.js +39 -0
  87. package/dist/utils/crc32.d.ts +0 -1
  88. package/dist/utils/crc32.js +0 -1
  89. package/dist/utils/evenDimensions.d.ts +0 -1
  90. package/dist/utils/evenDimensions.js +0 -1
  91. package/dist/utils/ffmpegBinaries.d.ts +0 -1
  92. package/dist/utils/ffmpegBinaries.js +0 -1
  93. package/dist/utils/ffprobe.d.ts +0 -1
  94. package/dist/utils/ffprobe.js +2 -2
  95. package/dist/utils/gpuEncoder.d.ts +0 -1
  96. package/dist/utils/gpuEncoder.js +0 -1
  97. package/dist/utils/gpuParityDiff.d.ts +0 -1
  98. package/dist/utils/gpuParityDiff.js +4 -5
  99. package/dist/utils/hdr.d.ts +0 -1
  100. package/dist/utils/hdr.js +1 -2
  101. package/dist/utils/htmlTemplate.d.ts +0 -1
  102. package/dist/utils/htmlTemplate.js +0 -1
  103. package/dist/utils/jpegInput.d.ts +0 -1
  104. package/dist/utils/jpegInput.js +0 -1
  105. package/dist/utils/layerCompositor.d.ts +0 -1
  106. package/dist/utils/layerCompositor.js +0 -1
  107. package/dist/utils/managedChildProcess.d.ts +0 -1
  108. package/dist/utils/managedChildProcess.js +0 -1
  109. package/dist/utils/notMediaPayload.d.ts +0 -1
  110. package/dist/utils/notMediaPayload.js +0 -1
  111. package/dist/utils/parityContract.d.ts +0 -1
  112. package/dist/utils/parityContract.js +0 -1
  113. package/dist/utils/processRss.d.ts +0 -1
  114. package/dist/utils/processRss.js +0 -1
  115. package/dist/utils/processTracker.d.ts +0 -1
  116. package/dist/utils/processTracker.js +0 -1
  117. package/dist/utils/psnr.d.ts +0 -1
  118. package/dist/utils/psnr.js +0 -1
  119. package/dist/utils/psnrFilterAvailability.d.ts +0 -1
  120. package/dist/utils/psnrFilterAvailability.js +0 -1
  121. package/dist/utils/readWebGlVendorInfoFromCanvas.d.ts +0 -1
  122. package/dist/utils/readWebGlVendorInfoFromCanvas.js +0 -1
  123. package/dist/utils/renderProvenance.d.ts +0 -1
  124. package/dist/utils/renderProvenance.js +0 -1
  125. package/dist/utils/runFfmpeg.d.ts +2 -1
  126. package/dist/utils/runFfmpeg.js +21 -1
  127. package/dist/utils/sdrCaptureColor.d.ts +0 -1
  128. package/dist/utils/sdrCaptureColor.js +0 -1
  129. package/dist/utils/shaderTransitions.d.ts +0 -1
  130. package/dist/utils/shaderTransitions.js +0 -1
  131. package/dist/utils/urlDownloader.d.ts +0 -1
  132. package/dist/utils/urlDownloader.js +0 -1
  133. package/package.json +3 -3
  134. package/dist/config.d.ts.map +0 -1
  135. package/dist/config.js.map +0 -1
  136. package/dist/index.d.ts.map +0 -1
  137. package/dist/index.js.map +0 -1
  138. package/dist/services/__fixtures__/jpeg.d.ts.map +0 -1
  139. package/dist/services/__fixtures__/jpeg.js.map +0 -1
  140. package/dist/services/audioFxRender.d.ts.map +0 -1
  141. package/dist/services/audioFxRender.js.map +0 -1
  142. package/dist/services/audioMixer.d.ts.map +0 -1
  143. package/dist/services/audioMixer.js.map +0 -1
  144. package/dist/services/audioMixer.types.d.ts.map +0 -1
  145. package/dist/services/audioMixer.types.js.map +0 -1
  146. package/dist/services/audioVolumeEnvelope.d.ts.map +0 -1
  147. package/dist/services/audioVolumeEnvelope.js.map +0 -1
  148. package/dist/services/browserLeasePool.d.ts.map +0 -1
  149. package/dist/services/browserLeasePool.js.map +0 -1
  150. package/dist/services/browserManager.d.ts.map +0 -1
  151. package/dist/services/browserManager.js.map +0 -1
  152. package/dist/services/captureFailure.d.ts.map +0 -1
  153. package/dist/services/captureFailure.js.map +0 -1
  154. package/dist/services/captureWarning.d.ts.map +0 -1
  155. package/dist/services/captureWarning.js.map +0 -1
  156. package/dist/services/chromeHostCeiling.d.ts.map +0 -1
  157. package/dist/services/chromeHostCeiling.js.map +0 -1
  158. package/dist/services/chromeMemorySampler.d.ts.map +0 -1
  159. package/dist/services/chromeMemorySampler.js.map +0 -1
  160. package/dist/services/chunkEncoder.d.ts.map +0 -1
  161. package/dist/services/chunkEncoder.js.map +0 -1
  162. package/dist/services/chunkEncoder.types.d.ts.map +0 -1
  163. package/dist/services/chunkEncoder.types.js.map +0 -1
  164. package/dist/services/drawElementCaptureError.d.ts.map +0 -1
  165. package/dist/services/drawElementCaptureError.js.map +0 -1
  166. package/dist/services/drawElementService.d.ts.map +0 -1
  167. package/dist/services/drawElementService.js.map +0 -1
  168. package/dist/services/extractedFrameIndex.d.ts.map +0 -1
  169. package/dist/services/extractedFrameIndex.js.map +0 -1
  170. package/dist/services/extractionCache.d.ts.map +0 -1
  171. package/dist/services/extractionCache.js.map +0 -1
  172. package/dist/services/fileServer.d.ts.map +0 -1
  173. package/dist/services/fileServer.js.map +0 -1
  174. package/dist/services/frameCapture.d.ts.map +0 -1
  175. package/dist/services/frameCapture.js.map +0 -1
  176. package/dist/services/hdrCapture.d.ts.map +0 -1
  177. package/dist/services/hdrCapture.js.map +0 -1
  178. package/dist/services/mediaHidden.d.ts.map +0 -1
  179. package/dist/services/mediaHidden.js.map +0 -1
  180. package/dist/services/mediaRenderIdBridge.d.ts.map +0 -1
  181. package/dist/services/mediaRenderIdBridge.js.map +0 -1
  182. package/dist/services/mediaTimelineWindow.d.ts.map +0 -1
  183. package/dist/services/mediaTimelineWindow.js.map +0 -1
  184. package/dist/services/motionBlur.d.ts.map +0 -1
  185. package/dist/services/motionBlur.js.map +0 -1
  186. package/dist/services/pageNavigationTimeoutErrorHint.d.ts.map +0 -1
  187. package/dist/services/pageNavigationTimeoutErrorHint.js.map +0 -1
  188. package/dist/services/parallelCoordinator.d.ts.map +0 -1
  189. package/dist/services/parallelCoordinator.js.map +0 -1
  190. package/dist/services/protocolTimeoutErrorHint.d.ts.map +0 -1
  191. package/dist/services/protocolTimeoutErrorHint.js.map +0 -1
  192. package/dist/services/referenceResolver.d.ts.map +0 -1
  193. package/dist/services/referenceResolver.js.map +0 -1
  194. package/dist/services/screenshotService.d.ts.map +0 -1
  195. package/dist/services/screenshotService.js.map +0 -1
  196. package/dist/services/streamingEncoder.d.ts.map +0 -1
  197. package/dist/services/streamingEncoder.js.map +0 -1
  198. package/dist/services/systemMemory.d.ts.map +0 -1
  199. package/dist/services/systemMemory.js.map +0 -1
  200. package/dist/services/threeDProjection.d.ts.map +0 -1
  201. package/dist/services/threeDProjection.js.map +0 -1
  202. package/dist/services/videoFrameExtractor.d.ts.map +0 -1
  203. package/dist/services/videoFrameExtractor.js.map +0 -1
  204. package/dist/services/videoFrameInjector.d.ts.map +0 -1
  205. package/dist/services/videoFrameInjector.js.map +0 -1
  206. package/dist/services/vp9Options.d.ts.map +0 -1
  207. package/dist/services/vp9Options.js.map +0 -1
  208. package/dist/services/wavChunks.d.ts.map +0 -1
  209. package/dist/services/wavChunks.js.map +0 -1
  210. package/dist/types.d.ts.map +0 -1
  211. package/dist/types.js.map +0 -1
  212. package/dist/utils/alphaBlit.d.ts.map +0 -1
  213. package/dist/utils/alphaBlit.js.map +0 -1
  214. package/dist/utils/alphaPlaneProbe.d.ts.map +0 -1
  215. package/dist/utils/alphaPlaneProbe.js.map +0 -1
  216. package/dist/utils/assertSwiftShader.d.ts.map +0 -1
  217. package/dist/utils/assertSwiftShader.js.map +0 -1
  218. package/dist/utils/crc32.d.ts.map +0 -1
  219. package/dist/utils/crc32.js.map +0 -1
  220. package/dist/utils/evenDimensions.d.ts.map +0 -1
  221. package/dist/utils/evenDimensions.js.map +0 -1
  222. package/dist/utils/ffmpegBinaries.d.ts.map +0 -1
  223. package/dist/utils/ffmpegBinaries.js.map +0 -1
  224. package/dist/utils/ffprobe.d.ts.map +0 -1
  225. package/dist/utils/ffprobe.js.map +0 -1
  226. package/dist/utils/gpuEncoder.d.ts.map +0 -1
  227. package/dist/utils/gpuEncoder.js.map +0 -1
  228. package/dist/utils/gpuParityDiff.d.ts.map +0 -1
  229. package/dist/utils/gpuParityDiff.js.map +0 -1
  230. package/dist/utils/hdr.d.ts.map +0 -1
  231. package/dist/utils/hdr.js.map +0 -1
  232. package/dist/utils/htmlTemplate.d.ts.map +0 -1
  233. package/dist/utils/htmlTemplate.js.map +0 -1
  234. package/dist/utils/jpegInput.d.ts.map +0 -1
  235. package/dist/utils/jpegInput.js.map +0 -1
  236. package/dist/utils/layerCompositor.d.ts.map +0 -1
  237. package/dist/utils/layerCompositor.js.map +0 -1
  238. package/dist/utils/managedChildProcess.d.ts.map +0 -1
  239. package/dist/utils/managedChildProcess.js.map +0 -1
  240. package/dist/utils/notMediaPayload.d.ts.map +0 -1
  241. package/dist/utils/notMediaPayload.js.map +0 -1
  242. package/dist/utils/parityContract.d.ts.map +0 -1
  243. package/dist/utils/parityContract.js.map +0 -1
  244. package/dist/utils/processRss.d.ts.map +0 -1
  245. package/dist/utils/processRss.js.map +0 -1
  246. package/dist/utils/processTracker.d.ts.map +0 -1
  247. package/dist/utils/processTracker.js.map +0 -1
  248. package/dist/utils/psnr.d.ts.map +0 -1
  249. package/dist/utils/psnr.js.map +0 -1
  250. package/dist/utils/psnrFilterAvailability.d.ts.map +0 -1
  251. package/dist/utils/psnrFilterAvailability.js.map +0 -1
  252. package/dist/utils/readWebGlVendorInfoFromCanvas.d.ts.map +0 -1
  253. package/dist/utils/readWebGlVendorInfoFromCanvas.js.map +0 -1
  254. package/dist/utils/renderProvenance.d.ts.map +0 -1
  255. package/dist/utils/renderProvenance.js.map +0 -1
  256. package/dist/utils/runFfmpeg.d.ts.map +0 -1
  257. package/dist/utils/runFfmpeg.js.map +0 -1
  258. package/dist/utils/sdrCaptureColor.d.ts.map +0 -1
  259. package/dist/utils/sdrCaptureColor.js.map +0 -1
  260. package/dist/utils/shaderTransitions.d.ts.map +0 -1
  261. package/dist/utils/shaderTransitions.js.map +0 -1
  262. package/dist/utils/urlDownloader.d.ts.map +0 -1
  263. package/dist/utils/urlDownloader.js.map +0 -1
@@ -9,7 +9,9 @@ import { audioGroupsById, isMemberGroupHidden, isSelfOrAncestorHidden } from "./
9
9
  import { copyFileSync, existsSync, linkSync, mkdirSync, rmSync } from "fs";
10
10
  import { join } from "path";
11
11
  import { cpus } from "os";
12
+ import { createConcurrencyLimit } from "../utils/concurrencyLimit.js";
12
13
  import { parseHTML } from "linkedom";
14
+ import { isPathInside } from "@hyperframes/parsers/asset-paths";
13
15
  import { resolveProjectRelativeSrc } from "@hyperframes/parsers/asset-resolution";
14
16
  import { MEDIA_RENDER_ID_ATTR, isAudibleVideoElement, fpsToFfmpegArg, fpsToNumber, MEDIA_DURATION_CLAMP_EPSILON_SECONDS, normalizeRateSpec, readElementRateSpec, shiftRateLane, sourceTimeAt, timeAtSourceTime, exportClipWindow, hasClipStarted, isInClipWindow, parseStrictFiniteTimingNumber, readMediaStart, toFps, firstFrameColourArgs, hdrToSdrToneMapFilter, parseFirstFrameColour, } from "@hyperframes/core";
15
17
  import { resolveReferencedStart } from "./referenceResolver.js";
@@ -22,7 +24,7 @@ import { runFfmpeg, runFfmpegPipeline } from "../utils/runFfmpeg.js";
22
24
  import { isFfmpegFilterAvailable } from "../utils/psnrFilterAvailability.js";
23
25
  import { DEFAULT_CONFIG } from "../config.js";
24
26
  import { unwrapTemplate } from "../utils/htmlTemplate.js";
25
- import { FRAME_FILENAME_PREFIX, gcExtractionCache, gcSweepDue, lookupCacheEntry, partialCacheEntryDir, publishCacheEntry, readKeyStat, rehydrateCacheEntry, touchCacheEntry, } from "./extractionCache.js";
27
+ import { FRAME_FILENAME_PREFIX, gcExtractionCache, gcSweepDue, lookupCacheEntry, partialCacheEntryDir, publishCacheEntry, readContentSha256, readKeyStat, rehydrateCacheEntry, touchCacheEntry, } from "./extractionCache.js";
26
28
  import { framePathsFromDirectory } from "./extractedFrameIndex.js";
27
29
  export { resolveProjectRelativeSrc };
28
30
  /**
@@ -105,6 +107,7 @@ export function extractionFrameCountForDuration(durationSeconds, fps, isVFR) {
105
107
  const frames = Number(frameCount);
106
108
  return Math.max(1, Number.isSafeInteger(frames) ? frames : Number.MAX_SAFE_INTEGER);
107
109
  }
110
+ const DOWNLOAD_SUBDIR = "_downloads";
108
111
  export const EXTRACT_CACHE_MIN_AGE_MS = 60 * 60 * 1000;
109
112
  const GC_STALENESS_MS = 24 * 60 * 60 * 1000;
110
113
  const SDR_TO_HDR_COLORSPACE_FILTER = "colorspace=all=bt2020:iall=bt709:range=tv";
@@ -487,6 +490,9 @@ function restoreSourceColourFilter(metadata) {
487
490
  * same absolute times as a single pass, so their frames are byte-identical to it.
488
491
  */
489
492
  const EXTRACTION_SEGMENT_SECONDS = 120;
493
+ // Caps extraction ffmpeg runs across all clips; uncapped, dozens of clips starved each other into timeouts.
494
+ const EXTRACTION_SLOTS = Math.max(1, Math.floor(cpus().length / 2));
495
+ const inExtractionSlot = createConcurrencyLimit(EXTRACTION_SLOTS);
490
496
  /** Split runs so no single ffmpeg process extracts more than `segmentFrames` frames. */
491
497
  function splitFrameRanges(ranges, segmentFrames) {
492
498
  const segments = [];
@@ -514,7 +520,7 @@ async function runSegmentedExtraction(job) {
514
520
  while (next < segmentCount && !signal.aborted) {
515
521
  const index = next++;
516
522
  const { firstFrame, frames } = segments[index];
517
- const result = await runFfmpeg([
523
+ const result = await inExtractionSlot(() => runFfmpeg([
518
524
  ...decodeArgs,
519
525
  "-noaccurate_seek",
520
526
  "-ss",
@@ -529,13 +535,13 @@ async function runSegmentedExtraction(job) {
529
535
  "-start_number",
530
536
  String(firstFrame + 1),
531
537
  ...filterAndEncodeArgs,
532
- ], { ...job.runOptions, signal });
538
+ ], { ...job.runOptions, signal }), signal);
533
539
  results[index] = result;
534
540
  if (!result.success)
535
541
  failed.abort();
536
542
  }
537
543
  };
538
- const workers = Math.min(segmentCount, Math.max(1, Math.floor(cpus().length / 2)));
544
+ const workers = Math.min(segmentCount, EXTRACTION_SLOTS);
539
545
  await Promise.all(Array.from({ length: workers }, worker));
540
546
  const ran = results.filter(Boolean);
541
547
  // Report the segment that failed, not the ones stopped because of it.
@@ -667,7 +673,7 @@ outputDirOverride) {
667
673
  NUT_RAW_PIXEL_FORMATS.has(metadata.pixelFormat ?? "")) {
668
674
  // ffmpeg <6.1 ignores frame durations in CFR resampling once any -vf is set,
669
675
  // cutting a trailing still short, so the SDR filters run in a second process.
670
- processResult = await runFfmpegPipeline([...args, "-an", "-sn", "-dn", "-c:v", "rawvideo", "-f", "nut", "pipe:1"], [
676
+ processResult = await inExtractionSlot(() => runFfmpegPipeline([...args, "-an", "-sn", "-dn", "-c:v", "rawvideo", "-f", "nut", "pipe:1"], [
671
677
  "-f",
672
678
  "nut",
673
679
  "-i",
@@ -677,7 +683,7 @@ outputDirOverride) {
677
683
  "-fps_mode",
678
684
  "passthrough",
679
685
  ...encodeArgs,
680
- ], runOptions);
686
+ ], runOptions), signal);
681
687
  }
682
688
  else {
683
689
  const filterArgs = vfFilters.length > 0 ? ["-vf", vfFilters.join(",")] : [];
@@ -694,7 +700,7 @@ outputDirOverride) {
694
700
  segments: splitFrameRanges(options.frameRanges ?? [{ firstFrame: 0, frames: totalFrames }], segmentFrames),
695
701
  runOptions,
696
702
  })
697
- : await runFfmpeg([...args, ...filterArgs, ...encodeArgs], runOptions);
703
+ : await inExtractionSlot(() => runFfmpeg([...args, ...filterArgs, ...encodeArgs], runOptions), signal);
698
704
  }
699
705
  if (processResult.failureReason === "external_interruption") {
700
706
  throw new VideoSourceExtractionError("external_interruption", true, "Video frame extraction interrupted by host lifecycle", `FFmpeg exited with code ${processResult.exitCode}: ${processResult.stderr.slice(-500)}`);
@@ -801,6 +807,9 @@ function canHoldFinalFramePastEof(video) {
801
807
  // deliberately below any supported output frame interval: coverage expects
802
808
  // one frame, while FFmpeg seeks to the separately probed real frame timestamp.
803
809
  const FINAL_FRAME_LOGICAL_DURATION_SECONDS = 1e-6;
810
+ export function isVideoPastTimelineEnd(video, timelineEnd) {
811
+ return video.start >= timelineEnd;
812
+ }
804
813
  /** Move a clip to its extraction window; a rate lane is shifted so it keeps integrating from the new origin. */
805
814
  export function rebaseVideoToWindow(video, window) {
806
815
  if (window.preserveTimelinePhase)
@@ -1166,15 +1175,16 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
1166
1175
  for (const video of videos) {
1167
1176
  if (signal?.aborted)
1168
1177
  break;
1169
- if (options.timelineEnd !== undefined && video.start >= options.timelineEnd)
1178
+ if (options.timelineEnd !== undefined && isVideoPastTimelineEnd(video, options.timelineEnd)) {
1170
1179
  continue;
1180
+ }
1171
1181
  try {
1172
1182
  let videoPath = video.src;
1173
1183
  if (!isHttpUrl(videoPath)) {
1174
1184
  videoPath = resolveProjectRelativeSrc(video.src, baseDir, compiledDir);
1175
1185
  }
1176
1186
  if (isHttpUrl(videoPath)) {
1177
- const downloadDir = join(options.outputDir, "_downloads");
1187
+ const downloadDir = join(options.outputDir, DOWNLOAD_SUBDIR);
1178
1188
  mkdirSync(downloadDir, { recursive: true });
1179
1189
  videoPath = await downloadToTemp(videoPath, downloadDir, undefined, signal, () => recordTransientRetries(1), { onTelemetry: writeUrlDownloadTelemetry });
1180
1190
  }
@@ -1218,6 +1228,11 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
1218
1228
  // HDR preflight. Without this, every render would write a new
1219
1229
  // normalized file with a fresh mtime → fresh cache key → perpetual misses.
1220
1230
  // Phase 3 updates mediaStart after trimming any invisible negative preroll.
1231
+ // Downloads land at a new path and mtime every render, so they are keyed by content instead.
1232
+ const contentKeyedDirs = [
1233
+ join(options.outputDir, DOWNLOAD_SUBDIR),
1234
+ ...(options.contentKeyedDirs ?? []),
1235
+ ];
1221
1236
  const cacheKeyInputs = resolvedVideos.map(({ video, videoPath }) => {
1222
1237
  const stat = readKeyStat(videoPath);
1223
1238
  // Missing files return null — skip the cache path for that entry. The
@@ -1231,6 +1246,7 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
1231
1246
  mtimeMs: stat.mtimeMs,
1232
1247
  size: stat.size,
1233
1248
  mediaStart: video.mediaStart,
1249
+ contentKeyed: contentKeyedDirs.some((dir) => isPathInside(videoPath, dir)),
1234
1250
  };
1235
1251
  });
1236
1252
  // Phase 2: Probe color spaces and normalize if mixed HDR/SDR
@@ -1410,12 +1426,30 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
1410
1426
  });
1411
1427
  return { ...rehydrated, ownedByLookup: true };
1412
1428
  }
1429
+ // Hashed only for works that reach a lookup (deferred ranges never do), once per file.
1430
+ const contentSha256ByPath = new Map();
1431
+ async function hashContentKeyedSources(works) {
1432
+ if (!cacheRootDir)
1433
+ return;
1434
+ const paths = new Set();
1435
+ for (const work of works) {
1436
+ const keyInput = cacheKeyInputs[work.index];
1437
+ if (keyInput?.contentKeyed)
1438
+ paths.add(keyInput.videoPath);
1439
+ }
1440
+ await Promise.all([...paths].map(async (path) => contentSha256ByPath.set(path, await readContentSha256(path, signal))));
1441
+ }
1413
1442
  function lookupCacheFor(work) {
1414
1443
  if (!cacheRootDir)
1415
1444
  return { work };
1416
1445
  const keyInput = cacheKeyInputs[work.index];
1417
1446
  if (!keyInput)
1418
1447
  return { work };
1448
+ const contentSha256 = keyInput.contentKeyed
1449
+ ? (contentSha256ByPath.get(keyInput.videoPath) ?? null)
1450
+ : undefined;
1451
+ if (contentSha256 === null)
1452
+ return { work };
1419
1453
  const transformParts = [
1420
1454
  work.sdrToHdrTransfer ? sdrToHdrTransformKey(work.sdrToHdrTransfer) : undefined,
1421
1455
  work.hdrToSdrTransformKey,
@@ -1427,6 +1461,7 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
1427
1461
  mtimeMs: keyInput.mtimeMs,
1428
1462
  size: keyInput.size,
1429
1463
  mediaStart: keyInput.mediaStart,
1464
+ contentSha256,
1430
1465
  duration: work.videoDuration,
1431
1466
  fps: fpsKey,
1432
1467
  format: work.format,
@@ -1657,9 +1692,9 @@ export async function extractAllVideoFrames(videos, baseDir, options, signal, co
1657
1692
  });
1658
1693
  }
1659
1694
  const cacheMisses = [];
1660
- for (const work of uniqueWorks.values()) {
1661
- if (uniqueOutcomes.has(work.dedupeKey))
1662
- continue;
1695
+ const worksToLookUp = [...uniqueWorks.values()].filter((work) => !uniqueOutcomes.has(work.dedupeKey));
1696
+ await hashContentKeyedSources(worksToLookUp);
1697
+ for (const work of worksToLookUp) {
1663
1698
  const lookup = lookupCacheFor(work);
1664
1699
  if ("work" in lookup) {
1665
1700
  cacheMisses.push(lookup);
@@ -1929,4 +1964,3 @@ export function createFrameLookupTable(videos, extracted, fps) {
1929
1964
  }
1930
1965
  return table;
1931
1966
  }
1932
- //# sourceMappingURL=videoFrameExtractor.js.map
@@ -149,4 +149,3 @@ export interface ElementStackingInfo {
149
149
  */
150
150
  export declare function queryElementStacking(page: Page, nativeHdrIds: Set<string>): Promise<ElementStackingInfo[]>;
151
151
  export {};
152
- //# sourceMappingURL=videoFrameInjector.d.ts.map
@@ -593,4 +593,3 @@ export async function queryElementStacking(page, nativeHdrIds) {
593
593
  return results;
594
594
  }, hdrIds, RENDER_FRAME_ID_PREFIX, RENDER_FRAME_ID_SUFFIX);
595
595
  }
596
- //# sourceMappingURL=videoFrameInjector.js.map
@@ -3,4 +3,3 @@ export declare const MIN_VP9_CPU_USED = -8;
3
3
  export declare const MAX_VP9_CPU_USED = 8;
4
4
  export declare function normalizeVp9CpuUsed(value: number | undefined): number;
5
5
  export declare function appendVp9CpuUsedArg(args: string[], value: number | undefined): void;
6
- //# sourceMappingURL=vp9Options.d.ts.map
@@ -10,4 +10,3 @@ export function normalizeVp9CpuUsed(value) {
10
10
  export function appendVp9CpuUsedArg(args, value) {
11
11
  args.push("-cpu-used", String(normalizeVp9CpuUsed(value)));
12
12
  }
13
- //# sourceMappingURL=vp9Options.js.map
@@ -17,4 +17,3 @@ export interface RiffChunk {
17
17
  export declare function riffChunks(buffer: Buffer): Generator<RiffChunk>;
18
18
  /** Canonical codec tag, or null for a truncated or unsupported extensible header. */
19
19
  export declare function wavFormatTag(buffer: Buffer, body: number, size: number): number | null;
20
- //# sourceMappingURL=wavChunks.d.ts.map
@@ -36,4 +36,3 @@ export function wavFormatTag(buffer, body, size) {
36
36
  return tag;
37
37
  return fmt.length < 40 ? null : extensibleFormatTag(fmt);
38
38
  }
39
- //# sourceMappingURL=wavChunks.js.map
package/dist/types.d.ts CHANGED
@@ -388,4 +388,3 @@ declare global {
388
388
  __hf?: HfProtocol;
389
389
  }
390
390
  }
391
- //# sourceMappingURL=types.d.ts.map
package/dist/types.js CHANGED
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=types.js.map
@@ -189,4 +189,3 @@ export declare function normalizeObjectFit(value: string | undefined): ObjectFit
189
189
  * flattening their scene rather than failing it.
190
190
  */
191
191
  export declare function parseTransformMatrix(css: string): number[] | null;
192
- //# sourceMappingURL=alphaBlit.d.ts.map
@@ -929,4 +929,3 @@ function warnIfZSignificant(parts) {
929
929
  `This warning is emitted once per process.`);
930
930
  }
931
931
  }
932
- //# sourceMappingURL=alphaBlit.js.map
@@ -6,4 +6,3 @@ export declare function sampledRgbaAlphaIsFullyOpaque(buf: Buffer): boolean | un
6
6
  */
7
7
  export declare function probeInputAlphaPlane(videoPath: string, decoder: string, signal?: AbortSignal): Promise<boolean | undefined>;
8
8
  export declare function inputAlphaOpaqueWarning(src: string): string;
9
- //# sourceMappingURL=alphaPlaneProbe.d.ts.map
@@ -62,4 +62,3 @@ export function inputAlphaOpaqueWarning(src) {
62
62
  "it with an alpha pixel format and avoid remuxing afterward, which can drop the " +
63
63
  "alpha while keeping the tag.\n");
64
64
  }
65
- //# sourceMappingURL=alphaPlaneProbe.js.map
@@ -56,4 +56,3 @@ export declare function readWebGlVendorInfo(page: Page): Promise<WebGlInfo>;
56
56
  */
57
57
  export declare function assertSwiftShader(page: Page, readInfo?: (page: Page) => Promise<WebGlInfo>): Promise<void>;
58
58
  export {};
59
- //# sourceMappingURL=assertSwiftShader.d.ts.map
@@ -103,4 +103,3 @@ export async function assertSwiftShader(page, readInfo = readWebGlVendorInfo) {
103
103
  `Ensure Chrome was launched with --use-gl=swiftshader --use-angle=swiftshader and that the ` +
104
104
  `SwiftShader libraries are present in the runtime image.`, vendor, renderer);
105
105
  }
106
- //# sourceMappingURL=assertSwiftShader.js.map
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Runs at most `limit` tasks at once; later tasks wait, in order, for a free slot. A waiter whose
3
+ * `signal` aborts stops waiting and runs at once without a slot, so a cancel never queues behind others.
4
+ */
5
+ export declare function createConcurrencyLimit(limit: number): <T>(task: () => Promise<T>, signal?: AbortSignal) => Promise<T>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Runs at most `limit` tasks at once; later tasks wait, in order, for a free slot. A waiter whose
3
+ * `signal` aborts stops waiting and runs at once without a slot, so a cancel never queues behind others.
4
+ */
5
+ export function createConcurrencyLimit(limit) {
6
+ let active = 0;
7
+ const waiting = [];
8
+ const waitForSlot = (signal) => new Promise((resolve) => {
9
+ const granted = () => {
10
+ signal?.removeEventListener("abort", aborted);
11
+ resolve(true);
12
+ };
13
+ const aborted = () => {
14
+ waiting.splice(waiting.indexOf(granted), 1);
15
+ resolve(false);
16
+ };
17
+ waiting.push(granted);
18
+ signal?.addEventListener("abort", aborted, { once: true });
19
+ });
20
+ return async (task, signal) => {
21
+ if (signal?.aborted)
22
+ return task();
23
+ if (active < limit)
24
+ active++;
25
+ else if (!(await waitForSlot(signal)))
26
+ return task();
27
+ try {
28
+ return await task();
29
+ }
30
+ finally {
31
+ // Hand the slot straight to the next waiter so a newcomer cannot take it first.
32
+ const next = waiting.shift();
33
+ if (next)
34
+ next();
35
+ else
36
+ active--;
37
+ }
38
+ };
39
+ }
@@ -1,2 +1 @@
1
1
  export declare function chunkCrc32(chunkType: string, chunkData: Buffer): number;
2
- //# sourceMappingURL=crc32.d.ts.map
@@ -32,4 +32,3 @@ export function chunkCrc32(chunkType, chunkData) {
32
32
  return nativeCrc32(chunkData, nativeCrc32(typeBytes));
33
33
  return crc32Fallback(chunkData, crc32Fallback(typeBytes, 0));
34
34
  }
35
- //# sourceMappingURL=crc32.js.map
@@ -32,4 +32,3 @@ export declare function requiresEvenDimensions(pixelFormat: string): boolean;
32
32
  * returns just the pad when there is no existing chain.
33
33
  */
34
34
  export declare function withEvenDimensionPad(vfChain: string, pixelFormat: string, width?: number, height?: number): string;
35
- //# sourceMappingURL=evenDimensions.d.ts.map
@@ -46,4 +46,3 @@ export function withEvenDimensionPad(vfChain, pixelFormat, width, height) {
46
46
  }
47
47
  return vfChain ? `${vfChain},${EVEN_DIMENSION_PAD}` : EVEN_DIMENSION_PAD;
48
48
  }
49
- //# sourceMappingURL=evenDimensions.js.map
@@ -3,4 +3,3 @@ export { FFMPEG_PATH_ENV, FFPROBE_PATH_ENV };
3
3
  export declare function getFfmpegBinary(): string;
4
4
  export declare function getFfprobeBinary(): string;
5
5
  export declare function assertConfiguredFfmpegBinariesExist(): void;
6
- //# sourceMappingURL=ffmpegBinaries.d.ts.map
@@ -27,4 +27,3 @@ function pathEncodingHint(configuredPath) {
27
27
  return "";
28
28
  return " The path contains a Unicode replacement character, which usually means it was mangled while being copied or decoded.";
29
29
  }
30
- //# sourceMappingURL=ffmpegBinaries.js.map
@@ -154,4 +154,3 @@ export interface KeyframeAnalysis {
154
154
  */
155
155
  export declare function analyzeKeyframeIntervals(filePath: string, metadata: Pick<VideoMetadata, "videoStreamDurationSeconds" | "videoStreamStartSeconds">): Promise<KeyframeAnalysis>;
156
156
  export {};
157
- //# sourceMappingURL=ffprobe.d.ts.map
@@ -141,6 +141,7 @@ const AUDIO_DURATION_PROBE_MARGIN_SECONDS = 0.05;
141
141
  // How far before the container's claimed end the decode probe starts reading,
142
142
  // so it decodes only the tail instead of the whole stream.
143
143
  const AUDIO_DURATION_PROBE_TAIL_SECONDS = 1;
144
+ const FFPROBE_READ_INTERVAL_EXPLICIT_FAR_END = "+2147483647";
144
145
  const STILL_IMAGE_DEMUXERS = new Set([
145
146
  "apng",
146
147
  "bmp_pipe",
@@ -845,7 +846,7 @@ async function probeDecodedAudioDuration(filePath, sampleRate, startSeconds, con
845
846
  }
846
847
  };
847
848
  const tailStart = Math.max(startSeconds, startSeconds + containerDurationSeconds - AUDIO_DURATION_PROBE_TAIL_SECONDS);
848
- const lastFrame = (await probe(`${tailStart}%`)) ?? (await probe());
849
+ const lastFrame = (await probe(`${tailStart}%${FFPROBE_READ_INTERVAL_EXPLICIT_FAR_END}`)) ?? (await probe());
849
850
  if (!lastFrame)
850
851
  return null;
851
852
  return lastFrame.timestamp + lastFrame.nbSamples / sampleRate - startSeconds;
@@ -928,4 +929,3 @@ async function analyzeKeyframeIntervalsUncached(filePath, videoStreamStartSecond
928
929
  isProblematic: maxInterval > PROBLEMATIC_KEYFRAME_INTERVAL_SECONDS,
929
930
  };
930
931
  }
931
- //# sourceMappingURL=ffprobe.js.map
@@ -31,4 +31,3 @@ export declare function getProbeArgs(encoder: ConcreteGpuEncoder): string[];
31
31
  * `-preset` entirely or accept the libx264 vocabulary).
32
32
  */
33
33
  export declare function mapPresetForGpuEncoder(encoder: GpuEncoder, preset: string): string;
34
- //# sourceMappingURL=gpuEncoder.d.ts.map
@@ -224,4 +224,3 @@ export function mapPresetForGpuEncoder(encoder, preset) {
224
224
  return preset;
225
225
  }
226
226
  }
227
- //# sourceMappingURL=gpuEncoder.js.map
@@ -139,4 +139,3 @@ export declare function diffGpuParityPngs(pngA: Buffer, pngB: Buffer, options?:
139
139
  * metrics without a second pass.
140
140
  */
141
141
  export declare function verifyGpuParity(a: RgbaFrame, b: RgbaFrame, options?: GpuParityDiffOptions): VerifyGpuParityResult;
142
- //# sourceMappingURL=gpuParityDiff.d.ts.map
@@ -49,7 +49,7 @@ const DEFAULT_BLACK_ONLY_FRACTION_THRESHOLD = 0.001;
49
49
  */
50
50
  export function diffGpuParityFrames(a, b, options = {}) {
51
51
  if (a.width !== b.width || a.height !== b.height) {
52
- throw new Error(`diffGpuParityFrames: frame size mismatch — A is ${a.width}x${a.height}, ` +
52
+ throw new Error(`diffGpuParityFrames: frame size mismatch: A is ${a.width}x${a.height}, ` +
53
53
  `B is ${b.width}x${b.height}`);
54
54
  }
55
55
  const expectedLen = a.width * a.height * 4;
@@ -66,7 +66,7 @@ export function diffGpuParityFrames(a, b, options = {}) {
66
66
  const contentSum = options.contentSumThreshold ?? DEFAULT_CONTENT_SUM_THRESHOLD;
67
67
  if (contentSum <= blackSum) {
68
68
  throw new Error(`diffGpuParityFrames: contentSumThreshold (${contentSum}) must be strictly greater ` +
69
- `than blackSumThreshold (${blackSum}) — overlapping thresholds would double-classify ` +
69
+ `than blackSumThreshold (${blackSum}): overlapping thresholds would double-classify ` +
70
70
  `borderline pixels`);
71
71
  }
72
72
  const total = a.width * a.height;
@@ -183,7 +183,7 @@ export function verifyGpuParity(a, b, options = {}) {
183
183
  ok: false,
184
184
  reason: `hardware-GPU frame has ${diff.blackOnlyInA.pixels} pixel(s) ` +
185
185
  `(${(diff.blackOnlyInA.fraction * 100).toFixed(3)}%) that are solid-black ` +
186
- `while software-GPU frame has content there${region} — likely shape-dependent ` +
186
+ `while software-GPU frame has content there${region}, likely a shape-dependent ` +
187
187
  `hardware-GPU capture bug`,
188
188
  diff,
189
189
  };
@@ -195,11 +195,10 @@ export function verifyGpuParity(a, b, options = {}) {
195
195
  ok: false,
196
196
  reason: `software-GPU frame has ${diff.blackOnlyInB.pixels} pixel(s) ` +
197
197
  `(${(diff.blackOnlyInB.fraction * 100).toFixed(3)}%) that are solid-black ` +
198
- `while hardware-GPU frame has content there${region} — unexpected inverse ` +
198
+ `while hardware-GPU frame has content there${region}, an unexpected inverse ` +
199
199
  `pattern, worth investigating`,
200
200
  diff,
201
201
  };
202
202
  }
203
203
  return { ok: true, reason: "", diff };
204
204
  }
205
- //# sourceMappingURL=gpuParityDiff.js.map
@@ -93,4 +93,3 @@ export declare function formatHdrAutoPromotionWarning(promotion: HdrAutoPromotio
93
93
  * contains HDR content and what the dominant transfer function is.
94
94
  */
95
95
  export declare function analyzeCompositionHdr(colorSpaces: Array<VideoColorSpace | null>): CompositionHdrInfo;
96
- //# sourceMappingURL=hdr.d.ts.map
package/dist/utils/hdr.js CHANGED
@@ -81,7 +81,7 @@ export function findHdrAutoPromotion(sources) {
81
81
  : null;
82
82
  }
83
83
  export function formatHdrAutoPromotionWarning(promotion) {
84
- return `[Render] HDR auto-promotion triggered by "${promotion.triggeringAsset}" — output: ${promotion.output.colorSpace} / ${promotion.output.codec}`;
84
+ return `[Render] HDR auto-promotion triggered by "${promotion.triggeringAsset}", output: ${promotion.output.colorSpace} / ${promotion.output.codec}`;
85
85
  }
86
86
  /**
87
87
  * Analyze a set of video color spaces to determine if the composition
@@ -103,4 +103,3 @@ export function analyzeCompositionHdr(colorSpaces) {
103
103
  const dominantTransfer = hasPq ? "pq" : "hlg";
104
104
  return { hasHdr: true, dominantTransfer };
105
105
  }
106
- //# sourceMappingURL=hdr.js.map
@@ -5,4 +5,3 @@
5
5
  * of inputs that contain multiple sibling templates or other top-level content.
6
6
  */
7
7
  export declare function unwrapTemplate(html: string): string;
8
- //# sourceMappingURL=htmlTemplate.d.ts.map
@@ -39,4 +39,3 @@ export function unwrapTemplate(html) {
39
39
  }
40
40
  return template.innerHTML ?? html;
41
41
  }
42
- //# sourceMappingURL=htmlTemplate.js.map
@@ -1,3 +1,2 @@
1
1
  /** Check JPEG headers before image2pipe; entropy-coded pixels still belong to FFmpeg. */
2
2
  export declare function jpegInputError(buffer: Buffer): string | undefined;
3
- //# sourceMappingURL=jpegInput.d.ts.map
@@ -59,4 +59,3 @@ function quantizationTableError(buffer, start, end) {
59
59
  }
60
60
  return undefined;
61
61
  }
62
- //# sourceMappingURL=jpegInput.js.map
@@ -33,4 +33,3 @@ export type CompositeLayer = {
33
33
  * hide them).
34
34
  */
35
35
  export declare function groupIntoLayers(elements: ElementStackingInfo[]): CompositeLayer[];
36
- //# sourceMappingURL=layerCompositor.d.ts.map
@@ -46,4 +46,3 @@ export function groupIntoLayers(elements) {
46
46
  }
47
47
  return layers;
48
48
  }
49
- //# sourceMappingURL=layerCompositor.js.map
@@ -47,4 +47,3 @@ export declare class ManagedChildProcess {
47
47
  private settle;
48
48
  private clearTimers;
49
49
  }
50
- //# sourceMappingURL=managedChildProcess.d.ts.map
@@ -145,4 +145,3 @@ export class ManagedChildProcess {
145
145
  this.escalationTimer = null;
146
146
  }
147
147
  }
148
- //# sourceMappingURL=managedChildProcess.js.map
@@ -61,4 +61,3 @@ export declare function isNotMediaPayload(filePath: string): Promise<boolean>;
61
61
  * through its `svg_pipe` demuxer, so image sources must not be sniffed.
62
62
  */
63
63
  export declare function assertMediaPayload(filePath: string, elementId: string): Promise<void>;
64
- //# sourceMappingURL=notMediaPayload.d.ts.map
@@ -142,4 +142,3 @@ export async function assertMediaPayload(filePath, elementId) {
142
142
  throw new NotMediaPayloadError([fingerprintElementId(elementId)]);
143
143
  }
144
144
  }
145
- //# sourceMappingURL=notMediaPayload.js.map
@@ -1,2 +1 @@
1
1
  export { MEDIA_VISUAL_STYLE_PROPERTIES, quantizeTimeToFrame } from "@hyperframes/core";
2
- //# sourceMappingURL=parityContract.d.ts.map
@@ -1,2 +1 @@
1
1
  export { MEDIA_VISUAL_STYLE_PROPERTIES, quantizeTimeToFrame } from "@hyperframes/core";
2
- //# sourceMappingURL=parityContract.js.map
@@ -20,4 +20,3 @@ export declare function parseProcStatusRss(pid: number, status: string): Process
20
20
  * rejects; a pid that exited between discovery and sampling is simply absent.
21
21
  */
22
22
  export declare function sampleProcessRss(pids: readonly number[], exec?: ExecFileLike, platform?: NodeJS.Platform, readStatus?: ReadFileLike): Promise<ProcessRssSample[]>;
23
- //# sourceMappingURL=processRss.d.ts.map
@@ -90,4 +90,3 @@ export async function sampleProcessRss(pids, exec = defaultExec(), platform = pr
90
90
  return [];
91
91
  }
92
92
  }
93
- //# sourceMappingURL=processRss.js.map
@@ -5,4 +5,3 @@ export declare function trackChildProcess(proc: ChildProcess): void;
5
5
  * after a short grace period.
6
6
  */
7
7
  export declare function killTrackedProcesses(): void;
8
- //# sourceMappingURL=processTracker.d.ts.map
@@ -36,4 +36,3 @@ export function killTrackedProcesses() {
36
36
  }
37
37
  }, 500).unref();
38
38
  }
39
- //# sourceMappingURL=processTracker.js.map
@@ -10,4 +10,3 @@ export declare function psnrDb(a: Buffer, b: Buffer): Promise<number>;
10
10
  * every prior eval used to separate real compositor damage from encoder noise.
11
11
  */
12
12
  export declare function resolveDeVerifyMinDb(): number;
13
- //# sourceMappingURL=psnr.d.ts.map
@@ -39,4 +39,3 @@ export function resolveDeVerifyMinDb() {
39
39
  const raw = Number(process.env.HF_DE_VERIFY_MIN_DB ?? "32");
40
40
  return Number.isFinite(raw) && raw >= 10 && raw <= 60 ? raw : 32;
41
41
  }
42
- //# sourceMappingURL=psnr.js.map
@@ -11,4 +11,3 @@ export declare function isPsnrFilterAvailable(): Promise<boolean>;
11
11
  export declare function isFfmpegFilterAvailable(name: string): Promise<boolean>;
12
12
  /** Test-only: drop the memoized probe result. */
13
13
  export declare function resetPsnrFilterAvailabilityCache(): void;
14
- //# sourceMappingURL=psnrFilterAvailability.d.ts.map
@@ -56,4 +56,3 @@ async function listFilters() {
56
56
  return null;
57
57
  }
58
58
  }
59
- //# sourceMappingURL=psnrFilterAvailability.js.map
@@ -17,4 +17,3 @@ export declare function readWebGlVendorInfoFromCanvas(page: Page): Promise<{
17
17
  vendor: string;
18
18
  renderer: string;
19
19
  }>;
20
- //# sourceMappingURL=readWebGlVendorInfoFromCanvas.d.ts.map
@@ -42,4 +42,3 @@ export async function readWebGlVendorInfoFromCanvas(page) {
42
42
  }
43
43
  });
44
44
  }
45
- //# sourceMappingURL=readWebGlVendorInfoFromCanvas.js.map
@@ -55,4 +55,3 @@ export interface RenderProvenance {
55
55
  * case-insensitive — a case-sensitive read works on mp4 and misses every webm.
56
56
  */
57
57
  export declare function readRenderProvenance(tags: Record<string, string | undefined> | undefined): RenderProvenance | null;
58
- //# sourceMappingURL=renderProvenance.d.ts.map
@@ -162,4 +162,3 @@ export function readRenderProvenance(tags) {
162
162
  return null;
163
163
  return { renderer, version: readTagCI(tags, PROVENANCE_VERSION_TAG) };
164
164
  }
165
- //# sourceMappingURL=renderProvenance.js.map
@@ -47,10 +47,11 @@ export declare function ffmpegStatsReader(onStats: (stats: FfmpegStats) => void)
47
47
  * exactly which option to fix.
48
48
  */
49
49
  export declare function formatFfmpegError(exitCode: number | null, stderr: string, tailLines?: number): string;
50
+ /** formatFfmpegError, led by the timeout when this process was killed at its deadline. */
51
+ export declare function describeFfmpegFailure(result: Pick<RunFfmpegResult, "exitCode" | "stderr" | "terminationReason">, timeoutMs: number): string;
50
52
  export declare function runFfmpeg(args: string[], opts?: RunFfmpegOptions): Promise<RunFfmpegResult>;
51
53
  /**
52
54
  * Runs `ffmpeg <producerArgs> | ffmpeg <consumerArgs>`. Fails when either side
53
55
  * fails and reports the first failure, its stderr last so error tails show it.
54
56
  */
55
57
  export declare function runFfmpegPipeline(producerArgs: string[], consumerArgs: string[], opts?: RunFfmpegOptions): Promise<RunFfmpegResult>;
56
- //# sourceMappingURL=runFfmpeg.d.ts.map