hyperframes 0.8.141 → 0.8.143

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 (200) hide show
  1. package/dist/{add-KH2CF4FD.js → add-Q5EYDUAY.js} +18 -17
  2. package/dist/{animatedGifPrep-QO4BSKR7.js → animatedGifPrep-H2DUQEZ3.js} +15 -15
  3. package/dist/{asset-4RDZILVJ.js → asset-C7JBYYX4.js} +4 -4
  4. package/dist/{assetCataloger-WGR4LYYN.js → assetCataloger-FRO4G6OU.js} +8 -7
  5. package/dist/{auth-WYQCOYE5.js → auth-FRWLCO36.js} +5 -4
  6. package/dist/{autoUpdate-PC5TN3NL.js → autoUpdate-E4OZXQK6.js} +2 -2
  7. package/dist/{backgroundChecks-7M3T44EP.js → backgroundChecks-FSUVHN5L.js} +3 -3
  8. package/dist/backgroundChecksWorker.js +3 -3
  9. package/dist/{batchRender-GOLLOE4V.js → batchRender-4U73BYTU.js} +11 -10
  10. package/dist/{beats-XJ7WP6QS.js → beats-U6KJWF35.js} +32 -28
  11. package/dist/{benchmark-HCGFBEZJ.js → benchmark-5ONT7V7B.js} +15 -14
  12. package/dist/{browser-VQKO2FKG.js → browser-R4DU46IE.js} +4 -4
  13. package/dist/{bundleWithLocalizedFonts-FH7PHTTX.js → bundleWithLocalizedFonts-VH55VOAL.js} +2 -2
  14. package/dist/{capture-TFZZSF6F.js → capture-26G2DPSI.js} +83 -41
  15. package/dist/{capture-XD3P3YQR.js → capture-OGQAEYKO.js} +24 -8
  16. package/dist/{catalog-4S33QWJJ.js → catalog-RKORTIUE.js} +19 -18
  17. package/dist/{catch-up-RW7YXXNT.js → catch-up-4OBERRQO.js} +5 -5
  18. package/dist/{check-XVTRRN4Y.js → check-P2XDN57S.js} +89 -85
  19. package/dist/{checkBrowser-HZXJ2EDU.js → checkBrowser-NTGJGAEA.js} +42 -42
  20. package/dist/{chunk-AVWEIOEN.js → chunk-2LBBHMKT.js} +1 -1
  21. package/dist/{chunk-E6SDW5FV.js → chunk-33RZPZ4K.js} +192 -45
  22. package/dist/{chunk-6IFXWJDX.js → chunk-3NE7ZYU2.js} +2 -2
  23. package/dist/{chunk-TQFG7HTI.js → chunk-3RM2ETQT.js} +0 -168
  24. package/dist/{chunk-PFCFR3KZ.js → chunk-442JNXRM.js} +1 -1
  25. package/dist/{chunk-6E6CM7WS.js → chunk-4M4EC7JX.js} +19 -12
  26. package/dist/{chunk-HKCNZITN.js → chunk-4OA4LDTU.js} +2 -2
  27. package/dist/{chunk-XTFJOR3K.js → chunk-4SFGME7K.js} +1 -1
  28. package/dist/{chunk-34TXESM7.js → chunk-5FISWJ37.js} +12 -4
  29. package/dist/{chunk-JYYOAKHS.js → chunk-6IIGT7BX.js} +1 -1
  30. package/dist/chunk-6TPZSTCL.js +3681 -0
  31. package/dist/{chunk-P6E4HFFU.js → chunk-6XMFEICO.js} +263 -75
  32. package/dist/{chunk-6Q6FR4KH.js → chunk-7UYBQ6NF.js} +296 -89
  33. package/dist/{chunk-BRITLL56.js → chunk-B4P5VDFQ.js} +1 -1
  34. package/dist/{chunk-U7E736AJ.js → chunk-BFDJ63J5.js} +32 -14
  35. package/dist/{chunk-WCJGTLPF.js → chunk-BHVFTYSI.js} +6 -3
  36. package/dist/{chunk-IO7ZIDRP.js → chunk-BT27OYYX.js} +53 -12
  37. package/dist/{chunk-KFH6UD26.js → chunk-BYK73CR7.js} +4 -4
  38. package/dist/{chunk-L3JSAB4L.js → chunk-CLOH4LIB.js} +3 -3
  39. package/dist/{chunk-R7UDXKI3.js → chunk-DF2BHILQ.js} +3 -3
  40. package/dist/{chunk-246MOR5U.js → chunk-DKSDVDXG.js} +175 -162
  41. package/dist/{chunk-35RSNI77.js → chunk-F26LCYRY.js} +42 -34
  42. package/dist/{chunk-5Z63TBTX.js → chunk-FH7WODJH.js} +1 -1
  43. package/dist/{chunk-NORZWWLK.js → chunk-FVYXDXEV.js} +2 -2
  44. package/dist/{chunk-YURXPGAM.js → chunk-GNBGPUJ7.js} +6 -8
  45. package/dist/{chunk-RVCWIIZ7.js → chunk-GV5R5B7Q.js} +1 -1
  46. package/dist/{chunk-GS6FE3IW.js → chunk-HC7EVDEL.js} +1 -1
  47. package/dist/{chunk-K2GOFLTX.js → chunk-HLYOEIWM.js} +14 -6
  48. package/dist/{chunk-XDSOIJC3.js → chunk-HMT2RPZU.js} +6 -6
  49. package/dist/{chunk-IKVBTDLO.js → chunk-HW4AKJ5F.js} +1 -1
  50. package/dist/{chunk-OLDDJS3S.js → chunk-I7QGQAZM.js} +8 -8
  51. package/dist/{chunk-JFKL3WAE.js → chunk-IWFLMU2N.js} +104 -19
  52. package/dist/{chunk-IHFUKJOR.js → chunk-K2FLNJVB.js} +8 -2
  53. package/dist/chunk-KJJLA674.js +121 -0
  54. package/dist/{chunk-XWVGSEUT.js → chunk-KO5QBV73.js} +1 -1
  55. package/dist/{chunk-INI3TM6I.js → chunk-KQLGTGE5.js} +3 -3
  56. package/dist/{chunk-E4BSCXMU.js → chunk-LVX6NK36.js} +3 -3
  57. package/dist/{chunk-BM5PX3DJ.js → chunk-LW6HO6U3.js} +4 -4
  58. package/dist/{chunk-OZUQF4NB.js → chunk-MQZVBHEY.js} +123 -8
  59. package/dist/{chunk-IV7EI5E2.js → chunk-N3DQEVSI.js} +2 -2
  60. package/dist/{chunk-A4KQZXZI.js → chunk-NE55C6S5.js} +4 -2
  61. package/dist/{chunk-EDYBFSPE.js → chunk-OBXQRJWQ.js} +7 -10
  62. package/dist/{chunk-RCFCZT5O.js → chunk-OSSHSIMD.js} +1 -1
  63. package/dist/chunk-P36MALQF.js +15 -0
  64. package/dist/{chunk-EKA4ZZBI.js → chunk-P7THMINS.js} +3 -3
  65. package/dist/{chunk-3NBKW2QJ.js → chunk-PAGIICKN.js} +2 -2
  66. package/dist/{chunk-O3SKIXQK.js → chunk-PJU63L6W.js} +1 -1
  67. package/dist/{chunk-RPYPW5NN.js → chunk-POLR33RB.js} +20 -13
  68. package/dist/{chunk-7M4KAPAA.js → chunk-PUGIRFPX.js} +2 -2
  69. package/dist/{chunk-7XTZVLE6.js → chunk-QFN7NVWM.js} +1 -1
  70. package/dist/{chunk-D2KNWIQ6.js → chunk-QFSCCQIR.js} +1 -1
  71. package/dist/{chunk-J5IPIQU2.js → chunk-QRKLPWEX.js} +1 -1
  72. package/dist/{chunk-N77KD7ZZ.js → chunk-QVYVUCWD.js} +1 -1
  73. package/dist/{chunk-GK4AIFIH.js → chunk-SDYDNHEE.js} +34 -3
  74. package/dist/{chunk-2NCHQUPX.js → chunk-SQLK7SJL.js} +1 -1
  75. package/dist/{chunk-PMRBLBUP.js → chunk-T42U2W2R.js} +14 -2
  76. package/dist/{chunk-Q65ZQFF2.js → chunk-TAMQYQGJ.js} +1 -1
  77. package/dist/{chunk-PXSM4HPB.js → chunk-U3X3TPBW.js} +1 -1
  78. package/dist/{chunk-3A5AAPMP.js → chunk-UICWP23D.js} +1 -1
  79. package/dist/{chunk-A7YQNIQT.js → chunk-UM2GRYM3.js} +113 -10
  80. package/dist/{chunk-TC2FBZJZ.js → chunk-VIVBA6E6.js} +2 -2
  81. package/dist/{chunk-W6HTOVHU.js → chunk-W35EKBS6.js} +2 -2
  82. package/dist/{chunk-YEIFI443.js → chunk-WPNE5NEP.js} +1 -1
  83. package/dist/{chunk-WY5OODN5.js → chunk-XONFUK3M.js} +3693 -28
  84. package/dist/{chunk-IYFKBFTW.js → chunk-Y6QL2LGO.js} +8 -5
  85. package/dist/{chunk-THXFSPLV.js → chunk-ZIRIDSDB.js} +1 -1
  86. package/dist/chunk-ZLW2V65P.js +209 -0
  87. package/dist/{chunk-4BB7V6AI.js → chunk-ZQQ3SEIE.js} +33 -32
  88. package/dist/{clean-L2E4VD57.js → clean-YHGPY33K.js} +23 -23
  89. package/dist/cli.js +57 -159
  90. package/dist/{cloud-IDUQRYLO.js → cloud-DOFI5ISR.js} +4 -4
  91. package/dist/{cloudrun-R3JXWXGG.js → cloudrun-KTZ4XDHL.js} +13 -12
  92. package/dist/commands/contrast-audit.browser.js +60 -4
  93. package/dist/commands/layout-audit.browser.js +88 -20
  94. package/dist/{compare-VYBWSP3Y.js → compare-SMMIZN2C.js} +37 -37
  95. package/dist/{compiler-ACHWOU5N.js → compiler-TEXQWW6N.js} +14 -11
  96. package/dist/{component-PYYV2V3F.js → component-B3GCNGSS.js} +5 -5
  97. package/dist/{compositions-B5GQSXH7.js → compositions-OQNZZTKF.js} +38 -34
  98. package/dist/{delete-EAX2U3WI.js → delete-EL5LVSEP.js} +6 -6
  99. package/dist/{deterministicFonts-F6WIVL2W.js → deterministicFonts-U2BIMGPG.js} +3 -3
  100. package/dist/{dist-NZSQCYOF.js → dist-5UVIRMSM.js} +7 -7
  101. package/dist/{dist-ROUDWGLO.js → dist-XN234YFQ.js} +41 -39
  102. package/dist/{doctor-PJX7MLFG.js → doctor-UOL3OI2A.js} +17 -17
  103. package/dist/{dom-IROKGVJI.js → dom-37K6YOH4.js} +2 -2
  104. package/dist/{events-SBC54MHO.js → events-K2DB2PBC.js} +2 -2
  105. package/dist/{events-YFFXKAQQ.js → events-NIZBS6S7.js} +3 -3
  106. package/dist/{feedback-UETLWREV.js → feedback-QMP4E6L7.js} +16 -15
  107. package/dist/{figma-QDSJPIRW.js → figma-2AUJRNVC.js} +3 -3
  108. package/dist/fontLocalizeCli.js +18 -18
  109. package/dist/{get-B5TS6C7H.js → get-P5NC7SRM.js} +6 -6
  110. package/dist/{gpuPolicy-LYOVBAJP.js → gpuPolicy-7N5MCE2G.js} +15 -15
  111. package/dist/{grade-compare-LBIHMAUN.js → grade-compare-HV5AFZ6P.js} +37 -37
  112. package/dist/{help-XBP6A6LT.js → help-3TSTXBLN.js} +1 -1
  113. package/dist/{history-2S42ZXKL.js → history-D65XFJ6D.js} +6 -6
  114. package/dist/hyperframe-runtime.js +25 -25
  115. package/dist/hyperframe.manifest.json +1 -1
  116. package/dist/hyperframe.runtime.iife.js +25 -25
  117. package/dist/hyperframes-player.global.js +3 -3
  118. package/dist/hyperframes-slideshow.global.js +23 -23
  119. package/dist/{info-I2VDAWT7.js → info-TXV7MLFO.js} +17 -16
  120. package/dist/{init-BGHSDODI.js → init-OSDMJZJV.js} +38 -38
  121. package/dist/{inspect-MZK5B5RP.js → inspect-RQQSAYIJ.js} +38 -38
  122. package/dist/{installer-LL4QAKFW.js → installer-CDOB32HE.js} +11 -10
  123. package/dist/{keyframes-2EBF7OSS.js → keyframes-V75Q6GRM.js} +10 -10
  124. package/dist/{lambda-XKFPAOFE.js → lambda-RODV4RCX.js} +12 -11
  125. package/dist/{layout-TP5ERKEF.js → layout-IZAI5SFC.js} +38 -38
  126. package/dist/{lint-FQ6CEI7E.js → lint-PLXOXY5R.js} +14 -14
  127. package/dist/{lintProject-LM3XZRPZ.js → lintProject-OQ6H6XBR.js} +7 -7
  128. package/dist/{list-FRNUJXZ3.js → list-BQBPNKDZ.js} +7 -7
  129. package/dist/{login-C25QU3BQ.js → login-NP6F4FHC.js} +20 -24
  130. package/dist/{logout-GJXZQKOA.js → logout-B4KS4A7S.js} +6 -6
  131. package/dist/{manager-DXB7JDHU.js → manager-GXYF4AVO.js} +2 -2
  132. package/dist/{manager-524RPYO7.js → manager-RFZNG5YT.js} +2 -2
  133. package/dist/{media-treatment-DCANGWSV.js → media-treatment-PXGMZ4A4.js} +55 -34
  134. package/dist/{models-GOD6ARB3.js → models-CEZM6XZ7.js} +17 -17
  135. package/dist/{motionShot-FSKETANX.js → motionShot-R4GHYWYM.js} +25 -25
  136. package/dist/{normalize-IGLHCWTF.js → normalize-H6KUHHEI.js} +18 -7
  137. package/dist/{normalize-audio-C2IM7OID.js → normalize-audio-MQ7NFCOV.js} +10 -6
  138. package/dist/{open-VVISXIII.js → open-AKQTGNXF.js} +5 -5
  139. package/dist/{pipeline-7YHZPYIS.js → pipeline-SYJYP2RM.js} +17 -17
  140. package/dist/{play-DSELK7G3.js → play-NBH4B7PL.js} +31 -30
  141. package/dist/{present-N72YFDKP.js → present-XAX55CFS.js} +26 -26
  142. package/dist/{preview-XTYN4NJ2.js → preview-OLANKNFA.js} +26 -26
  143. package/dist/{producer-NDCU3MHK.js → producer-Q6YNZZUJ.js} +1 -1
  144. package/dist/{projectConfig-MH4QU4AC.js → projectConfig-EM26P45P.js} +13 -12
  145. package/dist/{publication-KUSHI5MG.js → publication-OXWJZKSX.js} +8 -7
  146. package/dist/{publish-3XEEFWMF.js → publish-4VBWP2UB.js} +23 -22
  147. package/dist/{refresh-MFITBIKV.js → refresh-PVHBEABE.js} +2 -2
  148. package/dist/{remove-background-2QKJ7XOD.js → remove-background-REB7427G.js} +19 -19
  149. package/dist/{render-75E342ZU.js → render-3CVZ2SZG.js} +13 -12
  150. package/dist/{render-S73DW4KK.js → render-K25YOG3M.js} +22 -21
  151. package/dist/{render-2DVYTVLQ.js → render-TSE75QUL.js} +35 -35
  152. package/dist/{render-batch-YURBS54Q.js → render-batch-GGUOK3DS.js} +13 -12
  153. package/dist/{renderCancellation-373ASJTO.js → renderCancellation-PZRWB53I.js} +15 -15
  154. package/dist/renderSetupWorker.js +7 -7
  155. package/dist/{resolver-FE3GBZ4T.js → resolver-S5VK6UCB.js} +10 -9
  156. package/dist/{screenshotCapture-ECBTLCU6.js → screenshotCapture-TEUIWXWN.js} +53 -33
  157. package/dist/{sherpa-B2D3AGP6.js → sherpa-LVIUEAGF.js} +18 -18
  158. package/dist/skills/hyperframes-cli/references/cloud.md +1 -1
  159. package/dist/skills/hyperframes-cli/references/doctor-browser.md +24 -1
  160. package/dist/skills/media-use/references/grading.md +4 -2
  161. package/dist/skills/media-use/scripts/lib/cache.mjs +28 -14
  162. package/dist/skills/media-use/scripts/lib/cache.test.mjs +110 -0
  163. package/dist/skills/media-use/scripts/lib/duck.mjs +2 -1
  164. package/dist/skills/media-use/scripts/lib/duck.test.mjs +87 -0
  165. package/dist/skills/media-use/scripts/lib/probe.mjs +6 -1
  166. package/dist/skills/media-use/scripts/lib/probe.test.mjs +73 -0
  167. package/dist/skills/media-use/scripts/lib/words.mjs +1 -1
  168. package/dist/{skills-ICJ22CZZ.js → skills-I65FU5HD.js} +5 -5
  169. package/dist/{skillsUpdateCheck-GXZN56I5.js → skillsUpdateCheck-J57RNNIV.js} +3 -3
  170. package/dist/{slideshow-EJ4IMY6P.js → slideshow-4OJEPWNZ.js} +1 -1
  171. package/dist/{snapshot-XHKOAWF4.js → snapshot-YROOGY22.js} +42 -39
  172. package/dist/{src-I7UC3JTL.js → src-JO5JOV7Y.js} +16 -14
  173. package/dist/{src-74PFDTDX.js → src-X426BZAG.js} +17 -17
  174. package/dist/{staticProjectServer-2DGKD6TF.js → staticProjectServer-5VMBS262.js} +23 -23
  175. package/dist/{status-JA6SKQVH.js → status-LXPGSSKY.js} +6 -4
  176. package/dist/studio/assets/{hyperframes-player-5Vx2AiUz.js → hyperframes-player-BXSuksFh.js} +3 -3
  177. package/dist/studio/assets/{index-BAnh7cSQ.js → index-BgOVCqjo.js} +1 -1
  178. package/dist/studio/assets/{index-P8fgj_Xa.js → index-FgyO_5Kv.js} +1 -1
  179. package/dist/studio/assets/{index-C0thd4eM.js → index-J7jpL4pj.js} +157 -157
  180. package/dist/studio/index.html +1 -1
  181. package/dist/studio/index.js +148 -175
  182. package/dist/studio/index.js.map +1 -1
  183. package/dist/{studio-api-PROBO7JG.js → studio-api-VRBZUGAE.js} +22 -18
  184. package/dist/{studioServer-ID6UV2NE.js → studioServer-DBNKZ6I6.js} +50 -50
  185. package/dist/{synthesize-77PTU6C5.js → synthesize-C3IWDAXF.js} +2 -2
  186. package/dist/{telemetry-65LFHIWH.js → telemetry-CXAX3TO3.js} +3 -3
  187. package/dist/{timeline-6UV3JJXD.js → timeline-VQ34WH7J.js} +91 -70
  188. package/dist/{tokens-HIL4TZXI.js → tokens-62R7VFAZ.js} +4 -4
  189. package/dist/{transcribe-TIO6W3EQ.js → transcribe-7KR7IPJA.js} +18 -18
  190. package/dist/{transcribe-V7F6QDSN.js → transcribe-XOHPPL2O.js} +11 -11
  191. package/dist/{tts-TOHSPWEG.js → tts-MUV42JXT.js} +6 -6
  192. package/dist/{updateCheck-GZELANMA.js → updateCheck-POYNH3B5.js} +2 -2
  193. package/dist/{upgrade-BX3KDDZJ.js → upgrade-NBNOT7J2.js} +2 -2
  194. package/dist/{urlDownloader-R76OHFIE.js → urlDownloader-3NS63A7B.js} +14 -14
  195. package/dist/{validate-7UX4I443.js → validate-Y2QDHAEP.js} +40 -28
  196. package/dist/{video-RVGYEFQU.js → video-SJDMTSTL.js} +15 -15
  197. package/package.json +1 -1
  198. package/dist/chunk-24OWOBQH.js +0 -3656
  199. package/dist/chunk-SYKKFAUW.js +0 -3711
  200. /package/dist/{chunk-HBBJFK6I.js → chunk-APDLWWFG.js} +0 -0
