hyperframes 0.8.172 → 0.8.174

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 (185) hide show
  1. package/dist/{add-TJNZWO7P.js → add-XANMFNIP.js} +14 -15
  2. package/dist/{animatedGifPrep-K4WFG6KK.js → animatedGifPrep-OUQ4M2T3.js} +9 -11
  3. package/dist/api.js +19 -21
  4. package/dist/{asset-QN5J2P7H.js → asset-SVONSQ67.js} +2 -2
  5. package/dist/{assetCataloger-RLFDI5YD.js → assetCataloger-AG77T6SF.js} +9 -11
  6. package/dist/{audio-QJ4C3NMN.js → audio-DMQOTXKL.js} +16 -18
  7. package/dist/{auth-K7EHUGWE.js → auth-ED7SPBS6.js} +2 -2
  8. package/dist/{autoUpdate-76QXHQRT.js → autoUpdate-4QQYZOVT.js} +2 -2
  9. package/dist/{backgroundChecks-NMYRM5LV.js → backgroundChecks-2VT46P5S.js} +3 -3
  10. package/dist/backgroundChecksWorker.js +3 -3
  11. package/dist/{batchRender-RENYERF5.js → batchRender-KIYAPCTG.js} +4 -4
  12. package/dist/{beats-ZOR2HBAR.js → beats-OE7M5BEE.js} +6 -7
  13. package/dist/{benchmark-CY2VFIKL.js → benchmark-2ZQP2RNF.js} +11 -12
  14. package/dist/{browser-NPCKLUT7.js → browser-CSSJ3VWW.js} +5 -6
  15. package/dist/{bundleWithLocalizedFonts-FKH55KKW.js → bundleWithLocalizedFonts-ZUC4MLSO.js} +2 -2
  16. package/dist/{capture-TMSBTUYU.js → capture-3NXAHID3.js} +2 -2
  17. package/dist/{capture-IC2QJMMQ.js → capture-APNSW4ZT.js} +22 -18
  18. package/dist/{catalog-N7OCMRPT.js → catalog-CFDBIVSC.js} +15 -16
  19. package/dist/{catch-up-2MGK5I2D.js → catch-up-OUK522JT.js} +6 -7
  20. package/dist/{check-NU4GL2WC.js → check-PUDEOXGP.js} +37 -39
  21. package/dist/{checkBrowser-HRXAL4QD.js → checkBrowser-PMRJSTFJ.js} +34 -36
  22. package/dist/chunk-2CDBTQKS.js +113 -0
  23. package/dist/{chunk-C2F37AXS.js → chunk-2XSAYE7U.js} +2 -2
  24. package/dist/{chunk-3RM2ETQT.js → chunk-32GKETR7.js} +28 -2
  25. package/dist/{chunk-UIDRXHUY.js → chunk-3MDO2Q4F.js} +1 -1
  26. package/dist/{chunk-5B57KZJX.js → chunk-4PX47Z65.js} +1 -1
  27. package/dist/{chunk-IK3SOMZ4.js → chunk-4VTUDCHM.js} +19 -22
  28. package/dist/{chunk-Z6L3W5KZ.js → chunk-4WQUBVDO.js} +3 -3
  29. package/dist/{chunk-NLEDKGZT.js → chunk-55LJK3H2.js} +3 -3
  30. package/dist/{chunk-KRMOJUVL.js → chunk-6HF2WFPV.js} +5 -5
  31. package/dist/{chunk-EDUBJPGL.js → chunk-ALCCEHX2.js} +33 -7
  32. package/dist/{chunk-FXHGO3NH.js → chunk-APMA7XXB.js} +1 -1
  33. package/dist/{chunk-CDXC2UQ7.js → chunk-AR2SEGPZ.js} +1 -1
  34. package/dist/{chunk-K6SBDWUV.js → chunk-B23GBPCW.js} +2 -2
  35. package/dist/{chunk-YHECAUDC.js → chunk-CI7ZHFSV.js} +11 -11
  36. package/dist/chunk-CIWX5UKC.js +16 -0
  37. package/dist/{chunk-FYR6GKFN.js → chunk-CSMKMVGG.js} +6 -6
  38. package/dist/{chunk-TV2N4UIJ.js → chunk-D2YN4FNH.js} +2 -2
  39. package/dist/{chunk-CUDHVUIF.js → chunk-DRR3UMIY.js} +1 -1
  40. package/dist/{chunk-6K2N6WPO.js → chunk-EAR5LFOH.js} +42 -2
  41. package/dist/{chunk-MEEETF7G.js → chunk-EJZJ5AY7.js} +1 -1
  42. package/dist/{chunk-R73GAMUQ.js → chunk-G4UUEQDT.js} +1 -1
  43. package/dist/{chunk-G47TXPYN.js → chunk-GK2FIKIQ.js} +10 -8
  44. package/dist/{chunk-7DVH2IQQ.js → chunk-GXWV4FNV.js} +1 -1
  45. package/dist/{chunk-UNALPZL6.js → chunk-H2BPHBDY.js} +1 -1
  46. package/dist/{chunk-X3SCQP2A.js → chunk-HB2UP4V7.js} +1 -1
  47. package/dist/chunk-HIP62XAW.js +36 -0
  48. package/dist/{chunk-DQRZWV3B.js → chunk-HIYAJFRH.js} +1 -1
  49. package/dist/{chunk-4UR2EQSR.js → chunk-HZZYJV7K.js} +17 -19
  50. package/dist/{chunk-A2DMF2Q6.js → chunk-HZZZ6C6Z.js} +2 -2
  51. package/dist/{chunk-QQI7R2QL.js → chunk-JKPI7VLI.js} +1 -1
  52. package/dist/{chunk-4N2YVSXH.js → chunk-JL76Y45C.js} +7 -7
  53. package/dist/{chunk-EKKROA7V.js → chunk-LR72ON5B.js} +1 -1
  54. package/dist/{chunk-QVVANKN2.js → chunk-LUKY7253.js} +491 -133
  55. package/dist/{chunk-257IUNPQ.js → chunk-MXNPYP5F.js} +1 -1
  56. package/dist/{chunk-VFCKXTBB.js → chunk-NL5F3AD4.js} +27 -38
  57. package/dist/{chunk-S6JCFZVB.js → chunk-ONXTLGJB.js} +5 -5
  58. package/dist/{chunk-KRTCHLBA.js → chunk-PLYTTPVE.js} +2 -2
  59. package/dist/{chunk-R2P2SANE.js → chunk-QJCVK7CI.js} +4 -4
  60. package/dist/{chunk-HN5WVJZB.js → chunk-QRO2UBWS.js} +1 -1
  61. package/dist/{chunk-KOMXCNZX.js → chunk-QUK2IZKI.js} +1 -1
  62. package/dist/{chunk-2VR7HIPZ.js → chunk-RLBLLBLL.js} +2 -2
  63. package/dist/{chunk-PDFMNU6D.js → chunk-RMKL5FVH.js} +4 -17
  64. package/dist/{chunk-VQSSP7XG.js → chunk-RNKNDYBN.js} +1 -1
  65. package/dist/{chunk-BQYQV6JP.js → chunk-RYR3LTZR.js} +2 -2
  66. package/dist/{chunk-NYXHZOPD.js → chunk-RZ2FMZ5U.js} +1 -1
  67. package/dist/{chunk-DOV2QOFY.js → chunk-S5D4Q74P.js} +2 -2
  68. package/dist/{chunk-Z5ENX63S.js → chunk-SEHRMJTO.js} +13 -7
  69. package/dist/{chunk-XEJUMBIC.js → chunk-SEXAKOK3.js} +3 -3
  70. package/dist/{chunk-HZWXDKYB.js → chunk-SH43VDEF.js} +11 -15
  71. package/dist/{chunk-YAA3AOBA.js → chunk-SI76MFBF.js} +2 -2
  72. package/dist/{chunk-QWQ6GQTI.js → chunk-T6AGUTZJ.js} +2 -4
  73. package/dist/{chunk-ZY43P2M7.js → chunk-TI3HKGQC.js} +3 -3
  74. package/dist/{chunk-MFWQEG2W.js → chunk-UDJHYQSZ.js} +1 -1
  75. package/dist/{chunk-V5IZAL3H.js → chunk-UKAOWORD.js} +8 -8
  76. package/dist/chunk-UKJECUDK.js +3805 -0
  77. package/dist/{chunk-M235XUHL.js → chunk-UQLXFITA.js} +241 -6
  78. package/dist/{chunk-JYVGYKXG.js → chunk-W2LGJSEN.js} +73 -1
  79. package/dist/{chunk-UFAKRR5G.js → chunk-W3YVQ6VI.js} +12 -12
  80. package/dist/{chunk-FQP7TLRF.js → chunk-W4AECR7V.js} +1 -1
  81. package/dist/{chunk-AG2O2USE.js → chunk-X3BE2HX4.js} +3 -3
  82. package/dist/{chunk-TDPVEMBS.js → chunk-XFCLWWL3.js} +1 -1
  83. package/dist/{chunk-NZ5HOUJH.js → chunk-XVIFWEPR.js} +67 -33
  84. package/dist/{clean-JDODBRVL.js → clean-6SVCU47L.js} +18 -20
  85. package/dist/cli.js +53 -53
  86. package/dist/{cloud-YHJZ72XP.js → cloud-TIISRMZV.js} +4 -4
  87. package/dist/{cloudrun-E5EOHYTG.js → cloudrun-4TMBWELQ.js} +5 -5
  88. package/dist/{compare-VQQXHSE3.js → compare-YV2XTKYX.js} +28 -30
  89. package/dist/{compiler-I4GWSEK3.js → compiler-O5R3ZZDV.js} +5 -6
  90. package/dist/{component-WOSMKPL7.js → component-7LWSMRKZ.js} +3 -3
  91. package/dist/{compositions-WLJE5752.js → compositions-5VTSC4M3.js} +14 -16
  92. package/dist/{delete-PILRKH5C.js → delete-AV2SKLZW.js} +4 -4
  93. package/dist/{deploy-4MK3Y67M.js → deploy-NKWMPAMH.js} +19 -5
  94. package/dist/{destroy-GFQLTIY3.js → destroy-UKP522AE.js} +4 -2
  95. package/dist/{dist-7TYQROOE.js → dist-2FMTAVGL.js} +3 -3
  96. package/dist/{dist-SDXOTECD.js → dist-4FY5EEH5.js} +3 -3
  97. package/dist/{doctor-FNICQNSA.js → doctor-XOCYSEAZ.js} +14 -16
  98. package/dist/{events-5WNYSVPY.js → events-6QPRKX45.js} +4 -5
  99. package/dist/{events-YXPWFV5S.js → events-MAZUZI43.js} +5 -6
  100. package/dist/{feedback-KLA5RSSN.js → feedback-MGRILBMP.js} +10 -11
  101. package/dist/{ffmpeg-7BYARPLM.js → ffmpeg-YCULCUB2.js} +24 -4
  102. package/dist/{figma-PQIZI67M.js → figma-UMBACTCG.js} +3 -3
  103. package/dist/fontLocalizeCli.js +11 -13
  104. package/dist/{get-OBOWSUA7.js → get-LWEOLWYN.js} +4 -4
  105. package/dist/{gpuPolicy-HWH4OW6H.js → gpuPolicy-MCIQK5Z7.js} +9 -11
  106. package/dist/{grade-compare-5IOHWZX6.js → grade-compare-MZQOTX3F.js} +29 -31
  107. package/dist/{help-K4IK2N36.js → help-THPG2NRP.js} +1 -1
  108. package/dist/{history-AC5ZUFOX.js → history-2IQYTDU5.js} +8 -9
  109. package/dist/hyperframe-runtime.js +55 -55
  110. package/dist/hyperframe.manifest.json +1 -1
  111. package/dist/hyperframe.runtime.iife.js +55 -55
  112. package/dist/hyperframes-player.global.js +3 -3
  113. package/dist/{info-BD6555FQ.js → info-CXMADV6K.js} +10 -11
  114. package/dist/{init-KTNJH3QB.js → init-Y5GU454D.js} +34 -34
  115. package/dist/{inspect-PF2DWLRP.js → inspect-S7JDKEMJ.js} +29 -31
  116. package/dist/{installer-72NGZ5BM.js → installer-AY23RPEZ.js} +5 -5
  117. package/dist/{keyframes-P3GRO3LL.js → keyframes-FKYT6QAJ.js} +8 -9
  118. package/dist/{lambda-XRNX7HLH.js → lambda-7WMZGRH5.js} +16 -12
  119. package/dist/{layout-KN7SX3WH.js → layout-LL4GOS6G.js} +29 -31
  120. package/dist/{lint-TXBEZUA5.js → lint-2M7FY4ZT.js} +11 -12
  121. package/dist/{lintProject-65YGC4UB.js → lintProject-ARKJXDQF.js} +3 -3
  122. package/dist/{list-4YL3BA2G.js → list-SZBMUHBW.js} +4 -4
  123. package/dist/{login-JUI7PHHJ.js → login-QRACITGK.js} +4 -4
  124. package/dist/{manager-B6MVBM2E.js → manager-W2BTPAVT.js} +25 -3
  125. package/dist/{media-treatment-6DDWZLLE.js → media-treatment-E4VJETTT.js} +30 -22
  126. package/dist/{models-CLSFYHTD.js → models-AHO3MYE7.js} +13 -15
  127. package/dist/{motionShot-WMJSRE67.js → motionShot-LMMYPGPT.js} +21 -23
  128. package/dist/{normalize-audio-YZTHI75G.js → normalize-audio-RDWIWZOO.js} +6 -7
  129. package/dist/{open-VSJ3TPAB.js → open-WOKRHFDH.js} +31 -8
  130. package/dist/{parakeetRunner-YCZT3DG2.js → parakeetRunner-RY2KIE63.js} +16 -18
  131. package/dist/{pipeline-RV64A4MZ.js → pipeline-LEA32KLW.js} +11 -13
  132. package/dist/{play-CF6TJIQL.js → play-3S46XG66.js} +21 -23
  133. package/dist/{policies-DCSIM4AB.js → policies-5NTZOHJA.js} +2 -0
  134. package/dist/preflight-MCOFNWFQ.js +52 -0
  135. package/dist/{present-5XKI26BN.js → present-GR7F4CTI.js} +17 -19
  136. package/dist/{preview-RORZIRSN.js → preview-TKEAF3KR.js} +34 -25
  137. package/dist/{producer-K2H3YFX5.js → producer-BJ5SUPVD.js} +1 -1
  138. package/dist/{progress-5AM2MZ7V.js → progress-I37JB7R4.js} +1 -0
  139. package/dist/{projectConfig-Q2ECBQUG.js → projectConfig-YJBYWSNK.js} +7 -7
  140. package/dist/{publication-2V3WX4HW.js → publication-2HXIW4LS.js} +3 -3
  141. package/dist/{publish-7COI3FRD.js → publish-LHJFEKEI.js} +11 -11
  142. package/dist/{remove-background-QSOESZXW.js → remove-background-AQUUVAPD.js} +12 -14
  143. package/dist/{render-ACRKADG6.js → render-AOHXNGIM.js} +40 -38
  144. package/dist/{render-KHDJ2P4J.js → render-AXTGGHVZ.js} +9 -4
  145. package/dist/{render-3ZLZDN64.js → render-B5S7FLLS.js} +14 -15
  146. package/dist/{render-batch-OG3JHMDF.js → render-batch-DMQG3QWK.js} +4 -4
  147. package/dist/renderSetupWorker.js +3 -3
  148. package/dist/{resolver-ALLVWDQE.js → resolver-FV54X3T2.js} +5 -5
  149. package/dist/sam-IKPEJRRO.js +21 -0
  150. package/dist/{screenshotCapture-XAYELJK7.js → screenshotCapture-HXEZ3TNJ.js} +20 -3
  151. package/dist/{sherpa-QY3NGRLC.js → sherpa-RKURBTUM.js} +15 -17
  152. package/dist/skills/hyperframes/SKILL.md +42 -0
  153. package/dist/skills/hyperframes-cli/references/cloud.md +1 -1
  154. package/dist/skills/media-use/scripts/lib/recipe-store.mjs +5 -2
  155. package/dist/{skills-YIZYEARC.js → skills-YUXI4IRF.js} +11 -10
  156. package/dist/{skillsUpdateCheck-EXZOQQRS.js → skillsUpdateCheck-HK3GDYD6.js} +3 -3
  157. package/dist/{snapshot-3XMGHMRD.js → snapshot-D6Q52Z4X.js} +32 -34
  158. package/dist/{src-CGIRN4KP.js → src-DPR7JBU3.js} +10 -12
  159. package/dist/{src-RY4V2ZZT.js → src-MRYINZ62.js} +10 -10
  160. package/dist/{staticProjectServer-4E3ODA5P.js → staticProjectServer-RT7JATD2.js} +15 -16
  161. package/dist/{status-RGHSK3DJ.js → status-BV7QAUQD.js} +2 -3
  162. package/dist/studio/assets/{hyperframes-player-BDj9J28W.js → hyperframes-player-B4KfQdfl.js} +1 -1
  163. package/dist/studio/assets/{index--HWjGqrU.js → index-Bsc8xBh9.js} +1 -1
  164. package/dist/studio/assets/{index-DkQKsFxx.css → index-CESvLzz0.css} +1 -1
  165. package/dist/studio/assets/{index-CVxB8lqm.js → index-DGl_Zvb3.js} +128 -128
  166. package/dist/studio/index.html +2 -2
  167. package/dist/{studio-api-LTHBT45F.js → studio-api-NL2RMVB5.js} +9 -10
  168. package/dist/{studioServer-NDRRYB5V.js → studioServer-VL2GUVCR.js} +63 -56
  169. package/dist/{system-VRXC6S4A.js → system-7F3UEHQT.js} +2 -3
  170. package/dist/{telemetry-QBHPMHPC.js → telemetry-5PJWDFSZ.js} +5 -6
  171. package/dist/{timeline-J22LXNAI.js → timeline-OH35TN25.js} +124 -51
  172. package/dist/{tokens-EAPT2GUT.js → tokens-YISVK7W2.js} +2 -2
  173. package/dist/{transcribe-L5GHBNR6.js → transcribe-6KBSE76Q.js} +12 -14
  174. package/dist/{transcribe-6LCZK44H.js → transcribe-KRPN2FWA.js} +22 -24
  175. package/dist/{updateCheck-B3U7O3QS.js → updateCheck-QCZTFFSQ.js} +2 -2
  176. package/dist/{upgrade-UMJEDSYD.js → upgrade-DRFQISI6.js} +2 -2
  177. package/dist/{urlDownloader-SRL6J4NU.js → urlDownloader-CJDXTKMC.js} +8 -10
  178. package/dist/{validate-I3KHH5Z4.js → validate-BKY3FIJC.js} +23 -27
  179. package/dist/{video-HWLZYFUC.js → video-3UEJ57Q7.js} +9 -11
  180. package/package.json +1 -1
  181. package/dist/chunk-7KDQAD2W.js +0 -81
  182. package/dist/chunk-BXCMXMJQ.js +0 -73
  183. package/dist/chunk-KCF6GHJP.js +0 -250
  184. package/dist/chunk-Q2E3DQII.js +0 -3803
  185. package/dist/preflight-G5KP7ZKA.js +0 -32
