hyperframes 0.8.144 → 0.8.146

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/README.md +3 -2
  2. package/dist/{add-CWRTVGDB.js → add-6J4TLUDW.js} +15 -15
  3. package/dist/{animatedGifPrep-JTOHIWI4.js → animatedGifPrep-TPYA45ZZ.js} +10 -10
  4. package/dist/{asset-KU2Z4UFM.js → asset-B4C6ZU4V.js} +2 -2
  5. package/dist/{assetCataloger-3CS2P7PA.js → assetCataloger-GX4B55VB.js} +4 -4
  6. package/dist/{auth-IDSOIQWG.js → auth-T2V3URGO.js} +2 -2
  7. package/dist/{autoUpdate-373B4BA2.js → autoUpdate-O4R7IOYP.js} +2 -2
  8. package/dist/{backgroundChecks-53Q3NAMG.js → backgroundChecks-SQHGZCSH.js} +3 -3
  9. package/dist/backgroundChecksWorker.js +3 -3
  10. package/dist/{batchRender-UKZA6BME.js → batchRender-T7S2CGJE.js} +5 -5
  11. package/dist/{beats-N5JGEOFR.js → beats-RNEXDM7U.js} +16 -16
  12. package/dist/{benchmark-CUN3LN4V.js → benchmark-IVK6FCEU.js} +12 -12
  13. package/dist/{browser-NCZT5AP6.js → browser-WUE6VK2N.js} +5 -5
  14. package/dist/{bundleWithLocalizedFonts-FWC7PE2D.js → bundleWithLocalizedFonts-EEIRL7FT.js} +2 -2
  15. package/dist/{capture-YLS32UHT.js → capture-K3EONGGU.js} +2 -2
  16. package/dist/{capture-QBLG3VJR.js → capture-LEKIGJ4G.js} +13 -13
  17. package/dist/{catalog-HIWNAFHW.js → catalog-IXYQ2KXW.js} +15 -15
  18. package/dist/{catch-up-HGS7KIAC.js → catch-up-IIF7HKR6.js} +6 -6
  19. package/dist/{check-FH6UYYLO.js → check-W7CDOXNP.js} +38 -38
  20. package/dist/{checkBrowser-RNWNOMCZ.js → checkBrowser-5VSXEHBZ.js} +118 -61
  21. package/dist/{chunk-XU5GGV6R.js → chunk-2NAUEDA6.js} +2 -2
  22. package/dist/{chunk-GZM2EFOE.js → chunk-3HSWLZ6S.js} +1 -1
  23. package/dist/{chunk-YUAXFWSQ.js → chunk-4RUILXS6.js} +5 -5
  24. package/dist/{chunk-MXNDKDFT.js → chunk-54UXJKFF.js} +1 -1
  25. package/dist/{chunk-DIRJ322I.js → chunk-66SAATRI.js} +3 -3
  26. package/dist/{chunk-RI53TS2Y.js → chunk-6TTAXMDG.js} +2 -2
  27. package/dist/{chunk-YJXHMIZA.js → chunk-A72OAGNB.js} +6 -6
  28. package/dist/{chunk-G75ENCEZ.js → chunk-AIJS74LG.js} +3 -3
  29. package/dist/{chunk-GEWKFRFI.js → chunk-AJ5R4GM6.js} +1 -1
  30. package/dist/{chunk-3VYNNWVA.js → chunk-BAKPN2D2.js} +101 -94
  31. package/dist/{chunk-3XTEXWNN.js → chunk-CVPWZ5LY.js} +3 -3
  32. package/dist/{chunk-AUBOF2PN.js → chunk-DDNS2674.js} +1 -1
  33. package/dist/{chunk-QFSCCQIR.js → chunk-DMKI64EZ.js} +1 -1
  34. package/dist/{chunk-NOPBBSLA.js → chunk-DUU77E2S.js} +69 -64
  35. package/dist/{chunk-RVFEDAUV.js → chunk-EGO6Z24R.js} +3 -3
  36. package/dist/{chunk-KC5XXX3X.js → chunk-EOOEC32M.js} +1 -1
  37. package/dist/{chunk-2DA2BBNY.js → chunk-ETNQF37F.js} +10 -10
  38. package/dist/{chunk-54QISXOC.js → chunk-FDL4HV44.js} +2 -2
  39. package/dist/{chunk-VYSUZEJG.js → chunk-FJLHVAPO.js} +6 -6
  40. package/dist/{chunk-QZ3AZTXI.js → chunk-FJWEYVEM.js} +42 -16
  41. package/dist/{chunk-EX6C672Y.js → chunk-FKLYMV3U.js} +1 -1
  42. package/dist/{chunk-PUGIRFPX.js → chunk-FMNVTKX2.js} +4 -4
  43. package/dist/{chunk-L5TUCXWR.js → chunk-HBGJYBGE.js} +2 -2
  44. package/dist/{chunk-SLCFKB3Y.js → chunk-HTM4CIFS.js} +11 -8
  45. package/dist/{chunk-T42U2W2R.js → chunk-IXLUTE6N.js} +1 -1
  46. package/dist/{chunk-OUSLVRO4.js → chunk-JBQJKC23.js} +76 -6
  47. package/dist/{chunk-IEIJRMLZ.js → chunk-JDB65PPT.js} +62 -63
  48. package/dist/{chunk-USDEMXXL.js → chunk-JYVGYKXG.js} +1 -1
  49. package/dist/{chunk-P6WH6QTV.js → chunk-K7ES5RSK.js} +1 -1
  50. package/dist/{chunk-LC3RQURJ.js → chunk-KFZUUXUN.js} +3 -3
  51. package/dist/{chunk-OIDN7G42.js → chunk-KG265HQ7.js} +2 -2
  52. package/dist/{chunk-7RAYSCYT.js → chunk-KPJMBC4K.js} +2 -2
  53. package/dist/{chunk-MAYCCGMQ.js → chunk-KVGDFUVO.js} +1 -1
  54. package/dist/{chunk-JEHFZQYT.js → chunk-LE7T4ML7.js} +1 -1
  55. package/dist/{chunk-MQZVBHEY.js → chunk-LFNQDTSH.js} +1 -1
  56. package/dist/{chunk-ZOA2SC4P.js → chunk-MOL32UKR.js} +45 -11
  57. package/dist/{chunk-RG3QWWIE.js → chunk-QSSPIATO.js} +2 -2
  58. package/dist/{chunk-F2SMS24Q.js → chunk-R6R74HNZ.js} +117 -139
  59. package/dist/{chunk-7SDCIWHQ.js → chunk-SYMSKGXI.js} +2 -2
  60. package/dist/{chunk-ZEUONDQG.js → chunk-SYUGVPYH.js} +1 -1
  61. package/dist/{chunk-4OC7MQNB.js → chunk-TBOMPYG6.js} +2 -2
  62. package/dist/{chunk-KFKZ3ISO.js → chunk-TH4OXAWY.js} +1 -1
  63. package/dist/{chunk-4LAR447G.js → chunk-UOBYRLDD.js} +1 -1
  64. package/dist/{chunk-NV4RXIQ7.js → chunk-UZUUVYAO.js} +3 -3
  65. package/dist/{chunk-PJ3HDUCY.js → chunk-VAS6HQX3.js} +39 -9
  66. package/dist/{chunk-LFX2HEYP.js → chunk-VT563F4O.js} +7 -7
  67. package/dist/{chunk-5VMR4WBS.js → chunk-WU2B74TL.js} +363 -103
  68. package/dist/{chunk-5HJ343GH.js → chunk-WUZ6TMAO.js} +1 -1
  69. package/dist/{chunk-GQJZORQP.js → chunk-XBSPQ52S.js} +1 -1
  70. package/dist/{chunk-5WADG7PR.js → chunk-XJUZEB44.js} +1 -1
  71. package/dist/{chunk-I5KY7EZP.js → chunk-XVIYZU3D.js} +1 -1
  72. package/dist/{chunk-XGFHYAYN.js → chunk-Z5C4LEAD.js} +33 -28
  73. package/dist/chunk-Z6FLHIDV.js +3795 -0
  74. package/dist/{chunk-DDIVWXN7.js → chunk-ZFN6GQU4.js} +4 -4
  75. package/dist/{chunk-Y6UPYWJS.js → chunk-ZVZSFDW3.js} +2 -2
  76. package/dist/{chunk-A53CBD24.js → chunk-ZZ7H4IJ6.js} +9 -9
  77. package/dist/{clean-KPX27IKJ.js → clean-2GDD2B4F.js} +23 -23
  78. package/dist/cli.js +52 -52
  79. package/dist/{cloud-P7DAOISN.js → cloud-LUKGDTTE.js} +4 -4
  80. package/dist/{cloudrun-XM56TBOH.js → cloudrun-NQF5KFQI.js} +6 -6
  81. package/dist/{compare-F6YAFZZM.js → compare-4P6O4ONG.js} +32 -32
  82. package/dist/{compiler-JZ4GNFMG.js → compiler-ACCPOZMQ.js} +10 -6
  83. package/dist/{component-3CFOGIQA.js → component-SDDOLNJD.js} +3 -3
  84. package/dist/{compositions-CPCMWF24.js → compositions-P2L6HUVQ.js} +15 -15
  85. package/dist/{delete-GYVKOKB6.js → delete-Q6S4BJ3F.js} +2 -2
  86. package/dist/{deterministicFonts-U2BIMGPG.js → deterministicFonts-C5JQLCTS.js} +2 -2
  87. package/dist/{dist-YPWQDWJ4.js → dist-GPDOV3IQ.js} +4 -4
  88. package/dist/{dist-KDJTFJHA.js → dist-HUMFCJ6T.js} +3 -3
  89. package/dist/{doctor-GWI3B6JT.js → doctor-NL73UKHV.js} +15 -15
  90. package/dist/{events-BRRUDPPT.js → events-AVOPOKO3.js} +5 -5
  91. package/dist/{events-V2QFN4YM.js → events-X7KPU7LG.js} +4 -4
  92. package/dist/{feedback-CXMD7FWL.js → feedback-GJZ5NXSH.js} +10 -10
  93. package/dist/{ffmpeg-T5SH2EFJ.js → ffmpeg-5V4FP3R6.js} +2 -2
  94. package/dist/{figma-YABDWD66.js → figma-V7SVQQI5.js} +3 -3
  95. package/dist/fontLocalizeCli.js +14 -14
  96. package/dist/{get-L2SOQKHX.js → get-FO3YZYEU.js} +2 -2
  97. package/dist/{gpuPolicy-NBJNWHYS.js → gpuPolicy-QGS4TFWP.js} +10 -10
  98. package/dist/{grade-compare-STXQPKYQ.js → grade-compare-7ICSN7KE.js} +33 -33
  99. package/dist/{help-4H6BSFLB.js → help-Y5LYZG7K.js} +2 -2
  100. package/dist/{history-4IQOLTHJ.js → history-RKGBRNLD.js} +49 -22
  101. package/dist/hyperframe-runtime.js +214 -68
  102. package/dist/hyperframe.manifest.json +1 -1
  103. package/dist/hyperframe.runtime.iife.js +214 -68
  104. package/dist/hyperframes-player.global.js +4 -5
  105. package/dist/hyperframes-slideshow.global.js +3 -4
  106. package/dist/{info-2CZOTNBC.js → info-GGUTL2NR.js} +11 -11
  107. package/dist/{init-6BXK42VS.js → init-PG7NA5SQ.js} +31 -31
  108. package/dist/{inspect-VKU47TBH.js → inspect-FCXUB6DE.js} +33 -33
  109. package/dist/{installer-T2BSSUDY.js → installer-LZ4X5TZZ.js} +6 -6
  110. package/dist/{keyframes-IEYVHRPI.js → keyframes-R3K6WJ3N.js} +8 -8
  111. package/dist/{lambda-TIKG25CK.js → lambda-3GAKHMC3.js} +7 -7
  112. package/dist/{layout-XOI4PT7A.js → layout-XNIZIGA2.js} +33 -33
  113. package/dist/{lint-DWCMVIX5.js → lint-4KDS2F4O.js} +11 -11
  114. package/dist/{lintProject-UBZ3TDHU.js → lintProject-SSEXWCH6.js} +3 -3
  115. package/dist/{list-7GXKG5QM.js → list-OVPURFPK.js} +2 -2
  116. package/dist/{login-BQ5L2UHX.js → login-EE2AX2PE.js} +4 -4
  117. package/dist/{manager-YKMHR6LN.js → manager-5ORDVWJB.js} +3 -3
  118. package/dist/{media-treatment-IFB7OSZ3.js → media-treatment-UDUEOP67.js} +86 -55
  119. package/dist/{models-TY4PJ545.js → models-LPK2O4B2.js} +14 -14
  120. package/dist/{motionShot-WXMFHICW.js → motionShot-G76XBOYI.js} +35 -29
  121. package/dist/{normalize-audio-RFD776HQ.js → normalize-audio-TUKWZ3OR.js} +10 -10
  122. package/dist/{open-7IXXGO2E.js → open-7XB2TGVB.js} +6 -6
  123. package/dist/{parakeetRunner-IHLYYMTZ.js → parakeetRunner-DL556HXL.js} +14 -14
  124. package/dist/{pipeline-TXKPLL2U.js → pipeline-34N5DLWU.js} +11 -11
  125. package/dist/{play-J2KP64UK.js → play-DDA2UUQF.js} +26 -26
  126. package/dist/{preflight-B4AFK3RG.js → preflight-ONF5AJNO.js} +5 -5
  127. package/dist/{present-MHHNRVRA.js → present-LLNRKXF5.js} +23 -23
  128. package/dist/{preview-CONUOFFQ.js → preview-H3ZZS46F.js} +57 -26
  129. package/dist/{producer-ZI46K7HH.js → producer-IFQOZK2G.js} +1 -1
  130. package/dist/{projectConfig-FGGVG5MV.js → projectConfig-SBRMQZGG.js} +8 -8
  131. package/dist/{publication-TXFBMW6B.js → publication-5BQICRZO.js} +4 -4
  132. package/dist/{publish-YZSPBFRD.js → publish-XDUZA3E3.js} +27 -26
  133. package/dist/{remove-background-4ATVLHLG.js → remove-background-GNKRMFQS.js} +12 -12
  134. package/dist/{render-MH4IUPWB.js → render-JM6KNRIA.js} +27 -27
  135. package/dist/{render-6FBYLYGJ.js → render-KTTC3EE5.js} +12 -12
  136. package/dist/{render-GFW5BPES.js → render-PCFO45RK.js} +5 -5
  137. package/dist/{render-batch-XUCZ2PUJ.js → render-batch-7R2NRNVJ.js} +5 -5
  138. package/dist/{renderCancellation-XF7M7IUP.js → renderCancellation-GP3XD2FS.js} +10 -10
  139. package/dist/renderSetupWorker.js +3 -3
  140. package/dist/{resolver-W7AYCQGS.js → resolver-C4FPX72I.js} +6 -6
  141. package/dist/{sherpa-LDUB5NLY.js → sherpa-MZP3MV2X.js} +14 -14
  142. package/dist/skills/hyperframes/scripts/lib/frame-packets-core.mjs +2 -20
  143. package/dist/skills/hyperframes/scripts/lib/main-module.mjs +13 -0
  144. package/dist/skills/hyperframes/scripts/lib/main-module.test.mjs +51 -0
  145. package/dist/skills/hyperframes/scripts/plugin-cli.mjs +4 -3
  146. package/dist/skills/hyperframes/scripts/plugin-cli.test.mjs +5 -1
  147. package/dist/skills/hyperframes-cli/SKILL.md +2 -0
  148. package/dist/skills/media-use/audio/scripts/heygen-voice.mjs +2 -2
  149. package/dist/skills/media-use/audio/scripts/lib/main-module.mjs +13 -0
  150. package/dist/skills/media-use/references/media-treatments.md +5 -1
  151. package/dist/skills/media-use/scripts/lib/cube-validate.mjs +2 -3
  152. package/dist/skills/media-use/scripts/lib/main-module.mjs +13 -0
  153. package/dist/{skills-VENERS5X.js → skills-OET4XSHR.js} +7 -7
  154. package/dist/{skillsUpdateCheck-UXFYTACG.js → skillsUpdateCheck-IPFSKKJD.js} +3 -3
  155. package/dist/{slideshow-4OJEPWNZ.js → slideshow-YTWATJRT.js} +1 -1
  156. package/dist/{snapshot-C6T74HTI.js → snapshot-EC4N75MS.js} +34 -34
  157. package/dist/{src-VUJ2FUFK.js → src-LIERUCFW.js} +13 -9
  158. package/dist/{src-FS5RSVEI.js → src-ZZQJOKO6.js} +13 -13
  159. package/dist/{staticProjectServer-V2RZ4DWD.js → staticProjectServer-YH2RHYKW.js} +20 -20
  160. package/dist/{status-LXPGSSKY.js → status-PTKNQD2E.js} +2 -2
  161. package/dist/studio/assets/{hyperframes-player-Bw_jIaSX.js → hyperframes-player-tkxyWf5H.js} +3 -3
  162. package/dist/studio/assets/{index-Cj7W_c7p.js → index-BrdqOkqP.js} +1 -1
  163. package/dist/studio/assets/{index-BVM9NuWl.js → index-Cg48BxAo.js} +145 -145
  164. package/dist/studio/assets/{index-DyH9dT7b.js → index-Dllxg4aU.js} +1 -1
  165. package/dist/studio/index.html +1 -1
  166. package/dist/{studio-api-TQE7KWKO.js → studio-api-T2TS2CHL.js} +16 -14
  167. package/dist/{studioServer-CYKSQK7L.js → studioServer-GJVVJUEL.js} +54 -52
  168. package/dist/{system-OQLOGGPJ.js → system-OXRG57F2.js} +2 -2
  169. package/dist/{telemetry-A23PPRD6.js → telemetry-ZQ5XVE6Z.js} +5 -5
  170. package/dist/{timeline-T3QSGT3A.js → timeline-I2T5WIPD.js} +34 -25
  171. package/dist/{tokens-RT5HWA6C.js → tokens-ONUWOXEX.js} +2 -2
  172. package/dist/{transcribe-FOLNOC5G.js → transcribe-BCQMA537.js} +12 -12
  173. package/dist/{transcribe-HCF64LQK.js → transcribe-ZLJF7V5Y.js} +13 -13
  174. package/dist/{updateCheck-27PIP3AA.js → updateCheck-ZWHDXF73.js} +2 -2
  175. package/dist/{upgrade-TVGXBUPJ.js → upgrade-32JGFZWS.js} +2 -2
  176. package/dist/{urlDownloader-KBLBJKRL.js → urlDownloader-EVDP43GM.js} +9 -9
  177. package/dist/{validate-ZMYGK4QI.js → validate-G4PUGQCI.js} +27 -27
  178. package/dist/{video-AVE5GIGM.js → video-TILEY3VJ.js} +10 -10
  179. package/package.json +3 -2
  180. package/dist/chunk-WJB7WI4J.js +0 -3753
  181. package/dist/studio/chunk-3GHTHPZD.js +0 -1105
  182. package/dist/studio/chunk-3GHTHPZD.js.map +0 -1
  183. package/dist/studio/chunk-EEXSYY5F.js +0 -190
  184. package/dist/studio/chunk-EEXSYY5F.js.map +0 -1
  185. package/dist/studio/chunk-G3EDKRZH.js +0 -1442
  186. package/dist/studio/chunk-G3EDKRZH.js.map +0 -1
  187. package/dist/studio/chunk-PEAKCOUW.js +0 -942
  188. package/dist/studio/chunk-PEAKCOUW.js.map +0 -1
  189. package/dist/studio/chunk-PZ5AY32C.js +0 -10
  190. package/dist/studio/chunk-PZ5AY32C.js.map +0 -1
  191. package/dist/studio/chunk-Y2OHHNM2.js +0 -970
  192. package/dist/studio/chunk-Y2OHHNM2.js.map +0 -1
  193. package/dist/studio/domEditingLayers-PYST4G45.js +0 -47
  194. package/dist/studio/domEditingLayers-PYST4G45.js.map +0 -1
  195. package/dist/studio/index.css +0 -165
  196. package/dist/studio/index.css.map +0 -1
  197. package/dist/studio/index.d.ts +0 -4315
  198. package/dist/studio/index.js +0 -100971
  199. package/dist/studio/index.js.map +0 -1
  200. package/dist/studio/player.d.ts +0 -30
  201. package/dist/studio/player.js +0 -10
  202. package/dist/studio/player.js.map +0 -1
  203. package/dist/studio/styles/tailwind-preset.d.ts +0 -39
  204. package/dist/studio/styles/tailwind-preset.js +0 -50
  205. package/dist/studio/styles/tailwind-preset.js.map +0 -1
  206. package/dist/studio/styles.css +0 -1
  207. package/dist/studio/ui.d.ts +0 -297
  208. package/dist/studio/ui.js +0 -66
  209. package/dist/studio/ui.js.map +0 -1