@@ -11,12 +11,12 @@ import {
11
11
  iterateFontFamilyDeclarations,
12
12
  normalizeSystemFontPrimaryFamilies,
13
13
  resolveFontFamilyDeclarationFamilies
14
- } from "./chunk-7M4KAPAA.js";
14
+ } from "./chunk-PUGIRFPX.js";
15
15
  import {
16
16
  EncoderInterruptedError,
17
17
  encoderFailureError,
18
18
  prepareAnimatedGifInputs
19
- } from "./chunk-INI3TM6I.js";
19
+ } from "./chunk-KQLGTGE5.js";
20
20
  import {
21
21
  createStudioPositionSeekReapplyScript
22
22
  } from "./chunk-KC5XXX3X.js";
@@ -79,6 +79,7 @@ import {
79
79
  extractAllVideoFrames,
80
80
  extractAudioMetadata,
81
81
  extractMediaMetadata,
82
+ extractVideoFramesRange,
82
83
  extractionFrameCountForDuration,
83
84
  fetchPublicHttpsText,
84
85
  fingerprintElementId,
@@ -141,7 +142,7 @@ import {
141
142
  validateEngineConfigSnapshot,
142
143
  verifyDiskDrawElementSamples,
143
144
  writeCapturedFrame
144
- } from "./chunk-E6SDW5FV.js";
145
+ } from "./chunk-33RZPZ4K.js";
145
146
  import {
146
147
  assignBundledRuntimeCompositionIds,
147
148
  buildVariablesByCompScript,
@@ -151,7 +152,7 @@ import {
151
152
  ensureExternalScriptTag,
152
153
  inlineSubCompositions,
153
154
  prepareFlattenedInnerRoot
154
- } from "./chunk-35RSNI77.js";
155
+ } from "./chunk-F26LCYRY.js";
155
156
  import {
156
157
  LOW_MEMORY_TOTAL_MB_THRESHOLD,
157
158
  getCgroupMemoryLimitMb,
@@ -172,18 +173,7 @@ import {
172
173
  resolveAbsoluteMediaStartSeconds,
173
174
  resolveAuthoredTimingWindow,
174
175
  toFps
175
- } from "./chunk-6E6CM7WS.js";
176
- import {
177
- CANVAS_DIMENSIONS,
178
- HTML_BODY_CSS_HEIGHT_FIRST_RE,
179
- HTML_BODY_CSS_WIDTH_FIRST_RE,
180
- VALID_CANVAS_RESOLUTIONS,
181
- checkOutputResolutionCompatibility,
182
- extractMediaSrcMutations,
183
- isAspectAgnosticResolutionAlias,
184
- normalizeResolutionFlag,
185
- suggestMatchingPreset
186
- } from "./chunk-OZUQF4NB.js";
176
+ } from "./chunk-4M4EC7JX.js";
187
177
  import {
188
178
  COMPOSITION_SOURCE_URL,
189
179
  HF_COLOR_GRADING_ATTR,
@@ -210,10 +200,21 @@ import {
210
200
  shouldClampResolvedMediaDuration,
211
201
  sourceTimeAt,
212
202
  styleElementsFor
213
- } from "./chunk-SYKKFAUW.js";
203
+ } from "./chunk-6TPZSTCL.js";
214
204
  import {
215
205
  MAX_AUDIO_GAIN
216
206
  } from "./chunk-YA62XGXS.js";
