hyperframes 0.8.192 → 0.8.193

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 (168) hide show
  1. package/dist/{add-TZU2UW7A.js → add-JC6DKZKC.js} +11 -11
  2. package/dist/{animatedGifPrep-NLAXC3VV.js → animatedGifPrep-S6KXJGEL.js} +5 -5
  3. package/dist/api.js +13 -13
  4. package/dist/{asset-JAJXA6LB.js → asset-XITFIFE6.js} +2 -2
  5. package/dist/{assetCataloger-4WTX3J4I.js → assetCataloger-K5FNKG35.js} +5 -5
  6. package/dist/{audio-XLWC7JKS.js → audio-364UHTY4.js} +11 -11
  7. package/dist/{auth-5K6X3NPJ.js → auth-5JEESRE6.js} +1 -1
  8. package/dist/{autoUpdate-RNV7SKGB.js → autoUpdate-RVVYEHAA.js} +3 -3
  9. package/dist/{backgroundChecks-QXLVZVGX.js → backgroundChecks-DCBIYWIQ.js} +3 -3
  10. package/dist/backgroundChecksWorker.js +3 -3
  11. package/dist/{batchRender-THKSPDZR.js → batchRender-ZZ4QMBAA.js} +3 -3
  12. package/dist/{beats-K7CGCFVL.js → beats-YEL65M6G.js} +7 -7
  13. package/dist/{benchmark-PHRDIXNL.js → benchmark-RBTRPA76.js} +8 -8
  14. package/dist/{browser-GN6R5ZSK.js → browser-BVAYXT4R.js} +3 -3
  15. package/dist/{bundleWithLocalizedFonts-C325UNR4.js → bundleWithLocalizedFonts-JLB2OYMT.js} +2 -2
  16. package/dist/{capture-6UBQFHZQ.js → capture-GBXTMYLZ.js} +9 -9
  17. package/dist/{capture-BZ7APOGQ.js → capture-NIFX6IRS.js} +2 -2
  18. package/dist/{captureCompositionFrame-VORSCTWC.js → captureCompositionFrame-ATNNKUL5.js} +10 -10
  19. package/dist/{catalog-PHU2RUZ3.js → catalog-AGIF5SM5.js} +11 -11
  20. package/dist/{catch-up-HCNRM46J.js → catch-up-SZ3ULDTI.js} +4 -4
  21. package/dist/{check-TJ5ZLB4I.js → check-YLQS3TF4.js} +33 -33
  22. package/dist/{checkBrowser-DWP7ZXJ7.js → checkBrowser-QH4FMCBO.js} +28 -28
  23. package/dist/{chunk-7LLRMYP6.js → chunk-2LSCYS2H.js} +2 -2
  24. package/dist/{chunk-KZOZN4PI.js → chunk-2NERNYCJ.js} +1 -1
  25. package/dist/{chunk-RHYOWDI6.js → chunk-2SFDWMSW.js} +2 -2
  26. package/dist/{chunk-AEXVVABM.js → chunk-3W4B6G7Y.js} +1 -1
  27. package/dist/{chunk-E5V6WEMK.js → chunk-4LXZJIVY.js} +9 -9
  28. package/dist/{chunk-YWRQHRDY.js → chunk-4PPWAQYV.js} +7 -7
  29. package/dist/{chunk-WOKVXK4J.js → chunk-4TKJWWPL.js} +1 -1
  30. package/dist/{chunk-NXMYHJAL.js → chunk-4VYPICIA.js} +29 -1
  31. package/dist/{chunk-6WNLQI63.js → chunk-5J6TWLFG.js} +3 -3
  32. package/dist/{chunk-ULTKB5FC.js → chunk-6DLCOQR4.js} +461 -427
  33. package/dist/{chunk-CXRZBWSH.js → chunk-6LWUPIKD.js} +9 -9
  34. package/dist/{chunk-5IPKQHOL.js → chunk-6XUJVEY2.js} +1 -1
  35. package/dist/{chunk-MGBUWPXX.js → chunk-7HTH5PFK.js} +1 -1
  36. package/dist/{chunk-32NB4VMH.js → chunk-7QNIXBQD.js} +1 -1
  37. package/dist/{chunk-AR46ND2Q.js → chunk-7YKJF5JV.js} +1 -1
  38. package/dist/{chunk-7RSY7SZN.js → chunk-7YSFE4SZ.js} +1 -1
  39. package/dist/{chunk-IMSI7IFW.js → chunk-AR3DQYRR.js} +17 -17
  40. package/dist/{chunk-XX2PA4L3.js → chunk-BJAS2JLW.js} +1 -1
  41. package/dist/{chunk-J2ASTCU6.js → chunk-BP4EMEGH.js} +1 -1
  42. package/dist/{chunk-4HCJOFMB.js → chunk-C4Y3ZREE.js} +20 -1
  43. package/dist/{chunk-7UZC4N62.js → chunk-CGTZOY53.js} +1 -1
  44. package/dist/{chunk-OQL4AJ4X.js → chunk-D625D4TV.js} +4 -4
  45. package/dist/{chunk-R2U2G4OS.js → chunk-DSQ72G5I.js} +1 -1
  46. package/dist/{chunk-VRAXIQ6I.js → chunk-DYNHVCBF.js} +1 -1
  47. package/dist/{chunk-SBBQFPCJ.js → chunk-E77ALFLW.js} +1 -1
  48. package/dist/{chunk-5TRFLZ5Z.js → chunk-EFXMETRK.js} +1 -1
  49. package/dist/{chunk-MEE4NTPZ.js → chunk-F5LLORBP.js} +2 -2
  50. package/dist/{chunk-A4OI5ZNX.js → chunk-GKHMSSGY.js} +1 -1
  51. package/dist/{chunk-AMZJFCOX.js → chunk-GR5DQKDR.js} +5 -5
  52. package/dist/{chunk-W24SZ5FL.js → chunk-KU3UFQN7.js} +5 -8
  53. package/dist/{chunk-QX4TB4NH.js → chunk-L4JB7LI4.js} +320 -75
  54. package/dist/{chunk-K2AKVYNR.js → chunk-L5YLA54L.js} +2 -2
  55. package/dist/{chunk-3FV5BVWS.js → chunk-LFUVTS6V.js} +2 -2
  56. package/dist/{chunk-4E75LHAL.js → chunk-LMNZLZMJ.js} +1 -1
  57. package/dist/{chunk-LOKCBZYF.js → chunk-M3KZBDPB.js} +3 -3
  58. package/dist/{chunk-VOM2HLUI.js → chunk-MFUNDJEV.js} +3 -3
  59. package/dist/{chunk-7JJMT6LN.js → chunk-OFV3WSOE.js} +1 -1
  60. package/dist/{chunk-L2YGSAOL.js → chunk-OFYW4J7Y.js} +2 -2
  61. package/dist/{chunk-T6O5OLN2.js → chunk-QKX7ITER.js} +2 -2
  62. package/dist/{chunk-BV6YE455.js → chunk-RTLPWOO6.js} +1 -1
  63. package/dist/{chunk-BPKLUHFT.js → chunk-SOY2FPOR.js} +5 -5
  64. package/dist/{chunk-YMQQXPD5.js → chunk-TY3LDJA3.js} +5 -12
  65. package/dist/{chunk-2HP5GIQ3.js → chunk-TZEKVLPV.js} +1 -1
  66. package/dist/{chunk-QWLES6YV.js → chunk-UB7BIDBS.js} +3 -3
  67. package/dist/{chunk-JCDYDF54.js → chunk-UIC7B5KW.js} +1 -1
  68. package/dist/{chunk-2J3NA3OB.js → chunk-UNATIAOT.js} +7 -7
  69. package/dist/chunk-USWPZXEA.js +3897 -0
  70. package/dist/{chunk-ZEMDV6W2.js → chunk-V7ZA2BNW.js} +1 -1
  71. package/dist/{chunk-PFRG5P32.js → chunk-VLLFORE2.js} +1 -1
  72. package/dist/{chunk-EKGGSAWR.js → chunk-VPC4XIVI.js} +5 -5
  73. package/dist/{chunk-6XVKMBUA.js → chunk-VW63MHQU.js} +1 -1
  74. package/dist/{chunk-MVIJTXN5.js → chunk-WFS6S65A.js} +12 -12
  75. package/dist/{chunk-VNPADTDD.js → chunk-WIVOXGEP.js} +2 -2
  76. package/dist/{chunk-J2BSUF6X.js → chunk-X5CECNCK.js} +1 -1
  77. package/dist/{chunk-SK7TR7BL.js → chunk-XQPA4W3M.js} +2 -2
  78. package/dist/{chunk-BEOK6F26.js → chunk-YS4JUGNI.js} +2 -2
  79. package/dist/{chunk-ODBYZIOH.js → chunk-ZH7J2ZUL.js} +12 -12
  80. package/dist/{chunk-XF77MK3J.js → chunk-ZT45TCY3.js} +1 -1
  81. package/dist/{chunk-3CXIX6XS.js → chunk-ZTKFRXJB.js} +3 -3
  82. package/dist/{chunk-GANST5K3.js → chunk-ZZPBXRYQ.js} +1 -1
  83. package/dist/{clean-2RNCTDBT.js → clean-5HGESK5A.js} +14 -14
  84. package/dist/cli.js +54 -54
  85. package/dist/{cloud-NFIKESNZ.js → cloud-746PHS32.js} +4 -4
  86. package/dist/{cloudrun-7224BCX3.js → cloudrun-DO7WFLSM.js} +4 -4
  87. package/dist/{compare-HL44MXVX.js → compare-66YPRNG2.js} +26 -26
  88. package/dist/{compiler-WF5QTXV7.js → compiler-R4UYDWXO.js} +2 -2
  89. package/dist/{component-ZBZXSJBR.js → component-EQ3H6RFP.js} +3 -3
  90. package/dist/{compositions-76P7LDDX.js → compositions-ZZ7P5HT2.js} +9 -9
  91. package/dist/{contactSheet-43ISAESM.js → contactSheet-SZBJDOMT.js} +1 -1
  92. package/dist/{delete-4YZBYOHJ.js → delete-Z5MSLJSR.js} +2 -2
  93. package/dist/{deploy-UGUUGYLF.js → deploy-RGSAC2K5.js} +1 -1
  94. package/dist/{dist-5KKCRFPT.js → dist-RKK4YLAD.js} +2 -2
  95. package/dist/{doctor-GGVUK4NB.js → doctor-W4ZZDRTU.js} +9 -9
  96. package/dist/{events-OXPTHVDB.js → events-BSSL4A4W.js} +2 -2
  97. package/dist/{events-V2VU4J3B.js → events-UACT7PX3.js} +3 -3
  98. package/dist/{feedback-HFZ5SCUK.js → feedback-47ILDLQG.js} +6 -6
  99. package/dist/{ffmpeg-3VHY7GO3.js → ffmpeg-IEHSUNUT.js} +5 -5
  100. package/dist/{figma-7SEZTLBJ.js → figma-PLFIIYRU.js} +3 -3
  101. package/dist/fontLocalizeCli.js +7 -7
  102. package/dist/{get-Y2S2PXCM.js → get-PDWGJYNL.js} +2 -2
  103. package/dist/{gpuPolicy-UHPOWRV5.js → gpuPolicy-6UBXO6ME.js} +5 -5
  104. package/dist/{grade-compare-4VTXSQM5.js → grade-compare-5VWLQGM7.js} +26 -26
  105. package/dist/{help-HXNOACHI.js → help-DS3KMWYO.js} +1 -1
  106. package/dist/{history-XDJUI4LC.js → history-OC326NVZ.js} +9 -8
  107. package/dist/hyperframe.manifest.json +1 -1
  108. package/dist/hyperframe.runtime.iife.js +51 -51
  109. package/dist/hyperframes-player.global.js +1 -1
  110. package/dist/{info-KYRI3EZV.js → info-AUIFV6MX.js} +7 -7
  111. package/dist/{init-IL7EWMT5.js → init-MRTWWDFW.js} +25 -25
  112. package/dist/{inspect-TBNH23UC.js → inspect-55NOAXI2.js} +26 -26
  113. package/dist/{installer-O2YMFSI4.js → installer-YSFFGBBV.js} +4 -4
  114. package/dist/{keyframes-4GF62KAJ.js → keyframes-OO2BX2IB.js} +6 -6
  115. package/dist/{lambda-JFL6M4XZ.js → lambda-CXXY6QT3.js} +6 -6
  116. package/dist/{layout-7MAEFR65.js → layout-57GJXKDK.js} +26 -26
  117. package/dist/{lint-4AYHKYAM.js → lint-J4FK3Z6G.js} +6 -6
  118. package/dist/{list-3DP3D3MW.js → list-VDQUJ76B.js} +2 -2
  119. package/dist/{login-T54WQYRQ.js → login-TJSEALWW.js} +4 -4
  120. package/dist/{manager-QROK2IH3.js → manager-4PLYEEWP.js} +6 -6
  121. package/dist/{media-treatment-4CXF7MSG.js → media-treatment-GXP4PMJH.js} +11 -11
  122. package/dist/{models-IS3I6JKU.js → models-HQQQKEEP.js} +9 -9
  123. package/dist/{motionShot-DVYJZOTQ.js → motionShot-2BT5D7DC.js} +13 -13
  124. package/dist/{normalize-audio-4527JIK4.js → normalize-audio-SOLFMHNP.js} +4 -4
  125. package/dist/{open-5JE46SAX.js → open-KHEUODFQ.js} +11 -11
  126. package/dist/{parakeetRunner-7JIJGJJ7.js → parakeetRunner-BHU5NCAX.js} +10 -10
  127. package/dist/{pipeline-YEN3WFD2.js → pipeline-WFV5HDTD.js} +6 -6
  128. package/dist/{play-WFX67I7M.js → play-GB34CANJ.js} +17 -17
  129. package/dist/{preflight-D377HVUZ.js → preflight-REF3VSJ7.js} +6 -6
  130. package/dist/{present-XTSEKAC7.js → present-SIUTA7TD.js} +13 -13
  131. package/dist/{preview-5XH7EK6O.js → preview-T2GE7Z4A.js} +16 -16
  132. package/dist/{producer-TFFYF4ZM.js → producer-23KVQZAB.js} +1 -1
  133. package/dist/{projectConfig-6YUJHMCL.js → projectConfig-DBSNBPNP.js} +6 -6
  134. package/dist/{publication-JK33Y55E.js → publication-IXPUKYWJ.js} +2 -2
  135. package/dist/{publish-JHDGXWXU.js → publish-3BA5VHXJ.js} +7 -7
  136. package/dist/{remove-background-P44MYAPJ.js → remove-background-RMSCJVVQ.js} +7 -7
  137. package/dist/{render-RJ3I4E3A.js → render-6RNE2MLU.js} +12 -12
  138. package/dist/{render-RBINWWP5.js → render-XGOZMMWX.js} +27 -27
  139. package/dist/{render-HJ34EGMN.js → render-Y6CTQ3YW.js} +5 -5
  140. package/dist/{render-batch-3D6XQYUC.js → render-batch-VUR6N6EY.js} +5 -5
  141. package/dist/{resolver-HCLTFZUW.js → resolver-GJCUH57W.js} +4 -4
  142. package/dist/{sherpa-IPOUJM6Q.js → sherpa-VVAKRCPL.js} +9 -9
  143. package/dist/skills/hyperframes/references/format.md +1 -0
  144. package/dist/{skills-P67QEERC.js → skills-ZHBURVQG.js} +5 -5
  145. package/dist/{skillsUpdateCheck-IFMLRVIF.js → skillsUpdateCheck-VMDAL2O2.js} +3 -3
  146. package/dist/{snapshot-4YM4NNWJ.js → snapshot-KEOG56SL.js} +46 -41
  147. package/dist/{src-SSV66L3F.js → src-BH5NICGQ.js} +14 -4
  148. package/dist/{src-DCD3YMXX.js → src-TZLGFRRX.js} +6 -6
  149. package/dist/{staticProjectServer-C7PPGLEQ.js → staticProjectServer-BKXL5CXB.js} +14 -14
  150. package/dist/studio/assets/{hyperframes-player-ChN3cOr0.js → hyperframes-player-BMcUdmDb.js} +1 -1
  151. package/dist/studio/assets/{index-CHu83hHM.js → index-Ca-mgTnS.js} +4 -4
  152. package/dist/studio/assets/{index-BYbFcRR0.js → index-Ci6GuloR.js} +1 -1
  153. package/dist/studio/index.html +1 -1
  154. package/dist/{studio-api-6YZ7PIQR.js → studio-api-A5U6QAMC.js} +9 -7
  155. package/dist/{studioServer-EWHSE4GC.js → studioServer-5EC5CP4W.js} +43 -43
  156. package/dist/{telemetry-GGLBHZRZ.js → telemetry-BCKJXDSW.js} +3 -3
  157. package/dist/{timeline-NKHQJXJ2.js → timeline-AZWAXTAY.js} +15 -15
  158. package/dist/{tokens-FWNNDJ6R.js → tokens-X7NC3V7C.js} +2 -2
  159. package/dist/{transcribe-VD2TMMC2.js → transcribe-7NCY7QZ2.js} +8 -8
  160. package/dist/{transcribe-TRPKXZ7L.js → transcribe-SH26H755.js} +14 -14
  161. package/dist/{updateCheck-CUPS6LU3.js → updateCheck-Y7FUWQM4.js} +2 -2
  162. package/dist/{upgrade-23XO6MEX.js → upgrade-ZHGEVL65.js} +2 -2
  163. package/dist/{urlDownloader-YOAOONCK.js → urlDownloader-FPILIT7M.js} +4 -4
  164. package/dist/{validate-BWIW24G5.js → validate-KQOZR4F6.js} +20 -20
  165. package/dist/{video-XRXJS4GC.js → video-N2QAETFB.js} +5 -5
  166. package/dist/warmCheck.js +33 -33
  167. package/package.json +1 -1
  168. package/dist/chunk-B2XLXD7V.js +0 -3897
