hyperframes 0.8.169 → 0.8.171

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 (181) hide show
  1. package/dist/{add-7GLP4BPM.js → add-VMMGTSGT.js} +12 -11
  2. package/dist/{animatedGifPrep-NEBEGVSO.js → animatedGifPrep-MVP5LCEM.js} +5 -5
  3. package/dist/api.js +11 -11
  4. package/dist/{asset-RORTT5HS.js → asset-ZERIT5FT.js} +2 -2
  5. package/dist/{assetCataloger-RLJ6MDGF.js → assetCataloger-RN5A2SVA.js} +5 -5
  6. package/dist/{audio-OKDGU7TY.js → audio-RQUGFWYT.js} +11 -11
  7. package/dist/{auth-QWYNCU5U.js → auth-I3FNB6N2.js} +1 -1
  8. package/dist/{autoUpdate-EDJJPWAU.js → autoUpdate-IBAS4JVK.js} +2 -2
  9. package/dist/{backgroundChecks-KQR6FGVU.js → backgroundChecks-7UQBIPQC.js} +3 -3
  10. package/dist/backgroundChecksWorker.js +3 -3
  11. package/dist/{batchRender-YKTTAIHH.js → batchRender-KWBVAUE3.js} +3 -3
  12. package/dist/{beats-I6AGLTLW.js → beats-F2GFGFCV.js} +4 -4
  13. package/dist/{benchmark-NBSV7PNB.js → benchmark-XPQYX3OX.js} +8 -8
  14. package/dist/{browser-FPEL5FGW.js → browser-QCV62F7R.js} +3 -3
  15. package/dist/{bundleWithLocalizedFonts-TYQXMNSU.js → bundleWithLocalizedFonts-42V34HJF.js} +2 -2
  16. package/dist/{capture-FXGOI23U.js → capture-OKPMCIAC.js} +8 -8
  17. package/dist/{capture-5BRJJMZB.js → capture-WE32B5UZ.js} +2 -2
  18. package/dist/{catalog-SG3ZIS45.js → catalog-2LWFMJM3.js} +12 -11
  19. package/dist/{catch-up-ETXUT6Q5.js → catch-up-OWUGMOBS.js} +4 -4
  20. package/dist/{check-KXNNIEUR.js → check-7BK6UM3M.js} +35 -34
  21. package/dist/{checkBrowser-546UMI3N.js → checkBrowser-VG745SEX.js} +32 -31
  22. package/dist/{chunk-YZRS3COO.js → chunk-4QIJFIR5.js} +1 -1
  23. package/dist/{chunk-UCNQE52B.js → chunk-4RXJG3SY.js} +197 -26
  24. package/dist/{chunk-JPN7SVWC.js → chunk-5GQB63WX.js} +7 -7
  25. package/dist/{chunk-FSX7GTBB.js → chunk-5HLJ4JMB.js} +1 -1
  26. package/dist/{chunk-FQJDV2RI.js → chunk-6I24ZSCR.js} +1 -1
  27. package/dist/chunk-6M3IPJS6.js +3803 -0
  28. package/dist/{chunk-7635SDI5.js → chunk-77QCYRQH.js} +2 -2
  29. package/dist/{chunk-TJSTGSAW.js → chunk-7FMUTGOH.js} +2 -77
  30. package/dist/{chunk-QD5VJOQK.js → chunk-7YZSOHSC.js} +3 -3
  31. package/dist/{chunk-AP5AVVAB.js → chunk-A3SQJCPU.js} +1 -1
  32. package/dist/{chunk-XK5SZNYE.js → chunk-AAYNQ7WL.js} +9 -9
  33. package/dist/{chunk-T4HL3SZH.js → chunk-AGHHZIZN.js} +1 -1
  34. package/dist/{chunk-A6K7M46D.js → chunk-AWSVUIWG.js} +1 -1
  35. package/dist/{chunk-RUYYAL3T.js → chunk-BMPNGUYD.js} +2 -2
  36. package/dist/{chunk-BNEKKUPG.js → chunk-BYFG74OA.js} +2 -2
  37. package/dist/{chunk-VCXVZRR2.js → chunk-CO6V4KXX.js} +1 -1
  38. package/dist/{chunk-5ETJPA5Z.js → chunk-CSABTZ6S.js} +9 -9
  39. package/dist/{chunk-DCG22HKT.js → chunk-D2QELIQB.js} +72 -22
  40. package/dist/{chunk-J5Z56PU3.js → chunk-EDGJ2OMH.js} +1 -1
  41. package/dist/{chunk-SJPNVLYS.js → chunk-ERJHLFPD.js} +2 -2
  42. package/dist/{chunk-P24X6CGY.js → chunk-FAORS3UR.js} +28 -13
  43. package/dist/{chunk-EEP5Y5IE.js → chunk-FE2XTCTM.js} +18 -1
  44. package/dist/{chunk-TVDXMJ43.js → chunk-GBWSBTEE.js} +1 -1
  45. package/dist/{chunk-JGYHWVXQ.js → chunk-GMJ3ILLW.js} +34 -13
  46. package/dist/{chunk-K5PU5ISL.js → chunk-GSABLXZV.js} +1 -1
  47. package/dist/{chunk-KA4LSAD5.js → chunk-GU5FLCZV.js} +1 -1
  48. package/dist/{chunk-YT6TFGIS.js → chunk-IWLOARQZ.js} +2 -2
  49. package/dist/{chunk-EFP25BUY.js → chunk-JAERN4RH.js} +1 -1
  50. package/dist/chunk-JHOCK3DG.js +27 -0
  51. package/dist/{chunk-5SQHHBAR.js → chunk-JMJTXBVF.js} +22 -12
  52. package/dist/{chunk-NKG3LTPI.js → chunk-KQCWIE76.js} +2 -2
  53. package/dist/{chunk-S6U7YLPJ.js → chunk-KUW4LWY6.js} +1 -1
  54. package/dist/{chunk-PVTHDNDZ.js → chunk-L32QQH2K.js} +1 -1
  55. package/dist/{chunk-TEFHMDVR.js → chunk-LMMFO5UV.js} +2 -2
  56. package/dist/{chunk-CESKA6VO.js → chunk-NSJLCWLG.js} +1 -1
  57. package/dist/{chunk-MCPDZWZY.js → chunk-NYCJCQNY.js} +4 -4
  58. package/dist/{chunk-2F4HJFGW.js → chunk-PAFCKH3S.js} +2 -2
  59. package/dist/{chunk-U7P2XTRY.js → chunk-PECICVTJ.js} +2 -2
  60. package/dist/{chunk-GVX2443P.js → chunk-PH3RS5X4.js} +2 -2
  61. package/dist/{chunk-Q5K73VW3.js → chunk-PXA4S6OE.js} +2 -2
  62. package/dist/{chunk-O3J7BHBU.js → chunk-QZUVPWC4.js} +1 -1
  63. package/dist/{chunk-ZFJ5RI7A.js → chunk-RSW6LGGW.js} +3 -3
  64. package/dist/{chunk-EELTMBCC.js → chunk-RTW6WSC7.js} +4 -3
  65. package/dist/{chunk-CNP6AMFM.js → chunk-SLTUINB4.js} +2 -2
  66. package/dist/{chunk-RZKQ3G6B.js → chunk-T5LGOTQR.js} +1 -1
  67. package/dist/{chunk-WAVFNZB7.js → chunk-TZ3I23TZ.js} +21 -7
  68. package/dist/{chunk-QLHXC4E6.js → chunk-UJQQITCY.js} +1 -1
  69. package/dist/{chunk-XZNHVWDD.js → chunk-UUP4KOMD.js} +4 -4
  70. package/dist/{chunk-UISU4SYG.js → chunk-V2T7FFPB.js} +1 -1
  71. package/dist/{chunk-7FHFPHEM.js → chunk-VKFYI7AQ.js} +182 -77
  72. package/dist/{chunk-QABAVWEX.js → chunk-W47D3KOB.js} +1 -1
  73. package/dist/{chunk-YLAREDAU.js → chunk-X3U6KEID.js} +1 -1
  74. package/dist/{chunk-5FWVFCQM.js → chunk-XGFYN53T.js} +2 -2
  75. package/dist/{chunk-M4N6IHCQ.js → chunk-XRQBHOBT.js} +7 -1
  76. package/dist/{chunk-XJQ6NN2L.js → chunk-ZBUGFQ7Y.js} +51 -25
  77. package/dist/{clean-ARH23EGW.js → clean-FCBNQ3W2.js} +13 -13
  78. package/dist/cli.js +53 -53
  79. package/dist/{cloud-GBY7MRZM.js → cloud-3FZBQBOM.js} +4 -4
  80. package/dist/{cloudrun-HBVA5UZB.js → cloudrun-CDFL5JBL.js} +9 -11
  81. package/dist/{compare-Z4YNESYN.js → compare-E4332OOZ.js} +26 -25
  82. package/dist/{compiler-6WJ5SVTD.js → compiler-GU5GPO5A.js} +2 -2
  83. package/dist/{component-AR4MS4R7.js → component-VKSV3OKW.js} +3 -3
  84. package/dist/{compositions-ERZVZBYW.js → compositions-GOVXHFXC.js} +9 -9
  85. package/dist/{delete-NWSW3BET.js → delete-JYZTEBLQ.js} +2 -2
  86. package/dist/{deterministicFonts-KXVO7QEL.js → deterministicFonts-RWGQPEZU.js} +2 -2
  87. package/dist/{dist-VKLSNKRZ.js → dist-IDZRZHGE.js} +2 -2
  88. package/dist/{doctor-P4QZQRCB.js → doctor-ND3FZM6S.js} +7 -7
  89. package/dist/{events-F2UVJQIC.js → events-27JU7QRQ.js} +2 -2
  90. package/dist/{events-SV46AWMI.js → events-VL2JIO4R.js} +3 -3
  91. package/dist/{feedback-XS4IK6SW.js → feedback-PKVQWCVT.js} +6 -6
  92. package/dist/{figma-DELISEUP.js → figma-FZ4T4SE3.js} +3 -3
  93. package/dist/fontLocalizeCli.js +9 -9
  94. package/dist/{get-DNGXCEFB.js → get-HUAIHWXR.js} +2 -2
  95. package/dist/{gpuPolicy-JG5PUOJP.js → gpuPolicy-QWJYZLVJ.js} +5 -5
  96. package/dist/{grade-compare-F46JWE4O.js → grade-compare-CJ2ROYD6.js} +26 -25
  97. package/dist/{help-XVEBMX3U.js → help-OJ3QDJYS.js} +1 -1
  98. package/dist/{history-NS4PKG4S.js → history-P4LA65T5.js} +7 -7
  99. package/dist/hyperframe-runtime.js +58 -57
  100. package/dist/hyperframe.manifest.json +1 -1
  101. package/dist/hyperframe.runtime.iife.js +58 -57
  102. package/dist/hyperframes-player.global.js +3 -3
  103. package/dist/{info-DJ6VNESS.js → info-QHRJW6Y3.js} +7 -7
  104. package/dist/{init-TSRTMVRN.js → init-AG6YVVJN.js} +21 -20
  105. package/dist/{inspect-VTZXXDJ4.js → inspect-TT66DYEC.js} +27 -26
  106. package/dist/{installer-3ERHU4CD.js → installer-5ZKUQBWW.js} +4 -4
  107. package/dist/{keyframes-6DN7BOYJ.js → keyframes-CJJGCW3R.js} +6 -6
  108. package/dist/{lambda-RCOIEGL6.js → lambda-3BMEOSP7.js} +10 -12
  109. package/dist/{layout-FFGRLVK4.js → layout-BSDCTMJK.js} +27 -26
  110. package/dist/{lint-MBYIDFKS.js → lint-6CL2R2FK.js} +6 -6
  111. package/dist/{list-KEZDFW5R.js → list-5VYOLEFN.js} +2 -2
  112. package/dist/{login-7ZV374QL.js → login-PNRREAOC.js} +4 -4
  113. package/dist/{media-treatment-LGWWRXAX.js → media-treatment-KHJX73WZ.js} +8 -8
  114. package/dist/{models-TC4K6UQP.js → models-INX67ETR.js} +8 -8
  115. package/dist/{motionShot-4E3RTV5O.js → motionShot-VIUXVMTV.js} +12 -12
  116. package/dist/{normalize-audio-XCGB2IQP.js → normalize-audio-T5QMN476.js} +4 -4
  117. package/dist/{open-JNNJSNTH.js → open-T57KLGFX.js} +4 -4
  118. package/dist/{parakeetRunner-S3DG4BJB.js → parakeetRunner-PCCBODBS.js} +8 -8
  119. package/dist/{pipeline-3SIYCBLU.js → pipeline-GDC7SL5N.js} +5 -5
  120. package/dist/{play-LBPOOD3V.js → play-TQWHYMAT.js} +19 -18
  121. package/dist/{present-PWEN5SDL.js → present-U5OFT6IF.js} +14 -14
  122. package/dist/{preview-IS32RLKM.js → preview-WWTDQQSB.js} +20 -16
  123. package/dist/{producer-4UUUEPPS.js → producer-23NJEJRO.js} +1 -1
  124. package/dist/{projectConfig-K347VIO3.js → projectConfig-OXNA35QN.js} +7 -6
  125. package/dist/{publication-4CQS532O.js → publication-GY3OJ6VH.js} +2 -2
  126. package/dist/{publish-OJYF37FY.js → publish-WZD4NLWM.js} +8 -7
  127. package/dist/{remove-background-HO6YL2HU.js → remove-background-Q7CQ3PJF.js} +6 -6
  128. package/dist/{render-L76SEAMC.js → render-24JWWXMA.js} +3 -3
  129. package/dist/{render-QBQYF2NC.js → render-FTVXKXSQ.js} +24 -23
  130. package/dist/{render-Q6QAXJCN.js → render-RZUU76V5.js} +8 -8
  131. package/dist/{render-batch-JLANN5Y2.js → render-batch-FCR7RX6U.js} +7 -20
  132. package/dist/renderSetupWorker.js +9 -1
  133. package/dist/{resolver-EDUM4DHG.js → resolver-4SPHOGY7.js} +5 -4
  134. package/dist/{sherpa-QEM5XYHD.js → sherpa-VMADZBF7.js} +7 -7
  135. package/dist/skills/media-use/SKILL.md +3 -3
  136. package/dist/skills/media-use/audio/references/requirements.md +7 -7
  137. package/dist/skills/media-use/audio/references/sfx.md +19 -13
  138. package/dist/skills/media-use/audio/scripts/audio.mjs +9 -9
  139. package/dist/skills/media-use/audio/scripts/audio.test.mjs +17 -10
  140. package/dist/skills/media-use/audio/scripts/lib/media-record.mjs +7 -3
  141. package/dist/skills/media-use/audio/scripts/lib/media-record.test.mjs +22 -3
  142. package/dist/skills/media-use/audio/scripts/lib/openverse.mjs +134 -0
  143. package/dist/skills/media-use/audio/scripts/lib/sfx.mjs +120 -89
  144. package/dist/skills/media-use/audio/scripts/lib/sfx.test.mjs +222 -12
  145. package/dist/skills/media-use/references/audio.md +1 -1
  146. package/dist/skills/media-use/references/resolve.md +1 -1
  147. package/dist/skills/media-use/references/setup-providers.md +13 -12
  148. package/dist/skills/media-use/scripts/lib/heygen-cli.mjs +4 -7
  149. package/dist/skills/media-use/scripts/lib/heygen-cli.test.mjs +5 -5
  150. package/dist/skills/media-use/scripts/lib/manifest.d.mts +1 -0
  151. package/dist/skills/media-use/scripts/lib/manifest.mjs +9 -6
  152. package/dist/skills/media-use/scripts/lib/openverse.mjs +134 -0
  153. package/dist/skills/media-use/scripts/lib/openverse.test.mjs +219 -0
  154. package/dist/skills/media-use/scripts/lib/registry.mjs +4 -2
  155. package/dist/skills/media-use/scripts/lib/registry.test.mjs +13 -13
  156. package/dist/skills/media-use/scripts/lib/sfx-provider.mjs +23 -13
  157. package/dist/skills/media-use/scripts/resolve.mjs +45 -55
  158. package/dist/{skills-FSZK6FIG.js → skills-7LBLAEH4.js} +5 -5
  159. package/dist/{skillsUpdateCheck-3354HXDJ.js → skillsUpdateCheck-AHK7CQUP.js} +3 -3
  160. package/dist/{snapshot-5VVMFEMM.js → snapshot-DOS6NQXM.js} +29 -28
  161. package/dist/{src-RYILCNU7.js → src-J6KABXGZ.js} +8 -8
  162. package/dist/{src-ZGMLMQ3B.js → src-VFTQPSQD.js} +4 -4
  163. package/dist/{staticProjectServer-PIVSGEAO.js → staticProjectServer-2YNWMUSU.js} +15 -14
  164. package/dist/studio/assets/{hyperframes-player-B04Yx96S.js → hyperframes-player-DohJxMIU.js} +2 -2
  165. package/dist/studio/assets/{index-D2e0J6kh.js → index-BOkm4Ooc.js} +101 -101
  166. package/dist/studio/assets/{index-D9CDX_Rr.js → index-DfwtrPPt.js} +1 -1
  167. package/dist/studio/index.html +1 -1
  168. package/dist/{studio-api-PHADR6VB.js → studio-api-NEBM56HH.js} +8 -8
  169. package/dist/{studioServer-5AVDKN5V.js → studioServer-LYDRHW7D.js} +45 -39
  170. package/dist/{telemetry-JCTHMPSB.js → telemetry-FAYON6XS.js} +3 -3
  171. package/dist/{timeline-QU2F6R2M.js → timeline-UKJ53XLC.js} +16 -16
  172. package/dist/{tokens-YYK4G36C.js → tokens-SO3ZXEFM.js} +2 -2
  173. package/dist/{transcribe-7ORH7R6O.js → transcribe-IM5UNBSH.js} +6 -6
  174. package/dist/{transcribe-PRG4FLLA.js → transcribe-PS5XSTXN.js} +12 -12
  175. package/dist/{updateCheck-NV7QNANK.js → updateCheck-ZV422M72.js} +2 -2
  176. package/dist/{upgrade-UZXN36J2.js → upgrade-GHG5FWZJ.js} +2 -2
  177. package/dist/{urlDownloader-AW57H722.js → urlDownloader-BOLOMGC7.js} +4 -4
  178. package/dist/{validate-QD53ABUM.js → validate-K4ZGXH2M.js} +20 -20
  179. package/dist/{video-VLVPYQQR.js → video-HUNOZDLT.js} +5 -5
  180. package/package.json +1 -1
  181. package/dist/chunk-BIV5HVTQ.js +0 -3803
