hyperframes 0.8.110 → 0.8.112

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 (182) hide show
  1. package/dist/{add-D7AY7MSS.js → add-NIVC2YMT.js} +15 -15
  2. package/dist/{agentPromptGenerator-QL2KAWEP.js → agentPromptGenerator-VIIPZCJ3.js} +1 -1
  3. package/dist/{animatedGifPrep-NMGFOSIL.js → animatedGifPrep-NWAJKCHG.js} +6 -6
  4. package/dist/{asset-63Q4ARX7.js → asset-O6JJKF3Z.js} +2 -2
  5. package/dist/{assetCataloger-FXEHOUA3.js → assetCataloger-DJSPW3RL.js} +2 -2
  6. package/dist/{auth-D5QNNEKM.js → auth-6XRZQQQS.js} +2 -2
  7. package/dist/{autoUpdate-25QUBTDS.js → autoUpdate-GZHLQBLS.js} +2 -2
  8. package/dist/{backgroundChecks-G2AHVDCY.js → backgroundChecks-4QQRGJ5S.js} +3 -3
  9. package/dist/backgroundChecksWorker.js +3 -3
  10. package/dist/{batchRender-ZTHFMHZY.js → batchRender-PJGNXN7F.js} +3 -3
  11. package/dist/{beats-43LEYJ76.js → beats-VYR6B4UB.js} +10 -10
  12. package/dist/{benchmark-JQ5LYY6Z.js → benchmark-CGP2NKIP.js} +12 -12
  13. package/dist/{browser-KQLNYNOH.js → browser-ZWD4ETXK.js} +9 -9
  14. package/dist/{bundleWithLocalizedFonts-4Q3ETTHW.js → bundleWithLocalizedFonts-JWHKLSZM.js} +2 -2
  15. package/dist/{capture-4OPH4PMK.js → capture-C4MPRLJV.js} +40 -42
  16. package/dist/{capture-OG6532RA.js → capture-IQ7AUK6M.js} +3 -3
  17. package/dist/{captureFile-JOPOCRU7.js → captureFile-LYOJOUIE.js} +3 -1
  18. package/dist/{catalog-EAFDIYFH.js → catalog-RZ7PWQMS.js} +15 -15
  19. package/dist/{check-VAJ6G3RU.js → check-7UU4SSO6.js} +50 -38
  20. package/dist/{checkBrowser-GUWLYPVJ.js → checkBrowser-6KYNYIU7.js} +32 -31
  21. package/dist/{chunk-CFC3EEDQ.js → chunk-2BEOCUAG.js} +1 -1
  22. package/dist/{chunk-E5OSOQKO.js → chunk-2GXKCB7J.js} +1 -1
  23. package/dist/{chunk-HQGJLZB6.js → chunk-36XLW2TP.js} +2 -2
  24. package/dist/{chunk-NH75EKOP.js → chunk-3Q7HXIXZ.js} +1 -1
  25. package/dist/{chunk-2JXJ5SGK.js → chunk-4BXTKKRD.js} +6 -6
  26. package/dist/{chunk-XYVFPDNU.js → chunk-5SDXALUQ.js} +1 -1
  27. package/dist/{chunk-ITBEN3QD.js → chunk-7G25WGTA.js} +2 -2
  28. package/dist/{chunk-YIXEH4TF.js → chunk-7OJSZTJK.js} +2 -2
  29. package/dist/{chunk-5ER3PYYP.js → chunk-7VIXEM6Q.js} +1 -1
  30. package/dist/{chunk-U4U5YVVX.js → chunk-A6GVXZZ3.js} +1 -1
  31. package/dist/{chunk-ULNKBH6B.js → chunk-BD3MHTSR.js} +2 -2
  32. package/dist/{chunk-TU7KYFS3.js → chunk-BLI5XATY.js} +1 -1
  33. package/dist/{chunk-N32ITJ7L.js → chunk-BSBIG74E.js} +15 -12
  34. package/dist/{chunk-ZU54D6MI.js → chunk-BZGWHPRW.js} +3 -3
  35. package/dist/{chunk-B25H4M4V.js → chunk-C4JINRJK.js} +1 -1
  36. package/dist/{chunk-5ON5GH3X.js → chunk-CS4IE5G7.js} +1 -1
  37. package/dist/{chunk-47TRZ6A3.js → chunk-E664L6K3.js} +3 -3
  38. package/dist/{chunk-J4RPT4QW.js → chunk-E6RPWJVC.js} +1 -1
  39. package/dist/{chunk-GLSGKTFO.js → chunk-EA4LCCJI.js} +5 -5
  40. package/dist/{chunk-E67OVYX3.js → chunk-GODQ5XA4.js} +16 -8
  41. package/dist/{chunk-LAQEZHOH.js → chunk-H3WFEPV2.js} +1 -1
  42. package/dist/{chunk-U4TDAJZE.js → chunk-J2S4MY2M.js} +2 -2
  43. package/dist/{chunk-CQRF7VU3.js → chunk-JRULOVZK.js} +1 -1
  44. package/dist/{chunk-C4TZBEHY.js → chunk-KIIKVKHB.js} +2 -2
  45. package/dist/{chunk-M224DAMG.js → chunk-KPSRL2NB.js} +1 -1
  46. package/dist/{chunk-JTTAS7N6.js → chunk-KQ3VNA6R.js} +1 -1
  47. package/dist/{chunk-MPSW7EA2.js → chunk-KS5HFREQ.js} +4 -4
  48. package/dist/{chunk-L37M3PV5.js → chunk-LYBFDHXD.js} +3 -3
  49. package/dist/{chunk-AWUZ3AUD.js → chunk-M4RYK5OF.js} +1 -1
  50. package/dist/chunk-MRF4AMKD.js +104 -0
  51. package/dist/{chunk-JWPSBANO.js → chunk-NOOBRCMC.js} +3 -3
  52. package/dist/{chunk-TIZQC44K.js → chunk-OWN3ZIIK.js} +1 -1
  53. package/dist/{chunk-WTMGUNZZ.js → chunk-OXZO4WQI.js} +9 -8
  54. package/dist/{chunk-PZXUDWPP.js → chunk-P3AQVFY2.js} +3 -3
  55. package/dist/{chunk-OF3RKOPU.js → chunk-P74PW7KR.js} +189 -111
  56. package/dist/{chunk-TQP42SFX.js → chunk-POEGJGEA.js} +1 -1
  57. package/dist/{chunk-X4FEFEP4.js → chunk-PRETPA7Z.js} +1 -1
  58. package/dist/{chunk-QJUKISYK.js → chunk-Q7U7QRC7.js} +2 -2
  59. package/dist/chunk-S6TH5G6Z.js +3541 -0
  60. package/dist/{chunk-MGFVNTIB.js → chunk-TSZU5JMC.js} +2 -2
  61. package/dist/{chunk-MR2LOG32.js → chunk-TXVN43SX.js} +8 -8
  62. package/dist/{chunk-T3HJWJGC.js → chunk-UTXMQVB2.js} +9 -9
  63. package/dist/{chunk-I5WWEBDG.js → chunk-VHRHI3CU.js} +1 -1
  64. package/dist/{chunk-E4AYSXMS.js → chunk-VW6CVKVA.js} +2 -2
  65. package/dist/{chunk-BAVM2XBR.js → chunk-YAFO7V4A.js} +209 -33
  66. package/dist/{chunk-32P7FTFC.js → chunk-YQ5MFXWG.js} +8 -7
  67. package/dist/{clean-CXX7YDBQ.js → clean-263PH5CR.js} +15 -15
  68. package/dist/cli.js +50 -50
  69. package/dist/{cloud-KRQQC5AH.js → cloud-STLYEQNN.js} +4 -4
  70. package/dist/{cloudrun-LVZ4OPPC.js → cloudrun-7ZVNB6FY.js} +3 -3
  71. package/dist/commands/layout-audit.browser.js +178 -202
  72. package/dist/commands/motion-sample.browser.js +24 -71
  73. package/dist/commands/motion-signature.browser.js +374 -0
  74. package/dist/{compare-7MMDDERQ.js → compare-33JLJ52D.js} +26 -26
  75. package/dist/{compiler-C32VXLE2.js → compiler-H3QAMMC2.js} +3 -3
  76. package/dist/{component-U57T4J2P.js → component-O5JLM26B.js} +3 -3
  77. package/dist/{compositions-HG7JA7I4.js → compositions-CN4ZVT5G.js} +11 -11
  78. package/dist/{contactSheet-54AJDSR5.js → contactSheet-27SRU7A4.js} +2 -2
  79. package/dist/{delete-HXXHYTH2.js → delete-Z23A45R3.js} +2 -2
  80. package/dist/{deploy-4T3RMA5G.js → deploy-PJLSZMUH.js} +1 -1
  81. package/dist/{destroy-EYDBVHGF.js → destroy-IPUDK6YN.js} +1 -1
  82. package/dist/{dist-YUIPB7OX.js → dist-7VEVT4NT.js} +2 -2
  83. package/dist/{dist-FMHQMEMX.js → dist-ICXYT7XK.js} +1 -1
  84. package/dist/docker/Dockerfile.render +1 -1
  85. package/dist/{doctor-GKF42LFK.js → doctor-6QLXSGPK.js} +10 -10
  86. package/dist/{events-5E4LWTM3.js → events-EAAIWITP.js} +8 -8
  87. package/dist/{events-LGPPK5FN.js → events-UA4DJUO2.js} +9 -9
  88. package/dist/{feedback-53ZU2MPJ.js → feedback-2CIRCBHY.js} +10 -10
  89. package/dist/{figma-S4LBKUIF.js → figma-DFCCII66.js} +3 -3
  90. package/dist/fontLocalizeCli.js +8 -8
  91. package/dist/{get-ELQOB66I.js → get-UQ2AAXWM.js} +2 -2
  92. package/dist/{gpuPolicy-CA6KRFQQ.js → gpuPolicy-CPCLBMS5.js} +6 -6
  93. package/dist/{grade-compare-6BDBN6IQ.js → grade-compare-THUUFHO3.js} +24 -24
  94. package/dist/{help-JNBSADTC.js → help-SR2MRL3U.js} +1 -1
  95. package/dist/{history-TY3SEJWV.js → history-WLI7KFXB.js} +15 -15
  96. package/dist/hyperframe-runtime.js +49 -49
  97. package/dist/hyperframe.manifest.json +1 -1
  98. package/dist/hyperframe.runtime.iife.js +49 -49
  99. package/dist/hyperframes-player.global.js +1 -1
  100. package/dist/{info-QG6XUPA4.js → info-DFJM3YRJ.js} +11 -11
  101. package/dist/{init-RZF2YCRD.js → init-HEAMOTGH.js} +22 -22
  102. package/dist/{inspect-HYINM6BQ.js → inspect-TO2EXJNK.js} +25 -25
  103. package/dist/{installer-NBEN3ZIP.js → installer-REA7ZASD.js} +4 -4
  104. package/dist/{keyframes-VCVFJTYP.js → keyframes-XHEBAJY7.js} +12 -12
  105. package/dist/{lambda-BFHJMMCG.js → lambda-MSWYKDNT.js} +6 -6
  106. package/dist/{layout-GGRQADMQ.js → layout-UQXCTFFV.js} +25 -25
  107. package/dist/{lint-ZBMSFLOK.js → lint-BSMZ526C.js} +12 -12
  108. package/dist/{lintProject-X7L7EZWZ.js → lintProject-VNE322A7.js} +1 -1
  109. package/dist/{list-ZKWCM7JT.js → list-RNP5EMTX.js} +2 -2
  110. package/dist/{login-CZ4DAMX2.js → login-S6V75HG5.js} +4 -4
  111. package/dist/{media-treatment-65KBTTDZ.js → media-treatment-IHEEEDUQ.js} +15 -14
  112. package/dist/{models-RILNQV3Z.js → models-OQEBKNJI.js} +7 -7
  113. package/dist/{motionShot-5F4DCMWC.js → motionShot-EAIFVJ2I.js} +10 -10
  114. package/dist/{normalize-audio-SEAAEJRQ.js → normalize-audio-4ACUR6W6.js} +11 -11
  115. package/dist/{pipeline-5UY45ELH.js → pipeline-SOQHD5YN.js} +6 -6
  116. package/dist/{play-BIKUK4NL.js → play-3WJPS3FE.js} +20 -20
  117. package/dist/{preflight-3V5IHGWQ.js → preflight-ZUADCOLZ.js} +7 -7
  118. package/dist/{present-UAM37S3Z.js → present-MU23WZZA.js} +16 -16
  119. package/dist/{preview-TVU4J6VE.js → preview-VOTNRX67.js} +17 -17
  120. package/dist/{producer-7JGAPEAF.js → producer-HKRMTCPU.js} +1 -1
  121. package/dist/{projectConfig-JHEWPAA5.js → projectConfig-H37MQGE6.js} +6 -6
  122. package/dist/{publication-7XA2H7UB.js → publication-QVDKMAKD.js} +2 -2
  123. package/dist/{publish-257VZMWI.js → publish-54IPKU5O.js} +8 -8
  124. package/dist/{remove-background-EV6XVADN.js → remove-background-KQQ2WPKP.js} +7 -7
  125. package/dist/{render-QZD733OT.js → render-HJQ44SEI.js} +12 -12
  126. package/dist/{render-B66XOY6B.js → render-P7727PLY.js} +21 -21
  127. package/dist/{render-4C3YKVZI.js → render-S2T3SLI4.js} +3 -3
  128. package/dist/{render-batch-AFDBPDMM.js → render-batch-DUFAHD6F.js} +3 -3
  129. package/dist/{renderCancellation-VIZELWDD.js → renderCancellation-BSVXXGZM.js} +6 -6
  130. package/dist/renderSetupWorker.js +1 -1
  131. package/dist/{resolver-S72XBTEQ.js → resolver-PHWKDEH2.js} +4 -4
  132. package/dist/{screenshotCapture-FA5HPN7Q.js → screenshotCapture-ECBTLCU6.js} +3 -3
  133. package/dist/{sherpa-BAADWCHB.js → sherpa-GHQOWXFV.js} +7 -7
  134. package/dist/skills/hyperframes/references/frame-worker-core.md +2 -2
  135. package/dist/skills/hyperframes-cli/references/lint-validate-inspect.md +2 -2
  136. package/dist/skills/media-use/audio/references/bgm.md +1 -1
  137. package/dist/skills/media-use/audio/references/tts.md +1 -1
  138. package/dist/skills/media-use/audio/scripts/lib/python.mjs +19 -5
  139. package/dist/skills/media-use/audio/scripts/lib/python.test.mjs +69 -1
  140. package/dist/{skills-AB55WOXL.js → skills-SOCMD66Y.js} +40 -14
  141. package/dist/{skillsUpdateCheck-VRABW6UL.js → skillsUpdateCheck-PONPICQM.js} +3 -3
  142. package/dist/{snapshot-STEHSXMQ.js → snapshot-ECXEZ4TY.js} +50 -29
  143. package/dist/{src-GD7RGV5U.js → src-LVBNYMJW.js} +5 -5
  144. package/dist/{src-GRC63B6L.js → src-RQE5HXZK.js} +7 -7
  145. package/dist/{staticProjectServer-SFINO3DE.js → staticProjectServer-TQYP44CW.js} +14 -14
  146. package/dist/{status-LXQL3L3H.js → status-HVI7QZHE.js} +6 -6
  147. package/dist/studio/assets/{hyperframes-player-c6WR3RsF.js → hyperframes-player-CBpg41JM.js} +1 -1
  148. package/dist/studio/assets/{index-BJpQzV6h.js → index-BFitquwi.js} +1 -1
  149. package/dist/studio/assets/{index-Co6W8IVk.js → index-BKy_birQ.js} +194 -194
  150. package/dist/studio/assets/{index-C0KfbPAo.js → index-CZfrSyU9.js} +1 -1
  151. package/dist/studio/assets/{index-C7apTvpr.css → index-DbfKVTId.css} +1 -1
  152. package/dist/studio/{chunk-PQFEBX32.js → chunk-BIUXP3PG.js} +2 -2
  153. package/dist/studio/{chunk-6LUNLTHR.js → chunk-K47E2ZJA.js} +13 -8
  154. package/dist/studio/chunk-K47E2ZJA.js.map +1 -0
  155. package/dist/studio/{chunk-QUXZVHOJ.js → chunk-VWT7STY3.js} +2 -2
  156. package/dist/studio/{domEditingLayers-JQPQGGT7.js → domEditingLayers-V67MS4WP.js} +3 -3
  157. package/dist/studio/index.d.ts +81 -46
  158. package/dist/studio/index.html +2 -2
  159. package/dist/studio/index.js +7295 -6844
  160. package/dist/studio/index.js.map +1 -1
  161. package/dist/studio/player.js +2 -2
  162. package/dist/studio/styles.css +1 -1
  163. package/dist/{studio-api-WRSCXPWS.js → studio-api-EKF6TFDB.js} +8 -8
  164. package/dist/{studioServer-SMBPWSNR.js → studioServer-BSNDGK63.js} +38 -38
  165. package/dist/{system-EEWYEHYX.js → system-NLNIE7PO.js} +6 -6
  166. package/dist/{telemetry-VMNHQBUG.js → telemetry-XNDAM6JU.js} +9 -9
  167. package/dist/{timeline-JWJDKHRD.js → timeline-IKWTTCNY.js} +15 -15
  168. package/dist/{tokens-DETZVKSO.js → tokens-KOTFKBAK.js} +2 -2
  169. package/dist/{transcribe-GCKJF5A6.js → transcribe-ELJHKA5B.js} +7 -7
  170. package/dist/{transcribe-E5VBY6CU.js → transcribe-STEYOXIO.js} +12 -12
  171. package/dist/{updateCheck-PAC2DBB6.js → updateCheck-OJMEQUST.js} +2 -2
  172. package/dist/{upgrade-OYMNUBW2.js → upgrade-NIS32YR6.js} +2 -2
  173. package/dist/{urlDownloader-NYXPEBUN.js → urlDownloader-KJSQAFN7.js} +5 -5
  174. package/dist/{validate-KBPMDKZO.js → validate-7MCKNH5K.js} +15 -15
  175. package/dist/{video-KWQ5TSVD.js → video-TUXP3VGQ.js} +17 -9
  176. package/package.json +1 -1
  177. package/dist/chunk-5GQAJ43Q.js +0 -31
  178. package/dist/chunk-YLVI7VL5.js +0 -3541
  179. package/dist/studio/chunk-6LUNLTHR.js.map +0 -1
  180. /package/dist/studio/{chunk-PQFEBX32.js.map → chunk-BIUXP3PG.js.map} +0 -0
  181. /package/dist/studio/{chunk-QUXZVHOJ.js.map → chunk-VWT7STY3.js.map} +0 -0
  182. /package/dist/studio/{domEditingLayers-JQPQGGT7.js.map → domEditingLayers-V67MS4WP.js.map} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  renderFrameIdForRenderId,