@@ -26,7 +26,7 @@ import {
26
26
  renderFrameIdForRenderId,
27
27
  resolveAuthoredTimingWindow,
28
28
  toFps
29
- } from "./chunk-MGBUWPXX.js";
29
+ } from "./chunk-7HTH5PFK.js";
30
30
  import {
31
31
  AUDIO_GROUP_RENDER_ID_ATTR,
32
32
  COLOR_GRADING_SOURCE_HIDDEN_ATTR,
@@ -63,7 +63,7 @@ import {
63
63
  sourceTimeAt,
64
64
  timeAtSourceTime,
65
65
  volumeSegmentSampleCount
66
- } from "./chunk-B2XLXD7V.js";
66
+ } from "./chunk-USWPZXEA.js";
67
67
  import {
68
68
  clampAudioGain,
69
69
  clipGain,
@@ -1477,6 +1477,7 @@ function getLowMemoryFlags() {
1477
1477
  }
1478
1478
  var CANVAS_DRAW_ELEMENT_FEATURE_FLAG = "--enable-features=CanvasDrawElement";
1479
1479
  var WEBGPU_FLAG = "--enable-unsafe-webgpu";
1480
+ var DISABLE_DXC_FLAG = "--disable-dawn-features=use_dxc";
1480
1481
  function usesSoftwareWebGpu(requiresWebGpu, config) {
1481
1482
  return !!requiresWebGpu && !!config?.allowSoftwareWebGpu && !(config.disableGpu ?? DEFAULT_CONFIG.disableGpu) && (config.browserGpuMode ?? DEFAULT_CONFIG.browserGpuMode) === "software";
1482
1483
  }
@@ -1532,6 +1533,9 @@ function buildChromeArgs(options, config) {
1532
1533
  ];
1533
1534
  if (browserGpuMode !== "software" || options.requiresWebGpu) {
1534
1535
  chromeArgs.push(WEBGPU_FLAG);
1536
+ if (platform === "win32") {
1537
+ chromeArgs.push(DISABLE_DXC_FLAG);
1538
+ }
1535
1539
  }
1536
1540
  if (softwareWebGpu) chromeArgs.push("--use-vulkan=swiftshader");
1537
1541
  if (browserGpuMode === "software" && !softwareWebGpu) {
@@ -4798,6 +4802,7 @@ var CaptureFailure = class extends Error {
4798
4802
  kind;
4799
4803
  cause;
4800
4804
  workerDiagnostics;
4805
+ pageErrorLines;
4801
4806
  constructor(input) {
4802
4807
  super(input.message);
4803
4808
  this.name = "CaptureFailure";
@@ -4808,6 +4813,7 @@ var CaptureFailure = class extends Error {
4808
4813
  (diagnostic) => Object.freeze({ ...diagnostic, lines: Object.freeze([...diagnostic.lines]) })
4809
4814
  )
4810
4815
  );
4816
+ this.pageErrorLines = Object.freeze([...input.pageErrorLines ?? []]);
4811
4817
  if (input.cause instanceof Error && input.cause.stack) this.stack = input.cause.stack;
4812
4818
  }
4813
4819
  };
@@ -4893,32 +4899,37 @@ function ioError(error, message) {
4893
4899
  )
4894
4900
  ) || BROKEN_PIPE_MESSAGE.test(message) || hasIoOperationFailure(message);