@@ -6,24 +6,24 @@ var __filename = __hf_fileURLToPath(import.meta.url);
6
6
  var __dirname = __hf_dirname(__filename);
7
7
  import {
8
8
  maybePromptRenderFeedback
9
- } from "./chunk-2F4HJFGW.js";
9
+ } from "./chunk-PAFCKH3S.js";
10
10
  import {
11
11
  captureArtifactRevision
12
- } from "./chunk-NKG3LTPI.js";
13
- import "./chunk-YT6TFGIS.js";
12
+ } from "./chunk-KQCWIE76.js";
13
+ import "./chunk-IWLOARQZ.js";
14
14
  import "./chunk-X7MTZ4T2.js";
15
15
  import {
16
16
  reportVariableIssues,
17
17
  resolveVariablesArg,
18
18
  validateVariablesAgainstProject
19
- } from "./chunk-RZKQ3G6B.js";
19
+ } from "./chunk-T5LGOTQR.js";
20
20
  import {
21
21
  loadProducer
22
- } from "./chunk-CESKA6VO.js";
22
+ } from "./chunk-NSJLCWLG.js";
23
23
  import {
24
24
  renderJobObservabilityTelemetryPayload,
25
25
  startRenderCpuSampler
26
- } from "./chunk-QLHXC4E6.js";
26
+ } from "./chunk-UJQQITCY.js";
27
27
  import {
28
28
  hasExplicitCompositionArg,
29
29
  parseGifLoopArg,
@@ -32,11 +32,11 @@ import {
32
32
  resolveCompositionEntryArg,
33
33
  resolveDefaultFpsArg,
34
34
  windowsChromeCrashRemediation
35
- } from "./chunk-TEFHMDVR.js";
35
+ } from "./chunk-LMMFO5UV.js";
36
36
  import {
37
37
  sandboxDeniedRemediation
38
38
  } from "./chunk-WICIV6R3.js";