207
+ import {
208
+ CANVAS_DIMENSIONS,
209
+ HTML_BODY_CSS_HEIGHT_FIRST_RE,
210
+ HTML_BODY_CSS_WIDTH_FIRST_RE,
211
+ VALID_CANVAS_RESOLUTIONS,
212
+ checkOutputResolutionCompatibility,
213
+ extractMediaSrcMutations,
214
+ isAspectAgnosticResolutionAlias,
215
+ normalizeResolutionFlag,
216
+ suggestMatchingPreset
217
+ } from "./chunk-MQZVBHEY.js";
217
218
  import {
218
219
  redactKnownPaths,
219
220
  redactTelemetryString
@@ -223,23 +224,26 @@ import {
223
224
  } from "./chunk-TWWSYAKJ.js";
224
225
  import {
225
226
  lintHyperframeHtml
226
- } from "./chunk-WY5OODN5.js";
227
+ } from "./chunk-XONFUK3M.js";
227
228
  import {
228
229
  isUnresolvedAssetPlaceholder,
229
230
  readProjectFile,
230
231
  resolveProjectRelativeSrc
231
- } from "./chunk-JFKL3WAE.js";
232
+ } from "./chunk-IWFLMU2N.js";
233
+ import {
234
+ checkSubCompositionUsability
235
+ } from "./chunk-3RM2ETQT.js";
232
236
  import {
233
237
  CSS_URL_RE,
234
- checkSubCompositionUsability,
238
+ decodedUrlPath,
235
239
  isNonRelativeUrl,
236
240
  rewriteAssetPaths,
237
241
  rewriteCssAssetUrls,
238
242
  rewriteInlineStyleAssetUrls
239
- } from "./chunk-TQFG7HTI.js";
243
+ } from "./chunk-ZLW2V65P.js";
240
244
  import {
241
245
  parseHTML
242
- } from "./chunk-GK4AIFIH.js";
246
+ } from "./chunk-SDYDNHEE.js";
243
247
  import {
244
248
  TRANSITIONS,
245
249
  convertTransfer,
@@ -5691,8 +5695,9 @@ async function resolveMediaDuration(src, mediaStart, playbackRate, baseDir, down
5691
5695
  } catch {
5692
5696
  return { duration: null, resolvedPath: src };
5693
5697
  }
5694
- } else if (!filePath.startsWith("/")) {
5695
- filePath = join12(baseDir, filePath);
5698
+ } else {
5699
+ filePath = decodedUrlPath(src);
5700
+ if (!filePath.startsWith("/")) filePath = join12(baseDir, filePath);
5696
5701
  }