4895
4901
  }
4902
+ var ORDERED_KIND_RULES = [
4903
+ [
4904
+ "memory_exhaustion",
4905
+ (message) => BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE.test(message.trim()) || BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE.test(message) || matchesAny(message, MEMORY_EXHAUSTION_ERROR_PATTERNS)
4906
+ ],
4907
+ ["verification", (message) => matchesAny(message, VERIFICATION_ERROR_PATTERNS)],
4908
+ ["protocol_timeout", (message) => matchesAny(message, PROTOCOL_TIMEOUT_PATTERNS)],
4909
+ ["transient_browser", (message) => matchesAny(message, TRANSIENT_BROWSER_ERROR_PATTERNS)],
4910
+ ["authoring", (message) => matchesAny(message, AUTHORING_ERROR_PATTERNS)]
4911
+ ];
4912
+ function classifyKind(error, message, signal) {
4913
+ if (signal?.aborted || /(?:render|capture)?_?cancelled|AbortError/i.test(message)) {
4914
+ return "cancelled";
4915
+ }
4916
+ const rule = ORDERED_KIND_RULES.find(([, matches]) => matches(message));
4917
+ if (rule) return rule[0];
4918
+ return ioError(error, message) ? "io" : "authoring";
4919
+ }
4896
4920
  function classifyCaptureFailure(error, options = {}) {
4897
- if (error instanceof CaptureFailure && !options.workerDiagnostics && !options.signal?.aborted) {
4898
- return error;
4921
+ const prior = error instanceof CaptureFailure ? error : void 0;
4922
+ if (prior && !(options.workerDiagnostics || options.pageErrorLines || options.signal?.aborted)) {
4923
+ return prior;
4899
4924
  }
4900
4925
  const message = messageOf(error);
4901
- let kind;
4902
- if (options.signal?.aborted || /(?:render|capture)?_?cancelled|AbortError/i.test(message)) {
4903
- kind = "cancelled";
4904
- } else if (BUN_MEMORY_EXHAUSTION_EXACT_MESSAGE.test(message.trim()) || BUN_MEMORY_EXHAUSTION_WRAPPED_WORKER_MESSAGE.test(message) || matchesAny(message, MEMORY_EXHAUSTION_ERROR_PATTERNS)) {
4905
- kind = "memory_exhaustion";
4906
- } else if (matchesAny(message, VERIFICATION_ERROR_PATTERNS)) {
4907
- kind = "verification";
4908
- } else if (matchesAny(message, PROTOCOL_TIMEOUT_PATTERNS)) {
4909
- kind = "protocol_timeout";
4910
- } else if (matchesAny(message, TRANSIENT_BROWSER_ERROR_PATTERNS)) {
4911
- kind = "transient_browser";
4912
- } else if (matchesAny(message, AUTHORING_ERROR_PATTERNS)) {
4913
- kind = "authoring";
4914
- } else {
4915
- kind = ioError(error, message) ? "io" : "authoring";
4916
- }
4926
+ const kind = classifyKind(error, message, options.signal);
4917
4927
  return new CaptureFailure({
4918
4928
  kind,
4919
4929
  message,
4920
4930
  cause: error,
4921
- workerDiagnostics: options.workerDiagnostics ?? (error instanceof CaptureFailure ? error.workerDiagnostics : void 0)
4931
+ workerDiagnostics: options.workerDiagnostics ?? prior?.workerDiagnostics,
4932
+ pageErrorLines: options.pageErrorLines ?? prior?.pageErrorLines
4922
4933
  });
4923
4934
  }
4924
4935
  function isTransientBrowserError(error) {
@@ -5203,12 +5214,14 @@ async function driveWarmupTicks(options, state) {
5203
5214
  } else {
5204
5215
  if (!state.running) return;
5205
5216
  }
5217
+ let ticked = false;
5206
5218
  try {
5207
5219
  await options.tick(state.ticks * options.intervalMs, options.intervalMs);
5208
5220
  state.ticks += 1;
5221
+ ticked = true;
5209
5222
  } catch {
5210
5223
  }
5211
- await sleep(options.intervalMs);
5224
+ if (!(options.lockWarmupTicks && !state.running && ticked)) await sleep(options.intervalMs);
5212
5225
  }
5213
5226
  }