39
- import "./chunk-EFP25BUY.js";
39
+ import "./chunk-JAERN4RH.js";
40
40
  import {
41
41
  formatLintStartupMessage
42
42
  } from "./chunk-6CSYCFQV.js";
@@ -45,7 +45,7 @@ import {
45
45
  } from "./chunk-EDUBJPGL.js";
46
46
  import {
47
47
  resolveProject
48
- } from "./chunk-AP5AVVAB.js";
48
+ } from "./chunk-A3SQJCPU.js";
49
49
  import {
50
50
  errorBox,
51
51
  formatBytes,
@@ -57,7 +57,7 @@ import {
57
57
  import {
58
58
  recordRenderSuccess,
59
59
  registerRenderOutput
60
- } from "./chunk-JGYHWVXQ.js";
60
+ } from "./chunk-GMJ3ILLW.js";
61
61
  import "./chunk-FFDC5OWV.js";
62
62
  import "./chunk-DCAI5DBR.js";
63
63
  import "./chunk-DQBY7FRR.js";
@@ -69,15 +69,16 @@ import {
69
69
  loadProjectConfig,
70
70
  readProjectConfigWithStatus,
71
71
  seedProjectAuthoringSkill
72
- } from "./chunk-J5Z56PU3.js";
72
+ } from "./chunk-EDGJ2OMH.js";
73
73
  import "./chunk-XT7X6QCP.js";
74
74
  import "./chunk-4YYJOFKS.js";
