hyperframes 0.8.160 → 0.8.161

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 (100) hide show
  1. package/dist/{add-OGBTJCU4.js → add-7U5TQGSQ.js} +5 -5
  2. package/dist/{asset-DKQFFGPP.js → asset-N3JO5LHY.js} +2 -2
  3. package/dist/audio-QNPSENQR.js +1131 -0
  4. package/dist/{auth-AQMRAFXN.js → auth-HINUM4A7.js} +1 -1
  5. package/dist/{autoUpdate-NFQB7V2X.js → autoUpdate-AAMND4XK.js} +2 -2
  6. package/dist/{backgroundChecks-7JKE2FIU.js → backgroundChecks-FXIEHPND.js} +3 -3
  7. package/dist/backgroundChecksWorker.js +3 -3
  8. package/dist/beats-UZNREIRU.js +239 -0
  9. package/dist/{benchmark-RRU67WEY.js → benchmark-YM3QXPH6.js} +5 -5
  10. package/dist/{browser-K4TP4ZM2.js → browser-SD3T2XMH.js} +3 -3
  11. package/dist/{capture-T2TBROMS.js → capture-GUO23PVN.js} +1 -1
  12. package/dist/{catalog-IMIHQ4KX.js → catalog-6PF7KZAZ.js} +5 -5
  13. package/dist/{catch-up-UY5MJWOG.js → catch-up-5LTQTD3X.js} +4 -4
  14. package/dist/{check-6NAJSJHQ.js → check-NE2YXJR2.js} +18 -18
  15. package/dist/{checkBrowser-JWNQFYTY.js → checkBrowser-XDTXDEYO.js} +14 -14
  16. package/dist/{chunk-VD7WQYTO.js → chunk-5YSHR4XC.js} +5 -5
  17. package/dist/{chunk-FRGYHRP6.js → chunk-7ZKEOQ5N.js} +1 -1
  18. package/dist/{chunk-D46G5IQH.js → chunk-AHNJMWMU.js} +7 -7
  19. package/dist/{chunk-D2WGLWIK.js → chunk-AY2FEJDR.js} +2 -2
  20. package/dist/{chunk-V2FQQILJ.js → chunk-CGOGEA62.js} +1 -1
  21. package/dist/chunk-FFJ5TDRD.js +1181 -0
  22. package/dist/{chunk-GOASXWDD.js → chunk-G5AZMSQP.js} +1 -1
  23. package/dist/{chunk-PINFPWRV.js → chunk-GIPNECWL.js} +12 -10
  24. package/dist/{chunk-4VYNMVMC.js → chunk-H4VXLZ6O.js} +4 -4
  25. package/dist/{chunk-KRE55WLI.js → chunk-HM4PLNTX.js} +1 -1
  26. package/dist/{chunk-MYGXKD7A.js → chunk-I6CVW5CA.js} +2 -2
  27. package/dist/{chunk-VZ6LCTOZ.js → chunk-IL6C7T5X.js} +1 -1
  28. package/dist/{chunk-ICZVCVD3.js → chunk-KZPG4DXX.js} +1 -1
  29. package/dist/{chunk-6MCASYIS.js → chunk-ON2HYNGB.js} +4 -4
  30. package/dist/{chunk-IGTGLGML.js → chunk-PYMYGIZ4.js} +2 -2
  31. package/dist/{chunk-7OFNPEKR.js → chunk-PZH7FTRZ.js} +2 -2
  32. package/dist/{chunk-GOTCGKX6.js → chunk-RGYEL7QD.js} +1 -1
  33. package/dist/{chunk-3XPVZLAR.js → chunk-SAS6XBY5.js} +1 -1
  34. package/dist/{chunk-KWRBEDJI.js → chunk-TXG6W4X4.js} +2 -2
  35. package/dist/{chunk-TTFDAWCS.js → chunk-VYTGK5YA.js} +1 -1
  36. package/dist/{chunk-37LNY2EC.js → chunk-WDUEIP22.js} +1 -1
  37. package/dist/{chunk-TU2CQJO3.js → chunk-WNXVPPMV.js} +2 -2
  38. package/dist/{chunk-SHVDJON6.js → chunk-XWWYGXJ5.js} +1 -1
  39. package/dist/{clean-RRE6PMKZ.js → clean-4Y4G3YV3.js} +6 -6
  40. package/dist/cli.js +49 -49
  41. package/dist/{cloud-OIR6K7TS.js → cloud-BWXJB2B7.js} +4 -4
  42. package/dist/{compare-E57W737I.js → compare-OLLJBVNL.js} +11 -11
  43. package/dist/{component-I2O4AX56.js → component-ULSAC45J.js} +3 -3
  44. package/dist/{compositions-B6NKZHIN.js → compositions-G2JTQBTJ.js} +5 -5
  45. package/dist/{delete-DTUNBC6K.js → delete-BONV4XUI.js} +2 -2
  46. package/dist/{doctor-SCNB73Z3.js → doctor-EMLC4VZ4.js} +3 -3
  47. package/dist/{events-6LQNRKHZ.js → events-LF2J436R.js} +3 -3
  48. package/dist/{events-Q37UJL36.js → events-ZFGAA5UD.js} +2 -2
  49. package/dist/{feedback-FOEBE2OW.js → feedback-WKCUQE6T.js} +5 -5
  50. package/dist/{figma-54MRTBKH.js → figma-VJKG252Z.js} +3 -3
  51. package/dist/fontLocalizeCli.js +1 -1
  52. package/dist/{get-EPGHM2SA.js → get-OINAGI2B.js} +2 -2
  53. package/dist/{grade-compare-LOJWX6SK.js → grade-compare-DY5VFXPK.js} +11 -11
  54. package/dist/{help-6FPZI3WP.js → help-HHB7JRZA.js} +1 -1
  55. package/dist/{history-GRXSUA5R.js → history-D44JJBBC.js} +6 -6
  56. package/dist/hyperframes-player.global.js +1 -1
  57. package/dist/{info-LV7DFCLD.js → info-2WZLISAR.js} +5 -5
  58. package/dist/{init-3J7BSAC3.js → init-UYZS2WXQ.js} +6 -6
  59. package/dist/{inspect-5RON554C.js → inspect-IEFCB4PT.js} +13 -13
  60. package/dist/{keyframes-KHXTHI5C.js → keyframes-FS43QHM2.js} +6 -6
  61. package/dist/{layout-DVWWT2TR.js → layout-AK2A7Q46.js} +13 -13
  62. package/dist/{lint-Q5WFB5ST.js → lint-JRJUSZO7.js} +6 -6
  63. package/dist/{list-RFEUTW6N.js → list-BKKGPT7E.js} +2 -2
  64. package/dist/{login-WBHWA4M2.js → login-QJZTUDDO.js} +4 -4
  65. package/dist/{media-treatment-WRHVNWLS.js → media-treatment-473OM7G7.js} +6 -6
  66. package/dist/{motionShot-BZLRN3SS.js → motionShot-C2YDYRNB.js} +5 -5
  67. package/dist/{normalize-audio-4YXE3RIF.js → normalize-audio-M3KVTFTQ.js} +4 -4
  68. package/dist/{open-MCGYEFML.js → open-363TDMEP.js} +4 -4
  69. package/dist/{play-WXOV3BD7.js → play-2UB33EGB.js} +9 -9
  70. package/dist/{present-RVG4J6CJ.js → present-F3ASSDJX.js} +9 -9
  71. package/dist/{preview-PDUQR2JQ.js → preview-EF76WIHK.js} +5 -5
  72. package/dist/publish-VX5OH4ST.js +1 -1
  73. package/dist/{render-JNJVFBFF.js → render-GL72Z2W2.js} +6 -6
  74. package/dist/{render-5BGU3FXU.js → render-GUBYSVQD.js} +7 -7
  75. package/dist/skills/hyperframes-cli/references/beats.md +2 -6
  76. package/dist/{skills-LKJA27ZN.js → skills-7XI4DHLN.js} +5 -5
  77. package/dist/{skillsUpdateCheck-RFZJKZC4.js → skillsUpdateCheck-34WOCMHV.js} +3 -3
  78. package/dist/{snapshot-EOYA4MLG.js → snapshot-SGTO2OQ4.js} +13 -13
  79. package/dist/{staticProjectServer-S3NK3V4S.js → staticProjectServer-4CQ3KDQK.js} +5 -5
  80. package/dist/studio/assets/{hyperframes-player-CXL23NEv.js → hyperframes-player-C8VFb4NS.js} +1 -1
  81. package/dist/studio/assets/{index-D7BvLHtZ.js → index-J8Bpbg6o.js} +118 -118
  82. package/dist/studio/assets/{index-CejKvBNw.js → index-RZnZPb-B.js} +1 -1
  83. package/dist/studio/index.html +1 -1
  84. package/dist/{studio-api-YM5HLXUS.js → studio-api-RYCDLEOR.js} +3 -3
  85. package/dist/{studioServer-CEXJK5TC.js → studioServer-VIIVGFZH.js} +9 -9
  86. package/dist/{telemetry-7AWYECPL.js → telemetry-YKVYLJSB.js} +3 -3
  87. package/dist/{timeline-G7H373XX.js → timeline-LDRA7QZ3.js} +8 -8
  88. package/dist/{tokens-GYH7NXXA.js → tokens-ZAOFRU55.js} +2 -2
  89. package/dist/{transcribe-CIC7WAT5.js → transcribe-CJXUHTAS.js} +3 -3
  90. package/dist/{updateCheck-MQ44KGUR.js → updateCheck-TIRFQBSI.js} +2 -2
  91. package/dist/{upgrade-OL47SID3.js → upgrade-7R5G3MNO.js} +2 -2
  92. package/dist/{validate-TDCH6X3C.js → validate-VGEPWGQO.js} +11 -11
  93. package/package.json +2 -3
  94. package/dist/audio-GK4OVVTH.js +0 -2086
  95. package/dist/beat-analyzer.global.js +0 -341
  96. package/dist/beats-C3ZSK2R2.js +0 -322
  97. package/dist/lib-TPG2ZMAX.js +0 -128
  98. package/dist/studio/assets/index-Bl_xrA5T.js +0 -1
  99. /package/dist/{capture-ZPRK3TOZ.js → capture-M5ZAD3BI.js} +0 -0
  100. /package/dist/{lambda-4KCSMIM6.js → lambda-RAJA6ZNA.js} +0 -0