5697
5702
  if (!existsSync9(filePath)) {
5698
5703
  return { duration: null, resolvedPath: filePath };
@@ -6493,7 +6498,7 @@ async function readLocalFont(absPath) {
6493
6498
  return { kind: "inline", buffer: Buffer.concat(chunks, totalBytes) };
6494
6499
  }
6495
6500
  async function embedLocalFontFaces(html, projectDir) {
6496
- const { fontToDataUri: toDataUri } = await import("./deterministicFonts-F6WIVL2W.js");
6501
+ const { fontToDataUri: toDataUri } = await import("./deterministicFonts-U2BIMGPG.js");
6497
6502
  const styleBlockRe = /<style\b[^>]*>([\s\S]*?)<\/style>/gi;
6498
6503
  const fontFaceRe = /@font-face\s*\{([^}]*)\}/gi;
6499
6504
  let result = html;
@@ -8029,7 +8034,8 @@ async function runExtractVideosStage(input) {
8029
8034
  composition,
8030
8035
  abortSignal,
8031
8036
  assertNotAborted,
8032
- materializeSymlinks
8037
+ materializeSymlinks,
8038
+ deferRangeExtraction
8033
8039
  } = input;
8034
8040
  const stage2Start = Date.now();
8035
8041
  const extractionPolicy = resolveVideoExtractionPolicy();
@@ -8118,7 +8124,8 @@ async function runExtractVideosStage(input) {
8118
8124
  toneMapHdrToSdr: job.config.hdrMode === "force-sdr",
8119
8125
  timelineEnd: composition.duration,
8120
8126
  maxTransientRetries: extractionPolicy.maxTransientRetries,
8121
- collectProbeFailures: extractionPolicy.failureMode === "enforce"
8127
+ collectProbeFailures: extractionPolicy.failureMode === "enforce",
8128
+ deferRangeExtraction
8122
8129
  },
8123
8130
  abortSignal,
8124
8131
  cfg,
@@ -14319,7 +14326,7 @@ function startServer(options = {}) {
14319
14326
  });