75
75
  import {
76
76
  normalizeSkillSlug
77
77
  } from "./chunk-HVW7ABXD.js";
78
- import "./chunk-5SQHHBAR.js";
79
- import "./chunk-5FWVFCQM.js";
80
- import "./chunk-EELTMBCC.js";
78
+ import "./chunk-JMJTXBVF.js";
79
+ import "./chunk-JHOCK3DG.js";
80
+ import "./chunk-XGFYN53T.js";
81
+ import "./chunk-RTW6WSC7.js";
81
82
  import "./chunk-AWDFDFI3.js";
82
83
  import "./chunk-P6LJ4Y32.js";
83
84
  import "./chunk-GMECXFAN.js";
@@ -86,8 +87,8 @@ import {
86
87
  trackRenderError,
87
88
  trackRenderObservation,
88
89
  trackRenderPreflightRejected
89
- } from "./chunk-FQJDV2RI.js";
90
- import "./chunk-FSX7GTBB.js";
90
+ } from "./chunk-6I24ZSCR.js";
91
+ import "./chunk-5HLJ4JMB.js";
91
92
  import "./chunk-VWG7OQKU.js";
92
93
  import {
93
94
  bytesToMb
@@ -128,11 +129,11 @@ import {
128
129
  } from "./chunk-ISN5GRYI.js";
129
130
  import {
130
131
  VERSION
131
- } from "./chunk-BNEKKUPG.js";
132
+ } from "./chunk-BYFG74OA.js";
132
133
  import "./chunk-EOVYQ3IG.js";
133
134
  import {
134
135
  createRenderCancellationScope
135
- } from "./chunk-A6K7M46D.js";
136
+ } from "./chunk-AWSVUIWG.js";
136
137
  import {
137
138
  H264EncoderUnavailableError,
138
139
  chromeLaunchRemediation,
@@ -148,8 +149,8 @@ import {
148
149
  MIN_VP9_CPU_USED,
149
150
  audioFailureDiagnostics,
150
151
  isVideoFrameFormat
151
- } from "./chunk-7FHFPHEM.js";
152
- import "./chunk-P24X6CGY.js";
152
+ } from "./chunk-VKFYI7AQ.js";
153
+ import "./chunk-FAORS3UR.js";
153
154
  import "./chunk-KCF6GHJP.js";
154
155
  import "./chunk-JYVGYKXG.js";
155
156
  import "./chunk-7KDQAD2W.js";
@@ -158,8 +159,8 @@ import {
158
159
  fpsToFfmpegArg,
159
160
  fpsToNumber,
160
161
  parseFps
161
- } from "./chunk-O3J7BHBU.js";
162
- import "./chunk-BIV5HVTQ.js";
162
+ } from "./chunk-QZUVPWC4.js";
163
+ import "./chunk-6M3IPJS6.js";
163
164
  import "./chunk-VC76R6W2.js";
164
165
  import "./chunk-UJKQWGFF.js";