@@ -11,18 +11,19 @@ import {
11
11
  iterateFontFamilyDeclarations,
12
12
  normalizeSystemFontPrimaryFamilies,
13
13
  resolveFontFamilyDeclarationFamilies
14
- } from "./chunk-PUGIRFPX.js";
14
+ } from "./chunk-FMNVTKX2.js";
15
15
  import {
16
16
  EncoderInterruptedError,
17
17
  encoderFailureError,
18
18
  prepareAnimatedGifInputs
19
- } from "./chunk-OIDN7G42.js";
19
+ } from "./chunk-KG265HQ7.js";
20
20
  import {
21
21
  createStudioPositionSeekReapplyScript
22
- } from "./chunk-KC5XXX3X.js";
22
+ } from "./chunk-EOOEC32M.js";
23
23
  import {
24
24
  BROWSER_GPU_NOT_SOFTWARE,
25
25
  CaptureFailure,
26
+ DEFAULT_CONFIG,
26
27
  DrawElementVerificationError,
27
28
  HDR_AUTO_PROMOTION_PIPELINE,
28
29
  HF_AUDIO_GROUP_TAG,
@@ -68,6 +69,7 @@ import {
68
69
  decodePng,
69
70
  decodePngToRgb48le,
70
71
  deriveBeginFrameProbeTimeTicks,
72
+ describeFfmpegFailure,
71
73
  detectTransfer,
72
74
  distributeFrames,
73
75
  distributeFramesInterleaved,
@@ -103,6 +105,7 @@ import {
103
105
  isNotMediaPayload,
104
106
  isTransientBrowserError,
105
107
  isVideoFrameFormat,
108
+ isVideoPastTimelineEnd,
106
109
  mergeWorkerFrames,
107
110
  muxVideoWithAudio,
108
111
  normalizeObjectFit,
@@ -142,7 +145,7 @@ import {
142
145
  validateEngineConfigSnapshot,
143
146
  verifyDiskDrawElementSamples,
144
147
  writeCapturedFrame
145
- } from "./chunk-5VMR4WBS.js";
148
+ } from "./chunk-WU2B74TL.js";
146
149
  import {
147
150
  assignBundledRuntimeCompositionIds,
148
151
  buildVariablesByCompScript,
@@ -150,15 +153,17 @@ import {
150
153
  emitRootCompositionVariableStyles,
151
154
  ensureExternalLinkTag,
152
155
  ensureExternalScriptTag,
156
+ extractStandaloneEntryFromIndex,
153
157
  inlineSubCompositions,
158
+ isTemplateEntry,
154
159
  parsesAsScript,
155
160
  prepareFlattenedInnerRoot
156
- } from "./chunk-OUSLVRO4.js";
161
+ } from "./chunk-JBQJKC23.js";
157
162
  import {
158
163
  LOW_MEMORY_TOTAL_MB_THRESHOLD,
159
164
  getCgroupMemoryLimitMb,
160
165
  getSystemTotalMb
161
- } from "./chunk-USDEMXXL.js";
166
+ } from "./chunk-JYVGYKXG.js";
162
167
  import {
163
168
  HF_VFX_ATTR,
164
169
  MEDIA_START_BASIS_ATTR,
@@ -174,7 +179,7 @@ import {
174
179
  resolveAbsoluteMediaStartSeconds,
175
180
  resolveAuthoredTimingWindow,
176
181
  toFps
177
- } from "./chunk-3VYNNWVA.js";
182
+ } from "./chunk-BAKPN2D2.js";
178
183
  import {
179
184
  COMPOSITION_SOURCE_URL,
180
185
  HF_COLOR_GRADING_ATTR,
@@ -201,7 +206,7 @@ import {
201
206
  shouldClampResolvedMediaDuration,
202
207
  sourceTimeAt,
203
208
  styleElementsFor
204
- } from "./chunk-WJB7WI4J.js";
209
+ } from "./chunk-Z6FLHIDV.js";
205
210
  import {
206
211
  MAX_AUDIO_GAIN
207
212
  } from "./chunk-YA62XGXS.js";
@@ -215,7 +220,7 @@ import {
215
220
  isAspectAgnosticResolutionAlias,
216
221
  normalizeResolutionFlag,
217
222
  suggestMatchingPreset
218
- } from "./chunk-MQZVBHEY.js";
223
+ } from "./chunk-LFNQDTSH.js";
219
224
  import {
220
225
  redactKnownPaths,
221
226
  redactTelemetryString
@@ -225,7 +230,7 @@ import {
225
230
  } from "./chunk-TWWSYAKJ.js";
226
231
  import {
227
232
  lintHyperframeHtml
228
- } from "./chunk-IEIJRMLZ.js";
233
+ } from "./chunk-JDB65PPT.js";
229
234
  import {
230
235
  isUnresolvedAssetPlaceholder,
231
236
  readProjectFile,
@@ -482,7 +487,7 @@ function buildVirtualTimeShim(options) {
482
487
  const seedRandomFromFrame = options.seedRandomFromFrame === true;
483
488
  const seededRandomBlock = seedRandomFromFrame ? String.raw`
484
489
  // Seeded Math.random / crypto.getRandomValues, keyed by virtual time.
485
- // Mulberry32 — single uint32 state, deterministic, fast.
490
+ // Mulberry32: single uint32 state, deterministic, fast.
486
491
  var rngState = 0;
487
492
  function mulberry32() {
488
493
  rngState |= 0; rngState = (rngState + 0x6D2B79F5) | 0;
@@ -493,7 +498,7 @@ function buildVirtualTimeShim(options) {
493
498
  }
494
499
  function reseedRngFromTime(ms) {
495
500
  var ms32 = Math.max(0, Math.floor(Number(ms) || 0)) | 0;
496
- // Knuth's multiplicative hash + golden-ratio offset — gives a well-
501
+ // Knuth's multiplicative hash + golden-ratio offset gives a well-
497
502
  // distributed seed even for frame 0 (otherwise rngState=0 degenerates
498
503
  // the PRNG's first few outputs).
499
504
  rngState = (Math.imul(ms32, -1640531527) + 0x9E3779B9) | 0;
@@ -735,7 +740,7 @@ function buildRenderModeScript(fps) {
735
740
  };
736
741
  window.__playerReady = true;
737
742
  // Media-fallback player has no timeline to bind, so render-ready is immediate.
738
- // init.ts defers __renderReady until the timeline is bound \u2014 different runtime.
743
+ // init.ts defers __renderReady until the timeline is bound (a different runtime).
739
744
  window.__renderReady = true;
740
745
  return true;
741
746
  }
@@ -2262,7 +2267,7 @@ function blitHdrVideoLayer(canvas, el, time, fps, hdrVideoFrameSources, hdrStart
2262
2267
  if (matrix && !isTranslationOnly) {
2263
2268
  if (clipped && log) {
2264
2269
  log.debug(
2265
- `HDR clip rect on affine-transformed element ${el.id} \u2014 clip not applied (affine scissor not yet supported)`
2270
+ `HDR clip rect on affine-transformed element ${el.id}: clip not applied (affine scissor not yet supported)`
2266
2271
  );
2267
2272
  }
2268
2273
  blitRgb48leAffine(
@@ -2319,7 +2324,7 @@ function blitHdrImageLayer(canvas, el, hdrImageBuffers, hdrImageTransferCache, w
2319
2324
  return;
2320
2325
  }
2321
2326
  if (el.clipRect && log) {
2322
- log.debug(`HDR clip rect on image element ${el.id} \u2014 clip not yet supported for images`);
2327
+ log.debug(`HDR clip rect on image element ${el.id}: clip not yet supported for images`);
2323
2328
  }
2324
2329
  try {
2325
2330
  if (hdrPerf) hdrPerf.hdrImageLayerBlits += 1;
@@ -4470,7 +4475,7 @@ async function validateCompletedSegments(manifest, expectedHash, probeFrames) {
4470
4475
  function formatDowngradeWarning(outputFormat, forcedHdrWithoutSources) {
4471
4476
  const hdrSourceReason = forcedHdrWithoutSources ? "HDR was forced without detected HDR sources" : "HDR source detected";
4472
4477
  const formatReason = outputFormat === "hls" ? "HLS output is SDR-only (H.264 in MPEG-TS)" : "HDR + alpha is not supported";
4473
- return `[Render] ${hdrSourceReason}, but format is "${outputFormat}" \u2014 falling back to SDR. ${formatReason}. Use --format mp4 for HDR10 output.`;
4478
+ return `[Render] ${hdrSourceReason}, but format is "${outputFormat}", so falling back to SDR. ${formatReason}. Use --format mp4 for HDR10 output.`;
4474
4479
  }
4475
4480
  function findRenderHdrAutoPromotionTrigger(input) {
4476
4481
  for (const extracted of input.extractionResult?.extracted ?? []) {
@@ -4483,12 +4488,12 @@ function findRenderHdrAutoPromotionTrigger(input) {
4483
4488
  function logHdrResolution(input, hdrMode, effectiveHdr, forcedHdrWithoutSources) {
4484
4489
  if (forcedHdrWithoutSources) {
4485
4490
  input.log.warn(
4486
- "[Render] HDR forced by --hdr flag, but no HDR sources were detected \u2014 defaulting to HLG. SDR-only compositions may look perceptually wrong on HDR displays."
4491
+ "[Render] HDR forced by --hdr flag, but no HDR sources were detected, defaulting to HLG. SDR-only compositions may look perceptually wrong on HDR displays."
4487
4492
  );
4488
4493
  }
4489
4494
  if (!effectiveHdr) {
4490
4495
  input.log.info(
4491
- hdrMode === "force-sdr" ? "[Render] SDR forced by --sdr flag" : "[Render] No HDR sources detected \u2014 rendering SDR"
4496
+ hdrMode === "force-sdr" ? "[Render] SDR forced by --sdr flag" : "[Render] No HDR sources detected, rendering SDR"
4492
4497
  );
4493
4498
  return;
4494
4499
  }
@@ -4503,9 +4508,9 @@ function logHdrResolution(input, hdrMode, effectiveHdr, forcedHdrWithoutSources)
4503
4508
  );
4504
4509
  return;
4505
4510
  }
4506
- const reason = forcedHdrWithoutSources ? "forced by --hdr flag (no HDR sources detected \u2014 defaulting to HLG)" : "forced by --hdr flag";
4511
+ const reason = forcedHdrWithoutSources ? "forced by --hdr flag (no HDR sources detected, defaulting to HLG)" : "forced by --hdr flag";
4507
4512
  input.log.info(
4508
- `[Render] HDR ${reason} \u2014 output: ${effectiveHdr.transfer.toUpperCase()} (BT.2020, 10-bit H.265)`
4513
+ `[Render] HDR ${reason}, output: ${effectiveHdr.transfer.toUpperCase()} (BT.2020, 10-bit H.265)`
4509
4514
  );
4510
4515
  }
4511
4516
  function resolveEffectiveHdrMode(input) {
@@ -4592,14 +4597,14 @@ function resolveRenderWorkerCount(totalFrames, requestedWorkers, cfg, compiled,
4592
4597
  const reasonCodes = new Set(compiled.renderModeHints.reasons.map((r) => r.code));
4593
4598
  if (reasonCodes.has("htmlInCanvas")) {
4594
4599
  log.warn(
4595
- "[Render] html-in-canvas (drawElementImage) detected \u2014 pinning to 1 worker (Chrome concurrency limitation).",
4600
+ "[Render] html-in-canvas (drawElementImage) detected, pinning to 1 worker (Chrome concurrency limitation).",
4596
4601
  { requestedWorkers }
4597
4602
  );
4598
4603
  return 1;
4599
4604
  }
4600
4605
  if (cfg.lowMemoryMode && requestedWorkers === void 0) {
4601
4606
  log.info(
4602
- "[Render] Low-memory profile \u2014 pinning to 1 capture worker (auto-worker calibration skipped)."
4607
+ "[Render] Low-memory profile, pinning to 1 capture worker (auto-worker calibration skipped)."
4603
4608
  );
4604
4609
  return 1;
4605
4610
  }
@@ -5223,7 +5228,7 @@ function assertVideoFrameCoverage(reports, threshold) {
5223
5228
  const thresholdPct = (threshold * 100).toFixed(1);
5224
5229
  const suffix = sorted.length > 1 ? ` (+${sorted.length - 1} more clip(s) below threshold)` : "";
5225
5230
  throw new VideoFrameCoverageError(
5226
- `Video "${worst.videoId}" captured ${worst.capturedFrames} of expected ${worst.expectedFrames} frames (coverage ${pct}%, threshold ${thresholdPct}%). check/snapshot may pass while the encoded MP4 renders this clip blank \u2014 aborting render to prevent shipping a wrong MP4.${suffix} Set HF_VIDEO_COVERAGE_THRESHOLD=0 to disable this gate.`,
5231
+ `Video "${worst.videoId}" captured ${worst.capturedFrames} of expected ${worst.expectedFrames} frames (coverage ${pct}%, threshold ${thresholdPct}%). check/snapshot may pass while the encoded MP4 renders this clip blank, so the render is aborted to prevent shipping a wrong MP4.${suffix} Set HF_VIDEO_COVERAGE_THRESHOLD=0 to disable this gate.`,
5227
5232
  { threshold, worst, failedReports: sorted }
5228
5233
  );
5229
5234
  }
@@ -5330,7 +5335,7 @@ function collectRenderMedia(html) {
5330
5335
  }
5331
5336
 
5332
5337
  // ../core/dist/generated/position-edits-render-inline.js
5333
- var POSITION_EDITS_RENDER_IIFE = '"use strict";(()=>{function T(){return globalThis}function P(e,t){if(typeof window>"u")return;let o=T(),r=o.__hf?.onSwallowed;if(r)try{r({label:e,error:t})}catch(s){}(o.__hfDebug||o.__HYPERFRAMES_DEBUG)&&console.debug(`[hyperframes] ${e} swallowed:`,t)}var x=null;function R(e,t){if(x)try{x({source:"hf-preview",type:"analytics",event:e,properties:t??{}})}catch(o){P("runtime.analytics.site1",o)}}var W="http://www.w3.org/1999/xhtml";function N(e){return e!=null&&e.nodeType===1}function _(e){return N(e)&&(e.namespaceURI===W||e.namespaceURI==="http://www.w3.org/2000/svg")}var w="data-hf-edit-base-x",y="data-hf-edit-base-y",m="data-hf-edit-original-translate",k=e=>{let t=parseFloat(e??"");return Number.isFinite(t)?t:0},O=e=>{let t=[],o=0,r="";for(let s of e.trim())s==="("&&(o+=1),s===")"&&(o=Math.max(0,o-1)),/\\s/.test(s)&&o===0?(r&&t.push(r),r=""):r+=s;return r&&t.push(r),t},L=/^-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)px$/,E=(e,t)=>L.test(e)&&L.test(t)?`${parseFloat(e)+parseFloat(t)}px`:`calc(${e} + ${t})`,V=(e,t,o)=>{if(!e||e==="none")return`${t} ${o}`;let[r,s,a]=O(e);if(r===void 0)return`${t} ${o}`;if(s===void 0)return`${E(r,t)} ${o}`;let i=a===void 0?"":` ${a}`;return`${E(r,t)} ${E(s,o)}${i}`},j=e=>{try{e.ownerDocument.defaultView?.gsap?.getProperty?.(e,"x")}catch{}},G=e=>{let t=e.style.getPropertyValue("translate").trim();if(t)return t==="none"?"":t;try{let o=e.ownerDocument.defaultView,r=o?o.getComputedStyle(e).getPropertyValue("translate").trim():"";return r==="none"?"":r}catch{return""}},b=new WeakMap;function B(e,t){let o=b.get(e);if(!t?.force&&o!==void 0&&e.style.getPropertyValue("translate")!==o){R("position_edit_fold_skipped",{hfId:e.getAttribute("data-hf-id")});return}let r=k(e.getAttribute("data-x"))-k(e.getAttribute(w)),s=k(e.getAttribute("data-y"))-k(e.getAttribute(y));e.hasAttribute(m)||e.setAttribute(m,G(e)),o===void 0&&j(e);let a=e.getAttribute(m)??"",i=V(a,`${r}px`,`${s}px`);e.style.setProperty("translate",i),b.set(e,e.style.getPropertyValue("translate"))}function S(e,t){let o=e.querySelectorAll(`[${m}]:not([${w}]):not([${y}])`);for(let a=0;a<o.length;a++){let i=o[a];if(i===void 0||!_(i))continue;let g=i.getAttribute(m)??"";g===""?i.style.removeProperty("translate"):i.style.setProperty("translate",g),i.removeAttribute(m),b.delete(i)}let r=e.querySelectorAll(`[${w}], [${y}]`),s=0;for(let a=0;a<r.length;a++){let i=r[a];i===void 0||!_(i)||(B(i,t),s+=1)}return s}var $="__hfPositionEditsSeekReapplyWrapped",D=new WeakSet,M=new WeakMap,H=new WeakMap;function F(e){let t=e,o=()=>{try{S(t.document)}catch{}},r=n=>typeof n=="function"&&(D.has(n)||!!n[$]),s=n=>{D.add(n);try{Object.defineProperty(n,$,{value:!0})}catch{}},a=n=>{if(typeof n!="function"||r(n))return n;let l=function(...u){let d=n.apply(this,u);return o(),d};return s(l),l},i=(n,l)=>{let u=M.get(n);if(u?.has(l))return!0;let d=Object.getOwnPropertyDescriptor(n,l);if(d?.configurable===!1){let c=n[l];return typeof c=="function"&&(n[l]=a(c),o()),!1}let p=n[l],f=d?.set;return Object.defineProperty(n,l,{configurable:!0,enumerable:d?.enumerable??!0,get:()=>p,set:c=>{p=a(c),f?.call(n,c)}}),p=a(p),u??(u=new Set),u.add(l),M.set(n,u),o(),!0},g=(n,l)=>{let u=H.get(t),d=Object.getOwnPropertyDescriptor(t,n);if(!u?.has(n)){if(d?.configurable===!1){let c=t[n];return c?i(c,l):!1}let f=t[n];Object.defineProperty(t,n,{configurable:!0,enumerable:d?.enumerable??!0,get:()=>f,set:c=>{f=c,f&&i(f,l)}}),u??(u=new Set),u.add(n),H.set(t,u)}let p=t[n];return p?i(p,l):!1},v=()=>{let n=g("__hf","seek"),l=g("__player","renderSeek");return n&&l};if(v())return;let h=120,A=t.setInterval(()=>{if(v()){t.clearInterval(A);return}h-=1,h<=0&&t.clearInterval(A)},50)}function I(){document.querySelector(`[${w}], [${y}]`)&&(S(document),F(window))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",I,{once:!0}):I();})();\n';
5338
+ var POSITION_EDITS_RENDER_IIFE = '"use strict";(()=>{function T(){return globalThis}function P(e,t){if(typeof window>"u")return;let o=T(),r=o.__hf?.onSwallowed;if(r)try{r({label:e,error:t})}catch(s){}(o.__hfDebug||o.__HYPERFRAMES_DEBUG)&&console.debug(`[hyperframes] ${e} swallowed:`,t)}var x=null;function R(e,t){if(x)try{x({source:"hf-preview",type:"analytics",event:e,properties:t??{}})}catch(o){P("runtime.analytics.site1",o)}}var W="http://www.w3.org/1999/xhtml";function N(e){return e!=null&&e.nodeType===1}function k(e){return N(e)&&(e.namespaceURI===W||e.namespaceURI==="http://www.w3.org/2000/svg")}var w="data-hf-edit-base-x",y="data-hf-edit-base-y",m="data-hf-edit-original-translate",_=e=>{let t=parseFloat(e??"");return Number.isFinite(t)?t:0},O=e=>{let t=[],o=0,r="";for(let s of e.trim())s==="("&&(o+=1),s===")"&&(o=Math.max(0,o-1)),/\\s/.test(s)&&o===0?(r&&t.push(r),r=""):r+=s;return r&&t.push(r),t},L=/^-?(?:\\d+(?:\\.\\d+)?|\\.\\d+)px$/,E=(e,t)=>L.test(e)&&L.test(t)?`${parseFloat(e)+parseFloat(t)}px`:`calc(${e} + ${t})`,V=(e,t,o)=>{if(!e||e==="none")return`${t} ${o}`;let[r,s,a]=O(e);if(r===void 0)return`${t} ${o}`;if(s===void 0)return`${E(r,t)} ${o}`;let i=a===void 0?"":` ${a}`;return`${E(r,t)} ${E(s,o)}${i}`},j=e=>{try{e.ownerDocument.defaultView?.gsap?.getProperty?.(e,"x")}catch{}},C=e=>{let t=e.style.getPropertyValue("translate").trim();if(t)return t==="none"?"":t;try{let o=e.ownerDocument.defaultView,r=o?o.getComputedStyle(e).getPropertyValue("translate").trim():"";return r==="none"?"":r}catch{return""}},b=new WeakMap;function G(e,t){let o=b.get(e);if(!t?.force&&o!==void 0&&e.style.getPropertyValue("translate")!==o){R("position_edit_fold_skipped",{hfId:e.getAttribute("data-hf-id")});return}let r=_(e.getAttribute("data-x"))-_(e.getAttribute(w)),s=_(e.getAttribute("data-y"))-_(e.getAttribute(y));e.hasAttribute(m)||e.setAttribute(m,C(e)),o===void 0&&j(e);let a=e.getAttribute(m)??"",i=V(a,`${r}px`,`${s}px`);e.style.setProperty("translate",i),b.set(e,e.style.getPropertyValue("translate"))}function S(e,t){let o=e.querySelectorAll(`[${m}]:not([${w}]):not([${y}])`);for(let a=0;a<o.length;a++){let i=o[a];if(i===void 0||!k(i))continue;let g=i.getAttribute(m)??"";g===""?i.style.removeProperty("translate"):i.style.setProperty("translate",g),i.removeAttribute(m),b.delete(i)}let r=e.querySelectorAll(`[${w}], [${y}]`),s=0;for(let a=0;a<r.length;a++){let i=r[a];i===void 0||!k(i)||(G(i,t),s+=1)}return s}var $="__hfPositionEditsSeekReapplyWrapped",D=new WeakSet,M=new WeakMap,H=new WeakMap;function F(e){let t=e,o=()=>{try{S(t.document)}catch{}},r=n=>typeof n=="function"&&(D.has(n)||!!n[$]),s=n=>{D.add(n);try{Object.defineProperty(n,$,{value:!0})}catch{}},a=n=>{if(typeof n!="function"||r(n))return n;let l=function(...u){let d=n.apply(this,u);return o(),d};return s(l),l},i=(n,l)=>{let u=M.get(n);if(u?.has(l))return!0;let d=Object.getOwnPropertyDescriptor(n,l);if(d?.configurable===!1){let c=n[l];return typeof c=="function"&&(n[l]=a(c),o()),!1}let p=n[l],f=d?.set;return Object.defineProperty(n,l,{configurable:!0,enumerable:d?.enumerable??!0,get:()=>p,set:c=>{p=a(c),f?.call(n,c)}}),p=a(p),u??(u=new Set),u.add(l),M.set(n,u),o(),!0},g=(n,l)=>{let u=H.get(t),d=Object.getOwnPropertyDescriptor(t,n);if(!u?.has(n)){if(d?.configurable===!1){let c=t[n];return c?i(c,l):!1}let f=t[n];Object.defineProperty(t,n,{configurable:!0,enumerable:d?.enumerable??!0,get:()=>f,set:c=>{f=c,f&&i(f,l)}}),u??(u=new Set),u.add(n),H.set(t,u)}let p=t[n];return p?i(p,l):!1},h=()=>{let n=g("__hf","seek"),l=g("__player","renderSeek");return n&&l};if(h())return;let v=120,A=t.setInterval(()=>{if(h()){t.clearInterval(A);return}v-=1,v<=0&&t.clearInterval(A)},50)}function I(){document.querySelector(`[${w}], [${y}]`)&&(S(document),F(window))}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",I,{once:!0}):I();})();\n';
5334
5339
  function getPositionEditsRenderScript() {
5335
5340
  return POSITION_EDITS_RENDER_IIFE;
5336
5341
  }
@@ -5720,7 +5725,7 @@ async function resolveMediaDuration(src, mediaStart, playbackRate, baseDir, down
5720
5725
  if (tagName !== "video") {
5721
5726
  if (error instanceof NotMediaPayloadError) {
5722
5727
  log?.warn(
5723
- `[compile] Audio "${elementIdentity}" (${src}) is a text document, not a media file \u2014 the element is dropped from the render. Point it at a rendered media file.`
5728
+ `[compile] Audio "${elementIdentity}" (${src}) is a text document, not a media file, so the element is dropped from the render. Point it at a rendered media file.`
5724
5729
  );
5725
5730
  }
5726
5731
  return { duration: null, resolvedPath: filePath };
@@ -5809,7 +5814,7 @@ async function compileHtmlFile(html, baseDir, downloadDir, log) {
5809
5814
  if (r.maxDuration != null && shouldClampResolvedMediaDuration(r.tagName, r.duration, r.maxDuration)) {
5810
5815
  clampList.push({ id: r.id, duration: r.maxDuration });
5811
5816
  log?.warn(
5812
- `[compile] Audio "${r.id}" (${r.src}) is ${r.maxDuration.toFixed(2)}s but its data-duration is ${r.duration.toFixed(2)}s \u2014 the slot is shortened to the media length. Set data-duration to ~${r.maxDuration.toFixed(2)}s, trim data-media-start, or use a longer/looping source if that isn't intended.`
5817
+ `[compile] Audio "${r.id}" (${r.src}) is ${r.maxDuration.toFixed(2)}s but its data-duration is ${r.duration.toFixed(2)}s, so the slot is shortened to the media length. Set data-duration to ~${r.maxDuration.toFixed(2)}s, trim data-media-start, or use a longer/looping source if that isn't intended.`
5813
5818
  );
5814
5819
  }