14320
14327
  async function shutdown(signal) {
14321
14328
  log.info(`Received ${signal}, shutting down`);
14322
- const { drainBrowserPool } = await import("./src-I7UC3JTL.js");
14329
+ const { drainBrowserPool } = await import("./src-JO5JOV7Y.js");
14323
14330
  await drainBrowserPool().catch(() => {
14324
14331
  });
14325
14332
  const handle = await Promise.race([
@@ -14355,8 +14362,17 @@ if (isPublicServerEntry) {
14355
14362
  }
14356
14363
 
14357
14364
  // ../producer/src/services/distributed/plan.ts
14358
- import { cpSync as cpSync2, existsSync as existsSync21, mkdirSync as mkdirSync11, renameSync as renameSync4, rmSync as rmSync10, writeFileSync as writeFileSync8 } from "fs";
14359
- import { join as join32, relative as relative6, sep as sep3 } from "path";
14365
+ import {
14366
+ copyFileSync as copyFileSync4,
14367
+ cpSync as cpSync2,
14368
+ existsSync as existsSync21,
14369
+ linkSync,
14370
+ mkdirSync as mkdirSync11,
14371
+ renameSync as renameSync4,
14372
+ rmSync as rmSync10,
14373
+ writeFileSync as writeFileSync8
14374
+ } from "fs";
14375
+ import { extname as extname5, isAbsolute as isAbsolute3, join as join32, relative as relative6, sep as sep3 } from "path";
14360
14376
 
14361
14377
  // ../producer/src/services/render/stages/freezePlan.ts
14362
14378
  import { existsSync as existsSync19, mkdirSync as mkdirSync10, readFileSync as readFileSync9, readdirSync as readdirSync6, writeFileSync as writeFileSync7 } from "fs";
@@ -14756,6 +14772,24 @@ function readNonNegativeInteger(value, field) {
14756
14772
  }
14757
14773
  return value;
14758
14774
  }
14775
+ function readDeferredFrameRange(value, field) {
14776
+ const range = readRecord(value, field);
14777
+ const sourcePath = readNonEmptyString(range.sourcePath, `${field}.sourcePath`);
14778
+ if (sourcePath.startsWith("/") || sourcePath.split(/[\\/]/).some((part) => part === "..")) {
14779
+ metadataError(`${field}.sourcePath`, "must stay inside the plan directory");
14780
+ }
14781
+ const durationSeconds = readFiniteNumber(range.durationSeconds, `${field}.durationSeconds`);
14782
+ if (durationSeconds <= 0) metadataError(`${field}.durationSeconds`, "must be positive");
14783
+ if (range.format !== "jpg" && range.format !== "png") {
14784
+ metadataError(`${field}.format`, 'must be "jpg" or "png"');
14785
+ }
14786
+ return {
14787
+ sourcePath,
14788
+ startTime: readFiniteNumber(range.startTime, `${field}.startTime`),
14789
+ durationSeconds,
14790
+ format: range.format
14791
+ };
14792
+ }
14759
14793
  function readRateSpec(value, field) {
14760
14794
  if (value === void 0) return void 0;
14761
14795
  if (typeof value === "number") return readFiniteNumber(value, field);
@@ -14824,7 +14858,8 @@ function parsePlanVideosJson(value) {
14824
14858
  framePattern: readNonEmptyString(entry.framePattern, `${field}.framePattern`),
14825
14859
  fps: readFiniteNumber(entry.fps, `${field}.fps`),
14826
14860
  totalFrames: readNonNegativeInteger(entry.totalFrames, `${field}.totalFrames`),
14827
- metadata: readVideoMetadata(entry.metadata, `${field}.metadata`)
14861
+ metadata: readVideoMetadata(entry.metadata, `${field}.metadata`),
14862
+ ...entry.deferredRange === void 0 ? {} : { deferredRange: readDeferredFrameRange(entry.deferredRange, `${field}.deferredRange`) }
14828
14863
  };
14829
14864
  });
14830
14865
  const videoIds = /* @__PURE__ */ new Set();
@@ -15329,6 +15364,39 @@ function resolveDistributedEngineConfig(config) {
15329
15364
  forceScreenshotExplicitlyOptedOut: true
15330
15365
  };
15331
15366
  }