165
166
  import {
@@ -690,7 +691,7 @@ async function executeRenderPlan(plan, dependencies, cancellation) {
690
691
  let batchModule;
691
692
  let preparedBatch;
692
693
  if (plan.batchPath) {
693
- batchModule = await import("./batchRender-YKTTAIHH.js");
694
+ batchModule = await import("./batchRender-KWBVAUE3.js");
694
695
  try {
695
696
  preparedBatch = batchModule.prepareBatchRender({
696
697
  batchPath: plan.batchPath,
@@ -35,18 +35,18 @@ import {
35
35
  reportVariableIssues,
36
36
  resolveVariablesArg,
37
37
  validateVariablesAgainstProject
38
- } from "./chunk-RZKQ3G6B.js";
38
+ } from "./chunk-T5LGOTQR.js";
39
39
  import {
40
40
  resolveProject
41
- } from "./chunk-AP5AVVAB.js";
41
+ } from "./chunk-A3SQJCPU.js";
42
42
  import {
43
43
  errorBox,
44
44
  formatBytes,
45
45
  formatDuration
46
46
  } from "./chunk-K2FLNJVB.js";
47
47
  import "./chunk-442JNXRM.js";
48
- import "./chunk-FQJDV2RI.js";
49
- import "./chunk-FSX7GTBB.js";
48
+ import "./chunk-6I24ZSCR.js";
49
+ import "./chunk-5HLJ4JMB.js";
50
50
  import "./chunk-VWG7OQKU.js";
51
51
  import "./chunk-QWQ6GQTI.js";
52
52
  import {
@@ -61,12 +61,12 @@ import {
61
61
  } from "./chunk-ZTZA4UWZ.js";
62
62
  import {
63
63
  withMeta
64
- } from "./chunk-K5PU5ISL.js";
64
+ } from "./chunk-GSABLXZV.js";
65
65
  import "./chunk-K4WIOZFP.js";
66
66
  import "./chunk-XUXGIA7H.js";
67
67
  import "./chunk-WERLJGIC.js";
68
68
  import "./chunk-ISN5GRYI.js";
69
- import "./chunk-BNEKKUPG.js";
69
+ import "./chunk-BYFG74OA.js";
70
70
  import {
71
71
  downloadToFile
72
72
  } from "./chunk-BXCMXMJQ.js";
@@ -74,8 +74,8 @@ import "./chunk-EOVYQ3IG.js";
74
74
  import "./chunk-XT6MXC7A.js";
75
75
  import "./chunk-JYVGYKXG.js";
76
76
  import "./chunk-7KDQAD2W.js";
77
- import "./chunk-O3J7BHBU.js";
78
- import "./chunk-BIV5HVTQ.js";
77
+ import "./chunk-QZUVPWC4.js";
78
+ import "./chunk-6M3IPJS6.js";
79
79
  import "./chunk-VC76R6W2.js";
80
80
  import "./chunk-UJKQWGFF.js";
81
81
  import "./chunk-YMS5FOMC.js";
@@ -14,12 +14,15 @@ import {
14
14
  loadProjectVariableSchema,
15
15
  reportVariableIssues,
16
16
  validateVariablesAgainstSchema
17
- } from "./chunk-RZKQ3G6B.js";
17
+ } from "./chunk-T5LGOTQR.js";
18
18
  import "./chunk-FH7WODJH.js";
19
19
  import {
20
20
  errorBox
21
21
  } from "./chunk-K2FLNJVB.js";
22
22
  import "./chunk-442JNXRM.js";
23
+ import {
24
+ runWithConcurrencyLimit
25
+ } from "./chunk-JHOCK3DG.js";
23
26
  import {
24
27
  failCommand,
25
28
  setCommandExitCode
@@ -27,8 +30,8 @@ import {
27
30
  import {
28
31
  c
29
32
  } from "./chunk-ZTZA4UWZ.js";
30
- import "./chunk-O3J7BHBU.js";
31
- import "./chunk-BIV5HVTQ.js";
33
+ import "./chunk-QZUVPWC4.js";
34
+ import "./chunk-6M3IPJS6.js";
32
35
  import "./chunk-VC76R6W2.js";
33
36
  import "./chunk-UJKQWGFF.js";
34
37
  import "./chunk-YMS5FOMC.js";
@@ -269,24 +272,8 @@ function parseBatchFile(path) {
269
272
  }
270
273
  return out;
271
274
  }
272
- async function runWithConcurrencyLimit(inputs, limit, worker) {
273
- if (limit < 1) throw new Error(`runWithConcurrencyLimit: limit must be \u2265 1, got ${limit}`);
274
- const results = new Array(inputs.length);
275
- let cursor = 0;
276
- const workerCount = Math.min(limit, inputs.length);
277
- await Promise.all(
278
- Array.from({ length: workerCount }, async () => {
279
- while (cursor < inputs.length) {
280
- const idx = cursor++;
281
- results[idx] = await worker(inputs[idx], idx);
282
- }
283
- })
284
- );
285
- return results;
286
- }
287
275
  export {
288
276
  buildLambdaBatchRenderConfig,
289
277
  parseBatchFile,
290
- runRenderBatch,
291
- runWithConcurrencyLimit
278
+ runRenderBatch
292
279
  };
@@ -43,10 +43,18 @@ var disposeSignalHandlers = installRenderSetupSignalHandlers(
43
43
  (signal) => process.kill(process.pid, signal),
44
44
  process.env.HYPERFRAMES_RENDER_DETACHED !== "1"
45
45
  );
46
+ function lowerPriority() {
47
+ try {
48
+ setPriority(constants.priority.PRIORITY_LOW);
49
+ } catch (error) {
50
+ process.stderr.write(`Lint runs at normal priority: ${error.message}
51
+ `);
52
+ }
53
+ }
46
54
  async function runMode() {
47
55
  if (mode === "browser") return ensureBrowser(input);
48
56
  if (mode === "lint") {
49
- setPriority(constants.priority.PRIORITY_LOW);
57
+ lowerPriority();
50
58
  return lintProject(
51
59
  input.projectDir,
52
60
  input.entryFile,
@@ -11,13 +11,14 @@ import {
11
11
  resolveItemWithDependencies,
12
12
  resolveItemsByTag,
13
13
  unreachableRegistryMessage
14
- } from "./chunk-5SQHHBAR.js";
15
- import "./chunk-EELTMBCC.js";
14
+ } from "./chunk-JMJTXBVF.js";
15
+ import "./chunk-JHOCK3DG.js";
16
+ import "./chunk-RTW6WSC7.js";
16
17
  import "./chunk-AWDFDFI3.js";
17
18
  import "./chunk-P6LJ4Y32.js";
18
19
  import "./chunk-GMECXFAN.js";
19
- import "./chunk-O3J7BHBU.js";
20
- import "./chunk-BIV5HVTQ.js";
20
+ import "./chunk-QZUVPWC4.js";
21
+ import "./chunk-6M3IPJS6.js";
21
22
  import "./chunk-VC76R6W2.js";
22
23
  import "./chunk-UJKQWGFF.js";
23
24
  import "./chunk-YMS5FOMC.js";
@@ -17,24 +17,24 @@ import {
17
17
  sherpaRuntimeLoadError,
18
18
  sherpaUnsupportedReason,
19
19
  transcribeWithSherpa
20
- } from "./chunk-U7P2XTRY.js";
20
+ } from "./chunk-PECICVTJ.js";
21
21
  import "./chunk-BXCMXMJQ.js";
22
22
  import "./chunk-3DKN5WKL.js";
23
23
  import "./chunk-EOVYQ3IG.js";
24
- import "./chunk-UISU4SYG.js";
25
- import "./chunk-A6K7M46D.js";
24
+ import "./chunk-V2T7FFPB.js";
25
+ import "./chunk-AWSVUIWG.js";
26
26
  import "./chunk-6BEFEWFB.js";
27
27
  import "./chunk-X3SCQP2A.js";
28
28
  import "./chunk-PO2SDVQA.js";
29
29
  import "./chunk-IK3SOMZ4.js";
30
30
  import "./chunk-XT6MXC7A.js";
31
- import "./chunk-7FHFPHEM.js";
32
- import "./chunk-P24X6CGY.js";
31
+ import "./chunk-VKFYI7AQ.js";
32
+ import "./chunk-FAORS3UR.js";
33
33
  import "./chunk-KCF6GHJP.js";
34
34
  import "./chunk-JYVGYKXG.js";
35
35
  import "./chunk-7KDQAD2W.js";
36
- import "./chunk-O3J7BHBU.js";
37
- import "./chunk-BIV5HVTQ.js";
36
+ import "./chunk-QZUVPWC4.js";
37
+ import "./chunk-6M3IPJS6.js";
38
38
  import "./chunk-VC76R6W2.js";
39
39
  import "./chunk-UJKQWGFF.js";
40
40
  import "./chunk-YMS5FOMC.js";
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: media-use
3
- description: Agent Media OS for a HyperFrames project. Resolve BGM, SFX, image, icon, brand logo, voice, color grade, or LUT into a frozen local file or paste-ready block + ledger record (one verb, `resolve`); generate via TTS / music / image models when the catalog misses; produce voiceover, transcription, captions, and background removal through one shared audio engine; operate on media (cut / reframe / transform); and reuse assets across projects. Also use for vague feedback that real footage looks dark, flat, boring, should feel retro/camcorder/print/ASCII, needs privacy, or needs a media reveal. When the host app provides its own music or sound-effect tools, use those for music and sound effects; `resolve --type bgm|sfx` needs the heygen CLI. When `HEYGEN_API_BASE` is set, HeyGen calls go through that host with no CLI sign-in.
3
+ description: Agent Media OS for a HyperFrames project. Resolve BGM, SFX, image, icon, brand logo, voice, color grade, or LUT into a frozen local file or paste-ready block + ledger record (one verb, `resolve`); generate via TTS / music / image models when the catalog misses; produce voiceover, transcription, captions, and background removal through one shared audio engine; operate on media (cut / reframe / transform); and reuse assets across projects. Also use for vague feedback that real footage looks dark, flat, boring, should feel retro/camcorder/print/ASCII, needs privacy, or needs a media reveal. When the host app provides its own music or sound-effect tools, use those for music and sound effects; `resolve --type bgm` needs the heygen CLI, while `--type sfx` needs no account (Openverse, then a bundled library). When `HEYGEN_API_BASE` is set, HeyGen calls go through that host with no CLI sign-in.
4
4
  ---
5
5
 
6
6
  **Plugin installs:** Before setup or freshness commands, follow [plugin execution rules](../hyperframes/references/plugin-installation.md) when this skill is inside a HyperFrames plugin. Standalone installs keep the update instructions below.
@@ -13,7 +13,7 @@ Only when `HEYGEN_API_BASE` is set in your environment (a host app set it and pa
13
13
 
14
14
  First run otherwise (no `HEYGEN_API_BASE`), when you will use HeyGen media (catalog search, TTS, avatar video): install and sign in to the `heygen` CLI (the free-usage path), then verify with `npx hyperframes media-use resolve --doctor`. Setup and providers: `references/setup-providers.md`.
15
15
 
16
- Music and sound effects inside a host app: when the app you run in gives you its own music or sound-effect tools, use those. Without `HEYGEN_API_BASE`, `resolve --type bgm` and `--type sfx` search the HeyGen catalog through the `heygen` CLI; without it they fail and say so (`sfx` still answers from its bundled library).
16
+ Music and sound effects inside a host app: when the app you run in gives you its own music or sound-effect tools, use those. Without `HEYGEN_API_BASE`, `resolve --type bgm` searches the HeyGen catalog through the `heygen` CLI and fails without it, saying so. `resolve --type sfx` searches Openverse (CC0 and CC BY only, no account) and falls back to its bundled library offline; credit CC BY sounds as `audio/references/sfx.md` says.
17
17
 
18
18
  Without `HEYGEN_API_BASE`, before generating a voiceover or an avatar video, tell the person: signing in to the heygen CLI with OAuth (`heygen auth login --oauth`) gives a free allowance for TTS voiceover and avatar videos, while an API key bills API credits.
19
19
 
@@ -28,7 +28,7 @@ Returns one line: `resolved <id> → <path> (<type>, <metadata>)`. All search no
28
28
  | Type | One-line intent |
29
29
  | ------- | -------------------------------------------------------------------------------- |
30
30
  | `bgm` | background music (HeyGen catalog via the `heygen` CLI, 10k+ tracks) |
31
- | `sfx` | sound effects (bundled 19-file library + catalog via the `heygen` CLI) |
31
+ | `sfx` | sound effects (Openverse CC0 / CC BY, bundled 21-file library offline) |
32
32
  | `image` | photos, backgrounds (HeyGen asset search, 75k+ vectors) |
33
33
  | `icon` | icons, symbols (transparent) |
34
34
  | `logo` | official brand marks (theSVG → GitHub avatar → favicon; never redrawn) |
@@ -4,13 +4,13 @@
4
4
 
5
5
  Run `npx hyperframes auth status` to see what's configured and which engines a workflow will use (see the skill's **Preflight** section). Keys resolve in this order — **first match wins**:
6
6
 
7
- | Provider | Resolution order (first non-empty wins) | Local deps when used |
8
- | ------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
9
- | **HeyGen** (TTS + BGM/SFX retrieval) | `$HEYGEN_API_KEY` → `$HYPERFRAMES_API_KEY` → `~/.heygen/credentials` (shared with heygen-cli; `$HEYGEN_CONFIG_DIR` overrides the dir; written by `hyperframes auth login`) | none (REST) |
10
- | **ElevenLabs** (TTS fallback) | `$ELEVENLABS_API_KEY` | `pip install elevenlabs` |
11
- | **Lyria** (BGM fallback) | `$GEMINI_API_KEY` → `$GOOGLE_API_KEY` | `pip install google-genai` |
12
- | **Kokoro** (TTS, no key) | always — final voice fallback | `pip install kokoro-onnx soundfile` |
13
- | **MusicGen** (BGM, no key) | always — final music fallback | `pip install transformers torch soundfile numpy` |
7
+ | Provider | Resolution order (first non-empty wins) | Local deps when used |
8
+ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
9
+ | **HeyGen** (TTS + BGM retrieval) | `$HEYGEN_API_KEY` → `$HYPERFRAMES_API_KEY` → `~/.heygen/credentials` (shared with heygen-cli; `$HEYGEN_CONFIG_DIR` overrides the dir; written by `hyperframes auth login`) | none (REST) |
10
+ | **ElevenLabs** (TTS fallback) | `$ELEVENLABS_API_KEY` | `pip install elevenlabs` |
11
+ | **Lyria** (BGM fallback) | `$GEMINI_API_KEY` → `$GOOGLE_API_KEY` | `pip install google-genai` |
12
+ | **Kokoro** (TTS, no key) | always — final voice fallback | `pip install kokoro-onnx soundfile` |
13
+ | **MusicGen** (BGM, no key) | always — final music fallback | `pip install transformers torch soundfile numpy` |
14
14
 
15
15
  `hyperframes auth login` (browser OAuth) is the recommended setup: one sign-in, every project, no per-repo `.env`. An OAuth login is sent as `Authorization: Bearer`; an API key as `X-Api-Key`; both are tagged with `X-HeyGen-Source: cli`. OAuth CLI users can consume the web-plan free allowance for HeyGen TTS (10 min/month); API keys follow the normal API billing path. With no HeyGen credential, voice/BGM run fully locally (Kokoro / MusicGen) — `hyperframes auth status` and `hyperframes doctor` both report whether those local deps are installed.
16
16
 
@@ -1,35 +1,41 @@
1
1
  # Sound effects (SFX)
2
2
 
3
- Named sound effects, produced by the shared audio engine (`scripts/audio.mjs` → `scripts/lib/sfx.mjs`). **Provider-gated** by the engine's one switch — whether a HeyGen credential is present, decided once (not per cue):
3
+ Named sound effects, produced by the shared audio engine (`scripts/audio.mjs` → `scripts/lib/sfx.mjs`). No account or key is needed:
4
4
 
5
- - **HeyGen credential present → retrieve every cue** from HeyGen's audio library (`/v3/audio/sounds`, `type=sound_effects`, `min_score=0.4`). Search-and-download, **not** generation. The bundled library is NOT consulted.
6
- - **No credential → the bundled 21-file library** (`assets/sfx/` + `manifest.json`): match each cue name, copy the matched file into the project. Offline, deterministic, free.
5
+ - **Openverse first, per cue.** Each cue is searched on [Openverse](https://openverse.org)'s free audio API (most sound effects come from Freesound). Search-and-download, **not** generation.
6
+ - **The bundled 21-file library is the fallback** (`assets/sfx/` + `manifest.json`): a cue Openverse has no usable match for, and every cue once Openverse is offline or rate limited, is matched against it and the file copied into the project.
7
7
 
8
- There is no `npx hyperframes sfx` command. SFX is never generated — it is retrieved (online) or taken from the bundled library (offline).
8
+ There is no `npx hyperframes sfx` command. SFX is never generated — it is retrieved from Openverse (online) or taken from the bundled library (offline). `npx hyperframes media-use resolve --type sfx` follows the same order (`--local-only` skips Openverse).
9
+
10
+ ## Licences
11
+
12
+ Only **CC0** and **CC BY** sounds are used: never NonCommercial, ShareAlike or NoDerivatives. Each CC BY sound is credited in the project's `assets/sfx/CREDITS.md` (title, creator, licence, source link; for `resolve`, in a `CREDITS.md` beside the sound files it saves) and its `audio_meta.sfx[]` entry carries `license` and `credit`. Tell the person to include those credits wherever the video is published.
9
13
 
10
14
  ## Cues — request → meta
11
15
 
12
- Each line names the effects it wants: `lines[].sfx: ["whoosh", "ui click"]`. The engine flattens these into cues, resolves them per the switch, dedupes identical `(id, name)` pairs (the same effect named twice downloads/copies once), and writes `audio_meta.sfx[]`:
16
+ Each line names the effects it wants: `lines[].sfx: ["whoosh", "ui click"]`. The engine flattens these into cues, resolves each, dedupes identical `(id, name)` pairs (the same effect named twice downloads/copies once), and writes `audio_meta.sfx[]`:
13
17
 
14
18
  ```jsonc
15
19
  {
16
20
  "id": "3", // joins the cue to the caller's model (frame / scene / segment)
17
21
  "name": "whoosh",
18
22
  "file": "assets/sfx/whoosh.mp3", // downloaded or copied, relative to project root
19
- "source": "heygen" | "local", // which route resolved it
23
+ "source": "openverse" | "local", // which route resolved it
20
24
  "offset_s": 0, // delay from the line's start
21
25
  "duration_s": 0.57,
22
- "volume": 0.35 // SFX sit UNDER voice + BGM
26
+ "volume": 0.35, // SFX sit UNDER voice + BGM
27
+ "license": "by", // Openverse only: "cc0" or "by"
28
+ "credit": "\"Swoosh\" by Ana is licensed under CC BY 4.0. …" // Openverse only
23
29
  }
24
30
  ```
25
31
 
26
32
  A cue that matches nothing is **skipped** (recorded as an anomaly); SFX never blocks a render. Neither route replaces a file of yours already at the output name: the cue gets the next free name (`whoosh-2.mp3`), reported as an anomaly, and `file` carries the real path.
27
33
 
28
- ## HeyGen retrieval (credentialed)
34
+ ## Openverse
29
35
 
30
- `searchSounds(name, "sound_effects", { limit: 3, minScore: 0.4 })` → top hit → `assets/sfx/<slug>.mp3`. Results are ranked by `score` (each carries a presigned `audio_url`, `duration`, `description`). The floor is **0.4** because good SFX hits score ~0.5–0.67 — below the API's default `0.7`, which would silently drop most named cues (only whoosh/swoosh-family clears 0.7). `duration_s` comes from the result (else 1.0). Name effects concretely (`glass shatter`, not `dramatic sound`); a vague query returns a poor match.
36
+ One search per distinct effect name (20 results, `license=cc0,by`; each result's licence is checked again). The pick keeps Openverse's relevance order, prefers clips that fit a cue (15 s at most; past ~4 s ranks lower) and CC0 over CC BY when they are close. The file lands at `assets/sfx/<slug>.<ext>` and `duration_s` comes from the result. Name effects concretely (`glass shatter`, not `dramatic sound`); a vague query returns a poor match. Anonymous use allows 20 searches a minute and 200 a day: past that, the rest of the run uses the bundled library.
31
37
 
32
- ## Bundled library (no credential)
38
+ ## Bundled library (fallback)
33
39
 
34
40
  21 curated files in `assets/sfx/`, indexed by `manifest.json` — `{ file, duration, description }` per key (e.g. `whoosh`, `pop`, `click`, `chime`, `riser`, `impact-bass-1`, `glitch-1`, `typing`, …). A cue name resolves by **manifest key, file basename, or slug**, so `whoosh`, `whoosh.mp3`, or `"ui click"` (→ slug) all match. Matched files are copied into the project's `assets/sfx/`; `duration_s` comes from the manifest, so timing is known **offline** — e.g. `riser` is 10.03s, so trigger it at `climax − 10.03s`. The manifest's `description` field carries placement hints per effect; read `assets/sfx/manifest.json` for the full set and usage.
35
41
 
@@ -37,6 +43,6 @@ A cue that matches nothing is **skipped** (recorded as an anomaly); SFX never bl
37
43
 
38
44
  - **Volume ~0.35.** SFX must sit under narration and BGM, not fight them.
39
45
  - **No match → skip, don't fail.** A missing effect logs an anomaly and moves on; never a render blocker.
40
- - **Retrieval (credentialed) or bundled library (offline) — never generation.** You search HeyGen by text, or match a name against the 21-file manifest.
41
- - **One asset per distinct name.** Reuse across lines is deduped to a single download/copy, many cues.
42
- - **The switch is global, not per cue.** With a credential, retrieval handles even the long tail (effects not in the 21); without one, only the 21 bundled names resolve.
46
+ - **Retrieval (Openverse) or bundled library (offline) — never generation.**
47
+ - **One asset per distinct name.** Reuse across lines is deduped to a single search and download, many cues.
48
+ - **Credit CC BY sounds.** `CREDITS.md` lists them; keep it with the project.
@@ -6,12 +6,12 @@
6
6
  //
7
7
  // node <MEDIA_DIR>/scripts/audio.mjs --request ./audio_request.json --hyperframes . --out ./audio_meta.json
8
8
  //
9
- // The three capabilities degrade on ONE switch — whether HeyGen is configured
10
- // (credential present, NOT the CLI). This mirrors the table in ../SKILL.md:
9
+ // TTS and BGM degrade on ONE switch — whether HeyGen is configured (credential
10
+ // present, NOT the CLI). SFX needs no credential. This mirrors ../SKILL.md:
11
11
  //
12
12
  // TTS : HeyGen REST → ElevenLabs → Kokoro (CLI)
13
13
  // BGM : HeyGen retrieve → (no credential) Lyria/MusicGen generate
14
- // SFX : HeyGen retrieve → (no credential) bundled 19-file library
14
+ // SFX : Openverse (CC0 / CC BY) → (offline, rate limited, no match) bundled library
15
15
  //
16
16
  // ── audio_request.json (input) ────────────────────────────────────────────────
17
17
  // {
@@ -31,7 +31,7 @@
31
31
  // bgm: { path, volume, mode, query?, duration_s? } | null,
32
32
  // bgm_pending, bgm_provider, bgm_pid, bgm_log, bgm_mode, bgm_target_duration_s, …,
33
33
  // voices: [ { id, path, duration_s, words: [{id,text,start,end}] } ],
34
- // sfx: [ { id, name, file, source, offset_s, duration_s, volume } ],
34
+ // sfx: [ { id, name, file, source, offset_s, duration_s, volume, license?, credit? } ],
35
35
  // total_duration_s }
36
36
  //
37
37
  // --only tts,bgm,sfx runs a subset and MERGES into an existing --out (so a
@@ -52,7 +52,7 @@ import {
52
52
  withWordIds,
53
53
  } from "./lib/tts.mjs";
54
54
  import { generateBgmDetached, inferBgmPrompt, retrieveBgm } from "./lib/bgm.mjs";
55
- import { resolveSfx } from "./lib/sfx.mjs";
55
+ import { BUNDLED_SFX_DIR, resolveSfx } from "./lib/sfx.mjs";
56
56
  import { mapWithConcurrency } from "./lib/concurrency.mjs";
57
57
  import { openAudioMeta } from "./lib/audio-meta.mjs";
58
58
  import { recordInManifest, voicePaths, writtenAssets } from "./lib/media-record.mjs";
@@ -83,7 +83,7 @@ const ttsConcurrency = Math.max(1, Number(process.env.HYPERFRAMES_TTS_CONCURRENC
83
83
  const hyperframesDir = resolve(flag("hyperframes", "."));
84
84
  const requestPath = resolve(flag("request", join(hyperframesDir, "audio_request.json")));
85
85
  const outPath = resolve(flag("out", join(hyperframesDir, "audio_meta.json")));
86
- const sfxLibDir = resolve(flag("sfx-lib", join(HERE, "..", "assets", "sfx")));
86
+ const sfxLibDir = resolve(flag("sfx-lib", BUNDLED_SFX_DIR));
87
87
  const lyriaRecipe = resolve(flag("lyria-recipe", join(HERE, "lyria-recipe.py")));
88
88
  const onlyArg = flag("only", "tts,bgm,sfx");
89
89
  const only = new Set(
@@ -275,12 +275,12 @@ if (only.has("sfx")) {
275
275
  .map((name) => ({ id: String(l.id), name: String(name).trim() }))
276
276
  .filter((c) => c.name),
277
277
  );
278
- const headers = heygenOK && cues.length ? heygenAuthHeaders() : null;
279
- const res = await resolveSfx({ cues, heygenOK, headers, hyperframesDir, sfxLibDir });
278
+ const res = await resolveSfx({ cues, hyperframesDir, sfxLibDir });
280
279
  sfx = res.sfx;
281
280
  anomalies.push(...res.anomalies);
281
+ const openverse = sfx.filter((s) => s.source === "openverse").length;
282
282
  console.error(
283
- `· sfx: ${sfx.length} cue(s) resolved (${heygenOK ? "heygen retrieval" : "bundled library"})`,
283
+ `· sfx: ${sfx.length} cue(s) resolved (${openverse} Openverse, ${sfx.length - openverse} bundled library)`,
284
284
  );
285
285
  }
286
286
 
@@ -10,7 +10,11 @@ import { resolveSfx } from "./lib/sfx.mjs";
10
10
 
11
11
  // Proves the relocated engine (skills/media-use/audio/) still resolves its
12
12
  // bundled SFX library from the moved location — the path most likely to break
13
- // on a subtree move. Offline (heygenOK:false), no network.
13
+ // on a subtree move. Openverse is unreachable unless a test serves it.
14
+ const offline = async () => {
15
+ throw new TypeError("fetch failed");
16
+ };
17
+ globalThis.fetch = offline;
14
18
 
15
19
  const HERE = dirname(fileURLToPath(import.meta.url));
16
20
  const sfxLibDir = join(HERE, "..", "assets", "sfx"); // same offset the engine uses
@@ -21,7 +25,6 @@ test("bundled SFX library resolves from the relocated path", async () => {
21
25
  try {
22
26
  const { sfx, anomalies } = await resolveSfx({
23
27
  cues: [{ id: "1", name: "whoosh" }],
24
- heygenOK: false,
25
28
  hyperframesDir: dir,
26
29
  sfxLibDir,
27
30
  });
@@ -39,7 +42,6 @@ test("an unknown cue is reported, not fatal", async () => {
39
42
  try {
40
43
  const { sfx, anomalies } = await resolveSfx({
41
44
  cues: [{ id: "1", name: "definitely-not-a-real-sfx" }],
42
- heygenOK: false,
43
45
  hyperframesDir: dir,
44
46
  sfxLibDir,
45
47
  });
@@ -59,7 +61,6 @@ test("a person's own file under a bundled name survives, and the cue gets the ne
59
61
  const resolve = () =>
60
62
  resolveSfx({
61
63
  cues: [{ id: "1", name: "whoosh" }],
62
- heygenOK: false,
63
64
  hyperframesDir: dir,
64
65
  sfxLibDir,
65
66
  });
@@ -89,18 +90,24 @@ test("two effects never share a file when one's name is taken by the person, run
89
90
  try {
90
91
  mkdirSync(join(dir, "assets", "sfx"), { recursive: true });
91
92
  writeFileSync(join(dir, "assets", "sfx", "glitch.mp3"), "the person's own glitch");
92
- const realFetch = globalThis.fetch;
93
93
  globalThis.fetch = async (url) => {
94
- const query = new URL(url).searchParams.get("query");
94
+ const query = new URL(url).searchParams.get("q");
95
95
  if (query)
96
- return Response.json({ data: [{ audio_url: `https://sound.test/${query}`, score: 0.6 }] });
96
+ return Response.json({
97
+ results: [
98
+ {
99
+ license: "cc0",
100
+ filetype: "mp3",
101
+ duration: 500,
102
+ url: `https://sound.test/${encodeURIComponent(query)}`,
103
+ },
104
+ ],
105
+ });
97
106
  return new Response(`bytes of ${new URL(url).pathname}`);
98
107
  };
99
108
  const run = async (names) => {
100
109
  const { sfx } = await resolveSfx({
101
110
  cues: names.map((name, index) => ({ id: String(index), name })),
102
- heygenOK: true,
103
- headers: {},
104
111
  hyperframesDir: dir,
105
112
  sfxLibDir,
106
113
  });
@@ -119,7 +126,7 @@ test("two effects never share a file when one's name is taken by the person, run
119
126
  "assets/sfx/glitch-2.mp3",
120
127
  ]);
121
128
  } finally {
122
- globalThis.fetch = realFetch;
129
+ globalThis.fetch = offline;
123
130
  }
124
131
  } finally {
125
132
  rmSync(dir, { recursive: true, force: true });
@@ -43,7 +43,12 @@ export function voicePaths(hyperframesDir, lines, anomalies) {
43
43
  return paths;
44
44
  }
45
45
 
46
- const SFX_SOURCES = { heygen: "search", local: "bundled" };
46
+ // A cue's source as the manifest records it, and who provided it. A source missing here records as the person's
47
+ // file, so every rerun would write a numbered copy beside it.
48
+ const SFX_SOURCES = {
49
+ openverse: { source: "search", provider: "openverse.audio" },
50
+ local: { source: "bundled", provider: "bundled.sfx" },
51
+ };
47
52
 
48
53
  // The files one engine run wrote, each with how it was made, for the project's media manifest.
49
54
  export function writtenAssets({ only, lines, voices, ttsProvider, bgm, bgmFields, sfx }) {
@@ -73,8 +78,7 @@ export function writtenAssets({ only, lines, voices, ttsProvider, bgm, bgmFields
73
78
  }
74
79
  if (only.has("sfx")) {
75
80
  for (const cue of new Map(sfx.map((entry) => [entry.file, entry])).values()) {
76
- const source = SFX_SOURCES[cue.source];
77
- const provider = source === "search" ? "heygen" : "bundled.sfx";
81
+ const { source, provider } = SFX_SOURCES[cue.source];
78
82
  assets.push({
79
83
  path: cue.file,
80
84
  type: "sfx",
@@ -1,6 +1,6 @@
1
1
  import { strict as assert } from "node:assert";
2
2
  import { test } from "node:test";
3
- import { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
3
+ import { mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import { tmpdir } from "node:os";
6
6
  import { findByPrompt, readManifest } from "../../../scripts/lib/manifest.mjs";
@@ -97,7 +97,7 @@ test("music and sound effects are marked by where they came from", () => {
97
97
  sfx: [
98
98
  { file: "assets/sfx/whoosh.mp3", name: "whoosh", source: "local" },
99
99
  { file: "assets/sfx/whoosh.mp3", name: "whoosh", source: "local" },
100
- { file: "assets/sfx/glass.mp3", name: "glass", source: "heygen" },
100
+ { file: "assets/sfx/glass.mp3", name: "glass", source: "openverse" },
101
101
  ],
102
102
  });
103
103
 
@@ -106,11 +106,30 @@ test("music and sound effects are marked by where they came from", () => {
106
106
  [
107
107
  ["assets/bgm/track.mp3", "search", undefined],
108
108
  ["assets/sfx/whoosh.mp3", "bundled", "bundled.sfx"],
109
- ["assets/sfx/glass.mp3", "search", "heygen"],
109
+ ["assets/sfx/glass.mp3", "search", "openverse.audio"],
110
110
  ],
111
111
  );
112
112
  });
113
113
 
114
+ test("a rerun of an Openverse sound effect writes over its own file, not a numbered copy", (t) => {
115
+ const dir = project(t);
116
+ mkdirSync(join(dir, "assets/sfx"), { recursive: true });
117
+ const anomalies = [];
118
+ for (let run = 0; run < 3; run++) {
119
+ const file = agentWritePath(dir, "assets/sfx/door-knock.mp3", { anomalies });
120
+ writeFileSync(join(dir, file), "knock");
121
+ const sfx = [{ file, name: "door knock", source: "openverse", duration_s: 1 }];
122
+ recordInManifest(
123
+ dir,
124
+ writtenAssets({ only: new Set(["sfx"]), lines: [], voices: [], sfx, ...noBgm }),
125
+ );
126
+ }
127
+
128
+ assert.deepEqual(readdirSync(join(dir, "assets/sfx")), ["door-knock.mp3"]);
129
+ assert.deepEqual(anomalies, []);
130
+ assert.equal(readManifest(dir).length, 1);
131
+ });
132
+
114
133
  test("music made locally is marked generated once it is ready, not while pending", () => {
115
134
  const written = (bgm_pending) =>
116
135
  writtenAssets({