5815
5820
  }
@@ -6198,7 +6203,7 @@ ${safeText}
6198
6203
  } else {
6199
6204
  if (download.reason instanceof ScriptIntegrityError) throw download.reason;
6200
6205
  defaultLogger.warn(
6201
- `[Compiler] WARNING: Failed to download CDN script: ${src} \u2014 ${download.reason}. The render may fail if this script is required (e.g. GSAP). Consider bundling it locally in your project.`
6206
+ `[Compiler] WARNING: Failed to download CDN script: ${src} (${download.reason}). The render may fail if this script is required (e.g. GSAP). Consider bundling it locally in your project.`
6202
6207
  );
6203
6208
  }
6204
6209
  }
@@ -6250,7 +6255,7 @@ function collectExternalAssets(html, projectDir) {
6250
6255
  }
6251
6256
  if (externalAssets.size > 0) {
6252
6257
  defaultLogger.info(
6253
- `[Compiler] Found ${externalAssets.size} asset(s) outside project directory \u2014 will copy to render output`
6258
+ `[Compiler] Found ${externalAssets.size} asset(s) outside project directory, will copy to render output`
6254
6259
  );
6255
6260
  }
6256
6261
  return {
@@ -6275,7 +6280,7 @@ async function downloadAndRewriteUrls(urlSet, html, remoteDir, warnLabel, logLab
6275
6280
  urlToLocal.set(url, localPath);
6276
6281
  } catch (err) {
6277
6282
  const identity = safeDownloadUrlIdentity(url);
6278
- defaultLogger.warn(`[Compiler] ${warnLabel} \u2014 using original URL as fallback.`, {
6283
+ defaultLogger.warn(`[Compiler] ${warnLabel}, using original URL as fallback.`, {
6279
6284
  urlFingerprint: identity.urlFingerprint,
6280
6285
  host: identity.host,
6281
6286
  error: err instanceof Error ? err.message : String(err)
@@ -6368,7 +6373,7 @@ async function fetchExternalStylesheetCss(href) {
6368
6373
  timeoutMs: 15e3
6369
6374
  });
6370
6375
  } catch (err) {
6371
- defaultLogger.warn("[Compiler] External stylesheet fetch failed \u2014 preserving link tag.", {
6376
+ defaultLogger.warn("[Compiler] External stylesheet fetch failed, preserving link tag.", {
6372
6377
  urlFingerprint: identity.urlFingerprint,
6373
6378
  host: identity.host,
6374
6379
  error: err instanceof Error ? err.message : String(err)
@@ -6503,7 +6508,7 @@ async function readLocalFont(absPath) {
6503
6508
  return { kind: "inline", buffer: Buffer.concat(chunks, totalBytes) };
6504
6509
  }
6505
6510
  async function embedLocalFontFaces(html, projectDir) {
6506
- const { fontToDataUri: toDataUri } = await import("./deterministicFonts-U2BIMGPG.js");
6511
+ const { fontToDataUri: toDataUri } = await import("./deterministicFonts-C5JQLCTS.js");
6507
6512
  const styleBlockRe = /<style\b[^>]*>([\s\S]*?)<\/style>/gi;
6508
6513
  const fontFaceRe = /@font-face\s*\{([^}]*)\}/gi;
6509
6514
  let result = html;
@@ -7012,12 +7017,15 @@ async function resolveCompositionDurations(page, unresolved) {
7012
7017
  const resolved = [];
7013
7018
  for (const id of compIds) {
7014
7019
  const tl = timelines[id];
7015
- if (tl && typeof tl.duration === "function") {
7016
- const dur = tl.duration();
7017
- if (dur > 0) {
7018
- resolved.push({ id, duration: dur, source: "__timelines" });
7019
- continue;
7020
- }
7020
+ let dur = 0;
7021
+ try {
7022
+ dur = typeof tl?.duration === "function" ? Number(tl.duration()) : 0;
7023
+ } catch {
7024
+ dur = 0;
7025
+ }
7026
+ if (dur > 0) {
7027
+ resolved.push({ id, duration: dur, source: "__timelines" });
7028
+ continue;
7021
7029
  }
7022
7030
  const el = document.getElementById(id);
7023
7031
  if (el) {
@@ -7113,28 +7121,28 @@ async function runCompileStage(input) {
7113
7121
  cfg.useDrawElement = false;
7114
7122
  deCompileGate = "3d";
7115
7123
  log.info(
7116
- "[Render] Fast capture: composition uses a CSS 3D rendering context (perspective / preserve-3d / backface-visibility) \u2014 disabling drawElementImage for this render. Capture uses the platform's baseline route."
7124
+ "[Render] Fast capture: composition uses a CSS 3D rendering context (perspective / preserve-3d / backface-visibility), so disabling drawElementImage for this render. Capture uses the platform's baseline route."
7117
7125
  );
7118
7126
  }
7119
7127
  if (cfg.useDrawElement && process.env.HF_FAST_CAPTURE_BLEND !== "true" && compiled.usesMixBlendMode) {
7120
7128
  cfg.useDrawElement = false;
7121
7129
  deCompileGate = "mix_blend_mode";
7122
7130
  log.info(
7123
- "[Render] Fast capture: composition uses mix-blend-mode \u2014 disabling drawElementImage for this render. Capture uses the platform's baseline route."
7131
+ "[Render] Fast capture: composition uses mix-blend-mode, so disabling drawElementImage for this render. Capture uses the platform's baseline route."
7124
7132
  );
7125
7133
  }
7126
7134
  if (cfg.useDrawElement && process.env.HF_FAST_CAPTURE_ANCESTOR_BG !== "true" && compiled.hasAncestorBackgroundImage) {
7127
7135
  cfg.useDrawElement = false;
7128
7136
  deCompileGate = "ancestor_background_image";
7129
7137
  log.info(
7130
- "[Render] Fast capture: composition root's ancestors (body/html/wrapper) carry a background-image \u2014 disabling drawElementImage for this render. Capture uses the platform's baseline route."
7138
+ "[Render] Fast capture: composition root's ancestors (body/html/wrapper) carry a background-image, so disabling drawElementImage for this render. Capture uses the platform's baseline route."
7131
7139
  );
7132
7140
  }
7133
7141
  if (cfg.useDrawElement && process.env.PRODUCER_EXPERIMENTAL_FAST_CAPTURE !== "true" && compiled.hasShaderTransitions) {
7134
7142
  cfg.useDrawElement = false;
7135
7143
  deCompileGate = "shader_transitions";
7136
7144
  log.info(
7137
- "[Render] Fast capture: composition uses shader transitions \u2014 disabling drawElementImage so page-side compositing stays available."
7145
+ "[Render] Fast capture: composition uses shader transitions, so disabling drawElementImage so page-side compositing stays available."
7138
7146
  );
7139
7147
  }
7140
7148
  if (!cfg.useDrawElement && cfg.pageSideCompositingAutoDisabled) {
@@ -7449,7 +7457,7 @@ async function runProbeStage(input) {
7449
7457
  } else {
7450
7458
  beginFrameStalled = true;
7451
7459
  log.warn(
7452
- "[Render] BeginFrame liveness probe timed out \u2014 this composition stalls BeginFrame on this host (SwiftShader heavy-layer pattern). Relaunching the probe browser in screenshot capture mode; the render will use screenshot capture throughout.",
7460
+ "[Render] BeginFrame liveness probe timed out: this composition stalls BeginFrame on this host (SwiftShader heavy-layer pattern). Relaunching the probe browser in screenshot capture mode; the render will use screenshot capture throughout.",
7453
7461
  { probeTimeoutMs }
7454
7462
  );
7455
7463
  lastBrowserConsole = probeSession.browserConsoleBuffer;
@@ -7663,7 +7671,7 @@ async function runProbeStage(input) {
7663
7671
  video.start = win.visibleStart;
7664
7672
  video.end = win.visibleEnd;
7665
7673
  log.info(
7666
- `[Probe] Runtime video discovery: ${video.id} visible ${win.visibleStart.toFixed(2)}s\u2013${win.visibleEnd.toFixed(2)}s`
7674
+ `[Probe] Runtime video discovery: ${video.id} visible ${win.visibleStart.toFixed(2)}s to ${win.visibleEnd.toFixed(2)}s`
7667
7675
  );
7668
7676
  }
7669
7677
  }
@@ -7711,7 +7719,7 @@ async function runProbeStage(input) {
7711
7719
  });
7712
7720
  if (!timelinesInfo.gsapLoaded) {
7713
7721
  diagnostics.push(
7714
- "GSAP is not loaded \u2014 CDN script may have failed to download. Bundle GSAP locally in your project instead of using a CDN <script src>."
7722
+ "GSAP is not loaded. The CDN script may have failed to download. Bundle GSAP locally in your project instead of using a CDN <script src>."
7715
7723
  );
7716
7724
  } else if (timelinesInfo.timelineKeys.length === 0) {
7717
7725
  diagnostics.push(
@@ -7728,10 +7736,10 @@ async function runProbeStage(input) {
7728
7736
  log.warn("Failed to gather browser diagnostics for zero-duration composition", {
7729
7737
  error: err instanceof Error ? err.message : String(err)
7730
7738
  });
7731
- diagnostics.push("(Could not gather browser diagnostics \u2014 page may have crashed)");
7739
+ diagnostics.push("(Could not gather browser diagnostics. The page may have crashed.)");
7732
7740
  }
7733
7741
  const hint = diagnostics.length > 0 ? "\n\nDiagnostics:\n - " + diagnostics.join("\n - ") : "\n\nCheck that GSAP timelines are registered on window.__timelines.";
7734
- throw new Error("Composition duration is 0 \u2014 this would produce a black video." + hint);
7742
+ throw new Error("Composition duration is 0, so this would produce a black video." + hint);
7735
7743
  }
7736
7744
  if (probeSession) {
7737
7745
  const failedRequests = probeSession.browserConsoleBuffer.filter(isActionableProbeFailure);
@@ -7787,7 +7795,7 @@ function validateNoGpuEncode(config) {
7787
7795
  if (config.useGpu === true) {
7788
7796
  throw new PlanValidationError(
7789
7797
  BROWSER_GPU_NOT_SOFTWARE,
7790
- "[planValidation] GPU encode is banned in distributed mode: config.useGpu === true. Distributed retries must be byte-identical, but NVENC/QSV/VAAPI produce different output across machines. Set useGpu=false (the default) \u2014 software libx264/libx265 is the only supported encoder in distributed mode."
7798
+ "[planValidation] GPU encode is banned in distributed mode: config.useGpu === true. Distributed retries must be byte-identical, but NVENC/QSV/VAAPI produce different output across machines. Set useGpu=false (the default): software libx264/libx265 is the only supported encoder in distributed mode."
7791
7799
  );
7792
7800
  }
7793
7801
  if (config.browserGpuMode !== void 0 && config.browserGpuMode !== "software") {
@@ -8046,6 +8054,9 @@ async function runExtractVideosStage(input) {
8046
8054
  } = input;
8047
8055
  const stage2Start = Date.now();
8048
8056
  const extractionPolicy = resolveVideoExtractionPolicy();
8057
+ composition.videos = composition.videos.filter(
8058
+ (video) => !isVideoPastTimelineEnd(video, composition.duration)
8059
+ );
8049
8060
  let frameLookup = null;
8050
8061
  let extractionResult = null;
8051
8062
  let failureToEnforce = null;
@@ -8132,7 +8143,8 @@ async function runExtractVideosStage(input) {
8132
8143
  timelineEnd: composition.duration,
8133
8144
  maxTransientRetries: extractionPolicy.maxTransientRetries,
8134
8145
  collectProbeFailures: extractionPolicy.failureMode === "enforce",
8135
- deferRangeExtraction
8146
+ deferRangeExtraction,
8147
+ contentKeyedDirs: [join15(compiledDir, REMOTE_MEDIA_SUBDIR)]
8136
8148
  },
8137
8149
  abortSignal,
8138
8150
  cfg,
@@ -9936,8 +9948,9 @@ function sanitizeProbeFailure(reason, paths) {
9936
9948
  async function padOrTrimAudioToVideoFrameCount(input) {
9937
9949
  const probeVideo = input.probeVideoFrameInfo ?? ((videoPath) => defaultProbeVideoFrameInfo(videoPath, input.signal));
9938
9950
  const probeAudio = input.probeAudioInfo ?? defaultProbeAudioInfo;
9939
- const runner = input.runFfmpeg ?? ((args) => defaultRunFfmpeg(args, input.signal));
9940
- const probeTruePeak = input.probeAudioTruePeakDbfs ?? (input.runFfmpeg ? void 0 : defaultProbeAudioTruePeakDbfs);
9951
+ const timeoutMs = input.timeoutMs ?? DEFAULT_CONFIG.ffmpegProcessTimeout;
9952
+ const runner = input.runFfmpeg ?? ((args) => defaultRunFfmpeg(args, timeoutMs, input.signal));
9953
+ const probeTruePeak = input.probeAudioTruePeakDbfs ?? (input.runFfmpeg ? void 0 : (audioPath, signal) => defaultProbeAudioTruePeakDbfs(audioPath, timeoutMs, signal));
9941
9954
  const [videoResult, audioResult] = await Promise.allSettled([
9942
9955
  probeVideo(input.videoPath),
9943
9956
  probeAudio(input.audioPath, input.signal)
@@ -10173,13 +10186,13 @@ async function defaultProbeAudioInfo(audioPath, signal) {
10173
10186
  audioCodec: metadata.audioCodec
10174
10187
  };
10175
10188
  }
10176
- async function defaultProbeAudioTruePeakDbfs(audioPath, signal) {
10189
+ async function defaultProbeAudioTruePeakDbfs(audioPath, timeoutMs, signal) {
10177
10190
  const result = await runFfmpeg(
10178
10191
  ["-i", audioPath, "-map", "0:a:0", "-vn", "-af", "ebur128=peak=true", "-f", "null", "-"],
10179
- { signal }
10192
+ { signal, timeout: timeoutMs }
10180
10193
  );
10181
10194
  if (!result.success) {
10182
- throw new Error(`[audioPadTrim] ${formatFfmpegError(result.exitCode, result.stderr)}`);
10195
+ throw new Error(`[audioPadTrim] ${describeFfmpegFailure(result, timeoutMs)}`);
10183
10196
  }
10184
10197
  const matches = [...result.stderr.matchAll(/^\s*Peak:\s*([+-]?(?:[\d.]+|inf)) dBFS$/gim)];
10185
10198
  const token = matches.at(-1)?.[1]?.toLowerCase();
@@ -10189,12 +10202,12 @@ async function defaultProbeAudioTruePeakDbfs(audioPath, signal) {
10189
10202
  }
10190
10203
  return value;
10191
10204
  }
10192
- async function defaultRunFfmpeg(args, signal) {
10193
- const result = await runFfmpeg(args, { signal });
10205
+ async function defaultRunFfmpeg(args, timeoutMs, signal) {
10206
+ const result = await runFfmpeg(args, { signal, timeout: timeoutMs });
10194
10207
  if (result.success) return { success: true };
10195
10208
  return {
10196
10209
  success: false,
10197
- error: `[audioPadTrim] ${formatFfmpegError(result.exitCode, result.stderr)}`,
10210
+ error: `[audioPadTrim] ${describeFfmpegFailure(result, timeoutMs)}`,
10198
10211
  failureReason: result.failureReason
10199
10212
  };
10200
10213
  }
@@ -10267,6 +10280,7 @@ async function assembleOutput(input, onSecondsWritten) {
10267
10280
  outputPath,
10268
10281
  hasAudio,
10269
10282
  format,
10283
+ ffmpegProcessTimeout,
10270
10284
  abortSignal,
10271
10285
  assertNotAborted
10272
10286
  } = input;
@@ -10280,7 +10294,8 @@ async function assembleOutput(input, onSecondsWritten) {
10280
10294
  videoPath: videoOnlyPath,
10281
10295
  audioPath: audioOutputPath,
10282
10296
  outputPath: normalizedAudioPath,
10283
- signal: abortSignal
10297
+ signal: abortSignal,
10298
+ timeoutMs: ffmpegProcessTimeout
10284
10299
  });
10285
10300
  assertNotAborted();
10286
10301
  if (!normalizeResult.success) {
@@ -10296,7 +10311,8 @@ async function assembleOutput(input, onSecondsWritten) {
10296
10311
  outputPath,
10297
10312
  abortSignal,
10298
10313
  {
10299
- audioCodec: "aac"
10314
+ audioCodec: "aac",
10315
+ ffmpegProcessTimeout
10300
10316
  },
10301
10317
  job.config.fps,
10302
10318
  onSecondsWritten
@@ -10313,7 +10329,7 @@ async function assembleOutput(input, onSecondsWritten) {
10313
10329
  videoOnlyPath,
10314
10330
  outputPath,
10315
10331
  abortSignal,
10316
- void 0,
10332
+ { ffmpegProcessTimeout },
10317
10333
  job.config.fps,
10318
10334
  onSecondsWritten
10319
10335
  );
@@ -10331,7 +10347,8 @@ async function runHlsPackaging(input, normalizedAudioPath) {
10331
10347
  input.outputPath,
10332
10348
  {
10333
10349
  segmentSeconds: input.hlsSegmentSeconds ?? DEFAULT_HLS_SEGMENT_SECONDS,
10334
- signal: input.abortSignal
10350
+ signal: input.abortSignal,
10351
+ ffmpegProcessTimeout: input.ffmpegProcessTimeout
10335
10352
  }
10336
10353
  );
10337
10354
  input.assertNotAborted();
@@ -10689,7 +10706,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
10689
10706
  const madeProgress = captureAttemptMadeProgress(frameCount, remainingCount);
10690
10707
  if (!madeProgress) {
10691
10708
  options.log.warn(
10692
- "[Render] Capture attempt made no forward progress; composition is likely structurally broken \u2014 not retrying.",
10709
+ "[Render] Capture attempt made no forward progress; composition is likely structurally broken, not retrying.",
10693
10710
  { attempt, frameCount, remainingCount, workers: currentWorkers }
10694
10711
  );
10695
10712
  }
@@ -10758,7 +10775,7 @@ async function executeDiskCaptureWithAdaptiveRetry(options) {
10758
10775
  }
10759
10776
  if (!madeProgress) {
10760
10777
  options.log.warn(
10761
- "[Render] Capture attempt made no forward progress; composition is likely structurally broken \u2014 not retrying.",
10778
+ "[Render] Capture attempt made no forward progress; composition is likely structurally broken, not retrying.",
10762
10779
  { attempt, frameCount, remainingCount, workers: currentWorkers }
10763
10780
  );
10764
10781
  }
@@ -10793,36 +10810,6 @@ function createRenderJob(config) {
10793
10810
  warnings: []
10794
10811
  };
10795
10812
  }
10796
- function normalizeCompositionSrcPath(srcPath) {
10797
- return srcPath.replace(/\\/g, "/").replace(/^\.\//, "");
10798
- }
10799
- function readSceneRootDuration(entryHtml) {
10800
- if (!entryHtml) return null;
10801
- const { document: document2 } = parseHTML(entryHtml);
10802
- const template = document2.querySelector("template");
10803
- const scope = template ? parseHTML(template.innerHTML).document : document2;
10804
- const root = scope.querySelector("[data-composition-id]");
10805
- return root?.getAttribute("data-duration") ?? null;
10806
- }
10807
- function createStandaloneEntryRenderClone(root, host, sceneDuration) {
10808
- const hostClone = host.cloneNode(true);
10809
- hostClone.setAttribute("data-start", "0");
10810
- if (root === host) return hostClone;
10811
- const rootClone = root.cloneNode(false);
10812
- if (sceneDuration != null) {
10813
- rootClone.setAttribute("data-duration", sceneDuration);
10814
- } else {
10815
- rootClone.removeAttribute("data-duration");
10816
- }
10817
- rootClone.appendChild(hostClone);
10818
- return rootClone;
10819
- }
10820
- function replaceBodyWithRenderClone(body, renderClone) {
10821
- while (body.firstChild) {
10822
- body.removeChild(body.firstChild);
10823
- }
10824
- body.appendChild(renderClone);
10825
- }
10826
10813
  function explainStreamingEncodeGate(cfg, outputFormat, workerCount, durationSeconds, forceParallelStream = false) {
10827
10814
  if (!cfg.enableStreamingEncode) return { enabled: false, reason: "disabled_by_config" };
10828
10815
  if (outputFormat === "png-sequence" || outputFormat === "gif") {
@@ -11219,25 +11206,6 @@ function resolveCaptureForceScreenshotForPageSideCompositing(args) {
11219
11206
  function shouldDiscardProbeSessionForPageSideCompositing(args) {
11220
11207
  return args.hasProbeSession && args.usePageSideCompositing;
11221
11208
  }
11222
- function extractStandaloneEntryFromIndex(indexHtml, entryFile, entryHtml) {
11223
- const normalizedEntryFile = normalizeCompositionSrcPath(entryFile);
11224
- const { document: document2 } = parseHTML(indexHtml);
11225
- const body = document2.querySelector("body");
11226
- if (!body) return null;
11227
- const hosts = Array.from(document2.querySelectorAll("[data-composition-src]"));
11228
- const host = hosts.find(
11229
- (candidate) => normalizeCompositionSrcPath(candidate.getAttribute("data-composition-src") || "") === normalizedEntryFile
11230
- );
11231
- if (!host) return null;
11232
- const root = Array.from(body.children).find(
11233
- (candidate) => candidate.hasAttribute("data-composition-id")
11234
- ) ?? null;
11235
- if (!root) return null;
11236
- const sceneDuration = readSceneRootDuration(entryHtml) ?? host.getAttribute("data-duration");
11237
- const renderClone = createStandaloneEntryRenderClone(root, host, sceneDuration);
11238
- replaceBodyWithRenderClone(body, renderClone);
11239
- return document2.toString();
11240
- }
11241
11209
  function deVerifyFallbackTelemetry(err) {
11242
11210
  const details = getDrawElementVerificationDetails(err);
11243
11211
  return {
@@ -11270,7 +11238,7 @@ async function executeRenderJob(job, projectDir, outputPath, progressSink, abort
11270
11238
  execution.defer("remove workDir", () => {
11271
11239
  if (job.config.debug) return;
11272
11240
  if (job.status === "complete" && process.env.KEEP_TEMP === "1") {
11273
- log.info("KEEP_TEMP=1 \u2014 leaving workDir on disk for inspection", { workDir });
11241
+ log.info("KEEP_TEMP=1, leaving workDir on disk for inspection", { workDir });
11274
11242
  return;
11275
11243
  }
11276
11244
  rmSync8(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
@@ -11422,7 +11390,7 @@ async function executeRenderPipeline(input) {
11422
11390
  }
11423
11391
  assertNotAborted();
11424
11392
  const rawEntry = readFileSync7(htmlPath, "utf-8");
11425
- if (entryFile !== "index.html" && rawEntry.trimStart().startsWith("<template")) {
11393
+ if (entryFile !== "index.html" && isTemplateEntry(rawEntry)) {
11426
11394
  const wrapperPath = join25(workDir, "standalone-entry.html");
11427
11395
  const projectIndexPath = join25(projectDir, "index.html");
11428
11396
  if (!existsSync15(projectIndexPath)) {
@@ -11507,7 +11475,7 @@ async function executeRenderPipeline(input) {
11507
11475
  captureForceScreenshot = true;
11508
11476
  updateCaptureObservability({ forceScreenshot: captureForceScreenshot });
11509
11477
  log.info(
11510
- "[Render] Low-memory render profile active \u2014 screenshot capture, auto-worker calibration skipped" + (job.config.workers === void 0 ? ", pinned to 1 worker" : "") + ". Override with --no-low-memory-mode or PRODUCER_LOW_MEMORY_MODE=false.",
11478
+ "[Render] Low-memory render profile active: screenshot capture, auto-worker calibration skipped" + (job.config.workers === void 0 ? ", pinned to 1 worker" : "") + ". Override with --no-low-memory-mode or PRODUCER_LOW_MEMORY_MODE=false.",
11511
11479
  { totalMemMb: getSystemTotalMb(), thresholdMb: LOW_MEMORY_TOTAL_MB_THRESHOLD }
11512
11480
  );
11513
11481
  }
@@ -12075,7 +12043,7 @@ async function executeRenderPipeline(input) {
12075
12043
  cfg.useDrawElement = false;
12076
12044
  deClampReason = workerCount > 1 ? "parallel" : "disk_path";
12077
12045
  log.info(
12078
- "[Render] Fast capture: default-on drawElement disabled for this render \u2014 " + (workerCount > 1 ? "parallel capture" : "the disk capture path") + " has no runtime self-verification. Set PRODUCER_EXPERIMENTAL_FAST_CAPTURE=true to override."
12046
+ "[Render] Fast capture: default-on drawElement disabled for this render: " + (workerCount > 1 ? "parallel capture" : "the disk capture path") + " has no runtime self-verification. Set PRODUCER_EXPERIMENTAL_FAST_CAPTURE=true to override."
12079
12047
  );
12080
12048
  if (probeSession && probeSession.captureMode === "drawelement") {
12081
12049
  lastBrowserConsole = probeSession.browserConsoleBuffer;
@@ -12171,7 +12139,7 @@ async function executeRenderPipeline(input) {
12171
12139
  });
12172
12140
  updateCaptureObservability({ forceScreenshot: captureForceScreenshot });
12173
12141
  log.info(
12174
- `[Render] Page-side compositing enabled \u2014 bypassing Node-side layered shader-blend path. Engine will capture one ${needsAlpha ? "RGBA PNG" : "opaque RGB"} screenshot per output frame.`
12142
+ `[Render] Page-side compositing enabled, bypassing Node-side layered shader-blend path. Engine will capture one ${needsAlpha ? "RGBA PNG" : "opaque RGB"} screenshot per output frame.`
12175
12143
  );
12176
12144
  }
12177
12145
  const useLayeredComposite = !usePageSideCompositingForTransitions && shouldUseLayeredComposite({
@@ -12668,7 +12636,7 @@ async function executeRenderPipeline(input) {
12668
12636
  cfg.useDrawElement = false;
12669
12637
  deClampReason = deClampReason ?? "disk_path";
12670
12638
  log.info(
12671
- "[Render] Fast capture: drawElement disabled for the disk fallback \u2014 streaming encoder spawn failed and the disk path has no runtime self-verification."
12639
+ "[Render] Fast capture: drawElement disabled for the disk fallback: streaming encoder spawn failed and the disk path has no runtime self-verification."
12672
12640
  );
12673
12641
  if (probeSession && probeSession.captureMode === "drawelement") {
12674
12642
  lastBrowserConsole = probeSession.browserConsoleBuffer;
@@ -12840,6 +12808,7 @@ async function executeRenderPipeline(input) {
12840
12808
  hasAudio,
12841
12809
  format: outputFormat,
12842
12810
  hlsSegmentSeconds,
12811
+ ffmpegProcessTimeout: cfg.ffmpegProcessTimeout,
12843
12812
  abortSignal: executionSignal,
12844
12813
  assertNotAborted,
12845
12814
  onProgress
@@ -13206,10 +13175,10 @@ function validateJsonSafeValue(value, field) {
13206
13175
  walkVariables(value, field, /* @__PURE__ */ new WeakSet());
13207
13176
  }
13208
13177
  var LEAF_REJECTIONS = {
13209
- undefined: "undefined leaves are silently dropped by JSON.stringify \u2014 use null if you mean an absent value",
13178
+ undefined: "undefined leaves are silently dropped by JSON.stringify. Use null if you mean an absent value",
13210
13179
  function: "functions are not JSON-serializable",
13211
13180
  symbol: "Symbols are not JSON-serializable",
13212
- bigint: "BigInt values throw at JSON.stringify \u2014 encode as a string if you need 64-bit integers"
13181
+ bigint: "BigInt values throw at JSON.stringify. Encode as a string if you need 64-bit integers"
13213
13182
  };
13214
13183
  function walkVariables(value, path, seen) {
13215
13184
  const t = typeof value;
@@ -13230,7 +13199,7 @@ function walkVariables(value, path, seen) {
13230
13199
  if (seen.has(value)) {
13231
13200
  throw new InvalidConfigError(
13232
13201
  path,
13233
- "circular reference detected \u2014 JSON.stringify cannot serialize cycles"
13202
+ "circular reference detected: JSON.stringify cannot serialize cycles"
13234
13203
  );
13235
13204
  }
13236
13205
  seen.add(value);
@@ -13892,7 +13861,7 @@ function validateOutputResolutionOverride(body) {
13892
13861
  return `Invalid outputResolution "${body.outputResolution}". Must be one of: landscape, portrait, landscape-4k, portrait-4k, square, square-4k (aliases: 1080p, 4k, \u2026).`;
13893
13862
  }
13894
13863
  if (normalized !== void 0 && (body.format === "webm" || body.format === "mov")) {
13895
- return `outputResolution is not supported with format "${body.format}" \u2014 the alpha (webm/mov) capture path can't supersample. Use format "mp4", or omit outputResolution to render at the composition's native dimensions.`;
13864
+ return `outputResolution is not supported with format "${body.format}": the alpha (webm/mov) capture path can't supersample. Use format "mp4", or omit outputResolution to render at the composition's native dimensions.`;
13896
13865
  }
13897
13866
  return void 0;
13898
13867
  }
@@ -14339,7 +14308,7 @@ function startServer(options = {}) {
14339
14308
  });
14340
14309
  async function shutdown(signal) {
14341
14310
  log.info(`Received ${signal}, shutting down`);
14342
- const { drainBrowserPool } = await import("./src-VUJ2FUFK.js");
14311
+ const { drainBrowserPool } = await import("./src-LIERUCFW.js");
14343
14312
  await drainBrowserPool().catch(() => {
14344
14313
  });
14345
14314
  const handle = await Promise.race([
@@ -14599,7 +14568,7 @@ function collectPlanAssetShas(planDir) {
14599
14568
  }
14600
14569
  if (compositionHtml === null) {
14601
14570
  throw new Error(
14602
- `[freezePlan] compiled HTML missing at ${COMPILED_INDEX_RELATIVE_PATH} \u2014 upstream compile stage did not materialize the expected file.`
14571
+ `[freezePlan] compiled HTML missing at ${COMPILED_INDEX_RELATIVE_PATH} (upstream compile stage did not materialize the expected file).`
14603
14572
  );
14604
14573
  }
14605
14574
  return { compositionHtml, assets };
@@ -15178,7 +15147,7 @@ var PlanTooLargeError = class extends Error {
15178
15147
  const breakdownSuffix = breakdown ? ` Breakdown: video-frames=${formatBytes(breakdown.videoFramesBytes)}, compiled=${formatBytes(breakdown.compiledBytes)} (source-media=${formatBytes(breakdown.sourceMediaBytes)}), audio=${formatBytes(breakdown.audioBytes)}, metadata=${formatBytes(breakdown.metadataBytes)}, other=${formatBytes(breakdown.otherBytes)}, files=${breakdown.fileCount}.` : "";
15179
15148
  const observationSuffix = observedAt ? ` Observed at ${observedAt}.` : "";
15180
15149
  super(
15181
- `[plan] planDir size ${formatBytes(sizeBytes)} exceeds the configured ceiling ${formatBytes(limitBytes)} (PLAN_TOO_LARGE). The default 2 GB cap fits inside AWS Lambda's 10 GB /tmp budget alongside the chunk worker's frame buffer and ffmpeg's working set. To unblock: use the content-addressed \`planV2()\` transport, shorten the composition, lower the framerate, or use the in-process renderer (\`executeRenderJob\`) \u2014 it has no planDir size cap.` + observationSuffix + breakdownSuffix
15150
+ `[plan] planDir size ${formatBytes(sizeBytes)} exceeds the configured ceiling ${formatBytes(limitBytes)} (PLAN_TOO_LARGE). The default 2 GB cap fits inside AWS Lambda's 10 GB /tmp budget alongside the chunk worker's frame buffer and ffmpeg's working set. To unblock: use the content-addressed \`planV2()\` transport, shorten the composition, lower the framerate, or use the in-process renderer (\`executeRenderJob\`), which has no planDir size cap.` + observationSuffix + breakdownSuffix
15182
15151
  );
15183
15152
  this.name = "PlanTooLargeError";
15184
15153
  this.sizeBytes = sizeBytes;
@@ -15195,7 +15164,7 @@ var FormatNotSupportedInDistributedError = class extends Error {
15195
15164
  reason;
15196
15165
  constructor(format, reason) {
15197
15166
  super(
15198
- `[plan] format ${JSON.stringify(format)} is not supported in distributed mode: ${reason}. Render with the in-process renderer (\`executeRenderJob\`) \u2014 it has full format support \u2014 or pick a distributed-supported format: mp4 SDR, mov ProRes 4444, png-sequence, or webm VP9.`
15167
+ `[plan] format ${JSON.stringify(format)} is not supported in distributed mode: ${reason}. Render with the in-process renderer (\`executeRenderJob\`), which has full format support, or pick a distributed-supported format: mp4 SDR, mov ProRes 4444, png-sequence, or webm VP9.`
15199
15168
  );
15200
15169
  this.name = "FormatNotSupportedInDistributedError";
15201
15170
  this.format = format;
@@ -15284,7 +15253,7 @@ async function readFontSnapshotSha() {
15284
15253
  const data = module.EMBEDDED_FONT_DATA;
15285
15254
  if (!data || typeof data !== "object") {
15286
15255
  throw new Error(
15287
- "[plan] EMBEDDED_FONT_DATA missing from @hyperframes/core/fonts/embedded-data \u2014 was `bun run build:fonts` run?"
15256
+ "[plan] EMBEDDED_FONT_DATA missing from @hyperframes/core/fonts/embedded-data. Was `bun run build:fonts` run?"
15288
15257
  );
15289
15258
  }
15290
15259
  const dataObj = data;
@@ -15334,7 +15303,7 @@ function resolveEncoderTriple(config) {
15334
15303
  }
15335
15304
  if (config.codec !== void 0) {
15336
15305
  throw new Error(
15337
- `[plan] DistributedRenderConfig.codec is only valid for format="mp4"; received codec=${JSON.stringify(config.codec)} with format=${JSON.stringify(config.format)}. Omit codec for non-mp4 formats \u2014 mov is always ProRes 4444, webm is always libvpx-vp9, and png-sequence has no encoder.`
15306
+ `[plan] DistributedRenderConfig.codec is only valid for format="mp4"; received codec=${JSON.stringify(config.codec)} with format=${JSON.stringify(config.format)}. Omit codec for non-mp4 formats: mov is always ProRes 4444, webm is always libvpx-vp9, and png-sequence has no encoder.`
15338
15307
  );
15339
15308
  }
15340
15309
  return resolveNonMp4EncoderTriple(config.format, config.quality ?? "standard");
@@ -15524,7 +15493,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
15524
15493
  if (probeResult.fileServer) closeFileServerSafely(probeResult.fileServer, "plan", log);
15525
15494
  if (probeResult.probeSession) {
15526
15495
  try {
15527
- const { closeCaptureSession: closeCaptureSession2 } = await import("./src-VUJ2FUFK.js");
15496
+ const { closeCaptureSession: closeCaptureSession2 } = await import("./src-LIERUCFW.js");
15528
15497
  await closeCaptureSession2(probeResult.probeSession);
15529
15498
  } catch (err) {
15530
15499
  log.warn("[plan] probe session close failed", {
@@ -16546,6 +16515,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16546
16515
  const log = options?.logger ?? defaultLogger;
16547
16516
  const abortSignal = options?.abortSignal;
16548
16517
  const cfr = options?.cfr === true;
16518
+ const { ffmpegProcessTimeout } = resolveConfig();
16549
16519
  const planJsonPath = join36(planDir, "plan.json");
16550
16520
  const chunksJsonPath = join36(planDir, "meta", "chunks.json");
16551
16521
  if (!existsSync24(planJsonPath)) {
@@ -16585,10 +16555,13 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16585
16555
  const remuxArgs = ["-i", chunkPaths[0], "-c", "copy", "-r", fpsArg];
16586
16556
  appendRenderProvenanceArgs(remuxArgs, concatOutputPath);
16587
16557
  remuxArgs.push("-y", concatOutputPath);
16588
- const remuxResult = await runFfmpeg(remuxArgs, { signal: abortSignal });
16558
+ const remuxResult = await runFfmpeg(remuxArgs, {
16559
+ signal: abortSignal,
16560
+ timeout: ffmpegProcessTimeout
16561
+ });
16589
16562
  if (!remuxResult.success) {
16590
16563
  throw encoderFailureError("[assemble] ffmpeg single-chunk remux failed", {
16591
- error: `exit ${remuxResult.exitCode}: ${remuxResult.stderr.slice(-400)}`,
16564
+ error: describeFfmpegFailure(remuxResult, ffmpegProcessTimeout),
16592
16565
  failureReason: remuxResult.failureReason
16593
16566
  });
16594
16567
  }
@@ -16611,10 +16584,13 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16611
16584
  ];
16612
16585
  appendRenderProvenanceArgs(concatArgs, concatOutputPath);
16613
16586
  concatArgs.push("-y", concatOutputPath);
16614
- const concatResult = await runFfmpeg(concatArgs, { signal: abortSignal });
16587
+ const concatResult = await runFfmpeg(concatArgs, {
16588
+ signal: abortSignal,
16589
+ timeout: ffmpegProcessTimeout
16590
+ });
16615
16591
  if (!concatResult.success) {
16616
16592
  throw encoderFailureError("[assemble] ffmpeg concat-copy failed", {
16617
- error: `exit ${concatResult.exitCode}: ${concatResult.stderr.slice(-400)}`,
16593
+ error: describeFfmpegFailure(concatResult, ffmpegProcessTimeout),
16618
16594
  failureReason: concatResult.failureReason
16619
16595
  });
16620
16596
  }
@@ -16655,10 +16631,13 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16655
16631
  ];
16656
16632
  appendRenderProvenanceArgs(cfrArgs, cfrOutputPath);
16657
16633
  cfrArgs.push("-y", cfrOutputPath);
16658
- const cfrResult = await runFfmpeg(cfrArgs, { signal: abortSignal });
16634
+ const cfrResult = await runFfmpeg(cfrArgs, {
16635
+ signal: abortSignal,
16636
+ timeout: ffmpegProcessTimeout
16637
+ });
16659
16638
  if (!cfrResult.success) {
16660
16639
  throw encoderFailureError("[assemble] ffmpeg cfr re-encode failed", {
16661
- error: `exit ${cfrResult.exitCode}: ${cfrResult.stderr.slice(-400)}`,
16640
+ error: describeFfmpegFailure(cfrResult, ffmpegProcessTimeout),
16662
16641
  failureReason: cfrResult.failureReason
16663
16642
  });
16664
16643
  }
@@ -16676,7 +16655,8 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16676
16655
  videoPath: postConcatPath,
16677
16656
  audioPath,
16678
16657
  outputPath: paddedAudioPath,
16679
- signal: abortSignal
16658
+ signal: abortSignal,
16659
+ timeoutMs: ffmpegProcessTimeout
16680
16660
  });
16681
16661
  if (!padTrimResult.success) {
16682
16662
  throw encoderFailureError("[assemble] audio pad/trim failed", padTrimResult);
@@ -16695,9 +16675,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16695
16675
  normalizedAudioPath,
16696
16676
  muxOutputPath,
16697
16677
  abortSignal,
16698
- {
16699
- audioCodec: "aac"
16700
- },
16678
+ { audioCodec: "aac", ffmpegProcessTimeout },
16701
16679
  { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen }
16702
16680
  );
16703
16681
  if (!muxResult.success) {
@@ -16708,7 +16686,7 @@ async function assemble(planDir, chunkPaths, audioPath, outputPath, options) {
16708
16686
  muxOutputPath,
16709
16687
  outputPath,
16710
16688
  abortSignal,
16711
- void 0,
16689
+ { ffmpegProcessTimeout },
16712
16690
  {
16713
16691
  num: plan2.dimensions.fpsNum,
16714
16692
  den: plan2.dimensions.fpsDen