@@ -22,7 +22,7 @@ import {
22
22
  EncoderInterruptedError,
23
23
  encoderFailureError,
24
24
  prepareAnimatedGifInputs
25
- } from "./chunk-BQYQV6JP.js";
25
+ } from "./chunk-RYR3LTZR.js";
26
26
  import {
27
27
  BROWSER_GPU_NOT_SOFTWARE,
28
28
  CaptureFailure,
@@ -151,7 +151,7 @@ import {
151
151
  validateEngineConfigSnapshot,
152
152
  verifyDiskDrawElementSamples,
153
153
  writeCapturedFrame
154
- } from "./chunk-NZ5HOUJH.js";
154
+ } from "./chunk-XVIFWEPR.js";
155
155
  import {
156
156
  assignBundledRuntimeCompositionIds,
157
157
  buildVariablesByCompScript,
@@ -164,12 +164,12 @@ import {
164
164
  isTemplateEntry,
165
165
  parsesAsScript,
166
166
  prepareFlattenedInnerRoot
167
- } from "./chunk-M235XUHL.js";
167
+ } from "./chunk-UQLXFITA.js";
168
168
  import {
169
169
  LOW_MEMORY_TOTAL_MB_THRESHOLD,
170
170
  getCgroupMemoryLimitMb,
171
171
  getSystemTotalMb
172
- } from "./chunk-JYVGYKXG.js";
172
+ } from "./chunk-W2LGJSEN.js";
173
173
  import {
174
174
  DISTRIBUTED_FPS,
175
175
  HF_VFX_ATTR,
@@ -190,7 +190,7 @@ import {
190
190
  resolveAbsoluteMediaStartSeconds,
191
191
  resolveAuthoredTimingWindow,
192
192
  toFps
193
- } from "./chunk-PDFMNU6D.js";
193
+ } from "./chunk-RMKL5FVH.js";
194
194
  import {
195
195
  COMPOSITION_SOURCE_URL,
196
196
  HF_COLOR_GRADING_ATTR,
@@ -218,7 +218,7 @@ import {
218
218
  shouldClampResolvedMediaDuration,
219
219
  sourceTimeAt,
220
220
  styleElementsFor
221
- } from "./chunk-Q2E3DQII.js";
221
+ } from "./chunk-UKJECUDK.js";
222
222
  import {
223
223
  MAX_AUDIO_GAIN
224
224
  } from "./chunk-UJKQWGFF.js";
@@ -242,7 +242,7 @@ import {
242
242
  } from "./chunk-TWWSYAKJ.js";
