pixi-effects 0.37.0 → 0.38.0

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 (74) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +6 -5
  3. package/ai/chat-template.html +3 -3
  4. package/ai/tools/lookup.mjs +6 -3
  5. package/ai/tools/media-page.html +122 -0
  6. package/ai/tools/media.mjs +748 -0
  7. package/ai/tools/mediaBrowser.mjs +47 -0
  8. package/ai/tools/pixi-effects.mjs +11 -2
  9. package/dist/{Base-BlA6SeqJ.d.cts → Base-BKKwxavW.d.cts} +1 -1
  10. package/dist/{Base-YqM0Ljvp.d.ts → Base-ioh_AjLB.d.ts} +1 -1
  11. package/dist/Composition-23KGIJX4.cjs +16 -0
  12. package/dist/{Composition-MHDI7UNZ.cjs.map → Composition-23KGIJX4.cjs.map} +1 -1
  13. package/dist/Composition-5SQXSZNA.js +7 -0
  14. package/dist/{Composition-5KZETM4J.js.map → Composition-5SQXSZNA.js.map} +1 -1
  15. package/dist/Controller.d.cts +3 -2
  16. package/dist/Controller.d.ts +3 -2
  17. package/dist/{Movie-CfHaGmUP.d.ts → Movie-BtwFI2ne.d.ts} +3 -161
  18. package/dist/{Movie-CJN_gvLB.d.cts → Movie-CSWUTnMd.d.cts} +3 -161
  19. package/dist/{Spans-FSSO2HGX.js → Spans-4IBQASGK.js} +4 -4
  20. package/dist/{Spans-FSSO2HGX.js.map → Spans-4IBQASGK.js.map} +1 -1
  21. package/dist/{Spans-WVJH77BW.cjs → Spans-WJFPHMSQ.cjs} +9 -9
  22. package/dist/{Spans-WVJH77BW.cjs.map → Spans-WJFPHMSQ.cjs.map} +1 -1
  23. package/dist/{chunk-IPQNT65V.js → chunk-4CSL5QSL.js} +3 -3
  24. package/dist/{chunk-IPQNT65V.js.map → chunk-4CSL5QSL.js.map} +1 -1
  25. package/dist/{chunk-QHIOOK5S.cjs → chunk-7NXKBRT7.cjs} +4 -4
  26. package/dist/{chunk-QHIOOK5S.cjs.map → chunk-7NXKBRT7.cjs.map} +1 -1
  27. package/dist/{chunk-MJMOPWMK.cjs → chunk-FE42PKHP.cjs} +62 -62
  28. package/dist/{chunk-MJMOPWMK.cjs.map → chunk-FE42PKHP.cjs.map} +1 -1
  29. package/dist/{chunk-E26M4NTL.cjs → chunk-KNMDDUA3.cjs} +48 -453
  30. package/dist/chunk-KNMDDUA3.cjs.map +1 -0
  31. package/dist/chunk-LQDDDIC4.cjs +431 -0
  32. package/dist/chunk-LQDDDIC4.cjs.map +1 -0
  33. package/dist/{chunk-SBR75G73.js → chunk-UDTLYYGY.js} +4 -4
  34. package/dist/{chunk-SBR75G73.js.map → chunk-UDTLYYGY.js.map} +1 -1
  35. package/dist/chunk-UHNSL2KJ.js +425 -0
  36. package/dist/chunk-UHNSL2KJ.js.map +1 -0
  37. package/dist/{chunk-KNDEKWQO.js → chunk-XOCRS5MW.js} +9 -414
  38. package/dist/chunk-XOCRS5MW.js.map +1 -0
  39. package/dist/index.cjs +38 -33
  40. package/dist/index.d.cts +6 -5
  41. package/dist/index.d.ts +6 -5
  42. package/dist/index.js +4 -3
  43. package/dist/loader.css +1 -1
  44. package/dist/present.cjs +4 -3
  45. package/dist/present.cjs.map +1 -1
  46. package/dist/present.d.cts +3 -2
  47. package/dist/present.d.ts +3 -2
  48. package/dist/present.js +4 -3
  49. package/dist/present.js.map +1 -1
  50. package/dist/sound.cjs +12 -0
  51. package/dist/sound.cjs.map +1 -0
  52. package/dist/sound.d.cts +1 -0
  53. package/dist/sound.d.ts +1 -0
  54. package/dist/sound.js +3 -0
  55. package/dist/sound.js.map +1 -0
  56. package/dist/soundEntry-DT13DNt8.d.cts +191 -0
  57. package/dist/soundEntry-DT13DNt8.d.ts +191 -0
  58. package/dist/three.cjs +5 -5
  59. package/dist/three.d.cts +2 -2
  60. package/dist/three.d.ts +2 -2
  61. package/dist/three.js +1 -1
  62. package/dist/{types-DvnXXm33.d.cts → types-BXi-0iZS.d.cts} +1 -1
  63. package/dist/{types-DvnXXm33.d.ts → types-BXi-0iZS.d.ts} +1 -1
  64. package/docs/api.md +19 -0
  65. package/docs/media.md +136 -0
  66. package/llms-full.txt +165 -2
  67. package/llms.txt +1 -0
  68. package/package.json +2 -1
  69. package/skills/pixi-effects/SKILL.md +5 -1
  70. package/skills/pixi-effects/template.html +6 -6
  71. package/dist/Composition-5KZETM4J.js +0 -7
  72. package/dist/Composition-MHDI7UNZ.cjs +0 -16
  73. package/dist/chunk-E26M4NTL.cjs.map +0 -1
  74. package/dist/chunk-KNDEKWQO.js.map +0 -1