23
23
  resolveAuthoredTimingWindow,
24
24
  toFps
25
- } from "./chunk-B25H4M4V.js";
25
+ } from "./chunk-C4JINRJK.js";
26
26
  import {
27
27
  AUDIO_GROUP_RENDER_ID_ATTR,
28
28
  COLOR_GRADING_SOURCE_HIDDEN_ATTR,
@@ -52,7 +52,7 @@ import {
52
52
  shiftRateLane,
53
53
  sourceTimeAt,
54
54
  timeAtSourceTime
55
- } from "./chunk-YLVI7VL5.js";
55
+ } from "./chunk-S6TH5G6Z.js";
56
56
  import {
57
57
  chromeMajorCeiling,
58
58
  exceedsChromeCeiling
@@ -60,7 +60,7 @@ import {
60
60
  import {
61
61
  isWithinProjectRoot,
62
62
  resolveProjectRelativeSrc
63
- } from "./chunk-BAVM2XBR.js";
63
+ } from "./chunk-YAFO7V4A.js";
64
64
  import {
65
65
  FFMPEG_PATH_ENV,
66
66
  FFPROBE_PATH_ENV,
@@ -1329,7 +1329,8 @@ function probeNvidiaVramMb() {
1329
1329
  const out = execSync("nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits", {
1330
1330
  timeout: 3e3,
1331
1331
  encoding: "utf-8",
1332
- stdio: ["pipe", "pipe", "pipe"]
1332
+ stdio: ["pipe", "pipe", "pipe"],
1333
+ windowsHide: true
1333
1334
  }).trim();
1334
1335
  const mb = parseInt(out.split("\n")[0] ?? "", 10);
1335
1336
  if (Number.isFinite(mb) && mb > 0) {
@@ -1370,6 +1371,7 @@ function buildChromeArgs(options, config) {
1370
1371
  ...getBrowserGpuArgs(browserGpuMode, platform),
1371
1372
  "--font-render-hinting=none",
1372
1373
  "--force-color-profile=srgb",
1374
+ "--force-device-scale-factor=1",
1373
1375
  `--window-size=${options.width},${options.height}`,
1374
1376
  // Prevent Chrome from throttling background tabs/timers — critical when the
1375
1377
  // page is offscreen during headless capture
@@ -2507,18 +2509,25 @@ async function captureScreenshotWithAlpha(page, width, height) {
2507
2509
  }
2508
2510
  }
2509
2511
  var TRANSPARENT_BG_STYLE_ID = "__hf_transparent_bg__";
2510
- async function initTransparentBackground(page) {
2512
+ async function initTransparentBackground(page, { clearCompositionRoot = false } = {}) {
2511
2513
  const client = await getCdpSession(page);
2512
2514
  await client.send("Emulation.setDefaultBackgroundColorOverride", {
2513
2515
  color: { r: 0, g: 0, b: 0, a: 0 }
2514
2516
  });
2515
- await page.evaluate((styleId) => {
2516
- if (document.getElementById(styleId)) return;
2517
- const style = document.createElement("style");
2518
- style.id = styleId;
2519
- style.textContent = "html,body,[data-composition-id]{background:transparent !important;background-color:transparent !important;background-image:none !important;}";
2520
- document.head.appendChild(style);
2521
- }, TRANSPARENT_BG_STYLE_ID);
2517
+ await page.evaluate(
2518
+ (styleId, clearCompositionRoot2) => {
2519
+ const selector = clearCompositionRoot2 ? "html,body,[data-composition-id]" : "html,body";
2520
+ let style = document.getElementById(styleId);
2521
+ if (!style) {
2522
+ style = document.createElement("style");
2523
+ style.id = styleId;
2524
+ document.head.appendChild(style);
2525
+ }
2526
+ style.textContent = `${selector}{background:transparent !important;background-color:transparent !important;background-image:none !important;}`;
2527
+ },
2528
+ TRANSPARENT_BG_STYLE_ID,
2529
+ clearCompositionRoot
2530
+ );
2522
2531
  }
2523
2532
  async function captureAlphaPng(page, width, height) {
2524
2533
  const client = await getCdpSession(page);
@@ -4281,7 +4290,8 @@ async function listFilters() {
4281
4290
  try {
4282
4291
  const { stdout } = await execFileP(getFfmpegBinary(), ["-hide_banner", "-filters"], {
4283
4292
  maxBuffer: 4 * 1024 * 1024,
4284
- timeout: 5e3
4293
+ timeout: 5e3,
4294
+ windowsHide: true
4285
4295
  });
4286
4296
  return stdout;
4287
4297
  } catch {
@@ -9534,8 +9544,8 @@ function isMemberGroupHidden(groupsById, el) {
9534
9544
  }
9535
9545
 
9536
9546
  // ../engine/src/services/videoFrameExtractor.ts
9537
- import { copyFileSync as copyFileSync2, existsSync as existsSync8, linkSync as linkSync2, mkdirSync as mkdirSync6, rmSync as rmSync3 } from "fs";
9538
- import { join as join9 } from "path";
9547
+ import { copyFileSync as copyFileSync2, existsSync as existsSync8, linkSync as linkSync2, mkdirSync as mkdirSync6, rmSync as rmSync4 } from "fs";
9548
+ import { join as join10 } from "path";
9539
9549
 
9540
9550
  // ../engine/src/services/referenceResolver.ts
9541
9551
  function findReferenceTargetEl(doc, refId) {
@@ -9591,6 +9601,59 @@ function isKnownInactiveTimelineWindow(element, resolvedStart) {
9591
9601
  return end != null && end <= resolvedStart;
9592
9602
  }
9593
9603
 
9604
+ // ../engine/src/utils/alphaPlaneProbe.ts
9605
+ import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync5, rmSync } from "fs";
9606
+ import { tmpdir as tmpdir2 } from "os";
9607
+ import { join as join6 } from "path";
9608
+ var BYTES_PER_SAMPLE_FRAME = 8 * 8 * 4;
9609
+ var MAX_SAMPLE_BYTES = BYTES_PER_SAMPLE_FRAME * 3;
9610
+ function sampledRgbaAlphaIsFullyOpaque(buf) {
9611
+ if (buf.length === 0 || buf.length > MAX_SAMPLE_BYTES || buf.length % BYTES_PER_SAMPLE_FRAME !== 0) {
9612
+ return void 0;
9613
+ }
9614
+ for (let i = 3; i < buf.length; i += 4) {
9615
+ if (buf[i] !== 255) return false;
9616
+ }
9617
+ return true;
9618
+ }
9619
+ async function probeInputAlphaPlane(videoPath, decoder, signal) {
9620
+ let probeDir;
9621
+ try {
9622
+ probeDir = mkdtempSync2(join6(tmpdir2(), "hf-alpha-probe-"));
9623
+ const samplePath = join6(probeDir, "alpha.raw");
9624
+ const result = await runFfmpeg(
9625
+ [
9626
+ "-v",
9627
+ "error",
9628
+ "-c:v",
9629
+ decoder,
9630
+ "-i",
9631
+ videoPath,
9632
+ "-frames:v",
9633
+ "3",
9634
+ "-vf",
9635
+ "scale=8:8",
9636
+ "-pix_fmt",
9637
+ "rgba",
9638
+ "-f",
9639
+ "rawvideo",
9640
+ samplePath
9641
+ ],
9642
+ { timeout: 3e4, signal }
9643
+ );
9644
+ if (!result.success) return void 0;
9645
+ return sampledRgbaAlphaIsFullyOpaque(readFileSync5(samplePath));
9646
+ } catch {
9647
+ return void 0;
9648
+ } finally {
9649
+ if (probeDir) rmSync(probeDir, { recursive: true, force: true });
9650
+ }
9651
+ }
9652
+ function inputAlphaOpaqueWarning(src) {
9653
+ return `[hyperframes:render] WARNING: video src="${src}" declares an alpha channel but its first frames decode fully opaque. If it should be transparent, re-export it with an alpha pixel format and avoid remuxing afterward, which can drop the alpha while keeping the tag.
9654
+ `;
9655
+ }
9656
+
9594
9657
  // ../engine/src/utils/urlDownloader.ts
9595
9658
  import {
9596
9659
  closeSync as closeSync2,
@@ -9599,19 +9662,19 @@ import {
9599
9662
  existsSync as existsSync6,
9600
9663
  fsyncSync,
9601
9664
  linkSync,
9602
- mkdtempSync as mkdtempSync2,
9665
+ mkdtempSync as mkdtempSync3,
9603
9666
  mkdirSync as mkdirSync4,
9604
9667
  lstatSync,
9605
9668
  openSync as openSync2,
9606
9669
  readdirSync as readdirSync3,
9607
9670
  rmdirSync,
9608
- rmSync,
9671
+ rmSync as rmSync2,
9609
9672
  statSync as statSync4,
9610
9673
  unlinkSync
9611
9674
  } from "fs";
9612
9675
  import { createHash, randomUUID } from "crypto";
9613
9676
  import { BlockList, isIP } from "net";
9614
- import { dirname as dirname4, extname as extname2, join as join6 } from "path";
9677
+ import { dirname as dirname4, extname as extname2, join as join7 } from "path";
9615
9678
  import { Readable, Transform } from "stream";
9616
9679
  import { pipeline } from "stream/promises";
9617
9680
  var inFlightDownloads = /* @__PURE__ */ new Map();
@@ -9803,7 +9866,7 @@ function removeCacheLockDirectoryIfEmpty(lockPath) {
9803
9866
  }
9804
9867
  function releaseOwnedCachePathLock(lockPath, owner) {
9805
9868
  try {
9806
- rmdirSync(join6(lockPath, owner));
9869
+ rmdirSync(join7(lockPath, owner));
9807
9870
  } catch (error) {
9808
9871
  if (error.code === "ENOENT") return;
9809
9872
  throw error;
@@ -9844,12 +9907,12 @@ async function acquireCachePathLock(localPath, timeoutMs, signal) {
9844
9907
  if (createdLock) {
9845
9908
  const owner = `${CACHE_LOCK_OWNER_PREFIX}${randomUUID()}`;
9846
9909
  try {
9847
- mkdirSync4(join6(lockPath, owner));
9910
+ mkdirSync4(join7(lockPath, owner));
9848
9911
  const entries = readdirSync3(lockPath);
9849
9912
  if (entries.length === 1 && entries[0] === owner) {
9850
9913
  return () => releaseOwnedCachePathLock(lockPath, owner);
9851
9914
  }
9852
- rmdirSync(join6(lockPath, owner));
9915
+ rmdirSync(join7(lockPath, owner));
9853
9916
  removeCacheLockDirectoryIfEmpty(lockPath);
9854
9917
  continue;
9855
9918
  } catch (error) {
@@ -9867,7 +9930,7 @@ async function acquireCachePathLock(localPath, timeoutMs, signal) {
9867
9930
  if (Date.now() - observedLock.stats.mtimeMs > CACHE_LOCK_STALE_MS) {
9868
9931
  if (observedLock.owner) {
9869
9932
  try {
9870
- rmdirSync(join6(lockPath, observedLock.owner));
9933
+ rmdirSync(join7(lockPath, observedLock.owner));
9871
9934
  } catch (error) {
9872
9935
  if (error.code === "ENOENT") continue;
9873
9936
  throw error;
@@ -9875,7 +9938,7 @@ async function acquireCachePathLock(localPath, timeoutMs, signal) {
9875
9938
  removeCacheLockDirectoryIfEmpty(lockPath);
9876
9939
  continue;
9877
9940
  }
9878
- const reclaimPath = join6(lockPath, CACHE_LOCK_RECLAIM_NAME);
9941
+ const reclaimPath = join7(lockPath, CACHE_LOCK_RECLAIM_NAME);
9879
9942
  try {
9880
9943
  mkdirSync4(reclaimPath);
9881
9944
  } catch (error) {
@@ -10315,8 +10378,8 @@ function emitDownloadTelemetry(options, event) {
10315
10378
  }
10316
10379
  }
10317
10380
  async function runDownloadAttempt(url, localPath, timeoutMs, attempt, options, signal) {
10318
- const attemptDir = mkdtempSync2(join6(dirname4(localPath), ".hf-download-"));
10319
- const partialPath = join6(attemptDir, "payload");
10381
+ const attemptDir = mkdtempSync3(join7(dirname4(localPath), ".hf-download-"));
10382
+ const partialPath = join7(attemptDir, "payload");
10320
10383
  const controller = new AbortController();
10321
10384
  let timedOut = false;
10322
10385
  let callerAborted = signal?.aborted ?? false;
@@ -10418,7 +10481,7 @@ async function runDownloadAttempt(url, localPath, timeoutMs, attempt, options, s
10418
10481
  clearTimeout(timeoutId);
10419
10482
  signal?.removeEventListener("abort", onCallerAbort);
10420
10483
  controller.abort();
10421
- rmSync(attemptDir, { recursive: true, force: true });
10484
+ rmSync2(attemptDir, { recursive: true, force: true });
10422
10485
  }
10423
10486
  }
10424
10487
  async function downloadWithRetry(url, localPath, timeoutMs, signal, onTransientRetry, options = {}) {
@@ -10497,7 +10560,7 @@ async function reuseOrInvalidateCachedFile(url, localPath, timeoutMs, signal, op
10497
10560
  throw error;
10498
10561
  }
10499
10562
  if (!before.isFile() || before.size === 0) {
10500
- rmSync(localPath, { recursive: before.isDirectory(), force: true });
10563
+ rmSync2(localPath, { recursive: before.isDirectory(), force: true });
10501
10564
  return false;
10502
10565
  }
10503
10566
  let inspection;
@@ -10529,7 +10592,7 @@ async function reuseOrInvalidateCachedFile(url, localPath, timeoutMs, signal, op
10529
10592
  });
10530
10593
  return true;
10531
10594
  }
10532
- rmSync(localPath, { force: true });
10595
+ rmSync2(localPath, { force: true });
10533
10596
  return false;
10534
10597
  }
10535
10598
  return false;
@@ -10552,7 +10615,7 @@ async function downloadToTemp(url, destDir, timeoutMs = 3e5, signal, onTransient
10552
10615
  mkdirSync4(destDir, { recursive: true });
10553
10616
  }
10554
10617
  const filename = getFilenameFromUrl(url, validationScope);
10555
- const localPath = join6(destDir, filename);
10618
+ const localPath = join7(destDir, filename);
10556
10619
  const downloadPromise = (async () => {
10557
10620
  const cacheStartedAt = Date.now();
10558
10621
  const reused = await reuseOrInvalidateCachedFile(
@@ -10629,16 +10692,16 @@ import {
10629
10692
  mkdirSync as mkdirSync5,
10630
10693
  readdirSync as readdirSync5,
10631
10694
  renameSync,
10632
- rmSync as rmSync2,
10695
+ rmSync as rmSync3,
10633
10696
  statSync as statSync5,
10634
10697
  utimesSync,
10635
10698
  writeFileSync as writeFileSync3
10636
10699
  } from "fs";
10637
- import { join as join8 } from "path";
10700
+ import { join as join9 } from "path";
10638
10701
 
10639
10702
  // ../engine/src/services/extractedFrameIndex.ts
10640
10703
  import { readdirSync as readdirSync4 } from "fs";
10641
- import { join as join7 } from "path";
10704
+ import { join as join8 } from "path";
10642
10705
  var FRAME_FILENAME_PREFIX = "frame_";
10643
10706
  var ExtractedFrameSequenceError = class extends Error {
10644
10707
  constructor(message) {
@@ -10668,7 +10731,7 @@ function framePathsFromDirectory(outputDir, format) {
10668
10731
  `Duplicate extracted frame index ${index}: ${indexed.get(index)} and ${file}`
10669
10732
  );
10670
10733
  }
10671
- indexed.set(index, join7(outputDir, file));
10734
+ indexed.set(index, join8(outputDir, file));
10672
10735
  }
10673
10736
  const ordered = /* @__PURE__ */ new Map();
10674
10737
  for (let index = 0; index < indexed.size; index += 1) {
@@ -10725,8 +10788,8 @@ function hasFrameFiles(dir) {
10725
10788
  }
10726
10789
  function lookupCacheEntry(rootDir, input) {
10727
10790
  const keyHash = computeCacheKey(input);
10728
- const dir = join8(rootDir, cacheEntryDirName(keyHash));
10729
- const complete = existsSync7(join8(dir, COMPLETE_SENTINEL)) && hasFrameFiles(dir);
10791
+ const dir = join9(rootDir, cacheEntryDirName(keyHash));
10792
+ const complete = existsSync7(join9(dir, COMPLETE_SENTINEL)) && hasFrameFiles(dir);
10730
10793
  return { entry: { dir, keyHash }, hit: complete };
10731
10794
  }
10732
10795
  function partialCacheEntryDir(entry) {
@@ -10737,13 +10800,13 @@ function isTargetExistsRenameError(err) {
10737
10800
  return code === "EEXIST" || code === "ENOTEMPTY" || code === "EPERM";
10738
10801
  }
10739
10802
  function adoptPublishedWinner(entry, partialDir) {
10740
- if (!existsSync7(join8(entry.dir, COMPLETE_SENTINEL))) return null;
10803
+ if (!existsSync7(join9(entry.dir, COMPLETE_SENTINEL))) return null;
10741
10804
  removeDir(partialDir);
10742
10805
  return { dir: entry.dir, published: true };
10743
10806
  }
10744
10807
  function publishCacheEntry(entry, partialDir) {
10745
10808
  try {
10746
- writeFileSync3(join8(partialDir, COMPLETE_SENTINEL), "", "utf-8");
10809
+ writeFileSync3(join9(partialDir, COMPLETE_SENTINEL), "", "utf-8");
10747
10810
  } catch {
10748
10811
  return { dir: partialDir, published: false };
10749
10812
  }
@@ -10756,7 +10819,7 @@ function publishCacheEntry(entry, partialDir) {
10756
10819
  const winner = adoptPublishedWinner(entry, partialDir);
10757
10820
  if (winner) return winner;
10758
10821
  try {
10759
- rmSync2(entry.dir, { recursive: true, force: true });
10822
+ rmSync3(entry.dir, { recursive: true, force: true });
10760
10823
  } catch {
10761
10824
  return { dir: partialDir, published: false };
10762
10825
  }
@@ -10774,7 +10837,7 @@ function touchCacheDir(dir) {
10774
10837
  } catch {
10775
10838
  }
10776
10839
  try {
10777
- utimesSync(join8(dir, COMPLETE_SENTINEL), now, now);
10840
+ utimesSync(join9(dir, COMPLETE_SENTINEL), now, now);
10778
10841
  } catch {
10779
10842
  }
10780
10843
  }
@@ -10803,7 +10866,7 @@ function directorySizeBytes(path) {
10803
10866
  return 0;
10804
10867
  }
10805
10868
  for (const child of children) {
10806
- const childPath = join8(path, child);
10869
+ const childPath = join9(path, child);
10807
10870
  try {
10808
10871
  const stat = lstatSync2(childPath);
10809
10872
  if (stat.isDirectory()) {
@@ -10818,7 +10881,7 @@ function directorySizeBytes(path) {
10818
10881
  }
10819
10882
  function removeDir(path) {
10820
10883
  try {
10821
- rmSync2(path, { recursive: true, force: true });
10884
+ rmSync3(path, { recursive: true, force: true });
10822
10885
  } catch {
10823
10886
  }
10824
10887
  }
@@ -10832,7 +10895,7 @@ function collectGcEntry(dir, name, now, minAgeMs, stats, remove) {
10832
10895
  }
10833
10896
  let lastUseMs = dirStat.mtimeMs;
10834
10897
  try {
10835
- lastUseMs = statSync5(join8(dir, COMPLETE_SENTINEL)).mtimeMs;
10898
+ lastUseMs = statSync5(join9(dir, COMPLETE_SENTINEL)).mtimeMs;
10836
10899
  } catch {
10837
10900
  }
10838
10901
  return { dir, size: directorySizeBytes(dir), lastUseMs, ageMs: now - lastUseMs };
@@ -10842,14 +10905,14 @@ function collectGcEntry(dir, name, now, minAgeMs, stats, remove) {
10842
10905
  }
10843
10906
  function gcSweepDue(rootDir, maxAgeMs) {
10844
10907
  try {
10845
- return Date.now() - statSync5(join8(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
10908
+ return Date.now() - statSync5(join9(rootDir, GC_MARKER)).mtimeMs > maxAgeMs;
10846
10909
  } catch {
10847
10910
  return true;
10848
10911
  }
10849
10912
  }
10850
10913
  function markGcSweep(rootDir) {
10851
10914
  try {
10852
- writeFileSync3(join8(rootDir, GC_MARKER), "", "utf-8");
10915
+ writeFileSync3(join9(rootDir, GC_MARKER), "", "utf-8");
10853
10916
  } catch {
10854
10917
  }
10855
10918
  }
@@ -10864,7 +10927,7 @@ function gcExtractionCache(rootDir, opts) {
10864
10927
  for (const child of readdirSync5(rootDir, { withFileTypes: true })) {
10865
10928
  if (!child.isDirectory() || !isCacheLikeChild(child.name)) continue;
10866
10929
  const entry = collectGcEntry(
10867
- join8(rootDir, child.name),
10930
+ join9(rootDir, child.name),
10868
10931
  child.name,
10869
10932
  now,
10870
10933
  opts.minAgeMs,
@@ -11346,7 +11409,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
11346
11409
  const normalizedFps = toFps(options.fps);
11347
11410
  const fps = fpsToNumber(normalizedFps);
11348
11411
  const ffmpegFps = fpsToFfmpegArg(normalizedFps);
11349
- const videoOutputDir = outputDirOverride ?? join9(outputDir, videoId);
11412
+ const videoOutputDir = outputDirOverride ?? join10(outputDir, videoId);
11350
11413
  if (!existsSync8(videoOutputDir)) mkdirSync6(videoOutputDir, { recursive: true });
11351
11414
  let metadata;
11352
11415
  try {
@@ -11373,7 +11436,7 @@ async function extractVideoFramesRange(videoPath, videoId, startTime, duration,
11373
11436
  }
11374
11437
  const format = resolveFrameFormat(metadata, options.format);
11375
11438
  const framePattern = `${FRAME_FILENAME_PREFIX}%05d.${format}`;
11376
- const outputPattern = join9(videoOutputDir, framePattern);
11439
+ const outputPattern = join10(videoOutputDir, framePattern);
11377
11440
  const isHdr = isHdrColorSpace(metadata.colorSpace);
11378
11441
  const isMacOS = process.platform === "darwin";
11379
11442
  const toneMappedToSdr = options.toneMapHdrToSdr === true && isHdr && await toneMapsWithZscale();
@@ -11832,7 +11895,7 @@ function planSupersetGroups(misses, fps) {
11832
11895
  }
11833
11896
  function sliceSupersetMember(member, superset, outputDir, fps, configuredFps) {
11834
11897
  const { work } = member.miss;
11835
- rmSync3(outputDir, { recursive: true, force: true });
11898
+ rmSync4(outputDir, { recursive: true, force: true });
11836
11899
  mkdirSync6(outputDir, { recursive: true });
11837
11900
  const requestedFrames = extractionFrameCountForDuration(
11838
11901
  work.videoDuration,
@@ -11844,7 +11907,7 @@ function sliceSupersetMember(member, superset, outputDir, fps, configuredFps) {
11844
11907
  for (let i = 0; i < frameCount; i += 1) {
11845
11908
  const sourceFrame = superset.framePaths.get(member.offsetFrames + i);
11846
11909
  if (!sourceFrame) throw new Error(`superset frame ${member.offsetFrames + i} missing`);
11847
- linkOrCopyFrame(sourceFrame, join9(outputDir, frameFileName(i + 1, work.format)));
11910
+ linkOrCopyFrame(sourceFrame, join10(outputDir, frameFileName(i + 1, work.format)));
11848
11911
  }
11849
11912
  return extractedFramesFromDirectory(work, outputDir, work.videoPath, fps);
11850
11913
  }
@@ -11893,7 +11956,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
11893
11956
  videoPath = resolveProjectRelativeSrc(video.src, baseDir, compiledDir);
11894
11957
  }
11895
11958
  if (isHttpUrl(videoPath)) {
11896
- const downloadDir = join9(options.outputDir, "_downloads");
11959
+ const downloadDir = join10(options.outputDir, "_downloads");
11897
11960
  mkdirSync6(downloadDir, { recursive: true });
11898
11961
  videoPath = await downloadToTemp(
11899
11962
  videoPath,
@@ -11980,6 +12043,21 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
11980
12043
  const videoColorSpaces = videoMetadata.map((m) => m.colorSpace);
11981
12044
  const sdrToHdrTransfers = resolvedVideos.map(() => void 0);
11982
12045
  breakdown.hdrProbeMs = Date.now() - phase2ProbeStart;
12046
+ const alphaWarnedSrcs = /* @__PURE__ */ new Set();
12047
+ if (resolvedVideos.length > 0) {
12048
+ await Promise.all(
12049
+ resolvedVideos.map(async ({ video, videoPath }, index) => {
12050
+ if (signal?.aborted) return;
12051
+ const metadata = videoMetadata[index];
12052
+ if (!metadata?.hasAlpha || !codecMayHaveAlpha(metadata.videoCodec)) return;
12053
+ if (alphaWarnedSrcs.has(video.src)) return;
12054
+ alphaWarnedSrcs.add(video.src);
12055
+ const decoder = decoderForCodec(metadata.videoCodec);
12056
+ if (await probeInputAlphaPlane(videoPath, decoder, signal) !== true) return;
12057
+ process.stderr.write(inputAlphaOpaqueWarning(video.src));
12058
+ })
12059
+ );
12060
+ }
11983
12061
  const hdrPreflightStart = Date.now();
11984
12062
  const hdrInfo = analyzeCompositionHdr(videoColorSpaces);
11985
12063
  const hdrSkippedIndices = /* @__PURE__ */ new Set();
@@ -12104,7 +12182,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
12104
12182
  async function extractDirectMiss(miss, maxTransientRetries = options.maxTransientRetries ?? 0) {
12105
12183
  const { work, cacheTarget } = miss;
12106
12184
  if (!cacheTarget) {
12107
- const outputDir = join9(options.outputDir, work.video.id);
12185
+ const outputDir = join10(options.outputDir, work.video.id);
12108
12186
  const attempted2 = await runVideoExtractionWithRetry(
12109
12187
  () => extractVideoFramesRange(
12110
12188
  work.videoPath,
@@ -12120,14 +12198,14 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
12120
12198
  maxTransientRetries,
12121
12199
  onRetry: () => {
12122
12200
  recordTransientRetries(1);
12123
- rmSync3(outputDir, { recursive: true, force: true });
12201
+ rmSync4(outputDir, { recursive: true, force: true });
12124
12202
  }
12125
12203
  }
12126
12204
  );
12127
12205
  return attempted2.result;
12128
12206
  }
12129
12207
  const partialDir = partialCacheEntryDir(cacheTarget.entry);
12130
- rmSync3(partialDir, { recursive: true, force: true });
12208
+ rmSync4(partialDir, { recursive: true, force: true });
12131
12209
  mkdirSync6(partialDir, { recursive: true });
12132
12210
  const attempted = await runVideoExtractionWithRetry(
12133
12211
  () => extractVideoFramesRange(
@@ -12145,7 +12223,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
12145
12223
  maxTransientRetries,
12146
12224
  onRetry: () => {
12147
12225
  recordTransientRetries(1);
12148
- rmSync3(partialDir, { recursive: true, force: true });
12226
+ rmSync4(partialDir, { recursive: true, force: true });
12149
12227
  mkdirSync6(partialDir, { recursive: true });
12150
12228
  }
12151
12229
  }
@@ -12172,7 +12250,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
12172
12250
  return sliceSupersetMember(
12173
12251
  member,
12174
12252
  superset,
12175
- join9(options.outputDir, work.video.id),
12253
+ join10(options.outputDir, work.video.id),
12176
12254
  fps,
12177
12255
  configuredFps
12178
12256
  );
@@ -12189,9 +12267,9 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
12189
12267
  async function executeSupersetGroup(group) {
12190
12268
  const first = group.members[0]?.miss.work;
12191
12269
  if (!first) return [];
12192
- const tempDir = cacheRootDir ? join9(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join9(options.outputDir, group.groupId);
12270
+ const tempDir = cacheRootDir ? join10(cacheRootDir, `${group.groupId}.partial-${process.pid}`) : join10(options.outputDir, group.groupId);
12193
12271
  try {
12194
- rmSync3(tempDir, { recursive: true, force: true });
12272
+ rmSync4(tempDir, { recursive: true, force: true });
12195
12273
  const superset = await extractVideoFramesRange(
12196
12274
  first.videoPath,
12197
12275
  group.groupId,
@@ -12224,7 +12302,7 @@ async function extractAllVideoFrames(videos, baseDir, options, signal, config, c
12224
12302
  );
12225
12303
  return fallback;
12226
12304
  } finally {
12227
- rmSync3(tempDir, { recursive: true, force: true });
12305
+ rmSync4(tempDir, { recursive: true, force: true });
12228
12306
  }
12229
12307
  }
12230
12308
  const preparedExtractions = await Promise.all(
@@ -12510,7 +12588,7 @@ var FrameLookupTable = class {
12510
12588
  for (const video of this.videos.values()) {
12511
12589
  if (video.extracted.ownedByLookup) continue;
12512
12590
  if (existsSync8(video.extracted.outputDir)) {
12513
- rmSync3(video.extracted.outputDir, { recursive: true, force: true });
12591
+ rmSync4(video.extracted.outputDir, { recursive: true, force: true });
12514
12592
  }
12515
12593
  }
12516
12594
  this.videos.clear();
@@ -12957,8 +13035,8 @@ async function queryElementStacking(page, nativeHdrIds) {
12957
13035
  }
12958
13036
 
12959
13037
  // ../engine/src/services/audioMixer.ts
12960
- import { closeSync as closeSync3, existsSync as existsSync10, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync5, openSync as openSync3, rmSync as rmSync6, writeFileSync as writeFileSync6 } from "fs";
12961
- import { join as join12, dirname as dirname6, isAbsolute, relative } from "path";
13038
+ import { closeSync as closeSync3, existsSync as existsSync10, mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync6, openSync as openSync3, rmSync as rmSync7, writeFileSync as writeFileSync6 } from "fs";
13039
+ import { join as join13, dirname as dirname6, isAbsolute, relative } from "path";
12962
13040
 
12963
13041
  // ../engine/src/utils/notMediaPayload.ts
12964
13042
  import { createHash as createHash3 } from "crypto";
@@ -13073,8 +13151,8 @@ function clampFadesToDuration(fades, duration) {
13073
13151
  }
13074
13152
 
13075
13153
  // ../engine/src/services/audioVolumeEnvelope.ts
13076
- import { mkdtempSync as mkdtempSync3, readFileSync as readFileSync5, renameSync as renameSync2, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "fs";
13077
- import { dirname as dirname5, join as join10 } from "path";
13154
+ import { mkdtempSync as mkdtempSync4, readFileSync as readFileSync6, renameSync as renameSync2, rmSync as rmSync5, writeFileSync as writeFileSync4 } from "fs";
13155
+ import { dirname as dirname5, join as join11 } from "path";
13078
13156
 
13079
13157
  // ../core/dist/runtime/mediaVolumeEnvelope.js
13080
13158
  function normaliseEnvelope(keyframes, trackStart, baseVolume) {
@@ -13196,12 +13274,12 @@ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
13196
13274
  if (!gainAt) return false;
13197
13275
  let stagingDir;
13198
13276
  try {
13199
- const buffer = readFileSync5(wavPath);
13277
+ const buffer = readFileSync6(wavPath);
13200
13278
  const layout = parseWavLayout(buffer);
13201
13279
  if (!layout) return false;
13202
13280
  scaleSamples(buffer, layout, gainAt);
13203
- stagingDir = mkdtempSync3(join10(dirname5(wavPath), ".hf-volume-"));
13204
- const tempPath = join10(stagingDir, "audio.wav");
13281
+ stagingDir = mkdtempSync4(join11(dirname5(wavPath), ".hf-volume-"));
13282
+ const tempPath = join11(stagingDir, "audio.wav");
13205
13283
  writeFileSync4(tempPath, buffer, { flag: "wx" });
13206
13284
  renameSync2(tempPath, wavPath);
13207
13285
  return true;
@@ -13210,7 +13288,7 @@ function applyVolumeEnvelopeToWav(wavPath, keyframes, trackStart, baseVolume) {
13210
13288
  } finally {
13211
13289
  if (stagingDir) {
13212
13290
  try {
13213
- rmSync4(stagingDir, { recursive: true, force: true });
13291
+ rmSync5(stagingDir, { recursive: true, force: true });
13214
13292
  } catch {
13215
13293
  }
13216
13294
  }
@@ -13272,9 +13350,9 @@ function chainTailSeconds(chain, automation) {
13272
13350
  }
13273
13351
 
13274
13352
  // ../engine/src/services/audioFxRender.ts
13275
- import { existsSync as existsSync9, mkdtempSync as mkdtempSync4, readFileSync as readFileSync6, rmSync as rmSync5, writeFileSync as writeFileSync5 } from "fs";
13276
- import { tmpdir as tmpdir2 } from "os";
13277
- import { join as join11 } from "path";
13353
+ import { existsSync as existsSync9, mkdtempSync as mkdtempSync5, readFileSync as readFileSync7, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "fs";
13354
+ import { tmpdir as tmpdir3 } from "os";
13355
+ import { join as join12 } from "path";
13278
13356
  import { pathToFileURL } from "url";
13279
13357
 
13280
13358
  // ../core/dist/generated/audio-fx-runtime-inline.js
@@ -13309,7 +13387,7 @@ function readWavChunks(buf) {
13309
13387
  return { ...head, data };
13310
13388
  }
13311
13389
  function readWav(path) {
13312
- const buf = readFileSync6(path);
13390
+ const buf = readFileSync7(path);
13313
13391
  if (buf.length < 44 || buf.toString("ascii", 0, 4) !== "RIFF") {
13314
13392
  throw new AudioFxRenderError(`Not a WAV file: ${path}`);
13315
13393
  }
@@ -13404,7 +13482,7 @@ async function applyAudioFxChain(inputWav, chain, outputWav, options) {
13404
13482
  const { samples, sampleRate, channels, float } = readWav(inputWav);
13405
13483
  const planes = deinterleave(samples, channels);
13406
13484
  if ((planes[0]?.length ?? 0) === 0) return { path: inputWav, envelopeBaked: false };
13407
- const hostDir = mkdtempSync4(join11(tmpdir2(), "hf-fx-host-"));
13485
+ const hostDir = mkdtempSync5(join12(tmpdir3(), "hf-fx-host-"));
13408
13486
  let lease = null;
13409
13487
  try {
13410
13488
  if (options.signal?.aborted) {
@@ -13413,7 +13491,7 @@ async function applyAudioFxChain(inputWav, chain, outputWav, options) {
13413
13491
  lease = await acquireBrowser(["--no-sandbox", "--autoplay-policy=no-user-gesture-required"]);
13414
13492
  const page = await lease.browser.newPage();
13415
13493
  try {
13416
- const hostPage = join11(hostDir, "audio-fx.html");
13494
+ const hostPage = join12(hostDir, "audio-fx.html");
13417
13495
  writeFileSync5(hostPage, "<!doctype html><meta charset=utf-8><title>audio fx</title>");
13418
13496
  await page.goto(pathToFileURL(hostPage).href, { waitUntil: "domcontentloaded" });
13419
13497
  await page.addScriptTag({ content: getAudioFxRuntimeScript() });
@@ -13441,7 +13519,7 @@ async function applyAudioFxChain(inputWav, chain, outputWav, options) {
13441
13519
  `Audio FX failed for track ${options.trackId}: ${err.message}`
13442
13520
  );
13443
13521
  } finally {
13444
- rmSync5(hostDir, { recursive: true, force: true });
13522
+ rmSync6(hostDir, { recursive: true, force: true });
13445
13523
  await lease?.release().catch(() => void 0);
13446
13524
  }
13447
13525
  }
@@ -14047,8 +14125,8 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
14047
14125
  const runMix = async (ignoreAutomation) => {
14048
14126
  const inputs = [];
14049
14127
  tracks.forEach((track) => inputs.push("-i", track.srcPath));
14050
- const scriptDir = mkdtempSync5(join12(outputDir, ".filter-complex-"));
14051
- const scriptPath = join12(scriptDir, "graph.txt");
14128
+ const scriptDir = mkdtempSync6(join13(outputDir, ".filter-complex-"));
14129
+ const scriptPath = join13(scriptDir, "graph.txt");
14052
14130
  const fd = openSync3(scriptPath, "wx", 384);
14053
14131
  try {
14054
14132
  writeFileSync6(fd, buildFilterComplex(ignoreAutomation));
@@ -14079,7 +14157,7 @@ async function mixAudioTracks(tracks, outputPath, totalDuration, signal, config)
14079
14157
  currentArgs[currentArgs.indexOf("-filter_complex_script")] = "-/filter_complex";
14080
14158
  return await runFfmpeg(currentArgs, { signal, timeout: ffmpegProcessTimeout });
14081
14159
  } finally {
14082
- rmSync6(scriptDir, { recursive: true, force: true });
14160
+ rmSync7(scriptDir, { recursive: true, force: true });
14083
14161
  }
14084
14162
  };
14085
14163
  let result = await runMix(false);
@@ -14152,8 +14230,8 @@ async function mixGroupMembers(memberTracks, outputPath, totalDuration, signal,
14152
14230
  `${mixInputs}amix=inputs=${memberTracks.length}:duration=longest:dropout_transition=0[mixed];[mixed]volume=${formatFilterNumber(memberTracks.length)}[out]`
14153
14231
  );
14154
14232
  const filterComplex = [...inputFilters, mixFilter].join(";");
14155
- const scriptDir = mkdtempSync5(join12(outputDir, ".group-filter-complex-"));
14156
- const scriptPath = join12(scriptDir, "graph.txt");
14233
+ const scriptDir = mkdtempSync6(join13(outputDir, ".group-filter-complex-"));
14234
+ const scriptPath = join13(scriptDir, "graph.txt");
14157
14235
  const fd = openSync3(scriptPath, "wx", 384);
14158
14236
  try {
14159
14237
  writeFileSync6(fd, filterComplex);
@@ -14193,7 +14271,7 @@ async function mixGroupMembers(memberTracks, outputPath, totalDuration, signal,
14193
14271
  currentArgs[currentArgs.indexOf("-filter_complex_script")] = "-/filter_complex";
14194
14272
  return await runFfmpeg(currentArgs, { signal, timeout: ffmpegProcessTimeout });
14195
14273
  } finally {
14196
- rmSync6(scriptDir, { recursive: true, force: true });
14274
+ rmSync7(scriptDir, { recursive: true, force: true });
14197
14275
  }
14198
14276
  };
14199
14277
  let useNormalize = true;
@@ -14306,7 +14384,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14306
14384
  }
14307
14385
  let audioSrcPath = srcPath;
14308
14386
  if (element.type === "video") {
14309
- const extractedPath = join12(workDir, `${element.id}-extracted.wav`);
14387
+ const extractedPath = join13(workDir, `${element.id}-extracted.wav`);
14310
14388
  const extractResult = await extractAudioFromVideo(
14311
14389
  srcPath,
14312
14390
  extractedPath,
@@ -14333,7 +14411,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14333
14411
  }
14334
14412
  audioSrcPath = extractedPath;
14335
14413
  } else {
14336
- const trimmedPath = join12(workDir, `${element.id}-trimmed.wav`);
14414
+ const trimmedPath = join13(workDir, `${element.id}-trimmed.wav`);
14337
14415
  const prepResult = await prepareAudioTrack(
14338
14416
  srcPath,
14339
14417
  trimmedPath,
@@ -14377,7 +14455,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14377
14455
  const fxResult = await applyAudioFxChain(
14378
14456
  audioSrcPath,
14379
14457
  chain,
14380
- join12(workDir, `${element.id}-fx.wav`),
14458
+ join13(workDir, `${element.id}-fx.wav`),
14381
14459
  {
14382
14460
  trackId: element.id,
14383
14461
  signal: effectiveSignal,
@@ -14441,14 +14519,14 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14441
14519
  ).catch((err) => {
14442
14520
  internalController.abort();
14443
14521
  try {
14444
- rmSync6(workDir, { recursive: true, force: true });
14522
+ rmSync7(workDir, { recursive: true, force: true });
14445
14523
  } catch {
14446
14524
  }
14447
14525
  throw err;
14448
14526
  });
14449
14527
  const bail = () => {
14450
14528
  try {
14451
- rmSync6(workDir, { recursive: true, force: true });
14529
+ rmSync7(workDir, { recursive: true, force: true });
14452
14530
  } catch {
14453
14531
  }
14454
14532
  return {
@@ -14470,7 +14548,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14470
14548
  const meta = groupMeta.get(groupId);
14471
14549
  if (!meta) continue;
14472
14550
  const pathId = safePathSegment(groupId, groupIndex);
14473
- const groupWavPath = join12(workDir, `group-${pathId}.wav`);
14551
+ const groupWavPath = join13(workDir, `group-${pathId}.wav`);
14474
14552
  try {
14475
14553
  const subMix = await mixGroupMembers(
14476
14554
  memberTracks,
@@ -14506,7 +14584,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14506
14584
  const fxResult = await applyAudioFxChain(
14507
14585
  groupSrcPath,
14508
14586
  chain,
14509
- join12(workDir, `group-${pathId}-fx.wav`),
14587
+ join13(workDir, `group-${pathId}-fx.wav`),
14510
14588
  {
14511
14589
  trackId: groupId,
14512
14590
  signal: effectiveSignal,
@@ -14555,7 +14633,7 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14555
14633
  if (failures.length > 0) return bail();
14556
14634
  const mixResult = await mixAudioTracks(tracks, outputPath, totalDuration, signal, config);
14557
14635
  try {
14558
- rmSync6(workDir, { recursive: true, force: true });
14636
+ rmSync7(workDir, { recursive: true, force: true });
14559
14637
  } catch {
14560
14638
  }
14561
14639
  const degradedNote = groupsDegradedAutomation.length > 0 ? `Volume automation exceeded this ffmpeg build's expression limits in group(s) ${groupsDegradedAutomation.join(", ")}; rendered at base volume` : void 0;
@@ -14574,26 +14652,26 @@ async function processCompositionAudio(elements, baseDir, workDir, outputPath, t
14574
14652
  import { cpus, freemem } from "os";
14575
14653
  import { existsSync as existsSync11, mkdirSync as mkdirSync8, readdirSync as readdirSync6 } from "fs";
14576
14654
  import { copyFile, readFile as readFile2, rename } from "fs/promises";
14577
- import { join as join14 } from "path";
14655
+ import { join as join15 } from "path";
14578
14656
  import { getHeapStatistics } from "v8";
14579
14657
 
14580
14658
  // ../engine/src/utils/psnr.ts
14581
14659
  import { execFile as execFile3 } from "child_process";
14582
14660
  import { mkdtemp, rm, writeFile } from "fs/promises";
14583
- import { tmpdir as tmpdir3 } from "os";
14584
- import { join as join13 } from "path";
14661
+ import { tmpdir as tmpdir4 } from "os";
14662
+ import { join as join14 } from "path";
14585
14663
  import { promisify as promisify3 } from "util";
14586
14664
  async function psnrDb(a, b) {
14587
14665
  const execFileP = promisify3(execFile3);
14588
- const dir = await mkdtemp(join13(tmpdir3(), "hf-de-verify-"));
14666
+ const dir = await mkdtemp(join14(tmpdir4(), "hf-de-verify-"));
14589
14667
  try {
14590
- const pa = join13(dir, "a.jpg");
14591
- const pb = join13(dir, "b.jpg");
14668
+ const pa = join14(dir, "a.jpg");
14669
+ const pb = join14(dir, "b.jpg");
14592
14670
  await Promise.all([writeFile(pa, a), writeFile(pb, b)]);
14593
14671
  const { stderr } = await execFileP(
14594
14672
  getFfmpegBinary(),
14595
14673
  ["-hide_banner", "-i", pa, "-i", pb, "-lavfi", "psnr", "-f", "null", "-"],
14596
- { maxBuffer: 4 * 1024 * 1024 }
14674
+ { maxBuffer: 4 * 1024 * 1024, windowsHide: true }
14597
14675
  );
14598
14676
  const m = /average:(inf|[\d.]+)/.exec(stderr);
14599
14677
  if (!m) throw new Error(`psnr parse failed: ${stderr.slice(-300)}`);
@@ -14813,7 +14891,7 @@ function distributeFrames(totalFrames, workerCount, workDir, rangeStart = 0) {
14813
14891
  workerId: i,
14814
14892
  startFrame,
14815
14893
  endFrame,
14816
- outputDir: join14(workDir, `worker-${i}`),
14894
+ outputDir: join15(workDir, `worker-${i}`),
14817
14895
  outputFrameOffset: rangeStart
14818
14896
  });
14819
14897
  }
@@ -14827,7 +14905,7 @@ function distributeFramesInterleaved(totalFrames, workerCount, workDir, rangeSta
14827
14905
  startFrame: rangeStart + i,
14828
14906
  endFrame: rangeStart + totalFrames,
14829
14907
  frameStride: workerCount,
14830
- outputDir: join14(workDir, `worker-${i}`),
14908
+ outputDir: join15(workDir, `worker-${i}`),
14831
14909
  outputFrameOffset: rangeStart
14832
14910
  });
14833
14911
  }
@@ -15027,7 +15105,7 @@ async function verifyDiskDrawElementSamples(session, task, streaming) {
15027
15105
  for (const idx of selectVerifySampleIndicesForTask(truths.keys(), task)) {
15028
15106
  const truth = truths.get(idx);
15029
15107
  if (!truth) continue;
15030
- const framePath = join14(task.outputDir, `frame_${String(idx - offset).padStart(6, "0")}.${ext}`);
15108
+ const framePath = join15(task.outputDir, `frame_${String(idx - offset).padStart(6, "0")}.${ext}`);
15031
15109
  const db = await psnrForDiskSample(framePath, truth, task.workerId, idx);
15032
15110
  if (db === null) continue;
15033
15111
  assertDiskSampleAboveFloor(db, verifyMinDb, idx, task.workerId);
@@ -15270,8 +15348,8 @@ async function mergeWorkerFrames(workDir, tasks, outputDir) {
15270
15348
  }
15271
15349
  const files = readdirSync6(task.outputDir).filter((f) => f.startsWith("frame_") && (f.endsWith(".jpg") || f.endsWith(".png"))).sort();
15272
15350
  const copyTasks = files.map(async (file) => {
15273
- const sourcePath = join14(task.outputDir, file);
15274
- const targetPath = join14(outputDir, file);
15351
+ const sourcePath = join15(task.outputDir, file);
15352
+ const targetPath = join15(outputDir, file);
15275
15353
  try {
15276
15354
  await rename(sourcePath, targetPath);
15277
15355
  } catch {
@@ -15295,8 +15373,8 @@ function getSystemResources() {
15295
15373
  // ../engine/src/services/fileServer.ts
15296
15374
  import { Hono } from "hono";
15297
15375
  import { serve } from "@hono/node-server";
15298
- import { readFileSync as readFileSync7, openSync as openSync4, fstatSync, closeSync as closeSync4, statSync as statSync6, constants } from "fs";
15299
- import { join as join15, extname as extname3 } from "path";
15376
+ import { readFileSync as readFileSync8, openSync as openSync4, fstatSync, closeSync as closeSync4, statSync as statSync6, constants } from "fs";
15377
+ import { join as join16, extname as extname3 } from "path";
15300
15378
  var MIME_TYPES = {
15301
15379
  ".html": "text/html; charset=utf-8",
15302
15380
  ".css": "text/css; charset=utf-8",
@@ -15337,16 +15415,16 @@ function readRegularFile(filePath) {
15337
15415
  }
15338
15416
  try {
15339
15417
  if (!fstatSync(fd).isFile()) return null;
15340
- return readFileSync7(fd);
15418
+ return readFileSync8(fd);
15341
15419
  } finally {
15342
15420
  closeSync4(fd);
15343
15421
  }
15344
15422
  }
15345
15423
  function resolveContainedPaths(projectDir, compiledDir, relativePath) {
15346
- const projectPath = join15(projectDir, relativePath);
15424
+ const projectPath = join16(projectDir, relativePath);
15347
15425
  if (!isWithinProjectRoot(projectDir, projectPath)) return null;
15348
15426
  if (!compiledDir) return { projectPath, compiledPath: null };
15349
- const compiledPath = join15(compiledDir, relativePath);
15427
+ const compiledPath = join16(compiledDir, relativePath);
15350
15428
  if (!isWithinProjectRoot(compiledDir, compiledPath)) return null;
15351
15429
  return { projectPath, compiledPath };
15352
15430
  }
@@ -15539,7 +15617,7 @@ function verifyGpuParity(a, b, options = {}) {
15539
15617
 
15540
15618
  // ../engine/src/services/hdrCapture.ts
15541
15619
  import { existsSync as existsSync12, readdirSync as readdirSync7 } from "fs";
15542
- import { join as join16 } from "path";
15620
+ import { join as join17 } from "path";
15543
15621
  import { homedir as homedir2 } from "os";
15544
15622
  var PQ_M1 = 0.1593017578125;
15545
15623
  var PQ_M2 = 78.84375;
@@ -15662,12 +15740,12 @@ function float16ToPqRgb(rawBuffer, bytesPerRow, width, height) {
15662
15740
  return output;
15663
15741
  }
15664
15742
  function resolveHeadedChromePath() {
15665
- const baseDir = join16(homedir2(), ".cache", "puppeteer", "chrome");
15743
+ const baseDir = join17(homedir2(), ".cache", "puppeteer", "chrome");
15666
15744
  if (!existsSync12(baseDir)) return void 0;
15667
15745
  const versions = readdirSync7(baseDir).sort().reverse();
15668
15746
  for (const version of versions) {
15669
15747
  const candidates = [
15670
- join16(
15748
+ join17(
15671
15749
  baseDir,
15672
15750
  version,
15673
15751
  "chrome-mac-arm64",
@@ -15676,7 +15754,7 @@ function resolveHeadedChromePath() {
15676
15754
  "MacOS",
15677
15755
  "Google Chrome for Testing"
15678
15756
  ),
15679
- join16(
15757
+ join17(
15680
15758
  baseDir,
15681
15759
  version,
15682
15760
  "chrome-mac-x64",
@@ -15685,8 +15763,8 @@ function resolveHeadedChromePath() {
15685
15763
  "MacOS",
15686
15764
  "Google Chrome for Testing"
15687
15765
  ),
15688
- join16(baseDir, version, "chrome-linux64", "chrome"),
15689
- join16(baseDir, version, "chrome-win64", "chrome.exe")
15766
+ join17(baseDir, version, "chrome-linux64", "chrome"),
15767
+ join17(baseDir, version, "chrome-win64", "chrome.exe")
15690
15768
  ];
15691
15769
  for (const binary of candidates) {
15692
15770
  if (existsSync12(binary)) return binary;