15367
+ function pathInside(root, path) {
15368
+ const rel = relative6(root, path);
15369
+ return rel === "" || rel.startsWith("..") || isAbsolute3(rel) ? null : rel;
15370
+ }
15371
+ function createVideoSourceShipper(input) {
15372
+ const shipped = /* @__PURE__ */ new Map();
15373
+ return (srcPath) => {
15374
+ const known = shipped.get(srcPath);
15375
+ if (known) return known;
15376
+ const stagedRel = pathInside(input.workVideoFramesDir, srcPath);
15377
+ const current = stagedRel === null ? srcPath : join32(input.planDir, "video-frames", stagedRel);
15378
+ let result = null;
15379
+ for (const root of stagedRel === null ? [input.workCompiledDir, input.projectDir] : []) {
15380
+ const rel = pathInside(root, srcPath);
15381
+ if (rel !== null && existsSync21(join32(input.planDir, "compiled", rel))) {
15382
+ result = ["compiled", ...rel.split(sep3)].join("/");
15383
+ break;
15384
+ }
15385
+ }
15386
+ if (result === null) {
15387
+ result = `video-sources/${shipped.size}${extname5(current)}`;
15388
+ const destination = join32(input.planDir, ...result.split("/"));
15389
+ mkdirSync11(join32(input.planDir, "video-sources"), { recursive: true });
15390
+ try {
15391
+ linkSync(current, destination);
15392
+ } catch {
15393
+ copyFileSync4(current, destination);
15394
+ }
15395
+ }
15396
+ shipped.set(srcPath, result);
15397
+ return result;
15398
+ };
15399
+ }
15332
15400
  async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, options = {}) {
15333
15401
  const planDir = executionPlanDir;
15334
15402
  rejectUnsupportedDistributedFormat(config);
@@ -15442,7 +15510,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
15442
15510
  if (probeResult.fileServer) closeFileServerSafely(probeResult.fileServer, "plan", log);
15443
15511
  if (probeResult.probeSession) {
15444
15512
  try {
15445
- const { closeCaptureSession: closeCaptureSession2 } = await import("./src-I7UC3JTL.js");
15513
+ const { closeCaptureSession: closeCaptureSession2 } = await import("./src-JO5JOV7Y.js");
15446
15514
  await closeCaptureSession2(probeResult.probeSession);
15447
15515
  } catch (err) {
15448
15516
  log.warn("[plan] probe session close failed", {
@@ -15465,7 +15533,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
15465
15533
  composition,
15466
15534
  abortSignal,
15467
15535
  assertNotAborted,
15468
- materializeSymlinks: true
15536
+ materializeSymlinks: true,
15537
+ deferRangeExtraction: options.deferVideoExtraction
15469
15538
  });
15470
15539
  if (extractResult.failureToEnforce) throw extractResult.failureToEnforce;
15471
15540
  if (extractResult.extractionResult) {
@@ -15488,6 +15557,7 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
15488
15557
  const stagedVideoFrames = join32(compiledDir, "__hyperframes_video_frames");
15489
15558
  const videoFramesDst = join32(planDir, "video-frames");
15490
15559
  if (existsSync21(videoFramesDst)) rmSync10(videoFramesDst, { recursive: true, force: true });
15560
+ rmSync10(join32(planDir, "video-sources"), { recursive: true, force: true });
15491
15561
  if (existsSync21(stagedVideoFrames)) {
15492
15562
  renameSync4(stagedVideoFrames, videoFramesDst);
15493
15563
  } else {
@@ -15495,6 +15565,12 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
15495
15565
  }
15496
15566
  if (existsSync21(finalCompiledDir)) rmSync10(finalCompiledDir, { recursive: true, force: true });
15497
15567
  renameSync4(compiledDir, finalCompiledDir);
15568
+ const shipVideoSource = createVideoSourceShipper({
15569
+ planDir,
15570
+ projectDir,
15571
+ workCompiledDir: compiledDir,
15572
+ workVideoFramesDir: stagedVideoFrames
15573
+ });
15498
15574
  const planVideosJson = buildPlanVideosJson({
15499
15575
  videos: composition.videos,
15500
15576
  compositionEnd: job.duration ?? Number.NaN,
@@ -15504,7 +15580,8 @@ async function buildLocalExecutionPlan(projectDir, config, executionPlanDir, opt
15504
15580
  framePattern: ext.framePattern,
15505
15581
  fps: ext.fps,
15506
15582
  totalFrames: ext.totalFrames,
15507
- metadata: ext.metadata
15583
+ metadata: ext.metadata,
15584
+ ...ext.deferredRange ? { deferredRange: { ...ext.deferredRange, sourcePath: shipVideoSource(ext.srcPath) } } : {}
15508
15585
  }))
15509
15586
  });
15510
15587
  mkdirSync11(join32(planDir, "meta"), { recursive: true });
@@ -15624,7 +15701,7 @@ async function plan(projectDir, config, planDir) {
15624
15701
  // ../producer/src/services/distributed/planV2.ts
15625
15702
  import {
15626
15703
  closeSync as closeSync6,
15627
- copyFileSync as copyFileSync5,
15704
+ copyFileSync as copyFileSync6,
15628
15705
  existsSync as existsSync23,
15629
15706
  lstatSync as lstatSync3,
15630
15707
  mkdirSync as mkdirSync13,
@@ -15640,13 +15717,13 @@ import {
15640
15717
  } from "fs";
15641
15718
  import { createHash as createHash7 } from "crypto";
15642
15719
  import { tmpdir as tmpdir4 } from "os";
15643
- import { dirname as dirname14, isAbsolute as isAbsolute3, join as join35, relative as relative7, resolve as resolve10, sep as sep4 } from "path";
15720
+ import { dirname as dirname14, isAbsolute as isAbsolute4, join as join35, relative as relative7, resolve as resolve10, sep as sep4 } from "path";
15644
15721
 
15645
15722
  // ../producer/src/services/distributed/planV2Publisher.ts
15646
15723
  import {
15647
- copyFileSync as copyFileSync4,
15724
+ copyFileSync as copyFileSync5,
15648
15725
  existsSync as existsSync22,
15649
- linkSync,
15726
+ linkSync as linkSync2,
15650
15727
  mkdirSync as mkdirSync12,
15651
15728
  mkdtempSync as mkdtempSync5,
15652
15729
  renameSync as renameSync5,
@@ -15718,7 +15795,7 @@ var LocalPlanV2ArtifactPublisher = class {
15718
15795
  throw new PlanV2IntegrityError(`output directory already exists: ${destinationDir}`);
15719
15796
  }
15720
15797
  this.destinationDir = destinationDir;
15721
- this.#linkFile = options.linkFile ?? linkSync;
15798
+ this.#linkFile = options.linkFile ?? linkSync2;
15722
15799
  mkdirSync12(dirname13(destinationDir), { recursive: true });
15723
15800
  this.temporaryDir = mkdtempSync5(join34(dirname13(destinationDir), ".plan-v2-publish-"));
15724
15801
  }
@@ -15740,7 +15817,7 @@ var LocalPlanV2ArtifactPublisher = class {
15740
15817
  this.#linkFile(blob.sourcePath, temporaryPath);
15741
15818
  } catch (error) {
15742
15819
  if (!canFallbackToCopy(error)) throw error;
15743
- copyFileSync4(blob.sourcePath, temporaryPath);
15820
+ copyFileSync5(blob.sourcePath, temporaryPath);
15744
15821
  }
15745
15822
  renameSync5(temporaryPath, destinationPath);
15746
15823
  } finally {
@@ -15791,7 +15868,7 @@ function readJsonFile(path, label) {
15791
15868
  }
15792
15869
  function assertSafeRelativePath(path) {
15793
15870
  const normalized = path.split(/[\\/]+/);
15794
- if (path.length === 0 || isAbsolute3(path) || normalized.some((part) => part === "" || part === "." || part === "..")) {
15871
+ if (path.length === 0 || isAbsolute4(path) || normalized.some((part) => part === "" || part === "." || part === "..")) {
15795
15872
  throw new PlanV2IntegrityError(`unsafe artifact path: ${JSON.stringify(path)}`);
15796
15873
  }
15797
15874
  }
@@ -15873,7 +15950,7 @@ function artifactTargets(path, videoDependencies) {
15873
15950
  if (path === "meta/composition.json" || path === "meta/videos.json" || path.startsWith("compiled/")) {
15874
15951
  return { chunks: "all", assembler: false };
15875
15952
  }
15876
- if (path.startsWith("video-frames/")) {
15953
+ if (path.startsWith("video-frames/") || path.startsWith("video-sources/")) {
15877
15954
  return {
15878
15955
  chunks: videoDependencies === null ? "all" : videoDependencies.get(path) ?? [],
15879
15956
  assembler: false
@@ -15884,6 +15961,13 @@ function artifactTargets(path, videoDependencies) {
15884
15961
  function listVideoFramePaths(executionPlanDir, videos) {
15885
15962
  return videos.extracted.map((video) => {
15886
15963
  const outputDir = resolveExtractedVideoOutputDir(executionPlanDir, video.videoId);
15964
+ if (video.deferredRange) {
15965
+ const framePaths2 = /* @__PURE__ */ new Map();
15966
+ for (let index = 0; index < video.totalFrames; index++) {
15967
+ framePaths2.set(index, join35(outputDir, String(index)));
15968
+ }
15969
+ return { ...video, outputDir, framePaths: framePaths2, ownedByLookup: false };
15970
+ }
15887
15971
  const frameNames = readdirSync8(outputDir).sort();
15888
15972
  const framePaths = /* @__PURE__ */ new Map();
15889
15973
  for (const frameName of frameNames) {
@@ -15976,12 +16060,31 @@ function buildVideoChunkDependencies(executionPlanDir, dimensions) {
15976
16060
  extracted,
15977
16061
  resolveRenderFpsConfig({ num: fpsNum, den: fpsDen }).value
15978
16062
  );
16063
+ const deferredSources = new Map(
16064
+ parsedVideos.extracted.flatMap(
16065
+ (video) => video.deferredRange ? [[video.videoId, video.deferredRange.sourcePath]] : []
16066
+ )
16067
+ );
16068
+ const dependencies = collectChunkVideoDependencies({
16069
+ executionPlanDir,
16070
+ table,
16071
+ chunks: parsedChunks,
16072
+ fpsNum,
16073
+ fpsDen,
16074
+ deferredSources
16075
+ });
16076
+ return {
16077
+ mode: deferredSources.size > 0 ? "source-extract" : "exact-rendered-frames",
16078
+ dependencies
16079
+ };
16080
+ }
16081
+ function collectChunkVideoDependencies(input) {
15979
16082
  const mutable = /* @__PURE__ */ new Map();
15980
- for (const chunk of parsedChunks) {
16083
+ for (const chunk of input.chunks) {
15981
16084
  for (let frame = chunk.startFrame; frame < chunk.endFrame; frame++) {
15982
- const globalTime = frame * fpsDen / fpsNum;
15983
- for (const payload of table.getActiveFramePayloads(globalTime).values()) {
15984
- const path = relative7(resolve10(executionPlanDir), payload.framePath).split(sep4).join("/");
16085
+ const globalTime = frame * input.fpsDen / input.fpsNum;
16086
+ for (const [videoId, payload] of input.table.getActiveFramePayloads(globalTime)) {
16087
+ const path = input.deferredSources.get(videoId) ?? relative7(resolve10(input.executionPlanDir), payload.framePath).split(sep4).join("/");
15985
16088
  assertSafeRelativePath(path);
15986
16089
  const indexes = mutable.get(path) ?? /* @__PURE__ */ new Set();
15987
16090
  indexes.add(chunk.index);
@@ -15989,12 +16092,7 @@ function buildVideoChunkDependencies(executionPlanDir, dimensions) {
15989
16092
  }
15990
16093
  }
15991
16094
  }
15992
- return {
15993
- mode: "exact-rendered-frames",
15994
- dependencies: new Map(
15995
- [...mutable].map(([path, indexes]) => [path, [...indexes].sort((a, b) => a - b)])
15996
- )
15997
- };
16095
+ return new Map([...mutable].map(([path, indexes]) => [path, [...indexes].sort((a, b) => a - b)]));
15998
16096
  }
15999
16097
  function manifestPayload(manifest) {
16000
16098
  return manifest;
@@ -16008,7 +16106,7 @@ function writeBlob(sourcePath, destinationPath) {
16008
16106
  const temporaryDir = mkdtempSync6(join35(dirname14(destinationPath), ".plan-v2-blob-"));
16009
16107
  const temporaryPath = join35(temporaryDir, "blob");
16010
16108
  try {
16011
- copyFileSync5(sourcePath, temporaryPath);
16109
+ copyFileSync6(sourcePath, temporaryPath);
16012
16110
  renameSync6(temporaryPath, destinationPath);
16013
16111
  } finally {
16014
16112
  rmSync12(temporaryDir, { recursive: true, force: true });
@@ -16046,7 +16144,7 @@ function buildPlanV2Publication(executionPlanDir) {
16046
16144
  for (const file of listFiles(executionPlanDir)) {
16047
16145
  if (isExtractionCacheCompleteSentinelPath(file.path)) continue;
16048
16146
  const targets = artifactTargets(file.path, videoDependencyPlan.dependencies);
16049
- if (file.path.startsWith("video-frames/") && targets.chunks !== "all" && targets.chunks.length === 0 && !targets.assembler) {
16147
+ if ((file.path.startsWith("video-frames/") || file.path.startsWith("video-sources/")) && targets.chunks !== "all" && targets.chunks.length === 0 && !targets.assembler) {
16050
16148
  continue;
16051
16149
  }
16052
16150
  const sha256 = sha256File(file.absolutePath);
@@ -16114,14 +16212,21 @@ function createPlanV2FromV1(executionPlanDir, planV2Dir) {
16114
16212
  async function publishPlanV2FromExecutionPlan(executionPlanDir, publisher) {
16115
16213
  try {
16116
16214
  const publication = buildPlanV2Publication(executionPlanDir);
16117
- const concurrency = 16;
16118
- for (let offset = 0; offset < publication.blobs.length; offset += concurrency) {
16119
- const batch = publication.blobs.slice(offset, offset + concurrency);
16120
- const results = await Promise.allSettled(batch.map((blob) => publisher.putBlob(blob)));
16121
- for (const result of results) {
16122
- if (result.status === "rejected") throw result.reason;
16215
+ const uploadSlots = 32;
16216
+ let next = 0;
16217
+ let failure;
16218
+ const upload = async () => {
16219
+ while (!failure && next < publication.blobs.length) {
16220
+ const blob = publication.blobs[next++];
16221
+ try {
16222
+ await publisher.putBlob(blob);
16223
+ } catch (reason) {
16224
+ failure ??= { reason };
16225
+ }
16123
16226
  }
16124
- }
16227
+ };
16228
+ await Promise.all(Array.from({ length: uploadSlots }, upload));
16229
+ if (failure) throw failure.reason;
16125
16230
  await publisher.commitManifest(canonicalJsonStringify(publication.manifest));
16126
16231
  return publication.manifest;
16127
16232
  } catch (error) {
@@ -16139,7 +16244,8 @@ async function planV2WithPublisher(projectDir, config, publisher, options = {})
16139
16244
  const stagingRoot = mkdtempSync6(join35(options.stagingParentDir ?? tmpdir4(), ".execution-plan-"));
16140
16245
  try {
16141
16246
  await buildLocalExecutionPlan(projectDir, config, stagingRoot, {
16142
- executionPlanSizeLimitBytes: Number.MAX_SAFE_INTEGER
16247
+ executionPlanSizeLimitBytes: Number.MAX_SAFE_INTEGER,
16248
+ deferVideoExtraction: true
16143
16249
  });
16144
16250
  return await publishPlanV2FromExecutionPlan(stagingRoot, publisher);
16145
16251
  } catch (error) {
@@ -16268,7 +16374,7 @@ function parsePlanV2Manifest(value) {
16268
16374
  }
16269
16375
  if (!paths.has("plan.json"))
16270
16376
  throw new PlanV2IntegrityError("manifest must include the local execution plan.json artifact");
16271
- if (!isRecord3(value.limitations) || value.limitations.videoDependencyMode !== "exact-rendered-frames" && value.limitations.videoDependencyMode !== "full-source-pack") {
16377
+ if (!isRecord3(value.limitations) || value.limitations.videoDependencyMode !== "exact-rendered-frames" && value.limitations.videoDependencyMode !== "full-source-pack" && value.limitations.videoDependencyMode !== "source-extract") {
16272
16378
  throw new PlanV2IntegrityError("unsupported video dependency mode");
16273
16379
  }
16274
16380
  const parsed = {
@@ -16348,7 +16454,7 @@ function materializePlanV2Target(planV2Dir, target, destinationDir) {
16348
16454
  for (const { artifact, sourcePath } of verified) {
16349
16455
  const destinationPath = join35(tempDir, ...artifact.path.split("/"));
16350
16456
  mkdirSync13(dirname14(destinationPath), { recursive: true });
16351
- copyFileSync5(sourcePath, destinationPath);
16457
+ copyFileSync6(sourcePath, destinationPath);
16352
16458
  }
16353
16459
  if (target.role === "chunk") materializeExtractedVideoDirectories(tempDir);
16354
16460
  writeFileSync10(
@@ -16662,7 +16768,7 @@ function mergePngFrameDirs(chunkPaths, outputPath, totalFrames, audioPath, start
16662
16768
  // ../producer/src/services/distributed/renderChunk.ts
16663
16769
  import { randomBytes } from "crypto";
16664
16770
  import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync13, readdirSync as readdirSync10, rmSync as rmSync14, writeFileSync as writeFileSync12 } from "fs";
16665
- import { extname as extname5, join as join37 } from "path";
16771
+ import { extname as extname6, join as join37 } from "path";
16666
16772
  var FFMPEG_VERSION_MISMATCH = "FFMPEG_VERSION_MISMATCH";
16667
16773
  var PLAN_HASH_MISMATCH = "PLAN_HASH_MISMATCH";
16668
16774
  var MISSING_PLAN_ARTIFACT = "MISSING_PLAN_ARTIFACT";
@@ -16757,7 +16863,7 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v
16757
16863
  `[renderChunk] planDir missing extracted video frames for ${JSON.stringify(v.videoId)}: ${outputDir} not present. plan() should have written frames here; the planDir is malformed.`
16758
16864
  );
16759
16865
  }
16760
- const ext = (extname5(v.framePattern) || ".jpg").toLowerCase();
16866
+ const ext = (extname6(v.framePattern) || ".jpg").toLowerCase();
16761
16867
  const frames = readdirSync10(outputDir).filter((name) => name.toLowerCase().endsWith(ext)).sort((left, right) => {
16762
16868
  const leftNumber = frameNumberFromFileName(left);
16763
16869
  const rightNumber = frameNumberFromFileName(right);
@@ -16791,6 +16897,76 @@ function rebuildExtractedFramesFromPlanDir(planDir, videos, indexMode = "dense-v
16791
16897
  }
16792
16898
  return result;
16793
16899
  }
16900
+ function contiguousRuns(sortedIndexes) {
16901
+ const runs = [];
16902
+ for (const index of sortedIndexes) {
16903
+ const last = runs[runs.length - 1];
16904
+ if (last && last.firstFrame + last.frames === index) last.frames++;
16905
+ else runs.push({ firstFrame: index, frames: 1 });
16906
+ }
16907
+ return runs;
16908
+ }
16909
+ async function extractDeferredVideoFramesForChunk(input) {
16910
+ const deferred = input.planVideos.extracted.filter((video) => video.deferredRange);
16911
+ if (deferred.length === 0) return [];
16912
+ const table = createFrameLookupTable(
16913
+ input.planVideos.videos,
16914
+ deferred.map((video) => ({
16915
+ ...video,
16916
+ outputDir: input.outputRoot,
16917
+ framePaths: new Map(Array.from({ length: video.totalFrames }, (_, i) => [i, String(i)]))
16918
+ })),
16919
+ resolveRenderFpsConfig(input.fps).value
16920
+ );
16921
+ const shown = /* @__PURE__ */ new Map();
16922
+ for (let frame = input.slice.startFrame; frame < input.slice.endFrame; frame++) {
16923
+ const globalTime = frame * input.fps.den / input.fps.num;
16924
+ for (const [videoId, payload] of table.getActiveFramePayloads(globalTime)) {
16925
+ const indexes = shown.get(videoId) ?? /* @__PURE__ */ new Set();
16926
+ indexes.add(payload.frameIndex);
16927
+ shown.set(videoId, indexes);
16928
+ }
16929
+ }
16930
+ return Promise.all(
16931
+ deferred.map(async (video) => {
16932
+ const outputDir = join37(input.outputRoot, video.videoId);
16933
+ const indexes = [...shown.get(video.videoId) ?? []].sort((a, b) => a - b);
16934
+ if (indexes.length === 0) {
16935
+ return { ...video, outputDir, framePaths: /* @__PURE__ */ new Map(), ownedByLookup: false };
16936
+ }
16937
+ const range = video.deferredRange;
16938
+ const sourcePath = join37(input.planDir, ...range.sourcePath.split("/"));
16939
+ if (!existsSync25(sourcePath)) {
16940
+ throw new RenderChunkValidationError(
16941
+ MISSING_PLAN_ARTIFACT,
16942
+ `[renderChunk] planDir is missing the source for video ${JSON.stringify(video.videoId)}: ${range.sourcePath}`
16943
+ );
16944
+ }
16945
+ const extracted = await extractVideoFramesRange(
16946
+ sourcePath,
16947
+ video.videoId,
16948
+ range.startTime,
16949
+ range.durationSeconds,
16950
+ {
16951
+ fps: input.fps,
16952
+ outputDir: input.outputRoot,
16953
+ format: range.format,
16954
+ frameRanges: contiguousRuns(indexes)
16955
+ },
16956
+ void 0,
16957
+ input.cfg
16958
+ );
16959
+ const missing = indexes.find((index) => !extracted.framePaths.has(index));
16960
+ if (missing !== void 0) {
16961
+ throw new RenderChunkValidationError(
16962
+ INVALID_VIDEO_METADATA,
16963
+ `[renderChunk] video ${JSON.stringify(video.videoId)} has no frame ${missing}; the plan expected ${video.totalFrames} frames from ${range.sourcePath}.`
16964
+ );
16965
+ }
16966
+ return { ...video, outputDir, framePaths: extracted.framePaths, ownedByLookup: false };
16967
+ })
16968
+ );
16969
+ }
16794
16970
  function hashChunkOutput(outputPath, kind) {
16795
16971
  if (kind === "file") return sha256Hex(readFileSync13(outputPath));
16796
16972
  const entries = readdirSync10(outputPath).filter((name) => /\.(png|jpg|jpeg)$/i.test(name)).sort();
@@ -16924,23 +17100,34 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
16924
17100
  // the software-GPU clamp so buildChromeArgs includes BeginFrameControl.
16925
17101
  forceScreenshotExplicitlyOptedOut: !encoder.forceScreenshot
16926
17102
  };
17103
+ const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes(4).toString("hex")}`;
17104
+ mkdirSync15(workDir, { recursive: true });
17105
+ const framesDir = join37(workDir, "captured-frames");
17106
+ mkdirSync15(framesDir, { recursive: true });
17107
+ const videoFramesDir = `${workDir}.video-frames`;
16927
17108
  const videoFrameLookup = planVideos && planVideos.extracted.length > 0 ? createFrameLookupTable(
16928
17109
  planVideos.videos,
16929
- rebuildExtractedFramesFromPlanDir(
16930
- planDir,
16931
- planVideos.extracted,
16932
- v2Manifest === null ? "dense-v1" : "sparse-v2"
16933
- ),
17110
+ [
17111
+ ...rebuildExtractedFramesFromPlanDir(
17112
+ planDir,
17113
+ planVideos.extracted.filter((video) => !video.deferredRange),
17114
+ v2Manifest === null ? "dense-v1" : "sparse-v2"
17115
+ ),
17116
+ ...await extractDeferredVideoFramesForChunk({
17117
+ planDir,
17118
+ planVideos,
17119
+ slice,
17120
+ fps: { num: plan2.dimensions.fpsNum, den: plan2.dimensions.fpsDen },
17121
+ outputRoot: videoFramesDir,
17122
+ cfg
17123
+ })
17124
+ ],
16934
17125
  resolveRenderFpsConfig(job.config.fps).value
16935
17126
  ) : null;
16936
17127
  const createChunkVideoFrameInjector = createChunkVideoFrameInjectorFactory(videoFrameLookup);
16937
17128
  const videoCaptureBeyondViewport = resolveVideoCaptureBeyondViewport(
16938
17129
  planVideos?.videos.length ?? 0
16939
17130
  );
16940
- const workDir = `${outputChunkPath}.work.${process.pid}.${randomBytes(4).toString("hex")}`;
16941
- mkdirSync15(workDir, { recursive: true });
16942
- const framesDir = join37(workDir, "captured-frames");
16943
- mkdirSync15(framesDir, { recursive: true });
16944
17131
  const fileServer = await createFileServer({
16945
17132
  projectDir: compiledDir,
16946
17133
  compiledDir,
@@ -17217,6 +17404,7 @@ async function renderChunk(planDir, chunkIndex, outputChunkPath) {
17217
17404
  `, "utf-8");
17218
17405
  try {
17219
17406
  rmSync14(workDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
17407
+ rmSync14(videoFramesDir, { recursive: true, force: true, maxRetries: 3, retryDelay: 100 });
17220
17408
  } catch (err) {
17221
17409
  log.warn("[renderChunk] failed to remove work dir", {
17222
17410
  workDir,