@@ -0,0 +1,47 @@
1
+ // The browser engine of the media commands: the tool's local server, a headless Chrome (the one `check` and `render` use) and the page ai/tools/media-page.html.
2
+ // await withBrowser({ chrome, inputs: Map(id -> path or URL), outDir }, async ({ call }) => call('frames', { id, times, size, sheet }))
3
+ // `call` runs `window.media.<name>(args)` in the page and returns its JSON, or throws the sentence the page threw.
4
+ import fs from 'node:fs';
5
+ import os from 'node:os';
6
+ import path from 'node:path';
7
+ import { fileURLToPath, pathToFileURL } from 'node:url';
8
+
9
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
10
+
11
+ export async function withBrowser({ chrome, inputs, outDir, requestLog = null, timeoutSec = 180 }, fn) {
12
+ const check = await import(pathToFileURL(path.join(HERE, 'check.mjs')).href);
13
+ const { serveMedia } = await import(pathToFileURL(path.join(HERE, 'media.mjs')).href);
14
+ const chromePath = chrome ?? check.findChrome();
15
+ if (!chromePath || !fs.existsSync(chromePath)) throw new Error(`Chrome was not found${chromePath ? ` at ${chromePath}` : ''}: this command decodes video in a browser; install Chrome, or pass --chrome PATH (or set CHROME_PATH) with the right path`);
16
+ const srv = await serveMedia({ inputs, outDir, requestLog });
17
+ const userDataDir = fs.mkdtempSync(path.join(os.tmpdir(), 'pixi-effects-media-'));
18
+ let proc = null;
19
+ try {
20
+ const launched = await check.launchChrome(chromePath, userDataDir);
21
+ proc = launched.proc;
22
+ const cdp = launched.cdp;
23
+ await cdp.send('Runtime.enable');
24
+ await cdp.send('Page.enable');
25
+ await cdp.send('Page.navigate', { url: `http://127.0.0.1:${srv.port}/ai/tools/media-page.html` });
26
+ const deadline = Date.now() + timeoutSec * 1000;
27
+ while (!(await cdp.eval('window.__mediaReady === true').catch(() => false))) {
28
+ if (Date.now() > deadline) throw new Error('the media page did not start in the browser');
29
+ await check.sleep(100);
30
+ }
31
+ const call = async (name, args) => {
32
+ const run = cdp.eval(`(async () => { try { return { ok: await window.media.${name}(${JSON.stringify(args)}) }; } catch (e) { return { error: String(e && e.message || e) }; } })()`);
33
+ let timer;
34
+ const timeout = new Promise((_, bad) => { timer = setTimeout(() => bad(new Error(`timed out after ${timeoutSec} s`)), Math.max(1000, deadline - Date.now())); });
35
+ try {
36
+ const r = await Promise.race([run, timeout]);
37
+ if (r.error) throw new Error(r.error);
38
+ return r.ok;
39
+ } finally { clearTimeout(timer); }
40
+ };
41
+ return await fn({ call });
42
+ } finally {
43
+ try { proc?.kill(); } catch { /* gone */ }
44
+ await srv.close();
45
+ try { fs.rmSync(userDataDir, { recursive: true, force: true }); } catch { /* held a moment longer */ }
46
+ }
47
+ }
@@ -15,11 +15,19 @@ import { dirname, resolve } from 'node:path';
15
15
  import { fileURLToPath } from 'node:url';
16
16
  import { runLookup, LOOKUP_COMMANDS } from './lookup.mjs';
17
17
 
18
+ const MEDIA = ['probe', 'trim', 'frames', 'sound', 'audio', 'concat']; // footage tools: one file, `media.mjs`, which gets the command word too
19
+
18
20
  const TOOLS = { check: 'check.mjs', render: 'render.mjs', view: 'view.mjs' };
19
21
  const USAGE = `usage:
20
22
  pixi-effects check <page.html> [--at 3,6] [--out dir] review a video page: warnings, layout, sound, contact sheet, real export
21
23
  pixi-effects render <page.html> -o <file.mp4> export the video
22
24
  pixi-effects view <page.html> look at it in a browser, with a timeline
25
+ pixi-effects probe <file|url> what is in a video or audio file (codecs, size, duration), with no ffmpeg
26
+ pixi-effects trim <file|url> <start> <end> -o <out> cut a file (by copy when it can) and say the real times
27
+ pixi-effects frames <file|url> [--at 1,50%,end] [--sheet] pictures of a video at those times
28
+ pixi-effects sound <file|url> [--waveform] loudness, peak, silences of a file's sound
29
+ pixi-effects audio <file|url> -o <out.m4a> the sound of a file, copied out
30
+ pixi-effects concat <a> <b> … -o <out> join clips by copy and say where each starts
23
31
  pixi-effects new <name> [--size 1080x1920] [--duration 20] a page to start from (<name>.html), 1280x720 and 6 s unless asked
24
32
  pixi-effects recipe [id] the tested recipes; with an id, one of them with its code
25
33
  pixi-effects help <word> the docs about a word (mask, threeD, keyframes, music …)
@@ -28,7 +36,7 @@ const USAGE = `usage:
28
36
  function nearest(word) {
29
37
  const d = (a, b) => { const m = Array.from({ length: a.length + 1 }, (_, i) => [i, ...Array(b.length).fill(0)]); for (let j = 1; j <= b.length; j++) m[0][j] = j;
30
38
  for (let i = 1; i <= a.length; i++) for (let j = 1; j <= b.length; j++) m[i][j] = Math.min(m[i - 1][j] + 1, m[i][j - 1] + 1, m[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1)); return m[a.length][b.length]; };
31
- const best = [...Object.keys(TOOLS), ...LOOKUP_COMMANDS].map(k => [k, d(word, k)]).sort((x, y) => x[1] - y[1])[0];
39
+ const best = [...Object.keys(TOOLS), ...MEDIA, ...LOOKUP_COMMANDS].map(k => [k, d(word, k)]).sort((x, y) => x[1] - y[1])[0];
32
40
  return best[1] <= 2 ? best[0] : null;
33
41
  }
34
42
 