243
243
  import {
244
244
  lintHyperframeHtml
245
- } from "./chunk-G47TXPYN.js";
245
+ } from "./chunk-GK2FIKIQ.js";
246
246
  import {
247
247
  isUnresolvedAssetPlaceholder,
248
248
  readProjectFile,
@@ -250,7 +250,7 @@ import {
250
250
  } from "./chunk-6BNTGNGD.js";
251
251
  import {
252
252
  checkSubCompositionUsability
253
- } from "./chunk-3RM2ETQT.js";
253
+ } from "./chunk-32GKETR7.js";
254
254
  import {
255
255
  CSS_URL_RE,
256
256
  decodedUrlPath,
@@ -419,11 +419,11 @@ var defaultLogger = createConsoleLogger("info");
419
419
 
420
420
  // ../producer/src/services/fileServer.ts
421
421
  var readFileAsync = promisify(readFile);
422
- function isPathInside(child, parent, options = {}) {
422
+ function isPathInside(child2, parent, options = {}) {
423
423
  const { resolveSymlinks = false, pathModule } = options;
424
424
  const resolveFn = pathModule?.resolve ?? resolve2;
425
425
  const separator = pathModule?.sep ?? sep;
426
- const resolvedChild = resolveFn(child);
426
+ const resolvedChild = resolveFn(child2);
427
427
  const resolvedParent = resolveFn(parent);
428
428
  const normalizedChild = resolveSymlinks && existsSync2(resolvedChild) ? realpathSync.native(resolvedChild) : resolvedChild;
429
429
  const normalizedParent = resolveSymlinks && existsSync2(resolvedParent) ? realpathSync.native(resolvedParent) : resolvedParent;
@@ -3342,10 +3342,10 @@ function aggregateDrawElement(perfs, de) {
3342
3342
  gateReason: gateReasons.length > 0 ? gateReasons.join("|") : void 0,
3343
3343
  gpuRenderer: gpuRenderers.length > 0 ? gpuRenderers.join("|") : void 0,
3344
3344
  workerEncode: perfs.some((p) => p.deWorkerEncode),
3345
- verifyArmed: perfs.reduce((sum, p) => sum + (p.deVerifyArmed ?? 0), 0),
3345
+ verifyArmed: perfs.reduce((sum2, p) => sum2 + (p.deVerifyArmed ?? 0), 0),
3346
3346
  verifyChecked: drain?.verifyChecked ?? 0,
3347
3347
  verifyMinDb: roundDb(drain?.verifyMinDb),
3348
- verifyInitMs: perfs.reduce((sum, p) => sum + (p.deVerifyInitMs ?? 0), 0),
3348
+ verifyInitMs: perfs.reduce((sum2, p) => sum2 + (p.deVerifyInitMs ?? 0), 0),
3349
3349
  selfVerifyFallback: de.selfVerifyFallback,
3350
3350
  fallbackReason: de.fallbackReason,
3351
3351
  fallbackFailedDb: roundDb(de.fallbackFailedDb),
@@ -3354,9 +3354,9 @@ function aggregateDrawElement(perfs, de) {
3354
3354
  blankSuspects: drain?.blankSuspects ?? 0,
3355
3355
  blankDeterministicAccepts: drain?.blankDeterministicAccepts ?? 0,
3356
3356
  blankRecaptures: drain?.blankRecaptures ?? 0,
3357
- boundaryFrames: perfs.reduce((sum, p) => sum + (p.deBoundaryFrames ?? 0), 0),
3358
- ncprFallbacks: perfs.reduce((sum, p) => sum + (p.deNcprFallbacks ?? 0), 0),
3359
- frameTimeouts: perfs.reduce((sum, p) => sum + (p.deFrameTimeouts ?? 0), 0)
3357
+ boundaryFrames: perfs.reduce((sum2, p) => sum2 + (p.deBoundaryFrames ?? 0), 0),
3358
+ ncprFallbacks: perfs.reduce((sum2, p) => sum2 + (p.deNcprFallbacks ?? 0), 0),
3359
+ frameTimeouts: perfs.reduce((sum2, p) => sum2 + (p.deFrameTimeouts ?? 0), 0)
3360
3360
  };
3361
3361
  }
3362
3362
  function maxDefined(values) {
@@ -3371,9 +3371,9 @@ function aggregateChromeMemory(perfs) {
3371
3371
  rendererRssPeakMb: maxDefined(sampled.map((p) => p.chromeRendererRssPeakMb)),
3372
3372
  // Last samples are per session; summing approximates the whole fleet's
3373
3373
  // footprint at the end of capture (workers run concurrently).
3374
- rssLastMb: sampled.reduce((sum, p) => sum + (p.chromeRssLastMb ?? 0), 0),
3374
+ rssLastMb: sampled.reduce((sum2, p) => sum2 + (p.chromeRssLastMb ?? 0), 0),
3375
3375
  gpuProcessSeenLastSample: sampled.some((p) => p.chromeGpuProcessSeenLastSample === true),
3376
- samples: sampled.reduce((sum, p) => sum + (p.chromeMemorySamples ?? 0), 0)
3376
+ samples: sampled.reduce((sum2, p) => sum2 + (p.chromeMemorySamples ?? 0), 0)
3377
3377
  };
3378
3378
  }
3379
3379
  function aggregateDedup(perfs) {
@@ -3391,45 +3391,45 @@ function aggregateDedup(perfs) {
3391
3391
  return {
3392
3392
  enabled: perfs.some((p) => p.staticDedupEnabled),
3393
3393
  armed,
3394
- predictedFrames: perfs.reduce((sum, p) => sum + (p.staticDedupPredicted ?? 0), 0),
3395
- reusedFrames: perfs.reduce((sum, p) => sum + (p.staticDedupReused ?? 0), 0),
3394
+ predictedFrames: perfs.reduce((sum2, p) => sum2 + (p.staticDedupPredicted ?? 0), 0),
3395
+ reusedFrames: perfs.reduce((sum2, p) => sum2 + (p.staticDedupReused ?? 0), 0),
3396
3396
  skipReason: skipReasons.length > 0 ? skipReasons.join("|") : void 0,
3397
3397
  ...verificationPerfs.length === 0 ? {} : {
3398
3398
  verifiedFrames: verificationPerfs.reduce(
3399
- (sum, perf) => sum + (perf.staticDedupVerified ?? 0),
3399
+ (sum2, perf) => sum2 + (perf.staticDedupVerified ?? 0),
3400
3400
  0
3401
3401
  ),
3402
3402
  verificationOutcomes,
3403
3403
  plannedRuns: verificationPerfs.reduce(
3404
- (sum, perf) => sum + (perf.staticDedupVerificationPlannedRuns ?? 0),
3404
+ (sum2, perf) => sum2 + (perf.staticDedupVerificationPlannedRuns ?? 0),
3405
3405
  0
3406
3406
  ),
3407
3407
  completedRuns: verificationPerfs.reduce(
3408
- (sum, perf) => sum + (perf.staticDedupVerificationCompletedRuns ?? 0),
3408
+ (sum2, perf) => sum2 + (perf.staticDedupVerificationCompletedRuns ?? 0),
3409
3409
  0
3410
3410
  ),
3411
3411
  screenshots: verificationPerfs.reduce(
3412
- (sum, perf) => sum + (perf.staticDedupVerificationScreenshots ?? 0),
3412
+ (sum2, perf) => sum2 + (perf.staticDedupVerificationScreenshots ?? 0),
3413
3413
  0
3414
3414
  ),
3415
3415
  seeks: verificationPerfs.reduce(
3416
- (sum, perf) => sum + (perf.staticDedupVerificationSeeks ?? 0),
3416
+ (sum2, perf) => sum2 + (perf.staticDedupVerificationSeeks ?? 0),
3417
3417
  0
3418
3418
  ),
3419
3419
  comparisons: verificationPerfs.reduce(
3420
- (sum, perf) => sum + (perf.staticDedupVerificationComparisons ?? 0),
3420
+ (sum2, perf) => sum2 + (perf.staticDedupVerificationComparisons ?? 0),
3421
3421
  0
3422
3422
  ),
3423
3423
  verificationElapsedMs: verificationPerfs.reduce(
3424
- (sum, perf) => sum + (perf.staticDedupVerificationElapsedMs ?? 0),
3424
+ (sum2, perf) => sum2 + (perf.staticDedupVerificationElapsedMs ?? 0),
3425
3425
  0
3426
3426
  )
3427
3427
  }
3428
3428
  };
3429
3429
  }
3430
3430
  function aggregateBeginFrameReuse(perfs) {
3431
- const noDamageFrames = perfs.reduce((sum, p) => sum + (p.beginFrameNoDamage ?? 0), 0);
3432
- const hasDamageFrames = perfs.reduce((sum, p) => sum + (p.beginFrameHasDamage ?? 0), 0);
3431
+ const noDamageFrames = perfs.reduce((sum2, p) => sum2 + (p.beginFrameNoDamage ?? 0), 0);
3432
+ const hasDamageFrames = perfs.reduce((sum2, p) => sum2 + (p.beginFrameHasDamage ?? 0), 0);
3433
3433
  if (noDamageFrames + hasDamageFrames === 0) return void 0;
3434
3434
  return { noDamageFrames, hasDamageFrames };
3435
3435
  }
@@ -8021,7 +8021,7 @@ var VideoExtractionStageError = class extends Error {
8021
8021
  affectedElementCount: failure.count
8022
8022
  }))
8023
8023
  )) {
8024
- const total = failures.reduce((sum, failure) => sum + failure.count, 0);
8024
+ const total = failures.reduce((sum2, failure) => sum2 + failure.count, 0);
8025
8025
  const breakdown = failures.map((failure) => `${failure.kind}=${failure.count}`).join(",");
8026
8026
  super(`Video extraction failed for ${total} source(s) [${code}; ${breakdown}]`);
8027
8027
  this.code = code;
@@ -10160,6 +10160,16 @@ async function padOrTrimAudioToVideoFrameCount(input) {
10160
10160
  ...loweredDb > 0 ? { audioLoweredDb: loweredDb } : {}
10161
10161
  };
10162
10162
  }