@@ -1,341 +0,0 @@
1
- (() => {
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
-
28
- // ../../node_modules/.bun/bpm-detective@2.0.5/node_modules/bpm-detective/lib/detect.js
29
- var require_detect = __commonJS({
30
- "../../node_modules/.bun/bpm-detective@2.0.5/node_modules/bpm-detective/lib/detect.js"(exports) {
31
- "use strict";
32
- Object.defineProperty(exports, "__esModule", {
33
- value: true
34
- });
35
- exports.default = detect;
36
- var OfflineContext = window.OfflineAudioContext || window.webkitOfflineAudioContext;
37
- function detect(buffer) {
38
- var source = getLowPassSource(buffer);
39
- source.start(0);
40
- return [findPeaks, identifyIntervals, groupByTempo(buffer.sampleRate), getTopCandidate].reduce(function(state, fn) {
41
- return fn(state);
42
- }, source.buffer.getChannelData(0));
43
- }
44
- function getTopCandidate(candidates) {
45
- return candidates.sort(function(a, b) {
46
- return b.count - a.count;
47
- }).splice(0, 5)[0].tempo;
48
- }
49
- function getLowPassSource(buffer) {
50
- var length = buffer.length, numberOfChannels = buffer.numberOfChannels, sampleRate = buffer.sampleRate;
51
- var context = new OfflineContext(numberOfChannels, length, sampleRate);
52
- var source = context.createBufferSource();
53
- source.buffer = buffer;
54
- var filter = context.createBiquadFilter();
55
- filter.type = "lowpass";
56
- source.connect(filter);
57
- filter.connect(context.destination);
58
- return source;
59
- }
60
- function findPeaks(data) {
61
- var peaks = [];
62
- var threshold = 0.9;
63
- var minThresold = 0.3;
64
- var minPeaks = 15;
65
- while (peaks.length < minPeaks && threshold >= minThresold) {
66
- peaks = findPeaksAtThreshold(data, threshold);
67
- threshold -= 0.05;
68
- }
69
- if (peaks.length < minPeaks) {
70
- throw new Error("Could not find enough samples for a reliable detection.");
71
- }
72
- return peaks;
73
- }
74
- function findPeaksAtThreshold(data, threshold) {
75
- var peaks = [];
76
- for (var i = 0, l = data.length; i < l; i += 1) {
77
- if (data[i] > threshold) {
78
- peaks.push(i);
79
- i += 1e4;
80
- }
81
- }
82
- return peaks;
83
- }
84
- function identifyIntervals(peaks) {
85
- var intervals = [];
86
- peaks.forEach(function(peak, index) {
87
- var _loop = function _loop2(i2) {
88
- var interval = peaks[index + i2] - peak;
89
- var foundInterval = intervals.some(function(intervalCount) {
90
- if (intervalCount.interval === interval) {
91
- return intervalCount.count += 1;
92
- }
93
- });
94
- if (!foundInterval) {
95
- intervals.push({
96
- interval,
97
- count: 1
98
- });
99
- }
100
- };
101
- for (var i = 0; i < 10; i += 1) {
102
- _loop(i);
103
- }
104
- });
105
- return intervals;
106
- }
107
- function groupByTempo(sampleRate) {
108
- return function(intervalCounts) {
109
- var tempoCounts = [];
110
- intervalCounts.forEach(function(intervalCount) {
111
- if (intervalCount.interval !== 0) {
112
- var theoreticalTempo = 60 / (intervalCount.interval / sampleRate);
113
- while (theoreticalTempo < 90) {
114
- theoreticalTempo *= 2;
115
- }
116
- while (theoreticalTempo > 180) {
117
- theoreticalTempo /= 2;
118
- }
119
- theoreticalTempo = Math.round(theoreticalTempo);
120
- var foundTempo = tempoCounts.some(function(tempoCount) {
121
- if (tempoCount.tempo === theoreticalTempo) {
122
- return tempoCount.count += intervalCount.count;
123
- }
124
- });
125
- if (!foundTempo) {
126
- tempoCounts.push({
127
- tempo: theoreticalTempo,
128
- count: intervalCount.count
129
- });
130
- }
131
- }
132
- });
133
- return tempoCounts;
134
- };
135
- }
136
- }
137
- });
138
-
139
- // ../../node_modules/.bun/bpm-detective@2.0.5/node_modules/bpm-detective/lib/index.js
140
- var require_lib = __commonJS({
141
- "../../node_modules/.bun/bpm-detective@2.0.5/node_modules/bpm-detective/lib/index.js"(exports, module) {
142
- module.exports = require_detect().default;
143
- }
144
- });
145
-
146
- // ../core/src/beats/beatDetection.ts
147
- var bpmDetectivePromise = null;
148
- var defaultBpmDetectiveImport = () => (
149
- // @ts-ignore -- no type declarations for bpm-detective
150
- Promise.resolve().then(() => __toESM(require_lib(), 1))
151
- );
152
- function loadBpmDetective(importFn = defaultBpmDetectiveImport) {
153
- const useCache = importFn === defaultBpmDetectiveImport;
154
- if (useCache && bpmDetectivePromise) {
155
- return bpmDetectivePromise;
156
- }
157
- const promise = importFn().then((m) => (m.default ?? m) || null).catch(() => {
158
- if (useCache) bpmDetectivePromise = null;
159
- return null;
160
- });
161
- if (useCache) {
162
- bpmDetectivePromise = promise;
163
- }
164
- return promise;
165
- }
166
- var WINDOW_SIZE = 1024;
167
- var HOP_SIZE = 512;
168
- var STRENGTH_WINDOW_S = 0.05;
169
- function computeRmsAt(channelData, sampleRate, time) {
170
- const halfWindow = Math.floor(sampleRate * STRENGTH_WINDOW_S);
171
- const center = Math.floor(time * sampleRate);
172
- const start = Math.max(0, center - halfWindow);
173
- const end = Math.min(channelData.length, center + halfWindow);
174
- let sum = 0;
175
- for (let i = start; i < end; i++) {
176
- const s = channelData[i] ?? 0;
177
- sum += s * s;
178
- }
179
- return Math.sqrt(sum / Math.max(end - start, 1));
180
- }
181
- async function detectBeats(audioBuffer) {
182
- const channelData = audioBuffer.getChannelData(0);
183
- const sampleRate = audioBuffer.sampleRate;
184
- const energies = [];
185
- for (let i = 0; i < channelData.length - WINDOW_SIZE; i += HOP_SIZE) {
186
- let sum = 0;
187
- for (let j = 0; j < WINDOW_SIZE; j++) {
188
- const sample = channelData[i + j];
189
- sum += sample * sample;
190
- }
191
- energies.push(sum / WINDOW_SIZE);
192
- }
193
- const beats = [];
194
- const localWindowSize = 20;
195
- for (let i = localWindowSize; i < energies.length - localWindowSize; i++) {
196
- let localMean = 0;
197
- for (let j = i - localWindowSize; j < i + localWindowSize; j++) {
198
- localMean += energies[j];
199
- }
200
- localMean /= localWindowSize * 2;
201
- const threshold = localMean * 1.5;
202
- const current = energies[i];
203
- if (current > threshold && current > (energies[i - 1] ?? 0) && current > (energies[i + 1] ?? 0)) {
204
- const timeInSeconds = i * HOP_SIZE / sampleRate;
205
- if (beats.length === 0 || timeInSeconds - beats[beats.length - 1] > 0.1) {
206
- beats.push(Math.round(timeInSeconds * 1e3) / 1e3);
207
- }
208
- }
209
- }
210
- return beats;
211
- }
212
- function computeBpmFromBeats(beatTimes) {
213
- if (beatTimes.length < 4) return null;
214
- const iois = [];
215
- for (let i = 1; i < beatTimes.length; i++) {
216
- iois.push(beatTimes[i] - beatTimes[i - 1]);
217
- }
218
- const sorted = [...iois].sort((a, b) => a - b);
219
- const mid = Math.floor(sorted.length / 2);
220
- const medianIoi = sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
221
- if (medianIoi <= 0) return null;
222
- return Math.round(60 / medianIoi * 10) / 10;
223
- }
224
- function canonicalizeBpm(bpm) {
225
- let b = bpm;
226
- while (b > 120) b /= 2;
227
- while (b < 60) b *= 2;
228
- return b;
229
- }
230
- function octaveAlignBpm(bpm, reference) {
231
- const candidates = [bpm / 2, bpm, bpm * 2];
232
- let best = bpm;
233
- let bestDist = Number.POSITIVE_INFINITY;
234
- for (const c of candidates) {
235
- if (c <= 0) continue;
236
- const dist = Math.abs(c - reference);
237
- if (dist < bestDist) {
238
- bestDist = dist;
239
- best = c;
240
- }
241
- }
242
- return best;
243
- }
244
- function regularizeBeats(rawBeats, bpm, duration) {
245
- if (rawBeats.length === 0 || bpm <= 0 || duration <= 0) return rawBeats;
246
- const beatInterval = 60 / bpm;
247
- if (beatInterval < 0.125) return rawBeats;
248
- const threshold = beatInterval * 0.25;
249
- let bestOffset = 0;
250
- let bestScore = -1;
251
- for (const anchor of rawBeats.slice(0, 10)) {
252
- const offset = (anchor % beatInterval + beatInterval) % beatInterval;
253
- let score = 0;
254
- for (const rb of rawBeats) {
255
- const phase = (rb % beatInterval + beatInterval) % beatInterval;
256
- const dist = Math.min(Math.abs(phase - offset), beatInterval - Math.abs(phase - offset));
257
- if (dist < threshold) score++;
258
- }
259
- if (score > bestScore) {
260
- bestScore = score;
261
- bestOffset = offset;
262
- }
263
- }
264
- const beats = [];
265
- for (let t = bestOffset; t <= duration + 1e-3; t += beatInterval) {
266
- beats.push(Math.round(t * 1e3) / 1e3);
267
- }
268
- return beats;
269
- }
270
- function gateBeatsBySilence(beats, channelData, sampleRate) {
271
- if (beats.length === 0) return { times: beats, strengths: [], peak: 1e-6 };
272
- const energies = beats.map((t) => computeRmsAt(channelData, sampleRate, t));
273
- const peak = Math.max(...energies, 1e-6);
274
- const threshold = peak * 0.12;
275
- const times = [];
276
- const strengths = [];
277
- for (let i = 0; i < beats.length; i++) {
278
- if (energies[i] >= threshold) {
279
- times.push(beats[i]);
280
- strengths.push(Math.min(1, energies[i] / peak));
281
- }
282
- }
283
- return { times, strengths, peak };
284
- }
285
- async function analyzeMusicFromBuffer(audioBuffer, { pause } = {}) {
286
- const channelData = audioBuffer.getChannelData(0);
287
- const sampleRate = audioBuffer.sampleRate;
288
- const duration = audioBuffer.duration;
289
- await pause?.();
290
- const rawBeats = await detectBeats(audioBuffer);
291
- const onsetBpm = computeBpmFromBeats(rawBeats);
292
- let detectiveBpm = null;
293
- const detect = await loadBpmDetective();
294
- await pause?.();
295
- try {
296
- if (detect) detectiveBpm = detect(audioBuffer);
297
- } catch {
298
- }
299
- let bpm = onsetBpm;
300
- let confidence = "uncertain";
301
- let regularizeBpm = null;
302
- if (onsetBpm !== null && detectiveBpm !== null) {
303
- const pctDiff = Math.abs(canonicalizeBpm(onsetBpm) - canonicalizeBpm(detectiveBpm)) / canonicalizeBpm(detectiveBpm);
304
- if (pctDiff < 0.05) {
305
- bpm = octaveAlignBpm(detectiveBpm, onsetBpm);
306
- confidence = "high";
307
- regularizeBpm = bpm;
308
- } else if (pctDiff < 0.1) {
309
- bpm = Math.round((onsetBpm + detectiveBpm) / 2);
310
- confidence = "low";
311
- regularizeBpm = bpm;
312
- } else {
313
- bpm = onsetBpm;
314
- confidence = "uncertain";
315
- }
316
- } else if (onsetBpm !== null) {
317
- bpm = onsetBpm;
318
- confidence = "low";
319
- regularizeBpm = onsetBpm;
320
- } else if (detectiveBpm !== null) {
321
- bpm = detectiveBpm;
322
- confidence = "low";
323
- regularizeBpm = detectiveBpm;
324
- }
325
- await pause?.();
326
- const gridBeats = regularizeBpm !== null ? regularizeBeats(rawBeats, regularizeBpm, duration) : rawBeats;
327
- const gated = gateBeatsBySilence(gridBeats, channelData, sampleRate);
328
- return {
329
- beatTimes: gated.times,
330
- beatStrengths: gated.strengths,
331
- bpm,
332
- bpmConfidence: confidence,
333
- channelData,
334
- sampleRate,
335
- peak: gated.peak
336
- };
337
- }
338
-
339
- // <stdin>
340
- globalThis.__hfAnalyze = analyzeMusicFromBuffer;
341
- })();
@@ -1,322 +0,0 @@
1
- import { createRequire as __hf_createRequire } from "node:module";
2
- import { fileURLToPath as __hf_fileURLToPath } from "node:url";
3
- import { dirname as __hf_dirname } from "node:path";
4
- var require = __hf_createRequire(import.meta.url);
5
- var __filename = __hf_fileURLToPath(import.meta.url);
6
- var __dirname = __hf_dirname(__filename);
7
- import {
8
- launchManagedBrowser
9
- } from "./chunk-B5FZ2CQM.js";
10
- import {
11
- resolveProject
12
- } from "./chunk-37LNY2EC.js";
13
- import "./chunk-K2FLNJVB.js";
14
- import "./chunk-SB5DX6AD.js";
15
- import "./chunk-KRE55WLI.js";
16
- import "./chunk-ICZVCVD3.js";
17
- import "./chunk-VWG7OQKU.js";
18
- import "./chunk-QWQ6GQTI.js";
19
- import {
20
- defineCommand
21
- } from "./chunk-S3S4TGEH.js";
22
- import "./chunk-54HJ63Q2.js";
23
- import {
24
- failCommand
25
- } from "./chunk-PBN6GBJE.js";
26
- import {
27
- c
28
- } from "./chunk-ZTZA4UWZ.js";
29
- import "./chunk-K4WIOZFP.js";
30
- import "./chunk-XUXGIA7H.js";
31
- import "./chunk-WERLJGIC.js";
32
- import "./chunk-ISN5GRYI.js";
33
- import "./chunk-TU2CQJO3.js";
34
- import "./chunk-XT6MXC7A.js";
35
- import "./chunk-PLEMSN3E.js";
36
- import "./chunk-LYIG2GZ5.js";
37
- import "./chunk-KCF6GHJP.js";
38
- import "./chunk-JYVGYKXG.js";
39
- import "./chunk-7KDQAD2W.js";
40
- import "./chunk-Q3TFX4OZ.js";
41
- import "./chunk-P47XYVEQ.js";
42
- import "./chunk-VC76R6W2.js";
43
- import "./chunk-UJKQWGFF.js";
44
- import {
45
- decodeAuthoredAttribute,
46
- scanHtmlOpeningTags
47
- } from "./chunk-ALLKNYC3.js";
48
- import "./chunk-OFQWTKPW.js";
49
- import "./chunk-DPVXBVLL.js";
50
- import "./chunk-T76PLPD6.js";
51
- import "./chunk-FXMKHHPO.js";
52
- import "./chunk-RQVDTPGD.js";
53
- import "./chunk-TWWSYAKJ.js";
54
- import "./chunk-2742O5DO.js";
55
- import "./chunk-IWFLMU2N.js";
56
- import "./chunk-3VGU2SH7.js";
57
- import "./chunk-VAS6HQX3.js";
58
- import "./chunk-3RM2ETQT.js";
59
- import "./chunk-BSQ7XANM.js";
60
- import "./chunk-SDYDNHEE.js";
61
- import "./chunk-TYXH3EKP.js";
62
- import "./chunk-IXLUTE6N.js";
63
- import "./chunk-KNU5COPB.js";
64
- import "./chunk-KGPLIH7B.js";
65
- import "./chunk-3GXQPCJC.js";
66
- import "./chunk-M2WBOQ2Q.js";
67
-
68
- // src/commands/beats.ts
69
- import { existsSync as existsSync2, readFileSync as readFileSync2, mkdirSync, writeFileSync } from "fs";
70
- import { resolve, join as join2, dirname as dirname2 } from "path";
71
-
72
- // ../core/dist/beats/beatFile.js
73
- function audioRelPathForSrc(src) {
74
- if (!src)
75
- return null;
76
- if (/^(blob:|data:)/i.test(src))
77
- return null;
78
- let rel = null;
79
- const PREVIEW = "/preview/";
80
- const previewIdx = src.indexOf(PREVIEW);
81
- if (previewIdx !== -1) {
82
- let after = src.slice(previewIdx + PREVIEW.length);
83
- const queryOrHash = after.search(/[?#]/);
84
- if (queryOrHash !== -1)
85
- after = after.slice(0, queryOrHash);
86
- if (after.startsWith("comp/"))
87
- after = after.slice("comp/".length);
88
- rel = after ? decodeURIComponent(after) : null;
89
- }
90
- if (!rel) {
91
- try {
92
- rel = decodeURIComponent(new URL(src, "http://_").pathname);
93
- } catch {
94
- rel = src;
95
- }
96
- }
97
- if (!rel)
98
- return null;
99
- rel = rel.replace(/^\/+/, "");
100
- return rel || null;
101
- }
102
- function serializeBeats(times, strengths, audio) {
103
- const beats = times.map((t, i) => ({
104
- time: Math.round(t * 1e3) / 1e3,
105
- strength: Math.round((strengths[i] ?? 0.5) * 1e3) / 1e3
106
- }));
107
- const data = { version: 1, audio, beats };
108
- return `${JSON.stringify(data, null, 2)}
109
- `;
110
- }
111
- var MUSIC_ID_RE = /\b(music|bgm|soundtrack|background[-_]?music)\b/i;
112
- function attr(tag, name) {
113
- const attribute = tag.attributes.find((value) => value.name === name);
114
- return attribute?.kind === "value" ? decodeAuthoredAttribute(attribute.value) : null;
115
- }
116
- function isSoundingVideoTag(tag) {
117
- return attr(tag, "data-has-audio") === "true" && !tag.attributes.some((attribute) => attribute.name === "muted");
118
- }
119
- function isMusicSourceTag(tag) {
120
- return tag.closed && (tag.name === "audio" || tag.name === "video" && isSoundingVideoTag(tag));
121
- }
122
- function findMusicAudioSrc(html) {
123
- for (const tag of scanHtmlOpeningTags(html)) {
124
- if (!isMusicSourceTag(tag))
125
- continue;
126
- const src = attr(tag, "src");
127
- if (!src)
128
- continue;
129
- const role = attr(tag, "data-timeline-role");
130
- if (role) {
131
- if (role === "music")
132
- return src;
133
- continue;
134
- }
135
- const id = attr(tag, "id");
136
- if (id && MUSIC_ID_RE.test(id))
137
- return src;
138
- }
139
- return null;
140
- }
141
-
142
- // src/beats/headlessAnalyzer.ts
143
- import { existsSync, readFileSync } from "fs";
144
- import { createRequire } from "module";
145
- import { dirname, join } from "path";
146
- import { fileURLToPath } from "url";
147
- var require2 = createRequire(import.meta.url);
148
- var bundlePromise = null;
149
- function findPrebuiltBundle() {
150
- const here = dirname(fileURLToPath(import.meta.url));
151
- const candidates = [
152
- join(here, "beat-analyzer.global.js"),
153
- // dist root (tsup-bundled cli)
154
- join(here, "../beat-analyzer.global.js"),
155
- // dist/beats → dist
156
- join(here, "../dist/beat-analyzer.global.js")
157
- ];
158
- for (const p of candidates) {
159
- if (existsSync(p)) return p;
160
- }
161
- return null;
162
- }
163
- async function buildFromCoreSource() {
164
- const esbuild = await import("esbuild");
165
- const coreRoot = dirname(require2.resolve("@hyperframes/core/package.json"));
166
- const entry = join(coreRoot, "src/beats/beatDetection.ts");
167
- const result = await esbuild.build({
168
- stdin: {
169
- contents: `import { analyzeMusicFromBuffer } from ${JSON.stringify(entry)};
170
- globalThis.__hfAnalyze = analyzeMusicFromBuffer;`,
171
- resolveDir: coreRoot,
172
- loader: "ts"
173
- },
174
- bundle: true,
175
- format: "iife",
176
- platform: "browser",
177
- target: "es2020",
178
- write: false
179
- });
180
- const out = result.outputFiles?.[0];
181
- if (!out) throw new Error("Failed to bundle beat analyzer");
182
- return out.text;
183
- }
184
- function buildAnalyzerBundle() {
185
- if (bundlePromise) return bundlePromise;
186
- bundlePromise = (async () => {
187
- const prebuilt = findPrebuiltBundle();
188
- if (prebuilt) return readFileSync(prebuilt, "utf8");
189
- return buildFromCoreSource();
190
- })().catch((err) => {
191
- bundlePromise = null;
192
- throw err;
193
- });
194
- return bundlePromise;
195
- }
196
- var MAX_AUDIO_BYTES = 80 * 1024 * 1024;
197
- function inPageAnalyze(data) {
198
- const bin = atob(data);
199
- const bytes = new Uint8Array(bin.length);
200
- for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
201
- const win = window;
202
- if (typeof win.__hfAnalyze !== "function") throw new Error("beat analyzer not loaded");
203
- const ctx = new (win.AudioContext || win.webkitAudioContext)();
204
- return ctx.decodeAudioData(bytes.buffer).then((buf) => win.__hfAnalyze(buf)).then((r) => ({
205
- beatTimes: r.beatTimes,
206
- beatStrengths: r.beatStrengths,
207
- bpm: r.bpm,
208
- bpmConfidence: r.bpmConfidence
209
- })).finally(() => ctx.close());
210
- }
211
- async function detectOnPage(page, bundle, b64) {
212
- const pageErrors = [];
213
- page.on("pageerror", (e) => {
214
- pageErrors.push(e.message);
215
- });
216
- page.on("console", (m) => {
217
- if (m.type() === "error") pageErrors.push(m.text());
218
- });
219
- await page.setContent("<!doctype html><html><body></body></html>");
220
- await page.addScriptTag({ content: bundle });
221
- try {
222
- return await page.evaluate(inPageAnalyze, b64);
223
- } catch (err) {
224
- const detail = pageErrors.length ? ` (${pageErrors.join("; ")})` : "";
225
- throw new Error(`${err instanceof Error ? err.message : String(err)}${detail}`);
226
- }
227
- }
228
- async function analyzeBeatsHeadless(audioBytes) {
229
- if (audioBytes.length > MAX_AUDIO_BYTES) {
230
- const mb = Math.round(audioBytes.length / 1e6);
231
- throw new Error(
232
- `Audio file too large for headless analysis (${mb}MB > ${MAX_AUDIO_BYTES / 1e6}MB).`
233
- );
234
- }
235
- const bundle = await buildAnalyzerBundle();
236
- const { ensureBrowser } = await import("./manager-HEUPD2YB.js");
237
- const puppeteer = await import("puppeteer-core");
238
- const browser = await ensureBrowser();
239
- const chrome = await launchManagedBrowser(puppeteer.default, {
240
- headless: true,
241
- executablePath: browser.executablePath,
242
- args: ["--no-sandbox", "--disable-dev-shm-usage", "--autoplay-policy=no-user-gesture-required"]
243
- });
244
- try {
245
- const page = await chrome.newPage();
246
- return await detectOnPage(page, bundle, audioBytes.toString("base64"));
247
- } finally {
248
- await chrome.close();
249
- }
250
- }
251
-
252
- // src/commands/beats.ts
253
- var examples = [
254
- ["Generate the beat file for the current project", "hyperframes beats"],
255
- ["Generate for a specific directory", "hyperframes beats ./my-video"]
256
- ];
257
- function fail(message) {
258
- console.error(c.error(message));
259
- failCommand();
260
- }
261
- function resolveMusicTarget(project) {
262
- const src = findMusicAudioSrc(readFileSync2(project.indexPath, "utf-8"));
263
- if (!src) {
264
- fail(
265
- 'No music track found. Add data-timeline-role="music" to the <audio> element, or to a <video data-has-audio="true"> whose own sound is the music (or give it an id like music/bgm/soundtrack).'
266
- );
267
- }
268
- const rel = audioRelPathForSrc(src);
269
- if (!rel) fail(`Cannot derive a beat-file path for music src: ${src}`);
270
- const audioPath = resolve(project.dir, rel);
271
- if (!existsSync2(audioPath)) fail(`Audio file not found: ${rel}`);
272
- return { rel, audioPath };
273
- }
274
- async function detect(audioPath) {
275
- try {
276
- return await analyzeBeatsHeadless(readFileSync2(audioPath));
277
- } catch (err) {
278
- const msg = err instanceof Error ? err.message : String(err);
279
- const hint = /chrome|executable|browser|ENOENT/i.test(msg) ? "\nRun: npx hyperframes browser ensure" : "";
280
- fail(`Beat detection failed: ${msg}${hint}`);
281
- }
282
- }
283
- function report(file, result, json) {
284
- if (json) {
285
- console.log(
286
- JSON.stringify({ ok: true, file, count: result.beatTimes.length, bpm: result.bpm }, null, 2)
287
- );
288
- return;
289
- }
290
- console.log(
291
- c.success(
292
- `\u2713 Wrote ${result.beatTimes.length} beats \u2192 ${file} (bpm ${result.bpm ?? "?"}, ${result.bpmConfidence})`
293
- )
294
- );
295
- }
296
- var beats_default = defineCommand({
297
- meta: {
298
- name: "beats",
299
- description: "Detect beats in the music track (headless) and write beats/<audio>.json"
300
- },
301
- args: {
302
- dir: { type: "positional", description: "Project directory", required: false },
303
- json: { type: "boolean", description: "Output result as JSON", default: false }
304
- },
305
- async run({ args }) {
306
- const project = resolveProject(args.dir);
307
- const { rel, audioPath } = resolveMusicTarget(project);
308
- if (!args.json) console.log(c.dim(`Analyzing ${rel} in headless Chrome\u2026`));
309
- const result = await detect(audioPath);
310
- if (result.beatTimes.length === 0) {
311
- fail(`No beats detected in ${rel} \u2014 nothing written. (Track may be silent/ambient.)`);
312
- }
313
- const outPath = join2(project.dir, "beats", `${rel}.json`);
314
- mkdirSync(dirname2(outPath), { recursive: true });
315
- writeFileSync(outPath, serializeBeats(result.beatTimes, result.beatStrengths, rel));
316
- report(`beats/${rel}.json`, result, Boolean(args.json));
317
- }
318
- });
319
- export {
320
- beats_default as default,
321
- examples
322
- };