@@ -37,9 +45,10 @@ export function route(argv) {
37
45
  const [cmd, ...args] = argv;
38
46
  if (!cmd || cmd === '--help' || cmd === '-h') return { usage: USAGE };
39
47
  if (TOOLS[cmd]) return { tool: TOOLS[cmd], args };
48
+ if (MEDIA.includes(cmd)) return { tool: 'media.mjs', args: [cmd, ...args] };
40
49
  if (LOOKUP_COMMANDS.includes(cmd)) return { inline: cmd, args };
41
50
  const guess = /\.html?$/i.test(cmd) ? 'check' : nearest(cmd);
42
- return { error: `pixi-effects: unknown command "${cmd}"${guess ? `; did you mean "${guess}"?` : ''} The commands are: ${[...Object.keys(TOOLS), ...LOOKUP_COMMANDS].join(', ')}.\n${USAGE}` };
51
+ return { error: `pixi-effects: unknown command "${cmd}"${guess ? `; did you mean "${guess}"?` : ''} The commands are: ${[...Object.keys(TOOLS), ...MEDIA, ...LOOKUP_COMMANDS].join(', ')}.\n${USAGE}` };
43
52
  }
44
53
 
45
54
  const self = fileURLToPath(import.meta.url);
@@ -1,5 +1,5 @@
1
1
  import { Container } from 'pixi.js';
2
- import { S as SequenceSpec, C as CompositionShape } from './types-DvnXXm33.cjs';
2
+ import { a as SequenceSpec, C as CompositionShape } from './types-BXi-0iZS.cjs';
3
3
 
4
4
  /**
5
5
  * Resolves a routed keyframe path to a concrete tween target.
@@ -1,5 +1,5 @@
1
1
  import { Container } from 'pixi.js';
2
- import { S as SequenceSpec, C as CompositionShape } from './types-DvnXXm33.js';
2
+ import { a as SequenceSpec, C as CompositionShape } from './types-BXi-0iZS.js';
3
3
 
4
4
  /**
5
5
  * Resolves a routed keyframe path to a concrete tween target.
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ var chunkFE42PKHP_cjs = require('./chunk-FE42PKHP.cjs');
4
+ require('./chunk-7NXKBRT7.cjs');
5
+ require('./chunk-JN7JHNZR.cjs');
6
+ require('./chunk-3SAS3ZE5.cjs');
7
+ require('./chunk-TWZNOUM7.cjs');
8
+
9
+
10
+
11
+ Object.defineProperty(exports, "CompositionSequence", {
12
+ enumerable: true,
13
+ get: function () { return chunkFE42PKHP_cjs.CompositionSequence; }
14
+ });
15
+ //# sourceMappingURL=Composition-23KGIJX4.cjs.map
16
+ //# sourceMappingURL=Composition-23KGIJX4.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-MHDI7UNZ.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-23KGIJX4.cjs"}
@@ -0,0 +1,7 @@
1
+ export { CompositionSequence } from './chunk-4CSL5QSL.js';
2
+ import './chunk-UDTLYYGY.js';
3
+ import './chunk-VNP7QCJE.js';
4
+ import './chunk-32MMNDDN.js';
5
+ import './chunk-BXOCEZ4U.js';
6
+ //# sourceMappingURL=Composition-5SQXSZNA.js.map
7
+ //# sourceMappingURL=Composition-5SQXSZNA.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-5KZETM4J.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-5SQXSZNA.js"}
@@ -1,6 +1,7 @@
1
- import { l as Movie } from './Movie-CJN_gvLB.cjs';
1
+ import { M as Movie } from './Movie-CSWUTnMd.cjs';
2
2
  import 'pixi.js';
3
- import './types-DvnXXm33.cjs';
3
+ import './soundEntry-DT13DNt8.cjs';
4
+ import './types-BXi-0iZS.cjs';
4
5
 
5
6
  /**
6
7
  * The look of the bar. Each key sets a CSS custom property on the bar (so you can also set `--mc-accent` … in your own CSS, on the
@@ -1,6 +1,7 @@
1
- import { l as Movie } from './Movie-CfHaGmUP.js';
1
+ import { M as Movie } from './Movie-BtwFI2ne.js';
2
2
  import 'pixi.js';
3
- import './types-DvnXXm33.js';
3
+ import './soundEntry-DT13DNt8.js';
4
+ import './types-BXi-0iZS.js';
4
5
 
5
6
  /**
6
7
  * The look of the bar. Each key sets a CSS custom property on the bar (so you can also set `--mc-accent` … in your own CSS, on the
@@ -1,5 +1,6 @@
1
1
  import { Application } from 'pixi.js';
2
- import { $ as Stop, c as AssetSpec, m as CompositionSpec } from './types-DvnXXm33.js';
2
+ import { A as AudioReport, a as AudioInspectOptions } from './soundEntry-DT13DNt8.js';
3
+ import { d as Stop, A as AssetSpec, c as CompositionSpec } from './types-BXi-0iZS.js';
3
4
 
4
5
  type EaseFn = (p: number) => number;
5
6
 
@@ -126,165 +127,6 @@ declare class PureTimeline {
126
127
  */
127
128
  type Timeline = PureTimeline;
128
129
 