10163
+ async function constrainAacTruePeak(input) {
10164
+ const timeoutMs = input.timeoutMs ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
10165
+ return enforceAacTruePeak({
10166
+ audioPath: input.audioPath,
10167
+ targetDurationSeconds: input.targetDurationSeconds,
10168
+ signal: input.signal,
10169
+ probeTruePeak: (audioPath, signal) => defaultProbeAudioTruePeakDbfs(audioPath, timeoutMs, signal),
10170
+ runner: (args) => defaultRunFfmpeg(args, timeoutMs, input.signal)
10171
+ });
10172
+ }
10163
10173
  async function enforceAacTruePeak(input) {
10164
10174
  let scratchDir;
10165
10175
  try {
@@ -10755,7 +10765,7 @@ function countCapturedFrames(totalFrames, framesDir, frameExt) {
10755
10765
  return captured;
10756
10766
  }
10757
10767
  function countFrameRanges(ranges) {
10758
- return ranges.reduce((sum, range) => sum + (range.endFrame - range.startFrame), 0);
10768
+ return ranges.reduce((sum2, range) => sum2 + (range.endFrame - range.startFrame), 0);
10759
10769
  }
10760
10770
  async function executeDiskCaptureWithAdaptiveRetry(options) {
10761
10771
  const attempts = [];
@@ -11006,7 +11016,7 @@ function scanElementTags(html) {
11006
11016
  const byTag = Object.fromEntries(
11007
11017
  ranked.slice(0, MAX_REPORTED_ELEMENT_TAGS)
11008
11018
  );
11009
- const otherCount = ranked.slice(MAX_REPORTED_ELEMENT_TAGS).reduce((sum, [, count]) => sum + count, 0);
11019
+ const otherCount = ranked.slice(MAX_REPORTED_ELEMENT_TAGS).reduce((sum2, [, count]) => sum2 + count, 0);
11010
11020
  if (otherCount > 0) byTag.other = (byTag.other ?? 0) + otherCount;
11011
11021
  const arollVideoCount = markup.match(/<video\b[^>]*\bdata-aroll=["']true["'][^>]*>/gi)?.length ?? 0;
11012
11022
  const heygenVideoCount = markup.match(/<video\b[^>]*\bdata-media-source=["']heygen["'][^>]*>/gi)?.length ?? 0;
@@ -14002,15 +14012,15 @@ var ChunkExceedsWorkerTimeoutError = class extends Error {
14002
14012
  function resolveMaxParallelChunks(config, totalFrames, megapixels, log = defaultLogger) {
14003
14013
  if (config.maxParallelChunks !== void 0) return config.maxParallelChunks;
14004
14014
  const { workerTimeoutSeconds, workerConcurrency } = config;
14005
- const pinsChunking = config.chunkSize !== void 0 || config.targetChunkFrames !== void 0;
14006
- if (pinsChunking || workerTimeoutSeconds === void 0 && workerConcurrency === void 0) {
14007
- return DEFAULT_MAX_PARALLEL_CHUNKS;
14008
- }
14009
- const secondsPerFrame = ESTIMATED_SECONDS_PER_MEGAPIXEL_FRAME * megapixels;
14010
14015
  const wave = Math.min(
14011
14016
  workerConcurrency ?? DEFAULT_MAX_PARALLEL_CHUNKS,
14012
14017
  MAX_PARALLEL_CHUNKS_CEILING
14013
14018
  );
14019
+ const pinsChunking = config.chunkSize !== void 0 || config.targetChunkFrames !== void 0;
14020
+ if (pinsChunking || workerTimeoutSeconds === void 0 && workerConcurrency === void 0) {
14021
+ return wave;
14022
+ }
14023
+ const secondsPerFrame = ESTIMATED_SECONDS_PER_MEGAPIXEL_FRAME * megapixels;
14014
14024
  const minFramesPerChunk = Math.ceil(ESTIMATED_CHUNK_OVERHEAD_SECONDS / secondsPerFrame);
14015
14025
  const wide = Math.max(1, Math.min(wave, Math.floor(totalFrames / minFramesPerChunk)));
14016
14026
  if (workerTimeoutSeconds === void 0) return wide;
@@ -14027,7 +14037,7 @@ function resolveMaxParallelChunks(config, totalFrames, megapixels, log = default
14027
14037
  }
14028
14038
  if (needed > wave) {
14029
14039
  log.warn(
14030
- `[plan] ${needed} chunks are needed to keep each under the ${workerTimeoutSeconds} s worker time limit, but the plan assumes ${wave} workers at once, so the render runs in ${Math.ceil(needed / wave)} waves. Raise --concurrency to ${needed} to render in one wave (Lambda: hyperframes lambda deploy --concurrency ${needed}).`,
14040
+ `[plan] ${needed} chunks are needed to keep each under the ${workerTimeoutSeconds} s worker time limit, but the plan assumes ${wave} workers at once, so the render runs in ${Math.ceil(needed / wave)} waves. Raise --concurrency to ${needed} to render in one wave (Lambda: hyperframes lambda deploy --concurrency ${needed}, or a higher account concurrency quota).`,
14031
14041
  { needed, workerConcurrency: wave, workerTimeoutSeconds }
14032
14042
  );
14033
14043
  }
@@ -14199,21 +14209,6 @@ function buildLockedRenderConfig(input) {
14199
14209
  function carriesChunkAudio(config, options) {
14200
14210
  return options.chunksCarryAudio === true && config.format === "mp4" && config.cfr !== true;
14201
14211
  }
14202
- async function fitPlanAudioToFrames(audioPath, workDir, totalFrames, fps, run) {
14203
- const fittedPath = join29(workDir, "audio-fitted.m4a");
14204
- const result = await padOrTrimAudioToVideoFrameCount({
14205
- videoPath: audioPath,
14206
- probeVideoFrameInfo: async () => ({ frameCount: totalFrames, fpsNum: fps, fpsDen: 1 }),
14207
- audioPath,
14208
- outputPath: fittedPath,
14209
- signal: run.signal,
14210
- timeoutMs: run.timeoutMs
14211
- });
14212
- if (!result.success) {
14213
- throw encoderFailureError("[plan] audio pad/trim failed", result);
14214
- }
14215
- renameSync4(fittedPath, audioPath);
14216
- }
14217
14212
  function resolveEncoderTriple(config) {
14218
14213
  if (config.format === "mp4") {
14219
14214
  return resolveMp4EncoderTriple(config.codec);
@@ -14423,7 +14418,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
14423
14418
  if (probeResult.fileServer) closeFileServerSafely(probeResult.fileServer, "plan", log);
14424
14419
  if (probeResult.probeSession) {
14425
14420
  try {
14426
- const { closeCaptureSession: closeCaptureSession2 } = await import("./src-RY4V2ZZT.js");
14421
+ const { closeCaptureSession: closeCaptureSession2 } = await import("./src-MRYINZ62.js");
14427
14422
  await closeCaptureSession2(probeResult.probeSession);
14428
14423
  } catch (err) {
14429
14424
  log.warn("[plan] probe session close failed", {
@@ -14511,13 +14506,15 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
14511
14506
  "utf-8"
14512
14507
  );
14513
14508
  const digests = options.digests ?? /* @__PURE__ */ new Map();
14509
+ const chunksCarryAudio2 = carriesChunkAudio(config, options);
14510
+ const audioSeconds = chunksCarryAudio2 ? totalFrames / config.fps : probeResult.duration;
14514
14511
  stageStarted = Date.now();
14515
14512
  const [audioOutcome, overlapOutcome] = await Promise.allSettled([
14516
14513
  runAudioStage({
14517
14514
  projectDir,
14518
14515
  workDir,
14519
14516
  compiledDir: finalCompiledDir,
14520
- duration: probeResult.duration,
14517
+ duration: audioSeconds,
14521
14518
  ffmpegProcessTimeout: cfg.ffmpegProcessTimeout,
14522
14519
  audioGain: cfg.audioGain,
14523
14520
  audios: composition.audios,
@@ -14547,12 +14544,16 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
14547
14544
  if (audioResult.hasAudio && existsSync18(audioResult.audioOutputPath)) {
14548
14545
  renameSync4(audioResult.audioOutputPath, planAudioPath);
14549
14546
  }
14550
- const chunksCarryAudio2 = carriesChunkAudio(config, options);
14551
14547
  if (chunksCarryAudio2 && existsSync18(planAudioPath)) {
14552
- await fitPlanAudioToFrames(planAudioPath, workDir, totalFrames, config.fps, {
14548
+ stageStarted = Date.now();
14549
+ const peak = await constrainAacTruePeak({
14550
+ audioPath: planAudioPath,
14551
+ targetDurationSeconds: audioSeconds,
14553
14552
  signal: abortSignal,
14554
14553
  timeoutMs: cfg.ffmpegProcessTimeout
14555
14554
  });
14555
+ if (!peak.success) throw encoderFailureError("[plan] audio true-peak check failed", peak);
14556
+ logPlanStage(log, "audio-peak", stageStarted);
14556
14557
  }
14557
14558
  const ffmpegVersion = await readFfmpegVersion();
14558
14559
  const producerVersion = readProducerVersion();
@@ -14637,8 +14638,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
14637
14638
  producerVersion
14638
14639
  };
14639
14640
  }
14640
- async function plan(projectDir, config, planDir) {
14641
- const executionPlan = await buildLocalExecutionPlan(projectDir, config, planDir);
14641
+ async function plan(projectDir, config, planDir, options = {}) {
14642
+ const executionPlan = await buildLocalExecutionPlan(projectDir, config, planDir, options);
14642
14643
  return {
14643
14644
  planDir: executionPlan.executionPlanDir,
14644
14645
  planProtocol: PLAN_PROTOCOL_V1,
@@ -15963,7 +15964,7 @@ function startServer(options = {}) {
15963
15964
  });
15964
15965
  async function shutdown(signal) {
15965
15966
  log.info(`Received ${signal}, shutting down`);
15966
- const { drainBrowserPool } = await import("./src-RY4V2ZZT.js");
15967
+ const { drainBrowserPool } = await import("./src-MRYINZ62.js");
15967
15968
  await drainBrowserPool().catch(() => {
15968
15969
  });
15969
15970
  const handle = await Promise.race([
@@ -16225,7 +16226,7 @@ function resolveExtractedVideoOutputDir(planDir, videoId) {
16225
16226
  }
16226
16227
  function artifactTargets(path, videoDependencies, chunksCarryAudio2) {
16227
16228
  if (isPlanAudioArtifactPath(path)) {
16228
- return { chunks: chunksCarryAudio2 ? "all" : [], assembler: true };
16229
+ return chunksCarryAudio2 ? { chunks: "all", assembler: false } : { chunks: [], assembler: true };
16229
16230
  }
16230
16231
  if (path === "plan.json" || path === "meta/chunks.json" || path === "meta/encoder.json") {
16231
16232
  return { chunks: "all", assembler: true };
@@ -16786,7 +16787,7 @@ function materializePlanV2Target(planV2Dir, target, destinationDir) {
16786
16787
  planHash: manifest.planHash,
16787
16788
  sourcePlanV1Hash: getPlanV2ExecutionPlanHash(manifest),
16788
16789
  artifactCount: artifacts.length,
16789
- sizeBytes: artifacts.reduce((sum, artifact) => sum + artifact.sizeBytes, 0),
16790
+ sizeBytes: artifacts.reduce((sum2, artifact) => sum2 + artifact.sizeBytes, 0),
16790
16791
  // Join the artifact's OWN name, not the current constant: a plan written
16791
16792
  // before the container change carries the legacy name, and materializing it
16792
16793
  // under the new one would point at a file that was never written.
@@ -16823,24 +16824,371 @@ function validatePlanV2MaterializedTarget(planDir, expectedTarget) {
16823
16824
  }
16824
16825
 
16825
16826
  // ../producer/src/services/distributed/planV2Execution.ts
16826
- import { mkdtempSync as mkdtempSync8, rmSync as rmSync15 } from "fs";
16827
+ import { mkdtempSync as mkdtempSync9, rmSync as rmSync16 } from "fs";
16827
16828
  import { tmpdir as tmpdir5 } from "os";
16828
- import { join as join38 } from "path";
16829
+ import { join as join39 } from "path";
16829
16830
 
16830
16831
  // ../producer/src/services/distributed/assemble.ts
16831
16832
  import {
16832
16833
  cpSync as cpSync3,
16833
16834
  existsSync as existsSync24,
16834
- mkdirSync as mkdirSync14,
16835
- mkdtempSync as mkdtempSync7,
16835
+ mkdirSync as mkdirSync15,
16836
+ mkdtempSync as mkdtempSync8,
16836
16837
  readFileSync as readFileSync12,
16837
16838
  readdirSync as readdirSync9,
16838
- renameSync as renameSync7,
16839
- rmSync as rmSync13,
16839
+ renameSync as renameSync8,
16840
+ rmSync as rmSync14,
16840
16841
  statSync as statSync10,
16841
16842
  writeFileSync as writeFileSync11
16842
16843
  } from "fs";
16844
+ import { dirname as dirname16, join as join37 } from "path";
16845
+
16846
+ // ../producer/src/services/distributed/mp4Stitch.ts
16847
+ import {
16848
+ createReadStream as createReadStream5,
16849
+ createWriteStream,
16850
+ mkdirSync as mkdirSync14,
16851
+ mkdtempSync as mkdtempSync7,
16852
+ renameSync as renameSync7,
16853
+ rmSync as rmSync13
16854
+ } from "fs";
16855
+ import { open } from "fs/promises";
16843
16856
  import { dirname as dirname15, join as join36 } from "path";
16857
+ import { finished, pipeline } from "stream/promises";
16858
+ function boxAt(src, off, at, limit) {
16859
+ let size = src.readUInt32BE(off);
16860
+ let bodyStart = at + 8;
16861
+ if (size === 1) {
16862
+ size = Number(src.readBigUInt64BE(off + 8));
16863
+ bodyStart = at + 16;
16864
+ }
16865
+ if (size < 8 || at + size > limit) throw new Error(`[mp4Stitch] malformed box at ${at}`);
16866
+ return { type: src.toString("latin1", off + 4, off + 8), start: at, bodyStart, end: at + size };
16867
+ }
16868
+ function childBoxes(buf, parent) {
16869
+ const boxes = [];
16870
+ for (let at = parent.bodyStart; at < parent.end; at = boxes.at(-1).end) {
16871
+ boxes.push(boxAt(buf, at, at, parent.end));
16872
+ }
16873
+ return boxes;
16874
+ }
16875
+ function findChild(buf, parent, type) {
16876
+ return childBoxes(buf, parent).find((box2) => box2.type === type);
16877
+ }
16878
+ function child(buf, parent, type) {
16879
+ const found = findChild(buf, parent, type);
16880
+ if (!found) throw new Error(`[mp4Stitch] ${parent.type} has no ${type}`);
16881
+ return found;
16882
+ }
16883
+ var SCAN_BYTES = 64 * 1024;
16884
+ async function readMp4Layout(read) {
16885
+ const found = /* @__PURE__ */ new Map();
16886
+ let payload;
16887
+ let buf = Buffer.alloc(0);
16888
+ let bufAt = 0;
16889
+ const load = async (start, end) => {
16890
+ if (start >= bufAt && end <= bufAt + buf.length) return;
16891
+ buf = await read(start, Math.max(end, start + SCAN_BYTES));
16892
+ bufAt = start;
16893
+ };
16894
+ for (let at = 0; !(found.has("ftyp") && found.has("moov") && payload); ) {
16895
+ await load(at, at + 16);
16896
+ if (at + 8 > bufAt + buf.length) {
16897
+ throw new Error(`[mp4Stitch] chunk needs ftyp, moov and mdat; found ${[...found.keys()]}`);
16898
+ }
16899
+ const box2 = boxAt(buf, at - bufAt, at, Number.MAX_SAFE_INTEGER);
16900
+ if (box2.type === "mdat") payload ??= box2;
16901
+ if (box2.type === "ftyp" || box2.type === "moov") {
16902
+ await load(at, box2.end);
16903
+ found.set(box2.type, buf.subarray(at - bufAt, box2.end - bufAt));
16904
+ }
16905
+ at = box2.end;
16906
+ }
16907
+ const [ftyp, moov] = [found.get("ftyp"), found.get("moov")];
16908
+ if (moov.length !== moovSize(moov)) throw new Error("[mp4Stitch] moov is cut off");
16909
+ return { ftyp, moov, payloadStart: payload.bodyStart, payloadEnd: payload.end };
16910
+ }
16911
+ var moovSize = (moov) => boxAt(moov, 0, 0, Number.MAX_SAFE_INTEGER).end;
16912
+ function readTracks(moov) {
16913
+ const root = boxAt(moov, 0, 0, moov.length);
16914
+ return childBoxes(moov, root).filter((box2) => box2.type === "trak").map((trak) => readTrack(moov, trak));
16915
+ }
16916
+ function rows(buf, table, columns, countAt = 4) {
16917
+ const count = buf.readUInt32BE(table.bodyStart + countAt);
16918
+ const first = table.bodyStart + countAt + 4;
16919
+ return Array.from(
16920
+ { length: count },
16921
+ (_, row) => Array.from(
16922
+ { length: columns },
16923
+ (_2, col) => buf.readUInt32BE(first + (row * columns + col) * 4)
16924
+ )
16925
+ );
16926
+ }
16927
+ function readMediaTime(moov, trak) {
16928
+ const edts = findChild(moov, trak, "edts");
16929
+ if (!edts) return 0;
16930
+ const elst = child(moov, edts, "elst");
16931
+ const wide = moov[elst.bodyStart] === 1;
16932
+ const entries = moov.readUInt32BE(elst.bodyStart + 4);
16933
+ for (let i = 0, at = elst.bodyStart + 8; i < entries; i++, at += wide ? 20 : 12) {
16934
+ const offset = at + (wide ? 8 : 4);
16935
+ const mediaTime = wide ? Number(moov.readBigInt64BE(offset)) : moov.readInt32BE(offset);
16936
+ if (mediaTime !== -1) return mediaTime;
16937
+ }
16938
+ return 0;
16939
+ }
16940
+ function readSizes(moov, stsz) {
16941
+ const fixedSize = moov.readUInt32BE(stsz.bodyStart + 4);
16942
+ if (!fixedSize) return rows(moov, stsz, 1, 8).map(([size]) => size);
16943
+ return Array(moov.readUInt32BE(stsz.bodyStart + 8)).fill(fixedSize);
16944
+ }
16945
+ function readSync4(moov, stbl, sampleCount) {
16946
+ const stss = findChild(moov, stbl, "stss");
16947
+ if (!stss) return null;
16948
+ const sync = Array(sampleCount).fill(false);
16949
+ for (const [n] of rows(moov, stss, 1)) sync[n - 1] = true;
16950
+ return sync;
16951
+ }
16952
+ function readChunkOffsets(moov, stbl) {
16953
+ const stco = findChild(moov, stbl, "stco");
16954
+ if (stco) return rows(moov, stco, 1).map(([offset]) => offset);
16955
+ return rows(moov, child(moov, stbl, "co64"), 2).map(([hi, lo]) => hi * 2 ** 32 + lo);
16956
+ }
16957
+ function readSamplesPerChunk(moov, stbl, chunkCount) {
16958
+ const stsc = rows(moov, child(moov, stbl, "stsc"), 3);
16959
+ return stsc.flatMap(([firstChunk, perChunk, description], i) => {
16960
+ if (description !== 1) throw new Error("[mp4Stitch] chunk uses more than one sample entry");
16961
+ const nextFirst = stsc[i + 1]?.[0] ?? chunkCount + 1;
16962
+ return Array(nextFirst - firstChunk).fill(perChunk);
16963
+ });
16964
+ }
16965
+ function readTrack(moov, trak) {
16966
+ const mdia = child(moov, trak, "mdia");
16967
+ const hdlr = child(moov, mdia, "hdlr");
16968
+ const stbl = child(moov, child(moov, mdia, "minf"), "stbl");
16969
+ if (findChild(moov, stbl, "ctts")) throw new Error("[mp4Stitch] chunk has ctts (B-frames)");
16970
+ const stts = rows(moov, child(moov, stbl, "stts"), 2);
16971
+ const durations = stts.flatMap(([n, delta]) => Array(n).fill(delta));
16972
+ const sizes = readSizes(moov, child(moov, stbl, "stsz"));
16973
+ const chunkOffsets = readChunkOffsets(moov, stbl);
16974
+ const samplesPerChunk = readSamplesPerChunk(moov, stbl, chunkOffsets.length);
16975
+ if (durations.length !== sizes.length || sum(samplesPerChunk) !== sizes.length) {
16976
+ throw new Error("[mp4Stitch] sample tables disagree on the sample count");
16977
+ }
16978
+ const stsd = child(moov, stbl, "stsd");
16979
+ return {
16980
+ trak,
16981
+ handler: moov.toString("latin1", hdlr.bodyStart + 8, hdlr.bodyStart + 12),
16982
+ timescale: timescaleOf(moov, child(moov, mdia, "mdhd")),
16983
+ mediaTime: readMediaTime(moov, trak),
16984
+ stsd: moov.subarray(stsd.start, stsd.end),
16985
+ durations,
16986
+ sizes,
16987
+ sync: readSync4(moov, stbl, sizes.length),
16988
+ samplesPerChunk,
16989
+ chunkOffsets
16990
+ };
16991
+ }
16992
+ function sum(values) {
16993
+ return values.reduce((total, value) => total + value, 0);
16994
+ }
16995
+ function box(type, ...body) {
16996
+ const header = Buffer.alloc(8);
16997
+ header.writeUInt32BE(8 + sum(body.map((part) => part.length)));
16998
+ header.write(type, 4, "latin1");
16999
+ return Buffer.concat([header, ...body]);
17000
+ }
17001
+ function fullBox(type, version, body) {
17002
+ return box(type, Buffer.from([version, 0, 0, 0]), body);
17003
+ }
17004
+ function u32s(values) {
17005
+ const buf = Buffer.alloc(values.length * 4);
17006
+ values.forEach((value, i) => buf.writeUInt32BE(value, i * 4));
17007
+ return buf;
17008
+ }
17009
+ function runs(values) {
17010
+ const out = [];
17011
+ for (const value of values) {
17012
+ const last = out.at(-1);
17013
+ if (last && last[1] === value) last[0]++;
17014
+ else out.push([1, value]);
17015
+ }
17016
+ return out;
17017
+ }
17018
+ function rebuild(buf, parent, replace) {
17019
+ const parts = childBoxes(buf, parent).map(
17020
+ (box2) => replace[box2.type]?.(box2) ?? buf.subarray(box2.start, box2.end)
17021
+ );
17022
+ return box(parent.type, ...parts);
17023
+ }
17024
+ var DURATION_AT = {
17025
+ mvhd: [16, 24],
17026
+ mdhd: [16, 24],
17027
+ tkhd: [20, 28]
17028
+ };
17029
+ function withDuration(buf, target, duration) {
17030
+ const copy = Buffer.from(buf.subarray(target.start, target.end));
17031
+ const body = target.bodyStart - target.start;
17032
+ const wide = copy[body] === 1;
17033
+ const at = body + DURATION_AT[target.type][wide ? 1 : 0];
17034
+ if (wide) copy.writeBigUInt64BE(BigInt(duration), at);
17035
+ else if (duration <= 4294967295) copy.writeUInt32BE(duration, at);
17036
+ else throw new Error(`[mp4Stitch] ${target.type} duration ${duration} needs a version 1 box`);
17037
+ return copy;
17038
+ }
17039
+ function timescaleOf(buf, header) {
17040
+ return buf.readUInt32BE(header.bodyStart + (buf[header.bodyStart] === 1 ? 20 : 12));
17041
+ }
17042
+ function buildStbl(stsd, track) {
17043
+ const stts = runs(track.durations);
17044
+ const stsc = [];
17045
+ let firstChunk = 1;
17046
+ for (const [count, perChunk] of runs(track.samplesPerChunk)) {
17047
+ stsc.push([firstChunk, perChunk, 1]);
17048
+ firstChunk += count;
17049
+ }
17050
+ const co64 = Buffer.alloc(4 + track.chunkOffsets.length * 8);
17051
+ co64.writeUInt32BE(track.chunkOffsets.length);
17052
+ track.chunkOffsets.forEach((offset, i) => co64.writeBigUInt64BE(BigInt(offset), 4 + i * 8));
17053
+ const syncSamples = track.sync?.flatMap((isSync, i) => isSync ? [i + 1] : []) ?? null;
17054
+ return box(
17055
+ "stbl",
17056
+ stsd,
17057
+ fullBox("stts", 0, u32s([stts.length, ...stts.flat()])),
17058
+ ...syncSamples ? [fullBox("stss", 0, u32s([syncSamples.length, ...syncSamples]))] : [],
17059
+ fullBox("stsc", 0, u32s([stsc.length, ...stsc.flat()])),
17060
+ fullBox("stsz", 0, u32s([0, track.sizes.length, ...track.sizes])),
17061
+ fullBox("co64", 0, co64)
17062
+ );
17063
+ }
17064
+ var codecOf = (track) => track.stsd.toString("latin1", 20, 24);
17065
+ var sameTrack = (track, plan2) => track.handler === plan2.handler && track.timescale === plan2.timescale && codecOf(track) === codecOf(plan2);
17066
+ function planTracksOf(tracks, plan2, index) {
17067
+ let next = 0;
17068
+ const matched = plan2.map((planTrack) => {
17069
+ const track = tracks[next];
17070
+ if (track && sameTrack(track, planTrack)) return tracks[next++];
17071
+ if (planTrack.handler === "soun") return null;
17072
+ throw new Error(`[mp4Stitch] chunk ${index} tracks differ from chunk 0`);
17073
+ });
17074
+ if (next !== tracks.length)
17075
+ throw new Error(`[mp4Stitch] chunk ${index} tracks differ from chunk 0`);
17076
+ for (const track of tracks) {
17077
+ if (track.handler === "vide" && track.mediaTime !== 0) {
17078
+ throw new Error(`[mp4Stitch] chunk ${index} video starts at media time ${track.mediaTime}`);
17079
+ }
17080
+ }
17081
+ return matched;
17082
+ }
17083
+ function buildStitchedHeader(layouts) {
17084
+ const plan2 = readTracks(layouts[0].moov);
17085
+ const chunks = layouts.map((layout, i) => planTracksOf(readTracks(layout.moov), plan2, i));
17086
+ const payloadBases = [];
17087
+ let payloadBytes = 0;
17088
+ for (const layout of layouts) {
17089
+ payloadBases.push(payloadBytes);
17090
+ payloadBytes += layout.payloadEnd - layout.payloadStart;
17091
+ }
17092
+ const template = layouts[0].moov;
17093
+ const root = boxAt(template, 0, 0, template.length);
17094
+ const movieTimescale = timescaleOf(template, child(template, root, "mvhd"));
17095
+ const buildMoov = (dataStart2) => {
17096
+ const traks = plan2.map((track, t) => {
17097
+ const parts = chunks.flatMap((tracks, chunk) => {
17098
+ const part = tracks[t];
17099
+ return part ? [{ ...part, chunk }] : [];
17100
+ });
17101
+ const merged = {
17102
+ durations: parts.flatMap((part) => part.durations),
17103
+ sizes: parts.flatMap((part) => part.sizes),
17104
+ sync: parts.every((part) => !part.sync) ? null : parts.flatMap((part) => part.sync ?? part.sizes.map(() => true)),
17105
+ samplesPerChunk: parts.flatMap((part) => part.samplesPerChunk),
17106
+ chunkOffsets: parts.flatMap(
17107
+ (part) => part.chunkOffsets.map((offset) => {
17108
+ const i = part.chunk;
17109
+ const { payloadStart, payloadEnd } = layouts[i];
17110
+ if (offset < payloadStart || offset >= payloadEnd) {
17111
+ throw new Error(`[mp4Stitch] chunk ${i} has samples outside its mdat`);
17112
+ }
17113
+ return offset - payloadStart + payloadBases[i] + dataStart2;
17114
+ })
17115
+ )
17116
+ };
17117
+ const mediaDuration = sum(merged.durations);
17118
+ const shown = Math.round(
17119
+ (mediaDuration - track.mediaTime) * movieTimescale / track.timescale
17120
+ );
17121
+ const elst = Buffer.alloc(24);
17122
+ elst.writeUInt32BE(1);
17123
+ elst.writeBigUInt64BE(BigInt(shown), 4);
17124
+ elst.writeBigInt64BE(BigInt(track.mediaTime), 12);
17125
+ elst.writeUInt32BE(65536, 20);
17126
+ const edts = track.mediaTime ? box("edts", fullBox("elst", 1, elst)) : Buffer.alloc(0);
17127
+ const trak = rebuild(template, track.trak, {
17128
+ tkhd: (tkhd) => Buffer.concat([withDuration(template, tkhd, shown), edts]),
17129
+ edts: () => Buffer.alloc(0),
17130
+ mdia: (mdia) => rebuild(template, mdia, {
17131
+ mdhd: (mdhd) => withDuration(template, mdhd, mediaDuration),
17132
+ minf: (minf) => rebuild(template, minf, { stbl: () => buildStbl(track.stsd, merged) })
17133
+ })
17134
+ });
17135
+ return { trak, shown };
17136
+ });
17137
+ let next = 0;
17138
+ return rebuild(template, root, {
17139
+ mvhd: (mvhd) => withDuration(template, mvhd, Math.max(...traks.map((t) => t.shown))),
17140
+ trak: () => traks[next++].trak
17141
+ });
17142
+ };
17143
+ const ftyp = layouts[0].ftyp;
17144
+ const dataStart = ftyp.length + buildMoov(0).length + 16;
17145
+ const mdat = Buffer.alloc(16);
17146
+ mdat.writeUInt32BE(1);
17147
+ mdat.write("mdat", 4, "latin1");
17148
+ mdat.writeBigUInt64BE(BigInt(16 + payloadBytes), 8);
17149
+ return Buffer.concat([ftyp, buildMoov(dataStart), mdat]);
17150
+ }
17151
+ function fileRange(path) {
17152
+ return async (start, end) => {
17153
+ const file = await open(path, "r", 384);
17154
+ try {
17155
+ const buf = Buffer.alloc(end - start);
17156
+ const { bytesRead } = await file.read(buf, 0, buf.length, start);
17157
+ return buf.subarray(0, bytesRead);
17158
+ } finally {
17159
+ await file.close();
17160
+ }
17161
+ };
17162
+ }
17163
+ async function copyPayload(path, layout, index, out) {
17164
+ const { payloadStart, payloadEnd } = layout;
17165
+ const payload = createReadStream5(path, { start: payloadStart, end: payloadEnd - 1 });
17166
+ await pipeline(payload, out, { end: false });
17167
+ if (payload.bytesRead !== payloadEnd - payloadStart) {
17168
+ throw new Error(
17169
+ `[mp4Stitch] chunk ${index} mdat holds ${payload.bytesRead} of ${payloadEnd - payloadStart} payload bytes`
17170
+ );
17171
+ }
17172
+ }
17173
+ async function writeStitchedMp4(chunkPaths, outputPath) {
17174
+ const layouts = await Promise.all(chunkPaths.map((path) => readMp4Layout(fileRange(path))));
17175
+ const header = buildStitchedHeader(layouts);
17176
+ mkdirSync14(dirname15(outputPath), { recursive: true });
17177
+ const workDir = mkdtempSync7(`${outputPath}.stitch-`);
17178
+ const out = createWriteStream(join36(workDir, "out.mp4"));
17179
+ try {
17180
+ out.write(header);
17181
+ for (const [i, path] of chunkPaths.entries()) await copyPayload(path, layouts[i], i, out);
17182
+ out.end();
17183
+ await finished(out);
17184
+ renameSync7(join36(workDir, "out.mp4"), outputPath);
17185
+ } finally {
17186
+ out.destroy();
17187
+ rmSync13(workDir, { recursive: true, force: true });
17188
+ }
17189
+ }
17190
+
17191
+ // ../producer/src/services/distributed/assemble.ts
16844
17192
  function cfrRateControlArgs(locked) {
16845
17193
  const preset = getEncoderPreset(locked.quality ?? "standard", "mp4");
16846
17194
  if (locked.crf == null && locked.bitrate) {
@@ -16856,12 +17204,21 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16856
17204
  if (plan2.dimensions.format === "png-sequence") {
16857
17205
  return mergePngFrameDirs(chunkPaths, outputPath, plan2.totalFrames, audioPath, start);
16858
17206
  }
17207
+ if (chunksAreStitchedMp4(planDir, cfr)) {
17208
+ await writeStitchedMp4(chunkPaths, outputPath);
17209
+ return {
17210
+ outputPath,
17211
+ durationMs: Date.now() - start,
17212
+ framesEncoded: plan2.totalFrames,
17213
+ fileSize: statSync10(outputPath).size
17214
+ };
17215
+ }
16859
17216
  const format = plan2.dimensions.format;
16860
17217
  const cfrEncoder = cfr ? readCfrEncoder(planDir, format) : null;
16861
- if (!existsSync24(dirname15(outputPath))) {
16862
- mkdirSync14(dirname15(outputPath), { recursive: true });
17218
+ if (!existsSync24(dirname16(outputPath))) {
17219
+ mkdirSync15(dirname16(outputPath), { recursive: true });
16863
17220
  }
16864
- const workDir = mkdtempSync7(`${outputPath}.assemble-work-`);
17221
+ const workDir = mkdtempSync8(`${outputPath}.assemble-work-`);
16865
17222
  const fps = { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen };
16866
17223
  const stageMs = {};
16867
17224
  const ctx = {
@@ -16869,7 +17226,6 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16869
17226
  format,
16870
17227
  fps,
16871
17228
  fpsArg: fpsToFfmpegArg(fps),
16872
- chunkSeconds: chunksCarryAudio(planDir) ? plan2.chunks.map((chunk) => (chunk.endFrame - chunk.startFrame) * fps.den / fps.num) : null,
16873
17229
  signal: options?.abortSignal,
16874
17230
  timeout: resolveConfig().ffmpegProcessTimeout,
16875
17231
  log,
@@ -16882,10 +17238,10 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16882
17238
  };
16883
17239
  try {
16884
17240
  const videoSources = cfrEncoder ? [await reencodeCfr(ctx, chunkPaths, cfrEncoder)] : chunkPaths;
16885
- const finalPath = join36(workDir, `output.${format}`);
17241
+ const finalPath = join37(workDir, `output.${format}`);
16886
17242
  const audio = audioPath !== null && existsSync24(audioPath) ? audioPath : null;
16887
17243
  await writeJoined(ctx, videoSources, audio, finalPath);
16888
- renameSync7(finalPath, outputPath);
17244
+ renameSync8(finalPath, outputPath);
16889
17245
  log.info("[assemble] stage timings", {
16890
17246
  ...stageMs,
16891
17247
  chunks: chunkPaths.length,
@@ -16893,7 +17249,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16893
17249
  });
16894
17250
  } finally {
16895
17251
  try {
16896
- rmSync13(workDir, { recursive: true, force: true });
17252
+ rmSync14(workDir, { recursive: true, force: true });
16897
17253
  } catch (err) {
16898
17254
  log.warn("[assemble] failed to remove work dir", {
16899
17255
  workDir,
@@ -16910,8 +17266,8 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16910
17266
  };
16911
17267
  }
16912
17268
  function readAssemblePlan(planDir, chunkPaths) {
16913
- const planJsonPath = join36(planDir, "plan.json");
16914
- const chunksJsonPath = join36(planDir, "meta", "chunks.json");
17269
+ const planJsonPath = join37(planDir, "plan.json");
17270
+ const chunksJsonPath = join37(planDir, "meta", "chunks.json");
16915
17271
  if (!existsSync24(planJsonPath)) {
16916
17272
  throw new Error(`[assemble] planDir missing plan.json: ${planJsonPath}`);
16917
17273
  }
@@ -16932,13 +17288,13 @@ function readAssemblePlan(planDir, chunkPaths) {
16932
17288
  throw new Error(`[assemble] chunk path does not exist: ${path}`);
16933
17289
  }
16934
17290
  }
16935
- return { ...plan2, chunks };
17291
+ return plan2;
16936
17292
  }
16937
17293
  function videoInputArgs(ctx, videoSources) {
16938
- return videoSources.length === 1 ? ["-i", videoSources[0]] : concatDemuxerInput(videoSources, ctx.workDir, ctx.fpsArg, ctx.chunkSeconds);
17294
+ return videoSources.length === 1 ? ["-i", videoSources[0]] : concatDemuxerInput(videoSources, ctx.workDir, ctx.fpsArg);
16939
17295
  }
16940
17296
  async function reencodeCfr(ctx, chunkPaths, encoder) {
16941
- const cfrOutputPath = join36(ctx.workDir, `cfr.${ctx.format}`);
17297
+ const cfrOutputPath = join37(ctx.workDir, `cfr.${ctx.format}`);
16942
17298
  const cfrArgs = [
16943
17299
  ...videoInputArgs(ctx, chunkPaths),
16944
17300
  "-c:v",
@@ -16976,7 +17332,7 @@ async function writeJoined(ctx, videoSources, audioPath, finalPath) {
16976
17332
  );
16977
17333
  return;
16978
17334
  }
16979
- const paddedAudioPath = join36(ctx.workDir, "audio-padded.m4a");
17335
+ const paddedAudioPath = join37(ctx.workDir, "audio-padded.m4a");
16980
17336
  const padTrimResult = await ctx.timed(
16981
17337
  "audioMs",
16982
17338
  () => padOrTrimAudioToVideoFrameCount({
@@ -17015,15 +17371,10 @@ async function writeJoined(ctx, videoSources, audioPath, finalPath) {
17015
17371
  throw encoderFailureError("[assemble] audio mux failed", muxResult);
17016
17372
  }
17017
17373
  }
17018
- function concatDemuxerInput(chunkPaths, workDir, fpsArg, chunkSeconds) {
17019
- const listPath = join36(workDir, "concat-list.txt");
17020
- const head = chunkSeconds ? ["stream", "exact_stream_id 1"] : [];
17021
- const body = chunkPaths.map((path, i) => {
17022
- const line = `file '${path.replace(/'/g, "'\\''")}'`;
17023
- return chunkSeconds ? `${line}
17024
- duration ${chunkSeconds[i].toFixed(6)}` : line;
17025
- });
17026
- writeFileSync11(listPath, `${[...head, ...body].join("\n")}
17374
+ function concatDemuxerInput(chunkPaths, workDir, fpsArg) {
17375
+ const listPath = join37(workDir, "concat-list.txt");
17376
+ const body = chunkPaths.map((path) => `file '${path.replace(/'/g, "'\\''")}'`).join("\n");
17377
+ writeFileSync11(listPath, `${body}
17027
17378
  `, "utf-8");
17028
17379
  return ["-r", fpsArg, "-f", "concat", "-safe", "0", "-i", listPath];
17029
17380
  }
@@ -17032,7 +17383,7 @@ async function probeJoinedFrameInfo(videoPaths, fps, signal) {
17032
17383
  videoPaths.map((path) => defaultProbeVideoFrameInfo(path, signal))
17033
17384
  );
17034
17385
  return {
17035
- frameCount: infos.reduce((sum, info) => sum + info.frameCount, 0),
17386
+ frameCount: infos.reduce((sum2, info) => sum2 + info.frameCount, 0),
17036
17387
  fpsNum: fps.num,
17037
17388
  fpsDen: fps.den
17038
17389
  };
@@ -17046,8 +17397,15 @@ async function runAssembleFfmpeg(args, step, signal, timeout) {
17046
17397
  });
17047
17398
  }
17048
17399
  }
17400
+ function chunksAreStitchedMp4(planDir, cfr) {
17401
+ if (!chunksCarryAudio(planDir)) return false;
17402
+ if (cfr) {
17403
+ throw new Error("[assemble] cfr=true cannot re-encode a plan whose mp4 chunks carry audio");
17404
+ }
17405
+ return true;
17406
+ }
17049
17407
  function chunksCarryAudio(planDir) {
17050
- const encoderJsonPath = join36(planDir, "meta", "encoder.json");
17408
+ const encoderJsonPath = join37(planDir, "meta", "encoder.json");
17051
17409
  if (!existsSync24(encoderJsonPath)) return false;
17052
17410
  return JSON.parse(readFileSync12(encoderJsonPath, "utf-8")).chunksCarryAudio === true;
17053
17411
  }
@@ -17057,7 +17415,7 @@ function readCfrEncoder(planDir, format) {
17057
17415
  `[assemble] cfr=true is only supported for format="mp4" (got "${format}"). Stream-copy paths for webm and mov already produce exact avg_frame_rate; cfr re-encode is not needed.`
17058
17416
  );
17059
17417
  }
17060
- const encoderJsonPath = join36(planDir, "meta", "encoder.json");
17418
+ const encoderJsonPath = join37(planDir, "meta", "encoder.json");
17061
17419
  if (!existsSync24(encoderJsonPath)) {
17062
17420
  throw new Error(`[assemble] planDir missing meta/encoder.json: ${encoderJsonPath}`);
17063
17421
  }
@@ -17070,8 +17428,8 @@ function readCfrEncoder(planDir, format) {
17070
17428
  return encoderJson;
17071
17429
  }
17072
17430
  function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, startTimeMs) {
17073
- if (existsSync24(outputPath)) rmSync13(outputPath, { recursive: true, force: true });
17074
- mkdirSync14(outputPath, { recursive: true });
17431
+ if (existsSync24(outputPath)) rmSync14(outputPath, { recursive: true, force: true });
17432
+ mkdirSync15(outputPath, { recursive: true });
17075
17433
  let globalIdx = 0;
17076
17434
  for (const chunkDir of chunkPaths) {
17077
17435
  if (!statSync10(chunkDir).isDirectory()) {
@@ -17084,8 +17442,8 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
17084
17442
  throw new Error(`[assemble] png-sequence chunk has no frames: ${chunkDir}`);
17085
17443
  }
17086
17444
  for (const frame of frames) {
17087
- const dst = join36(outputPath, formatExportFrameName(globalIdx, "png"));
17088
- cpSync3(join36(chunkDir, frame), dst);
17445
+ const dst = join37(outputPath, formatExportFrameName(globalIdx, "png"));
17446
+ cpSync3(join37(chunkDir, frame), dst);
17089
17447
  globalIdx += 1;
17090
17448
  }
17091
17449
  }
@@ -17095,13 +17453,13 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
17095
17453
  );
17096
17454
  }
17097
17455
  if (audioPath !== null && existsSync24(audioPath)) {
17098
- const sidecar = join36(outputPath, MIXED_AUDIO_FILENAME);
17456
+ const sidecar = join37(outputPath, MIXED_AUDIO_FILENAME);
17099
17457
  cpSync3(audioPath, sidecar);
17100
17458
  }
17101
17459
  let fileSize = 0;
17102
17460
  for (const name of readdirSync9(outputPath)) {
17103
17461
  try {
17104
- fileSize += statSync10(join36(outputPath, name)).size;
17462
+ fileSize += statSync10(join37(outputPath, name)).size;
17105
17463
  } catch {
17106
17464
  }
17107
17465
  }
@@ -17115,8 +17473,8 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
17115
17473
 
17116
17474
  // ../producer/src/services/distributed/renderChunk.ts
17117
17475
  import { randomBytes } from "crypto";
17118
- import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync13, readdirSync as readdirSync10, rmSync as rmSync14, writeFileSync as writeFileSync12 } from "fs";
17119
- import { extname as extname6, join as join37 } from "path";
17476
+ import { existsSync as existsSync25, mkdirSync as mkdirSync16, readFileSync as readFileSync13, readdirSync as readdirSync10, rmSync as rmSync15, writeFileSync as writeFileSync12 } from "fs";
17477
+ import { extname as extname6, join as join38 } from "path";
17120
17478
 
17121
17479
  // ../producer/src/services/distributed/chunkAudio.ts
17122
17480
  function audioCutForChunk(grid, chunks, index, fps) {
@@ -17302,7 +17660,7 @@ function frameNumberFromFileName(name) {
17302
17660
  function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v1") {
17303
17661
  const result = [];
17304
17662
  for (const v of videos) {
17305
- const outputDir = join37(planDir, "video-frames", v.videoId);
17663
+ const outputDir = join38(planDir, "video-frames", v.videoId);
17306
17664
  if (!existsSync25(outputDir)) {
17307
17665
  throw new Error(
17308
17666
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
@@ -17321,7 +17679,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v
17321
17679
  if (!frameName) continue;
17322
17680
  const frameNumber = indexMode === "sparse-v2" ? frameNumberFromFileName(frameName) : null;
17323
17681
  const frameIndex = frameNumber === null ? i : frameNumber - 1;
17324
- framePaths.set(frameIndex, join37(outputDir, frameName));
17682
+ framePaths.set(frameIndex, join38(outputDir, frameName));
17325
17683
  }
17326
17684
  result.push({
17327
17685
  videoId: v.videoId,
@@ -17343,13 +17701,13 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v
17343
17701
  return result;
17344
17702
  }
17345
17703
  function contiguousRuns(sortedIndexes) {
17346
- const runs = [];
17704
+ const runs2 = [];
17347
17705
  for (const index of sortedIndexes) {
17348
- const last = runs[runs.length - 1];
17706
+ const last = runs2[runs2.length - 1];
17349
17707
  if (last && last.firstFrame + last.frames === index) last.frames++;
17350
- else runs.push({ firstFrame: index, frames: 1 });
17708
+ else runs2.push({ firstFrame: index, frames: 1 });
17351
17709
  }
17352
- return runs;
17710
+ return runs2;
17353
17711
  }
17354
17712
  async function extractDeferredVideoFramesForChunk(input) {
17355
17713
  const deferred = input.planVideos.extracted.filter((video) => video.deferredRange);
@@ -17374,13 +17732,13 @@ async function extractDeferredVideoFramesForChunk(input) {
17374
17732
  }
17375
17733
  return Promise.all(
17376
17734
  deferred.map(async (video) => {
17377
- const outputDir = join37(input.outputRoot, video.videoId);
17735
+ const outputDir = join38(input.outputRoot, video.videoId);
17378
17736
  const indexes = [...shown.get(video.videoId) ?? []].sort((a, b) => a - b);
17379
17737
  if (indexes.length === 0) {
17380
17738
  return { ...video, outputDir, framePaths: /* @__PURE__ */ new Map(), ownedByLookup: false };
17381
17739
  }
17382
17740
  const range = video.deferredRange;
17383
- const sourcePath = join37(input.planDir, ...range.sourcePath.split("/"));
17741
+ const sourcePath = join38(input.planDir, ...range.sourcePath.split("/"));
17384
17742
  if (!existsSync25(sourcePath)) {
17385
17743
  throw new RenderChunkValidationError(
17386
17744
  MISSING_PLAN_ARTIFACT,
@@ -17416,7 +17774,7 @@ function hashChunkOutput(outputPath, kind) {
17416
17774
  if (kind === "file") return sha256Hex(readFileSync13(outputPath));
17417
17775
  const entries = readdirSync10(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
17418
17776
  const lines = entries.map(
17419
- (name) => `${name}\0${sha256Hex(readFileSync13(join37(outputPath, name)))}`
17777
+ (name) => `${name}\0${sha256Hex(readFileSync13(join38(outputPath, name)))}`
17420
17778
  );
17421
17779
  return sha256Hex(lines.join("\0"));
17422
17780
  }
@@ -17433,9 +17791,9 @@ function resolveLockedVp9CpuUsed(lockedEncoder) {
17433
17791
  async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17434
17792
  const start = Date.now();
17435
17793
  const log = defaultLogger;
17436
- const planJsonPath = join37(planDir, "plan.json");
17437
- const encoderJsonPath = join37(planDir, "meta", "encoder.json");
17438
- const chunksJsonPath = join37(planDir, "meta", "chunks.json");
17794
+ const planJsonPath = join38(planDir, "plan.json");
17795
+ const encoderJsonPath = join38(planDir, "meta", "encoder.json");
17796
+ const chunksJsonPath = join38(planDir, "meta", "chunks.json");
17439
17797
  if (!existsSync25(planJsonPath)) {
17440
17798
  throw new RenderChunkValidationError(
17441
17799
  MISSING_PLAN_ARTIFACT,
@@ -17459,7 +17817,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17459
17817
  }
17460
17818
  const encoder = JSON.parse(readFileSync13(encoderJsonPath, "utf-8"));
17461
17819
  const chunks = JSON.parse(readFileSync13(chunksJsonPath, "utf-8"));
17462
- const videosJsonPath = join37(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
17820
+ const videosJsonPath = join38(planDir, PLAN_VIDEOS_META_RELATIVE_PATH);
17463
17821
  let planVideos = null;
17464
17822
  if (existsSync25(videosJsonPath)) {
17465
17823
  try {
@@ -17489,7 +17847,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17489
17847
  `[renderChunk] chunk ${chunkIndex} has non-positive frame count: ${framesInChunk}`
17490
17848
  );
17491
17849
  }
17492
- const compiledDir = join37(planDir, "compiled");
17850
+ const compiledDir = join38(planDir, "compiled");
17493
17851
  if (!existsSync25(compiledDir)) {
17494
17852
  throw new RenderChunkValidationError(
17495
17853
  MISSING_PLAN_ARTIFACT,
@@ -17546,9 +17904,9 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17546
17904
  forceScreenshotExplicitlyOptedOut: !encoder.forceScreenshot
17547
17905
  };
17548
17906
  const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes(4).toString("hex")}`;
17549
- mkdirSync15(workDir, { recursive: true });
17550
- const framesDir = join37(workDir, "captured-frames");
17551
- mkdirSync15(framesDir, { recursive: true });
17907
+ mkdirSync16(workDir, { recursive: true });
17908
+ const framesDir = join38(workDir, "captured-frames");
17909
+ mkdirSync16(framesDir, { recursive: true });
17552
17910
  const videoFramesDir = `${workDir}.video-frames`;
17553
17911
  const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? createFrameLookupTable(
17554
17912
  planVideos.videos,
@@ -17601,7 +17959,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17601
17959
  // `beginFrameTimeTicks` is host-independent. Only chunks ever set this.
17602
17960
  lockWarmupTicks: true,
17603
17961
  requiresWebGpu: compositionRequiresWebGpu(
17604
- readFileSync13(join37(compiledDir, "index.html"), "utf-8")
17962
+ readFileSync13(join38(compiledDir, "index.html"), "utf-8")
17605
17963
  )
17606
17964
  };
17607
17965
  const chunkWorkerCount = calculateOptimalWorkers(framesInChunk, void 0, cfg);
@@ -17732,8 +18090,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17732
18090
  return observedMode;
17733
18091
  },
17734
18092
  resetForScreenshotRetry: () => {
17735
- rmSync14(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
17736
- mkdirSync15(framesDir, { recursive: true });
18093
+ rmSync15(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
18094
+ mkdirSync16(framesDir, { recursive: true });
17737
18095
  capturePerfs.length = 0;
17738
18096
  captureAttempts.length = 0;
17739
18097
  job.framesRendered = 0;
@@ -17764,10 +18122,10 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17764
18122
  const effectiveBitrate = encoder.crf != null ? void 0 : encoder.bitrate;
17765
18123
  const videoOnlyPath = encoder.chunksCarryAudio ? `${outputChunkPath}.video.mp4` : outputChunkPath;
17766
18124
  if (isPngSequence) {
17767
- if (!existsSync25(outputChunkPath)) mkdirSync15(outputChunkPath, { recursive: true });
18125
+ if (!existsSync25(outputChunkPath)) mkdirSync16(outputChunkPath, { recursive: true });
17768
18126
  } else {
17769
- const outDir = join37(outputChunkPath, "..");
17770
- if (!existsSync25(outDir)) mkdirSync15(outDir, { recursive: true });
18127
+ const outDir = join38(outputChunkPath, "..");
18128
+ if (!existsSync25(outDir)) mkdirSync16(outDir, { recursive: true });
17771
18129
  }
17772
18130
  const encodeStarted = Date.now();
17773
18131
  await runEncodeStage({
@@ -17819,7 +18177,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17819
18177
  fps: { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen },
17820
18178
  timeoutMs: cfg.ffmpegProcessTimeout
17821
18179
  });
17822
- rmSync14(videoOnlyPath, { force: true });
18180
+ rmSync15(videoOnlyPath, { force: true });
17823
18181
  }
17824
18182
  encodeStageMs = Date.now() - encodeStarted;
17825
18183
  } finally {
@@ -17861,8 +18219,8 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17861
18219
  writeFileSync12(perfPath, `${JSON.stringify(perfPayload, null, 2)}
17862
18220
  `, "utf-8");
17863
18221
  try {
17864
- rmSync14(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
17865
- rmSync14(videoFramesDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
18222
+ rmSync15(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
18223
+ rmSync15(videoFramesDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
17866
18224
  } catch (err) {
17867
18225
  log.warn("[renderChunk] failed to remove work dir", {
17868
18226
  workDir,
@@ -17890,18 +18248,18 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17890
18248
 
17891
18249
  // ../producer/src/services/distributed/planV2Execution.ts
17892
18250
  async function renderChunkV2(planV2Dir, chunkIndex, outputChunkPath) {
17893
- const workRoot = mkdtempSync8(join38(tmpdir5(), "hf-plan-v2-chunk-"));
17894
- const materializedPlanDir = join38(workRoot, "plan");
18251
+ const workRoot = mkdtempSync9(join39(tmpdir5(), "hf-plan-v2-chunk-"));
18252
+ const materializedPlanDir = join39(workRoot, "plan");
17895
18253
  try {
17896
18254
  materializePlanV2Target(planV2Dir, { role: "chunk", chunkIndex }, materializedPlanDir);
17897
18255
  return await renderChunk(materializedPlanDir, chunkIndex, outputChunkPath);
17898
18256
  } finally {
17899
- rmSync15(workRoot, { recursive: true, force: true });
18257
+ rmSync16(workRoot, { recursive: true, force: true });
17900
18258
  }
17901
18259
  }
17902
18260
  async function assembleV2(planV2Dir, chunkPaths, outputPath, options) {
17903
- const workRoot = mkdtempSync8(join38(tmpdir5(), "hf-plan-v2-assembler-"));
17904
- const materializedPlanDir = join38(workRoot, "plan");
18261
+ const workRoot = mkdtempSync9(join39(tmpdir5(), "hf-plan-v2-assembler-"));
18262
+ const materializedPlanDir = join39(workRoot, "plan");
17905
18263
  try {
17906
18264
  const materialized = materializePlanV2Target(
17907
18265
  planV2Dir,
@@ -17916,14 +18274,14 @@ async function assembleV2(planV2Dir, chunkPaths, outputPath, options) {
17916
18274
  options
17917
18275
  );
17918
18276
  } finally {
17919
- rmSync15(workRoot, { recursive: true, force: true });
18277
+ rmSync16(workRoot, { recursive: true, force: true });
17920
18278
  }
17921
18279
  }
17922
18280
 
17923
18281
  // ../producer/src/services/distributed/projectHash.ts
17924
18282
  import { readdirSync as readdirSync11, readFileSync as readFileSync14 } from "fs";
17925
18283
  import { createHash as createHash7 } from "crypto";
17926
- import { join as join39, relative as relative8 } from "path";
18284
+ import { join as join40, relative as relative8 } from "path";
17927
18285
 
17928
18286
  export {
17929
18287
  createConsoleLogger,