5214
5227
  function resolveCaptureSessionOptions(options, browserVersion, platform = process.platform) {
@@ -8608,6 +8621,10 @@ var withoutQuery = (url) => url.split(/[?#]/, 1)[0] ?? url;
8608
8621
  function declareContentAddressedUrl(url, sha256) {
8609
8622
  contentAddressedUrls.set(withoutQuery(url), sha256);
8610
8623
  }
8624
+ var probeFactsUrls = /* @__PURE__ */ new Map();
8625
+ function declareProbeFactsUrl(url, factsUrl) {
8626
+ probeFactsUrls.set(withoutQuery(url), factsUrl);
8627
+ }
8611
8628
  function mediaFileIdentity(filePath) {
8612
8629
  if (/^https?:\/\//i.test(filePath)) {
8613
8630
  const sha256 = contentAddressedUrls.get(withoutQuery(filePath));
@@ -8636,6 +8653,75 @@ function writeMetadataCache(cache, key, identity, promise) {
8636
8653
  }
8637
8654
  );
8638
8655
  }
8656
+ var PROBE_FACTS_VERSION = "v2";
8657
+ var PROBE_JSON_ARGS = ["-print_format", "json", "-show_format", "-show_streams"];
8658
+ var storedFacts = /* @__PURE__ */ new Map();
8659
+ function readStoredFacts(filePath) {
8660
+ if (!/^https?:\/\//i.test(filePath)) return void 0;
8661
+ const factsUrl = probeFactsUrls.get(withoutQuery(filePath));
8662
+ if (!factsUrl) return void 0;
8663
+ let facts = storedFacts.get(factsUrl);
8664
+ if (!facts) {
8665
+ facts = (async () => {
8666
+ try {
8667
+ const response = await fetch(factsUrl, { signal: AbortSignal.timeout(1e4) });
8668
+ if (!response.ok) return null;
8669
+ const parsed = JSON.parse(await response.text());
8670
+ return Array.isArray(parsed.ffprobe?.streams) ? parsed : null;
8671
+ } catch {
8672
+ return null;
8673
+ }
8674
+ })();
8675
+ storedFacts.set(factsUrl, facts);
8676
+ }
8677
+ return facts;
8678
+ }
8679
+ function readProbeJson(filePath, signal) {
8680
+ const pending = readStoredFacts(filePath);
8681
+ if (!pending) return runFfprobe(filePath, PROBE_JSON_ARGS, signal);
8682
+ return pending.then(
8683
+ (stored) => stored ? JSON.stringify(stored.ffprobe) : runFfprobe(filePath, PROBE_JSON_ARGS, signal)
8684
+ );
8685
+ }
8686
+ var runtimeFfprobeMajor;
8687
+ function ffprobeMajor() {
8688
+ runtimeFfprobeMajor ??= new Promise((resolve) => {
8689
+ let out = "";
8690
+ const binary = getFfprobeBinary();
8691
+ const proc = spawn3(binary, ["-version"], { stdio: ["ignore", "pipe", "ignore"] });
8692
+ proc.stdout.on("data", (chunk) => out += String(chunk));
8693
+ proc.on("error", () => resolve(void 0));
8694
+ proc.on("close", () => resolve(Number(/version n?(\d+)/.exec(out)?.[1]) || void 0));
8695
+ });
8696
+ return runtimeFfprobeMajor;
8697
+ }
8698
+ async function buildProbeFactsText(filePath, signal) {
8699
+ const facts = {
8700
+ ffprobe: parseProbeJson(await runFfprobe(filePath, PROBE_JSON_ARGS, signal)),
8701
+ ffprobeMajor: await ffprobeMajor()
8702
+ };
8703
+ try {
8704
+ const metadata = await extractMediaMetadata(filePath);
8705
+ const window2 = resolveStreamWindow(filePath, {
8706
+ videoStreamStartSeconds: metadata.videoStreamStartSeconds,
8707
+ videoStreamDurationSeconds: resolvePlayableVideoDuration(metadata) - (metadata.videoStreamLeadSeconds ?? 0)
8708
+ });
8709
+ if (window2.videoStreamDurationSeconds > 0) {
8710
+ facts.finalFrame = {
8711
+ streamStart: window2.videoStreamStartSeconds,
8712
+ streamDuration: window2.videoStreamDurationSeconds,
8713
+ seconds: await extractFinalVideoFrameTimestamp(filePath, window2, signal),
8714
+ lastPacketSeconds: await extractFinalPacketDuration(filePath, window2, signal)
8715
+ };
8716
+ }
8717
+ } catch {
8718
+ if (signal?.aborted) throw signal.reason;
8719
+ }
8720
+ return JSON.stringify(facts);
8721
+ }
8722
+ function resolvePlayableVideoDuration(metadata) {
8723
+ return Number.isFinite(metadata.videoStreamDurationSeconds) && metadata.videoStreamDurationSeconds > 0 ? (metadata.videoStreamLeadSeconds ?? 0) + metadata.videoStreamDurationSeconds : metadata.durationSeconds;
8724
+ }
8639
8725
  async function probeMediaOutput(filePath, signal) {
8640
8726
  let cache = mediaProbeOutputCache;
8641
8727
  if (signal) {
@@ -8651,11 +8737,7 @@ async function probeMediaOutput(filePath, signal) {
8651
8737
  }
8652
8738
  return cached.promise;
8653
8739
  }
8654
- const promise = runFfprobe(
8655
- filePath,
8656
- ["-print_format", "json", "-show_format", "-show_streams"],
8657
- signal
8658
- ).then(parseProbeJson);
8740
+ const promise = readProbeJson(filePath, signal).then(parseProbeJson);
8659
8741
  if (identity !== null) {
8660
8742
  cache.set(filePath, { identity, promise });
8661
8743
  if (!signal && cache.size > MEDIA_PROBE_OUTPUT_CACHE_MAX_ENTRIES) {
@@ -8911,6 +8993,43 @@ function resolveStreamWindow(filePath, metadata) {
8911
8993
  const cacheKey = `${filePath}\0${String(videoStreamStartSeconds)}\0${String(videoStreamDurationSeconds)}`;
8912
8994
  return { videoStreamStartSeconds, videoStreamDurationSeconds, cacheKey };
8913
8995
  }
8996
+ function readStoredFinalFrame(filePath, metadata) {
8997
+ const { videoStreamStartSeconds, videoStreamDurationSeconds } = resolveStreamWindow(
8998
+ filePath,
8999
+ metadata
9000
+ );
9001
+ return readStoredFacts(filePath)?.then(async (facts) => {
9002
+ const stored = facts?.finalFrame;
9003
+ if (facts?.ffprobeMajor !== void 0 && facts.ffprobeMajor !== await ffprobeMajor())
9004
+ return void 0;
9005
+ return stored && stored.streamStart === videoStreamStartSeconds && stored.streamDuration === videoStreamDurationSeconds ? stored : void 0;
9006
+ });
9007
+ }
9008
+ async function extractFinalPacketDuration(filePath, window2, signal) {
9009
+ const streamEnd = window2.videoStreamStartSeconds + window2.videoStreamDurationSeconds;
9010
+ const intervalStart = Math.max(window2.videoStreamStartSeconds, streamEnd - 1);
9011
+ const stdout = await runFfprobe(
9012
+ filePath,
9013
+ [
9014
+ "-select_streams",
9015
+ "v:0",
9016
+ "-read_intervals",
9017
+ `${intervalStart}%${streamEnd}`,
9018
+ "-show_entries",
9019
+ "packet=pts_time,duration_time",
9020
+ "-of",
9021
+ "csv=p=0"
9022
+ ],
9023
+ signal,
9024
+ { retainTail: true, maxChars: 64 * 1024 }
9025
+ );
9026
+ const packets = stdout.split("\n").map((line) => line.trim().split(",").map(Number)).filter(([pts, duration]) => Number.isFinite(pts) && Number.isFinite(duration));
9027
+ const last = packets.reduce(
9028
+ (best, packet) => !best || packet[0] > best[0] ? packet : best,
9029
+ void 0
9030
+ );
9031
+ return last?.[1];
9032
+ }
8914
9033
  async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
8915
9034
  const {
8916
9035
  videoStreamStartSeconds,
@@ -8926,6 +9045,9 @@ async function extractFinalVideoFrameTimestamp(filePath, metadata, signal) {
8926
9045
  const cached = readMetadataCache(probeCache, cacheKey, identity);
8927
9046
  if (cached) return cached;
8928
9047
  const probePromise = (async () => {
9048
+ const pendingStored = readStoredFinalFrame(filePath, metadata);
9049
+ const stored = pendingStored && await pendingStored;
9050
+ if (stored) return stored.seconds;
8929
9051
  if (!(videoDurationSeconds > 0) || !Number.isFinite(videoDurationSeconds)) {
8930
9052
  throw new Error(
8931
9053
  `[FFmpeg] Cannot locate final video frame for invalid duration ${String(videoDurationSeconds)}`
@@ -11528,12 +11650,52 @@ import {
11528
11650
  lstatSync as lstatSync2,
11529
11651
  mkdirSync as mkdirSync5,
11530
11652
  readdirSync as readdirSync5,
11531
- renameSync,
11532
11653
  rmSync as rmSync3,
11533
11654
  statSync as statSync6,
11534
11655
  utimesSync,
11535
11656
  writeFileSync as writeFileSync3
11536
11657
  } from "fs";
11658
+
11659
+ // ../engine/src/utils/renameWithRetry.ts
11660
+ import { renameSync } from "fs";
11661
+ import { rename } from "fs/promises";
11662
+ var RETRYABLE = /* @__PURE__ */ new Set(["EPERM", "EACCES", "EBUSY"]);
11663
+ var BACKOFF_MS = [10, 20, 40, 80, 160, 320, 640];
11664
+ function isRetryable(error, platform) {
11665
+ if (platform !== "win32") return false;
11666
+ return RETRYABLE.has(error?.code ?? "");
11667
+ }
11668
+ function sleepSync(ms) {
11669
+ Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);
11670
+ }
11671
+ function renameWithRetry(from, to, options = {}) {
11672
+ const doRename = options.rename ?? renameSync;
11673
+ const platform = options.platform ?? process.platform;
11674
+ for (let attempt = 0; ; attempt++) {
11675
+ try {
11676
+ doRename(from, to);
11677
+ return;
11678
+ } catch (error) {
11679
+ if (attempt >= BACKOFF_MS.length || !isRetryable(error, platform)) throw error;
11680
+ sleepSync(BACKOFF_MS[attempt]);
11681
+ }
11682
+ }
11683
+ }
11684
+ async function renameWithRetryAsync(from, to, options = {}) {
11685
+ const doRename = options.rename ?? rename;
11686
+ const platform = options.platform ?? process.platform;
11687
+ for (let attempt = 0; ; attempt++) {
11688
+ try {
11689
+ await doRename(from, to);
11690
+ return;
11691
+ } catch (error) {
11692
+ if (attempt >= BACKOFF_MS.length || !isRetryable(error, platform)) throw error;
11693
+ await new Promise((resolve) => setTimeout(resolve, BACKOFF_MS[attempt]));
11694
+ }
11695
+ }
11696
+ }
11697
+
11698
+ // ../engine/src/services/extractionCache.ts
11537
11699
  import { join as join9 } from "path";
11538
11700
  var COMPLETE_SENTINEL = ".hf-complete";
11539
11701
  var GC_MARKER = ".hf-last-gc";
@@ -11608,7 +11770,7 @@ function publishCacheEntry(entry, partialDir) {
11608
11770
  return { dir: partialDir, published: false };
11609
11771
  }
11610
11772
  try {
11611
- renameSync(partialDir, entry.dir);
11773
+ renameWithRetry(partialDir, entry.dir);
11612
11774
  return { dir: entry.dir, published: true };
11613
11775
  } catch (err) {
11614
11776
  if (!isTargetExistsRenameError(err)) return { dir: partialDir, published: false };
@@ -11621,7 +11783,7 @@ function publishCacheEntry(entry, partialDir) {
11621
11783
  return { dir: partialDir, published: false };
11622
11784
  }
11623
11785
  try {
11624
- renameSync(partialDir, entry.dir);
11786
+ renameWithRetry(partialDir, entry.dir);
11625
11787
  return { dir: entry.dir, published: true };
11626
11788
  } catch {
11627
11789
  return adoptPublishedWinner(entry, partialDir) ?? { dir: partialDir, published: false };
@@ -11806,6 +11968,24 @@ function extractionFrameCountForDuration(durationSeconds, fps, isVFR) {
11806
11968
  const frames = Number(frameCount);
11807
11969
  return Math.max(1, Number.isSafeInteger(frames) ? frames : Number.MAX_SAFE_INTEGER);
11808
11970
  }
11971
+ function exactSourceRate(probed) {
11972
+ const nominal = Math.round(probed * 1.001);
11973
+ return [nominal, nominal * 1e3 / 1001].find((rate) => Math.abs(rate - probed) <= 5e-3 + 1e-9) ?? null;
11974
+ }
11975
+ function tailFramesFromFinalFrame(input) {
11976
+ const sourceRate = exactSourceRate(input.sourceFps);
11977
+ if (!sourceRate || !(input.outputFps > 0)) return null;
11978
+ const lead = input.streamLeadSeconds;
11979
+ if (lead !== 0 && !(Math.abs((input.lastPacketSeconds ?? NaN) - 1 / sourceRate) <= 1e-4)) {
11980
+ return null;
11981
+ }
11982
+ const seek = input.startTime + input.firstFrame / input.outputFps;
11983
+ const slots = (lead + input.finalFrameSeconds + 1 / sourceRate - seek) * input.outputFps;
11984
+ const distanceToSlot = Math.abs(slots - Math.round(slots));
11985
+ if (distanceToSlot >= 5e-5 && distanceToSlot < 5e-4) return null;
11986
+ const count = Math.min(input.tailFrames, Math.ceil(slots - 5e-5));
11987
+ return count > 0 ? count : null;
11988
+ }
11809
11989
  var DOWNLOAD_SUBDIR = "_downloads";
11810
11990
  var EXTRACT_CACHE_MIN_AGE_MS = 60 * 60 * 1e3;
11811
11991
  var GC_STALENESS_MS = 24 * 60 * 60 * 1e3;
@@ -12180,6 +12360,8 @@ function undoTickRoundingOnTheSourceFrameGrid(seek, lead) {
12180
12360
  }
12181
12361
  var EXTRACTION_SLOTS = Math.max(1, Math.floor(cpus().length / 2));
12182
12362
  var inExtractionSlot = createConcurrencyLimit(EXTRACTION_SLOTS);
12363
+ var TAIL_PROBE_SLOTS = Math.max(1, Number(process.env.HF_TAIL_PROBE_SLOTS) || 16);
12364
+ var inTailProbeSlot = createConcurrencyLimit(TAIL_PROBE_SLOTS);
12183
12365
  function splitFrameRanges(ranges, segmentFrames) {
12184
12366
  const segments = [];
12185
12367
  for (const range of ranges) {
@@ -12193,7 +12375,7 @@ function splitFrameRanges(ranges, segmentFrames) {
12193
12375
  return segments;
12194
12376
  }
12195
12377
  async function runSegmentedExtraction(job) {
12196
- const { decodeArgs, filterAndEncodeArgs, videoPath, startTime, fps, segments } = job;
12378
+ const { decodeArgs, filterAndEncodeArgs, videoPath, startTime, fps, segments, gate } = job;
12197
12379
  const segmentCount = segments.length;
12198
12380
  const failed = new AbortController();
12199
12381
  const signal = job.runOptions.signal ? AbortSignal.any([job.runOptions.signal, failed.signal]) : failed.signal;
@@ -12204,7 +12386,7 @@ async function runSegmentedExtraction(job) {
12204
12386
  const index = next++;
12205
12387
  const { firstFrame, frames } = segments[index];
12206
12388
  const seek = startTime + firstFrame / fps;
12207
- const result = await inExtractionSlot(
12389
+ const result = await gate(
12208
12390
  () => runFfmpeg(
12209
12391
  [
12210
12392
  ...decodeArgs,
@@ -12355,6 +12537,7 @@ async function extractVideoFramesRangeUnredacted(videoPath, videoId, startTime,
12355
12537
  videoPath,
12356
12538
  startTime,
12357
12539
  fps,
12540
+ gate: options.tailProbe ? inTailProbeSlot : inExtractionSlot,
12358
12541
  segments: splitFrameRanges(
12359
12542
  options.frameRanges ?? [{ firstFrame: 0, frames: totalFrames }],
12360
12543
  segmentFrames
@@ -12455,9 +12638,6 @@ function resolveSegmentDuration(requested, mediaStart, sourceDuration) {
12455
12638
  const sourceRemaining = sourceDuration - mediaStart;
12456
12639
  return sourceRemaining > 0 ? sourceRemaining : sourceDuration;
12457
12640
  }
12458
- function resolvePlayableVideoDuration(metadata) {
12459
- return Number.isFinite(metadata.videoStreamDurationSeconds) && metadata.videoStreamDurationSeconds > 0 ? (metadata.videoStreamLeadSeconds ?? 0) + metadata.videoStreamDurationSeconds : metadata.durationSeconds;
12460
- }
12461
12641
  function canHoldFinalFramePastEof(video) {
12462
12642
  const timelineDuration = video.end - video.start;
12463
12643
  return !video.loop && Number.isFinite(timelineDuration) && timelineDuration > 0;
@@ -13136,23 +13316,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
13136
13316
  );
13137
13317
  const tailFrames = Math.min(expectedFrames, Math.ceil(fps));
13138
13318
  if (expectedFrames <= tailFrames) return null;
13139
- const probeDir = join10(options.outputDir, `${work.video.id}.tail-probe`);
13140
- try {
13141
- const tail = await extractVideoFramesRange(
13142
- work.videoPath,
13143
- work.video.id,
13144
- work.extractionMediaStart,
13145
- work.videoDuration,
13146
- {
13147
- ...scopedExtractionOptions(work),
13148
- frameRanges: [{ firstFrame: expectedFrames - tailFrames, frames: tailFrames }]
13149
- },
13150
- signal,
13151
- config,
13152
- probeDir
13153
- );
13154
- const totalFrames = expectedFrames - tailFrames + tail.totalFrames;
13155
- if (totalFrames <= expectedFrames * 0.6) return null;
13319
+ const deferred = (totalFrames) => {
13156
13320
  const outputDir = join10(options.outputDir, work.video.id);
13157
13321
  mkdirSync6(outputDir, { recursive: true });
13158
13322
  return {
@@ -13170,6 +13334,45 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
13170
13334
  format: work.format
13171
13335
  }
13172
13336
  };
13337
+ };
13338
+ if (work.extractionMediaStart + work.videoDuration + 1 <= resolvePlayableVideoDuration(work.metadata)) {
13339
+ return deferred(expectedFrames);
13340
+ }
13341
+ const firstTailFrame = expectedFrames - tailFrames;
13342
+ const storedFinalFrame = await readStoredFinalFrame(work.videoPath, work.metadata);
13343
+ const storedTailFrames = storedFinalFrame === void 0 ? null : tailFramesFromFinalFrame({
13344
+ startTime: work.extractionMediaStart,
13345
+ firstFrame: firstTailFrame,
13346
+ tailFrames,
13347
+ outputFps: fps,
13348
+ sourceFps: work.metadata.fps,
13349
+ finalFrameSeconds: storedFinalFrame.seconds,
13350
+ lastPacketSeconds: storedFinalFrame.lastPacketSeconds,
13351
+ streamLeadSeconds: work.metadata.videoStreamLeadSeconds ?? 0
13352
+ });
13353
+ if (storedTailFrames !== null) {
13354
+ const totalFrames = firstTailFrame + storedTailFrames;
13355
+ return totalFrames <= expectedFrames * 0.6 ? null : deferred(totalFrames);
13356
+ }
13357
+ const probeDir = join10(options.outputDir, `${work.video.id}.tail-probe`);
13358
+ try {
13359
+ const tail = await extractVideoFramesRange(
13360
+ work.videoPath,
13361
+ work.video.id,
13362
+ work.extractionMediaStart,
13363
+ work.videoDuration,
13364
+ {
13365
+ ...scopedExtractionOptions(work),
13366
+ frameRanges: [{ firstFrame: firstTailFrame, frames: tailFrames }],
13367
+ tailProbe: isHttpUrl(work.videoPath)
13368
+ },
13369
+ signal,
13370
+ config,
13371
+ probeDir
13372
+ );
13373
+ const totalFrames = firstTailFrame + tail.totalFrames;
13374
+ if (totalFrames <= expectedFrames * 0.6) return null;
13375
+ return deferred(totalFrames);
13173
13376
  } catch {
13174
13377
  return null;
13175
13378
  } finally {
@@ -14048,16 +14251,7 @@ async function queryElementStacking(page, nativeHdrIds) {
14048
14251
  }
14049
14252
 
14050
14253
  // ../engine/src/services/audioMixer.ts
14051
- import {
14052
- closeSync as closeSync4,
14053
- existsSync as existsSync11,
14054
- mkdirSync as mkdirSync7,
14055
- mkdtempSync as mkdtempSync7,
14056
- openSync as openSync4,
14057
- renameSync as renameSync3,
14058
- rmSync as rmSync8,
14059
- writeFileSync as writeFileSync7
14060
- } from "fs";
14254
+ import { closeSync as closeSync4, existsSync as existsSync11, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync7, openSync as openSync4, rmSync as rmSync8, writeFileSync as writeFileSync7 } from "fs";
14061
14255
  import { join as join14, dirname as dirname7, isAbsolute, relative } from "path";
14062
14256
 
14063
14257
  // ../engine/src/utils/notMediaPayload.ts
@@ -14176,6 +14370,7 @@ function clampFadesToDuration(fades, duration) {
14176
14370
  import { cpus as cpus2 } from "os";
14177
14371
 
14178
14372
  // ../engine/src/services/aacEncode.ts
14373
+ import { execFile as execFile3 } from "child_process";
14179
14374
  import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync5, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "fs";
14180
14375
  import { dirname as dirname5, join as join11 } from "path";
14181
14376
  var SAMPLE_RATE = 48e3;
@@ -14211,12 +14406,35 @@ function planSegments(totalDuration, count) {
14211
14406
  return { trim, keepFrom: cut - firstFrame, keepTo: next - firstFrame };
14212
14407
  });
14213
14408
  }
14409
+ var settsDurationSupport = /* @__PURE__ */ new Map();
14410
+ function supportsSettsDuration(binary = getFfmpegBinary()) {
14411
+ let supported = settsDurationSupport.get(binary);
14412
+ if (!supported) {
14413
+ supported = new Promise((resolve) => {
14414
+ execFile3(binary, ["-hide_banner", "-h", "bsf=setts"], (error, stdout) => {
14415
+ resolve(error !== null || stdout.includes("duration"));
14416
+ });
14417
+ });
14418
+ settsDurationSupport.set(binary, supported);
14419
+ }
14420
+ return supported;
14421
+ }
14422
+ function encodeInOnePass(input, outputPath, { signal, timeout, filter }) {
14423
+ const filters = [filter, `aresample=${SAMPLE_RATE}`].filter(Boolean).join(",");
14424
+ return runFfmpeg(["-i", input, "-af", filters, ...AAC_ARGS, "-y", outputPath], {
14425
+ signal,
14426
+ timeout
14427
+ });
14428
+ }
14214
14429
  async function encodeAac(input, outputPath, totalDuration, {
14215
14430
  signal,
14216
14431
  timeout,
14217
14432
  filter,
14218
14433
  segments: count = aacSegmentCount(totalDuration)
14219
14434
  }) {
14435
+ if (!await supportsSettsDuration()) {
14436
+ return encodeInOnePass(input, outputPath, { signal, timeout, filter });
14437
+ }
14220
14438
  const dir = mkdtempSync4(join11(dirname5(outputPath), ".aac-segments-"));
14221
14439
  try {
14222
14440
  const segments = planSegments(totalDuration, count).map((segment, k) => ({
@@ -14382,7 +14600,7 @@ function audioFailureDiagnostics(values) {
14382
14600
  }
14383
14601
 
14384
14602
  // ../engine/src/services/audioVolumeEnvelope.ts
14385
- import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync6, renameSync as renameSync2, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "fs";
14603
+ import { mkdtempSync as mkdtempSync5, readFileSync as readFileSync6, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "fs";
14386
14604
  import { dirname as dirname6, join as join12 } from "path";
14387
14605
 
14388
14606
  // ../core/dist/runtime/mediaVolumeEnvelope.js
@@ -14512,7 +14730,7 @@ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
14512
14730
  stagingDir = mkdtempSync5(join12(dirname6(wavPath), ".hf-volume-"));
14513
14731
  const tempPath = join12(stagingDir, "audio.wav");
14514
14732
  writeFileSync5(tempPath, buffer, { flag: "wx" });
14515
- renameSync2(tempPath, wavPath);
14733
+ renameWithRetry(tempPath, wavPath);
14516
14734
  return true;
14517
14735
  } catch {
14518
14736
  return false;
@@ -16010,7 +16228,7 @@ async function mixGroupMembers(memberTracks, outputPath, totalDuration, signal,
16010
16228
  try {
16011
16229
  const summed = await sumInSlices(memberTracks, scratchDir, totalDuration, signal, config);
16012
16230
  if (!summed.success) return summed;
16013
- renameSync3(summed.track.srcPath, outputPath);
16231
+ renameWithRetry(summed.track.srcPath, outputPath);
16014
16232
  return { success: true, degradedAutomation: summed.degradedAutomation };
16015
16233
  } finally {
16016
16234
  rmSync8(scratchDir, { recursive: true, force: true });
@@ -16052,12 +16270,15 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
16052
16270
  }
16053
16271
  async function mixThroughFloatSum(tracks, masterChain, outputPath, workDir, totalDuration, signal, config) {
16054
16272
  const sumPath = join14(workDir, "master-sum.wav");
16273
+ const mixStart = Date.now();
16055
16274
  const sum = await mixAudioTracks(tracks, sumPath, totalDuration, signal, config);
16056
16275
  if (!sum.success) return { ...sum, outputPath };
16276
+ const masterStart = Date.now();
16057
16277
  const encoderInput = masterChain ? (await applyAudioFxChain(sumPath, masterChain, join14(workDir, "master-fx.wav"), {
16058
16278
  trackId: "master",
16059
16279
  signal
16060
16280
  })).path : sumPath;
16281
+ const encodeStart = Date.now();
16061
16282
  const encoded = await encodeAac(encoderInput, outputPath, totalDuration, {
16062
16283
  signal,
16063
16284
  timeout: config?.ffmpegProcessTimeout ?? DEFAULT_CONFIG.ffmpegProcessTimeout
@@ -16077,8 +16298,17 @@ async function mixThroughFloatSum(tracks, masterChain, outputPath, workDir, tota
16077
16298
  failures: [failure]
16078
16299
  };
16079
16300
  }
16080
- if (config?.keepEncoderInputAt) renameSync3(encoderInput, config.keepEncoderInputAt);
16081
- return { ...sum, outputPath, durationMs: sum.durationMs + encoded.durationMs };
16301
+ if (config?.keepEncoderInputAt) renameWithRetry(encoderInput, config.keepEncoderInputAt);
16302
+ return {
16303
+ ...sum,
16304
+ outputPath,
16305
+ durationMs: sum.durationMs + encoded.durationMs,
16306
+ phaseMs: {
16307
+ mix: masterStart - mixStart,
16308
+ master: encodeStart - masterStart,
16309
+ encode: Date.now() - encodeStart
16310
+ }
16311
+ };
16082
16312
  }
16083
16313
  async function processCompositionAudio(elements, baseDir, workDir, outputPath, totalDuration, signal, config, compiledDir) {
16084
16314
  const startMs = Date.now();
@@ -16363,6 +16593,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
16363
16593
  failures
16364
16594
  };
16365
16595
  };
16596
+ const prepareMs = Date.now() - startMs;
16366
16597
  if (failures.length > 0) return bail();
16367
16598
  let masterChain;
16368
16599
  const masterFxJson = config?.masterFxChain;
@@ -16473,6 +16704,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
16473
16704
  }
16474
16705
  }
16475
16706
  if (failures.length > 0) return bail();
16707
+ const groupsMs = Date.now() - startMs - prepareMs;
16476
16708
  let mixResult;
16477
16709
  try {
16478
16710
  mixResult = tracks.length > 0 ? await mixThroughFloatSum(
@@ -16491,6 +16723,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
16491
16723
  return {
16492
16724
  ...mixResult,
16493
16725
  durationMs: Date.now() - startMs,
16726
+ phaseMs: { prepare: prepareMs, groups: groupsMs, ...mixResult.phaseMs },
16494
16727
  // Both, when both degraded. `mixResult.error ?? degradedNote` reported only
16495
16728
  // the outer mix and dropped the one that names which GROUPS lost their
16496
16729
  // members' automation — two different losses, and the operator needs to
@@ -16502,18 +16735,18 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
16502
16735
  // ../engine/src/services/parallelCoordinator.ts
16503
16736
  import { cpus as cpus3, freemem } from "os";
16504
16737
  import { existsSync as existsSync12, mkdirSync as mkdirSync8, readdirSync as readdirSync6 } from "fs";
16505
- import { copyFile, readFile as readFile2, rename } from "fs/promises";
16738
+ import { copyFile, readFile as readFile2 } from "fs/promises";
16506
16739
  import { join as join16 } from "path";
16507
16740
  import { getHeapStatistics } from "v8";
16508
16741
 
16509
16742
  // ../engine/src/utils/psnr.ts
16510
- import { execFile as execFile3 } from "child_process";
16743
+ import { execFile as execFile4 } from "child_process";
16511
16744
  import { mkdtemp, rm, writeFile } from "fs/promises";
16512
16745
  import { tmpdir as tmpdir4 } from "os";
16513
16746
  import { join as join15 } from "path";
16514
16747
  import { promisify as promisify3 } from "util";
16515
16748
  async function psnrDb(a, b) {
16516
- const execFileP = promisify3(execFile3);
16749
+ const execFileP = promisify3(execFile4);
16517
16750
  const dir = await mkdtemp(join15(tmpdir4(), "hf-de-verify-"));
16518
16751
  try {
16519
16752
  const pa = join15(dir, "a.jpg");
@@ -17047,7 +17280,8 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
17047
17280
  endFrame: task.endFrame,
17048
17281
  frameStride: task.frameStride,
17049
17282
  durationMs: Date.now() - startTime,
17050
- perf
17283
+ perf,
17284
+ pageErrorLines: pageErrorLinesOf(activeSession)
17051
17285
  };
17052
17286
  } catch (error) {
17053
17287
  const diagnostics = session ? selectWorkerDiagnostics(session.browserConsoleBuffer) : [];
@@ -17060,7 +17294,8 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
17060
17294
  };
17061
17295
  const failure = classifyCaptureFailure(error, {
17062
17296
  signal,
17063
- workerDiagnostics: [workerDiagnostic]
17297
+ workerDiagnostics: [workerDiagnostic],
17298
+ pageErrorLines: session ? pageErrorLinesOf(session) : void 0
17064
17299
  });
17065
17300
  onFailure?.(failure);
17066
17301
  return {
@@ -17073,6 +17308,7 @@ async function executeWorkerTask(task, serverUrl, captureOptions, createBeforeCa
17073
17308
  perf,
17074
17309
  error: failure.message,
17075
17310
  diagnostics: diagnostics.length > 0 ? diagnostics : void 0,
17311
+ pageErrorLines: session ? pageErrorLinesOf(session) : void 0,
17076
17312
  failure
17077
17313
  };
17078
17314
  } finally {
@@ -17089,6 +17325,9 @@ function isPoolFatalWorkerFailure(failure, streaming) {
17089
17325
  if (streaming) return failure.kind !== "cancelled";
17090
17326
  return isFatalCaptureFailure(failure);
17091
17327
  }
17328
+ function pageErrorLinesOf(session) {
17329
+ return session.browserConsoleBuffer.filter((line) => line.includes("PAGEERROR"));
17330
+ }
17092
17331
  function createPoolFailureHandler(args) {
17093
17332
  let firstFatalFailure;
17094
17333
  return {
@@ -17180,7 +17419,8 @@ async function executeParallelCapture(serverUrl, workDir, tasks, captureOptions,
17180
17419
  kind: representative?.kind ?? "io",
17181
17420
  message: `[Parallel] Capture failed: ${errorMessages}`,
17182
17421
  cause: representative,
17183
- workerDiagnostics
17422
+ workerDiagnostics,
17423
+ pageErrorLines: [...new Set(results.flatMap((result) => result.pageErrorLines ?? []))]
17184
17424
  });
17185
17425
  }
17186
17426
  return results;
@@ -17198,7 +17438,7 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
17198
17438
  const sourcePath = join16(task.outputDir, file);
17199
17439
  const targetPath = join16(outputDir, file);
17200
17440
  try {
17201
- await rename(sourcePath, targetPath);
17441
+ await renameWithRetryAsync(sourcePath, targetPath);
17202
17442
  } catch {
17203
17443
  await copyFile(sourcePath, targetPath);
17204
17444
  }
@@ -17747,6 +17987,10 @@ export {
17747
17987
  describeFfmpegFailure,
17748
17988
  runFfmpeg,
17749
17989
  declareContentAddressedUrl,
17990
+ declareProbeFactsUrl,
17991
+ PROBE_FACTS_VERSION,
17992
+ buildProbeFactsText,
17993
+ resolvePlayableVideoDuration,
17750
17994
  probeMediaProfile,
17751
17995
  extractMediaMetadata,
17752
17996
  extractFinalVideoFrameTimestamp,
@@ -17785,6 +18029,8 @@ export {
17785
18029
  fetchPublicHttpsText,
17786
18030
  downloadToTemp,
17787
18031
  isHttpUrl,
18032
+ renameWithRetry,
18033
+ renameWithRetryAsync,
17788
18034
  directorySizeBytes,
17789
18035
  gcExtractionCache,
17790
18036
  VIDEO_FRAME_FORMATS,
@@ -17799,7 +18045,6 @@ export {
17799
18045
  parseVideoElements,
17800
18046
  parseImageElements,
17801
18047
  extractVideoFramesRange,
17802
- resolvePlayableVideoDuration,
17803
18048
  isVideoPastTimelineEnd,
17804
18049
  rebaseVideoToWindow,
17805
18050
  resolveTimelineExtractionWindow,