129
- /** One note or chord of a track, as a score reader sees it. */
130
- interface MusicNote {
131
- /** Where it starts: beats from the start, and the same moment in seconds (the tempo map applied; swing and humanize are not). */
132
- beat: number;
133
- time: number;
134
- /** How long it is held, in beats and in seconds. */
135
- duration: number;
136
- seconds: number;
137
- /** The bar it starts in (1-based, from `meter`) and its beat inside that bar (1 = the downbeat, 1.5 = the "and" of 1). */
138
- bar: number;
139
- beatInBar: number;
140
- /** The audible MIDI notes (`music.transpose` and the track's `transpose` are in). */
141
- midi: number[];
142
- /** What the score called it: `Am7`, `c4`, `[c4 e4 g4]`. */
143
- name: string;
144
- /** More than one note at once. */
145
- chord: boolean;
146
- /** 0–1 (0.8 normal, 1 accented with `!`, 0.55 soft with `,`). */
147
- velocity: number;
148
- }
149
- interface MusicTrackEvents {
150
- inst: string;
151
- /** The track's length in beats and in bars (not a whole number when a bar is short: that is what to look for). */
152
- beats: number;
153
- bars: number;
154
- notes: MusicNote[];
155
- }
156
- interface MusicDrumHit {
157
- beat: number;
158
- time: number;
159
- bar: number;
160
- beatInBar: number;
161
- velocity: number;
162
- }
163
- interface MusicDrumEvents {
164
- kind: string;
165
- hits: MusicDrumHit[];
166
- }
167
- interface MusicEvents {
168
- /** The tempo at the start. */
169
- bpm: number;
170
- meter: number;
171
- beats: number;
172
- bars: number;
173
- /** The music without its reverb tail. */
174
- seconds: number;
175
- tracks: MusicTrackEvents[];
176
- /** Every drum that is hit, over all sections, with every hit written out. */
177
- drums: MusicDrumEvents[];
178
- }
179
- /** What the `check` tool prints about a music layer: lengths in bars (a short track shows), what starts in each bar, where the drums play. */
180
- interface MusicSummary {
181
- bpm: number;
182
- meter: number;
183
- /** The score set `meter`; when false 4 is only assumed. */
184
- meterSet: boolean;
185
- beats: number;
186
- bars: number;
187
- seconds: number;
188
- tail: number;
189
- tracks: Array<{
190
- inst: string;
191
- beats: number;
192
- bars: number;
193
- events: number;
194
- perBar: string[];
195
- }>;
196
- drums: Array<{
197
- from: number;
198
- to: number;
199
- kinds: string[];
200
- }>;
201
- }
202
-
203
- interface AudioInspectOptions {
204
- /** Width of each loudness window in seconds. Default 0.1. */
205
- window?: number;
206
- /** The scenes to measure one by one (`movie.inspectAudio()` fills this from the movie's named top-level compositions). Default: the whole movie as one. */
207
- scenes?: Array<{
208
- name: string;
209
- start: number;
210
- end: number;
211
- }>;
212
- }
213
- /** One sound measured ON ITS OWN (not mixed), so overlapping layers do not blur it. */
214
- interface SoundMeasure {
215
- /** Seconds of audio the source has (an sfx: its length; a file: the file's length). */
216
- length: number;
217
- /** Its own loudest sample, dBFS (before the layer's volume). */
218
- peakDb: number;
219
- /** Seconds from its start to its loudest sample — the moment to line up with the picture. */
220
- loudestAt: number;
221
- /** Spectral centroid in Hz: < 500 dark / boomy, 1–4 k mid, > 8 k airy / hissy. */
222
- brightnessHz: number;
223
- }
224
- interface AudioSourceReport {
225
- /** `layer "pop-1"` (or `unnamed audio layer`). */
226
- layer: string;
227
- /** `sfx "pop"`, `asset "bgm"`, `video "green"`. */
228
- source: string;
229
- /** Movie time, seconds. */
230
- start: number;
231
- end: number;
232
- /** Loudest sample of the MIX while this source plays, dBFS (−120 = silence). */
233
- peakDb: number;
234
- sound: SoundMeasure;
235
- /**
236
- * How far below the loudest sample of the MIX around its own loudest moment this source is, dB (0 = it is the loudest thing there; 20 = the mix is 20 dB louder, so
237
- * the source is hardly heard). Absent for a sound inside a remapped composition (its time is not the movie's).
238
- */
239
- belowMixDb?: number;
240
- /** For a `music` layer: its score read back (bars per track, what starts in each bar, the drum spans). */
241
- music?: MusicSummary;
242
- }
243
- interface AudioReport {
244
- duration: number;
245
- sampleRate: number;
246
- /** Loudest sample of the mix before limiting, dBFS. Above 0 the mix was limited. */
247
- peakDb: number;
248
- peakAt: number;
249
- /** Every audio layer / video soundtrack in the mix, in start order. */
250
- sources: AudioSourceReport[];
251
- /** The mix over time: one row per window, `t` = window start. */
252
- windows: Array<{
253
- t: number;
254
- rmsDb: number;
255
- peakDb: number;
256
- brightnessHz: number;
257
- }>;
258
- /** Problems worth fixing: limiting, clipping, a true peak above 0 dBTP, inaudible layers, sounds cut off by the end of the movie. Read this first. */
259
- issues: string[];
260
- /** The mix as a whole (ITU-R BS.1770 loudness; `integratedLufs` is null for a mix shorter than 0.4 s or with nothing above −70 LUFS). */
261
- loudness: {
262
- integratedLufs: number | null;
263
- truePeakDb: number;
264
- clippedSamples: number;
265
- silences: Array<{
266
- from: number;
267
- to: number;
268
- }>;
269
- };
270
- /** The same measure for each scene (`silent`: nothing above −60 dBFS). */
271
- scenes: Array<{
272
- name: string;
273
- from: number;
274
- to: number;
275
- lufs: number | null;
276
- peakDb: number;
277
- silent: boolean;
278
- }>;
279
- /** When each sound starts: what a waveform marks. */
280
- cues: Array<{
281
- t: number;
282
- name: string;
283
- }>;
284
- /** Advice, not faults: a mix that is quiet or loud for web video, little headroom, silent stretches. */
285
- notes: string[];
286
- }
287
-
288
130
  interface FontReport {
289
131
  /** Text layers none of whose fonts is available here: they are drawn in a fallback. */
290
132
  missing: Array<{
@@ -921,4 +763,4 @@ declare class Movie {
921
763
  destroy(): Promise<void>;
922
764
  }
923
765
 
924
- export { type AudioInspectOptions as A, type TimelineHtmlOptions as B, type ContactSheetOptions as C, type TimelineRow as D, type TimelineSvgOptions as E, type FontReport as F, type TimelineTransition as G, dismissLoader as H, type InspectOptions as I, failLoader as J, resolveLoader as K, type LayerInfo as L, type MusicEvents as M, type OnionSkinOptions as O, type ProgressEvent as P, type RebuildOptions as R, type SnapshotOptions as S, type ThumbnailOptions as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type FrameEvent as c, type InspectReport as d, type IssueGroup as e, type LoadProgressState as f, type LoadStage as g, type LoaderOption as h, type LoopEvent as i, type MotionBlurOptions as j, type MotionBlurSpec as k, Movie as l, type MovieErrorEvent as m, type MovieOptions as n, type MusicDrumEvents as o, type MusicDrumHit as p, type MusicNote as q, type MusicSummary as r, type MusicTrackEvents as s, type RebuildReason as t, type RebuildReport as u, type RenderOptions as v, type ReviewOptions as w, type ReviewReport as x, type SoundMeasure as y, type TimelineData as z };
766
+ export { type ContactSheetOptions as C, type FontReport as F, type InspectOptions as I, type LayerInfo as L, Movie as M, type OnionSkinOptions as O, type ProgressEvent as P, type RebuildOptions as R, type SnapshotOptions as S, type ThumbnailOptions as T, type VolumeEvent as V, type MotionBlurSpec as a, type FrameEvent as b, type InspectReport as c, type IssueGroup as d, type LoadProgressState as e, type LoadStage as f, type LoaderOption as g, type LoopEvent as h, type MotionBlurOptions as i, type MovieErrorEvent as j, type MovieOptions as k, type RebuildReason as l, type RebuildReport as m, type RenderOptions as n, type ReviewOptions as o, type ReviewReport as p, type TimelineData as q, type TimelineHtmlOptions as r, type TimelineRow as s, type TimelineSvgOptions as t, type TimelineTransition as u, dismissLoader as v, failLoader as w, resolveLoader as x };
@@ -1,5 +1,6 @@
1
1
  import { Application } from 'pixi.js';
2
- import { $ as Stop, c as AssetSpec, m as CompositionSpec } from './types-DvnXXm33.cjs';
2
+ import { A as AudioReport, a as AudioInspectOptions } from './soundEntry-DT13DNt8.cjs';
3
+ import { d as Stop, A as AssetSpec, c as CompositionSpec } from './types-BXi-0iZS.cjs';
3
4
 
4
5
  type EaseFn = (p: number) => number;
5
6
 
@@ -126,165 +127,6 @@ declare class PureTimeline {
126
127
  */
127
128
  type Timeline = PureTimeline;
128
129
 
129
- /** One note or chord of a track, as a score reader sees it. */
130
- interface MusicNote {
131
- /** Where it starts: beats from the start, and the same moment in seconds (the tempo map applied; swing and humanize are not). */
132
- beat: number;
133
- time: number;
134
- /** How long it is held, in beats and in seconds. */
135
- duration: number;
136
- seconds: number;
137
- /** The bar it starts in (1-based, from `meter`) and its beat inside that bar (1 = the downbeat, 1.5 = the "and" of 1). */
138
- bar: number;
139
- beatInBar: number;
140
- /** The audible MIDI notes (`music.transpose` and the track's `transpose` are in). */
141
- midi: number[];
142
- /** What the score called it: `Am7`, `c4`, `[c4 e4 g4]`. */
143
- name: string;
144
- /** More than one note at once. */
145
- chord: boolean;
146
- /** 0–1 (0.8 normal, 1 accented with `!`, 0.55 soft with `,`). */
147
- velocity: number;
148
- }
149
- interface MusicTrackEvents {
150
- inst: string;
151
- /** The track's length in beats and in bars (not a whole number when a bar is short: that is what to look for). */
152
- beats: number;
153
- bars: number;
154
- notes: MusicNote[];
155
- }
156
- interface MusicDrumHit {
157
- beat: number;
158
- time: number;
159
- bar: number;
160
- beatInBar: number;
161
- velocity: number;
162
- }
163
- interface MusicDrumEvents {
164
- kind: string;
165
- hits: MusicDrumHit[];
166
- }
167
- interface MusicEvents {
168
- /** The tempo at the start. */
169
- bpm: number;
170
- meter: number;
171
- beats: number;
172
- bars: number;
173
- /** The music without its reverb tail. */
174
- seconds: number;
175
- tracks: MusicTrackEvents[];
176
- /** Every drum that is hit, over all sections, with every hit written out. */
177
- drums: MusicDrumEvents[];
178
- }
179
- /** What the `check` tool prints about a music layer: lengths in bars (a short track shows), what starts in each bar, where the drums play. */
180
- interface MusicSummary {
181
- bpm: number;
182
- meter: number;
183
- /** The score set `meter`; when false 4 is only assumed. */
184
- meterSet: boolean;
185
- beats: number;
186
- bars: number;
187
- seconds: number;
188
- tail: number;
189
- tracks: Array<{
190
- inst: string;
191
- beats: number;
192
- bars: number;
193
- events: number;
194
- perBar: string[];
195
- }>;
196
- drums: Array<{
197
- from: number;
198
- to: number;
199
- kinds: string[];
200
- }>;
201
- }
202
-
203
- interface AudioInspectOptions {
204
- /** Width of each loudness window in seconds. Default 0.1. */
205
- window?: number;
206
- /** The scenes to measure one by one (`movie.inspectAudio()` fills this from the movie's named top-level compositions). Default: the whole movie as one. */
207
- scenes?: Array<{
208
- name: string;
209
- start: number;
210
- end: number;
211
- }>;
212
- }
213
- /** One sound measured ON ITS OWN (not mixed), so overlapping layers do not blur it. */
214
- interface SoundMeasure {
215
- /** Seconds of audio the source has (an sfx: its length; a file: the file's length). */
216
- length: number;
217
- /** Its own loudest sample, dBFS (before the layer's volume). */
218
- peakDb: number;
219
- /** Seconds from its start to its loudest sample — the moment to line up with the picture. */
220
- loudestAt: number;
221
- /** Spectral centroid in Hz: < 500 dark / boomy, 1–4 k mid, > 8 k airy / hissy. */
222
- brightnessHz: number;
223
- }
224
- interface AudioSourceReport {
225
- /** `layer "pop-1"` (or `unnamed audio layer`). */
226
- layer: string;
227
- /** `sfx "pop"`, `asset "bgm"`, `video "green"`. */
228
- source: string;
229
- /** Movie time, seconds. */
230
- start: number;
231
- end: number;
232
- /** Loudest sample of the MIX while this source plays, dBFS (−120 = silence). */
233
- peakDb: number;
234
- sound: SoundMeasure;
235
- /**
236
- * How far below the loudest sample of the MIX around its own loudest moment this source is, dB (0 = it is the loudest thing there; 20 = the mix is 20 dB louder, so
237
- * the source is hardly heard). Absent for a sound inside a remapped composition (its time is not the movie's).
238
- */
239
- belowMixDb?: number;
240
- /** For a `music` layer: its score read back (bars per track, what starts in each bar, the drum spans). */
241
- music?: MusicSummary;
242
- }
243
- interface AudioReport {
244
- duration: number;
245
- sampleRate: number;
246
- /** Loudest sample of the mix before limiting, dBFS. Above 0 the mix was limited. */
247
- peakDb: number;
248
- peakAt: number;
249
- /** Every audio layer / video soundtrack in the mix, in start order. */
250
- sources: AudioSourceReport[];
251
- /** The mix over time: one row per window, `t` = window start. */
252
- windows: Array<{
253
- t: number;
254
- rmsDb: number;
255
- peakDb: number;
256
- brightnessHz: number;
257
- }>;
258
- /** Problems worth fixing: limiting, clipping, a true peak above 0 dBTP, inaudible layers, sounds cut off by the end of the movie. Read this first. */
259
- issues: string[];
260
- /** The mix as a whole (ITU-R BS.1770 loudness; `integratedLufs` is null for a mix shorter than 0.4 s or with nothing above −70 LUFS). */
261
- loudness: {
262
- integratedLufs: number | null;
263
- truePeakDb: number;
264
- clippedSamples: number;
265
- silences: Array<{
266
- from: number;
267
- to: number;
268
- }>;
269
- };
270
- /** The same measure for each scene (`silent`: nothing above −60 dBFS). */
271
- scenes: Array<{
272
- name: string;
273
- from: number;
274
- to: number;
275
- lufs: number | null;
276
- peakDb: number;
277
- silent: boolean;
278
- }>;
279
- /** When each sound starts: what a waveform marks. */
280
- cues: Array<{
281
- t: number;
282
- name: string;
283
- }>;
284
- /** Advice, not faults: a mix that is quiet or loud for web video, little headroom, silent stretches. */
285
- notes: string[];
286
- }
287
-
288
130
  interface FontReport {
289
131
  /** Text layers none of whose fonts is available here: they are drawn in a fallback. */
290
132
  missing: Array<{
@@ -921,4 +763,4 @@ declare class Movie {
921
763
  destroy(): Promise<void>;
922
764
  }
923
765
 
924
- export { type AudioInspectOptions as A, type TimelineHtmlOptions as B, type ContactSheetOptions as C, type TimelineRow as D, type TimelineSvgOptions as E, type FontReport as F, type TimelineTransition as G, dismissLoader as H, type InspectOptions as I, failLoader as J, resolveLoader as K, type LayerInfo as L, type MusicEvents as M, type OnionSkinOptions as O, type ProgressEvent as P, type RebuildOptions as R, type SnapshotOptions as S, type ThumbnailOptions as T, type VolumeEvent as V, type AudioReport as a, type AudioSourceReport as b, type FrameEvent as c, type InspectReport as d, type IssueGroup as e, type LoadProgressState as f, type LoadStage as g, type LoaderOption as h, type LoopEvent as i, type MotionBlurOptions as j, type MotionBlurSpec as k, Movie as l, type MovieErrorEvent as m, type MovieOptions as n, type MusicDrumEvents as o, type MusicDrumHit as p, type MusicNote as q, type MusicSummary as r, type MusicTrackEvents as s, type RebuildReason as t, type RebuildReport as u, type RenderOptions as v, type ReviewOptions as w, type ReviewReport as x, type SoundMeasure as y, type TimelineData as z };
766
+ export { type ContactSheetOptions as C, type FontReport as F, type InspectOptions as I, type LayerInfo as L, Movie as M, type OnionSkinOptions as O, type ProgressEvent as P, type RebuildOptions as R, type SnapshotOptions as S, type ThumbnailOptions as T, type VolumeEvent as V, type MotionBlurSpec as a, type FrameEvent as b, type InspectReport as c, type IssueGroup as d, type LoadProgressState as e, type LoadStage as f, type LoaderOption as g, type LoopEvent as h, type MotionBlurOptions as i, type MovieErrorEvent as j, type MovieOptions as k, type RebuildReason as l, type RebuildReport as m, type RenderOptions as n, type ReviewOptions as o, type ReviewReport as p, type TimelineData as q, type TimelineHtmlOptions as r, type TimelineRow as s, type TimelineSvgOptions as t, type TimelineTransition as u, dismissLoader as v, failLoader as w, resolveLoader as x };
@@ -1,5 +1,5 @@
1
- import { CompositionSequence } from './chunk-IPQNT65V.js';
2
- import { spansMeta, resolveNumber, bindCounterKeyframes, TextSequence } from './chunk-SBR75G73.js';
1
+ import { CompositionSequence } from './chunk-4CSL5QSL.js';
2
+ import { spansMeta, resolveNumber, bindCounterKeyframes, TextSequence } from './chunk-UDTLYYGY.js';
3
3
  import './chunk-VNP7QCJE.js';
4
4
  import './chunk-32MMNDDN.js';
5
5
  import './chunk-BXOCEZ4U.js';
@@ -49,5 +49,5 @@ var SpansSequence = class extends CompositionSequence {
49
49
  };
50
50
 
51
51
  export { SpansSequence };
52
- //# sourceMappingURL=Spans-FSSO2HGX.js.map
53
- //# sourceMappingURL=Spans-FSSO2HGX.js.map
52
+ //# sourceMappingURL=Spans-4IBQASGK.js.map
53
+ //# sourceMappingURL=Spans-4IBQASGK.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sequences/Spans.ts"],"names":[],"mappings":";;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4B,mBAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAI,aAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAA,oBAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiB,YAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-FSSO2HGX.js","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/sequences/Spans.ts"],"names":[],"mappings":";;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4B,mBAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAI,aAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAA,oBAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiB,YAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-4IBQASGK.js","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunkMJMOPWMK_cjs = require('./chunk-MJMOPWMK.cjs');
4
- var chunkQHIOOK5S_cjs = require('./chunk-QHIOOK5S.cjs');
3
+ var chunkFE42PKHP_cjs = require('./chunk-FE42PKHP.cjs');
4
+ var chunk7NXKBRT7_cjs = require('./chunk-7NXKBRT7.cjs');
5
5
  require('./chunk-JN7JHNZR.cjs');
6
6
  require('./chunk-3SAS3ZE5.cjs');
7
7
  require('./chunk-TWZNOUM7.cjs');
@@ -12,12 +12,12 @@ var strip = (props) => {
12
12
  const { visibleChars: _gone, ...rest } = props;
13
13
  return rest;
14
14
  };
15
- var SpansSequence = class extends chunkMJMOPWMK_cjs.CompositionSequence {
15
+ var SpansSequence = class extends chunkFE42PKHP_cjs.CompositionSequence {
16
16
  _meta;
17
17
  _count = { value: 0, visibleChars: 0 };
18
18
  constructor(spec, parent, root) {
19
19
  super(spec, parent, root);
20
- this._meta = chunkQHIOOK5S_cjs.spansMeta.get(spec);
20
+ this._meta = chunk7NXKBRT7_cjs.spansMeta.get(spec);
21
21
  }
22
22
  /** `visibleChars` is the group's own counter, not a property to write on the container. */
23
23
  displayProps() {
@@ -33,8 +33,8 @@ var SpansSequence = class extends chunkMJMOPWMK_cjs.CompositionSequence {
33
33
  if (!this._meta?.typed) return;
34
34
  const scope = this.scope();
35
35
  const first = this.spec.initial?.visibleChars;
36
- this._count.visibleChars = first === void 0 ? 0 : chunkQHIOOK5S_cjs.resolveNumber(first, scope);
37
- chunkQHIOOK5S_cjs.bindCounterKeyframes(timeline, this._count, "visibleChars", () => this._distribute(), this.spec.keyframes ?? [], this.duration, offset + this.at, scope);
36
+ this._count.visibleChars = first === void 0 ? 0 : chunk7NXKBRT7_cjs.resolveNumber(first, scope);
37
+ chunk7NXKBRT7_cjs.bindCounterKeyframes(timeline, this._count, "visibleChars", () => this._distribute(), this.spec.keyframes ?? [], this.duration, offset + this.at, scope);
38
38
  this._distribute();
39
39
  }
40
40
  /** Every piece shows its part of the first N characters of the whole text. */
@@ -43,7 +43,7 @@ var SpansSequence = class extends chunkMJMOPWMK_cjs.CompositionSequence {
43
43
  const total = Math.max(0, Math.floor(this._count.visibleChars));
44
44
  let i = 0;
45
45
  for (const child of this._children) {
46
- if (!(child instanceof chunkQHIOOK5S_cjs.TextSequence)) continue;
46
+ if (!(child instanceof chunk7NXKBRT7_cjs.TextSequence)) continue;
47
47
  const p = pieces[i++];
48
48
  if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));
49
49
  }
@@ -51,5 +51,5 @@ var SpansSequence = class extends chunkMJMOPWMK_cjs.CompositionSequence {
51
51
  };
52
52
 
53
53
  exports.SpansSequence = SpansSequence;
54
- //# sourceMappingURL=Spans-WVJH77BW.cjs.map
55
- //# sourceMappingURL=Spans-WVJH77BW.cjs.map
54
+ //# sourceMappingURL=Spans-WJFPHMSQ.cjs.map
55
+ //# sourceMappingURL=Spans-WJFPHMSQ.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sequences/Spans.ts"],"names":["CompositionSequence","spansMeta","resolveNumber","bindCounterKeyframes","TextSequence"],"mappings":";;;;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4BA,qCAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQC,2BAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAIC,+BAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAAC,sCAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiBC,8BAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-WVJH77BW.cjs","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/sequences/Spans.ts"],"names":["CompositionSequence","spansMeta","resolveNumber","bindCounterKeyframes","TextSequence"],"mappings":";;;;;;;;;AAQA,IAAM,KAAA,GAAQ,CAAC,KAAA,KAAgD;AAC7D,EAAA,IAAI,CAAC,KAAA,IAAS,EAAE,cAAA,IAAkB,QAAQ,OAAO,KAAA;AACjD,EAAA,MAAM,EAAE,YAAA,EAAc,KAAA,EAAO,GAAG,MAAK,GAAI,KAAA;AACzC,EAAA,OAAO,IAAA;AACT,CAAA;AAEO,IAAM,aAAA,GAAN,cAA4BA,qCAAA,CAAoB;AAAA,EACpC,KAAA;AAAA,EACA,MAAA,GAAuB,EAAE,KAAA,EAAO,CAAA,EAAG,cAAc,CAAA,EAAE;AAAA,EAEpE,WAAA,CAAY,IAAA,EAAoB,MAAA,EAAiC,IAAA,EAAwB;AACvF,IAAA,KAAA,CAAM,IAAA,EAAM,QAAQ,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,KAAA,GAAQC,2BAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAAA,EACjC;AAAA;AAAA,EAGmB,YAAA,GAAyH;AAC1I,IAAA,MAAM,CAAA,GAAI,MAAM,YAAA,EAAa;AAC7B,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO,OAAO,CAAA;AAC/B,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA,CAAM,CAAA,CAAE,OAA4B,CAAA;AAAA,MAC7C,SAAA,EAAW,EAAE,SAAA,EAAW,GAAA,CAAI,SAAO,EAAE,GAAG,EAAA,EAAI,GAAA,EAAK,KAAA,CAAM,EAAA,CAAG,GAAG,CAAA,EAAG,EAAA,EAAI,KAAA,CAAM,EAAA,CAAG,EAAE,CAAA,EAAG,MAAM,KAAA,CAAM,EAAA,CAAG,IAAI,CAAA,EAAE,CAAE;AAAA,KAC3G;AAAA,EACF;AAAA,EAES,YAAA,CAAa,QAAA,EAAoB,MAAA,GAAS,CAAA,EAAS;AAC1D,IAAA,KAAA,CAAM,YAAA,CAAa,UAAU,MAAM,CAAA;AACnC,IAAA,IAAI,CAAC,IAAA,CAAK,KAAA,EAAO,KAAA,EAAO;AACxB,IAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,EAAM;AACzB,IAAA,MAAM,KAAA,GAAS,IAAA,CAAK,IAAA,CAAK,OAAA,EAAiD,YAAA;AAC1E,IAAA,IAAA,CAAK,OAAO,YAAA,GAAe,KAAA,KAAU,SAAY,CAAA,GAAIC,+BAAA,CAAc,OAAO,KAAK,CAAA;AAC/E,IAAAC,sCAAA,CAAqB,UAAU,IAAA,CAAK,MAAA,EAAQ,gBAAgB,MAAM,IAAA,CAAK,aAAY,EAAG,IAAA,CAAK,IAAA,CAAK,SAAA,IAAa,EAAC,EAAG,IAAA,CAAK,UAAW,MAAA,GAAS,IAAA,CAAK,IAAI,KAAK,CAAA;AACxJ,IAAA,IAAA,CAAK,WAAA,EAAY;AAAA,EACnB;AAAA;AAAA,EAGQ,WAAA,GAAoB;AAC1B,IAAA,MAAM,MAAA,GAAS,KAAK,KAAA,CAAO,MAAA;AAC3B,IAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,KAAA,CAAM,IAAA,CAAK,MAAA,CAAO,YAAY,CAAC,CAAA;AAC9D,IAAA,IAAI,CAAA,GAAI,CAAA;AACR,IAAA,KAAA,MAAW,KAAA,IAAS,KAAK,SAAA,EAAW;AAClC,MAAA,IAAI,EAAE,iBAAiBC,8BAAA,CAAA,EAAe;AACtC,MAAA,MAAM,CAAA,GAAI,OAAO,CAAA,EAAG,CAAA;AACpB,MAAA,IAAI,CAAA,EAAG,KAAA,CAAM,eAAA,CAAgB,IAAA,CAAK,IAAI,CAAA,CAAE,MAAA,EAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAA,CAAE,KAAK,CAAC,CAAC,CAAA;AAAA,IAC/E;AAAA,EACF;AACF","file":"Spans-WJFPHMSQ.cjs","sourcesContent":["// The sequence behind a text layer with `spans`: a composition of ordinary text layers (see src/text/spans.ts) that also owns the typewriter\n// (`visibleChars`) of the whole text: it counts over every character of every piece, and tells each piece how many of its own to show.\nimport { CompositionSequence } from './Composition';\nimport { TextSequence, bindCounterKeyframes, resolveNumber, type CounterState } from './Text';\nimport { spansMeta, type SpansMeta } from '../text/spans';\nimport type { CompositionShape, SequenceSpec, Props } from '../types';\nimport type { Timeline } from '../core/timelineEngine';\n\nconst strip = (props: Props | undefined): Props | undefined => {\n if (!props || !('visibleChars' in props)) return props;\n const { visibleChars: _gone, ...rest } = props as Record<string, unknown>;\n return rest as unknown as Props;\n};\n\nexport class SpansSequence extends CompositionSequence {\n private readonly _meta: SpansMeta | undefined;\n private readonly _count: CounterState = { value: 0, visibleChars: 0 };\n\n constructor(spec: SequenceSpec, parent: CompositionShape | null, root: CompositionShape) {\n super(spec, parent, root);\n this._meta = spansMeta.get(spec);\n }\n\n /** `visibleChars` is the group's own counter, not a property to write on the container. */\n protected override displayProps(): { initial: CompositionSequence['spec']['initial']; keyframes: CompositionSequence['spec']['keyframes'] } {\n const p = super.displayProps();\n if (!this._meta?.typed) return p;\n return {\n initial: strip(p.initial as Props | undefined) as never,\n keyframes: p.keyframes?.map(kf => ({ ...kf, set: strip(kf.set), to: strip(kf.to), from: strip(kf.from) })),\n };\n }\n\n override bindTimeline(timeline: Timeline, offset = 0): void {\n super.bindTimeline(timeline, offset);\n if (!this._meta?.typed) return;\n const scope = this.scope();\n const first = (this.spec.initial as Record<string, unknown> | undefined)?.visibleChars;\n this._count.visibleChars = first === undefined ? 0 : resolveNumber(first, scope); // like a text: it starts at 0 once it is animated\n bindCounterKeyframes(timeline, this._count, 'visibleChars', () => this._distribute(), this.spec.keyframes ?? [], this.duration!, offset + this.at, scope);\n this._distribute();\n }\n\n /** Every piece shows its part of the first N characters of the whole text. */\n private _distribute(): void {\n const pieces = this._meta!.pieces;\n const total = Math.max(0, Math.floor(this._count.visibleChars));\n let i = 0;\n for (const child of this._children) {\n if (!(child instanceof TextSequence)) continue;\n const p = pieces[i++];\n if (p) child.setVisibleChars(Math.min(p.length, Math.max(0, total - p.start)));\n }\n }\n}\n"]}