pixi-effects 0.4.0 → 0.6.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.
- package/CHANGELOG.md +45 -1
- package/README.md +11 -6
- package/ai/SKILL.md +7 -4
- package/ai/reference/cheatsheet.md +18 -5
- package/ai/reference/pitfalls.md +16 -11
- package/ai/reference/recipes.md +153 -1
- package/ai/template.html +6 -3
- package/ai/tools/check.mjs +385 -0
- package/dist/{Base-DhY9oMxr.d.ts → Base-4vNLl4tH.d.cts} +6 -1
- package/dist/{Base-5R7C5pHR.d.cts → Base-CD4AoT5-.d.ts} +6 -1
- package/dist/Composition-7SO5WYHU.js +4 -0
- package/dist/{Composition-RGTRZ2JX.js.map → Composition-7SO5WYHU.js.map} +1 -1
- package/dist/Composition-Y5VZSDDP.cjs +13 -0
- package/dist/{Composition-D7RCAGEA.cjs.map → Composition-Y5VZSDDP.cjs.map} +1 -1
- package/dist/Controller.cjs +47 -15
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +5 -2
- package/dist/Controller.d.ts +5 -2
- package/dist/Controller.js +47 -15
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-DRZtIGU7.d.ts → Movie-CADDBfpl.d.cts} +58 -2
- package/dist/{Movie-CghFXprP.d.cts → Movie-Ch2SUI1h.d.ts} +58 -2
- package/dist/{chunk-QGBOC5YL.cjs → chunk-4AGJF5RK.cjs} +33 -21
- package/dist/chunk-4AGJF5RK.cjs.map +1 -0
- package/dist/{chunk-ZQX7WIYL.js → chunk-7IJHJXDI.js} +380 -64
- package/dist/chunk-7IJHJXDI.js.map +1 -0
- package/dist/{chunk-A574IA4F.js → chunk-B2FTJLNB.js} +18 -6
- package/dist/chunk-B2FTJLNB.js.map +1 -0
- package/dist/chunk-DKGG7WD4.js +61 -0
- package/dist/chunk-DKGG7WD4.js.map +1 -0
- package/dist/{chunk-6BQ6IEW2.cjs → chunk-KQM2ZZMK.cjs} +380 -63
- package/dist/chunk-KQM2ZZMK.cjs.map +1 -0
- package/dist/chunk-UQBGW5DO.cjs +64 -0
- package/dist/chunk-UQBGW5DO.cjs.map +1 -0
- package/dist/index.cjs +333 -89
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +54 -5
- package/dist/index.d.ts +54 -5
- package/dist/index.js +317 -75
- package/dist/index.js.map +1 -1
- package/dist/sfx-MZJZXYY3.cjs +446 -0
- package/dist/sfx-MZJZXYY3.cjs.map +1 -0
- package/dist/sfx-S37DDC66.js +434 -0
- package/dist/sfx-S37DDC66.js.map +1 -0
- package/dist/three.cjs +5 -5
- package/dist/three.d.cts +2 -2
- package/dist/three.d.ts +2 -2
- package/dist/three.js +1 -1
- package/dist/{types-CRE9WKd4.d.ts → types-DrW9QeKU.d.cts} +118 -12
- package/dist/{types-CRE9WKd4.d.cts → types-DrW9QeKU.d.ts} +118 -12
- package/docs/api.md +37 -0
- package/docs/dsl.md +70 -10
- package/llms-full.txt +300 -30
- package/llms.txt +1 -1
- package/package.json +2 -1
- package/dist/Composition-D7RCAGEA.cjs +0 -13
- package/dist/Composition-RGTRZ2JX.js +0 -4
- package/dist/chunk-6BQ6IEW2.cjs.map +0 -1
- package/dist/chunk-A574IA4F.js.map +0 -1
- package/dist/chunk-QGBOC5YL.cjs.map +0 -1
- package/dist/chunk-ZQX7WIYL.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
3
|
+
var chunkUQBGW5DO_cjs = require('./chunk-UQBGW5DO.cjs');
|
|
4
|
+
var chunk4AGJF5RK_cjs = require('./chunk-4AGJF5RK.cjs');
|
|
5
|
+
var chunkKQM2ZZMK_cjs = require('./chunk-KQM2ZZMK.cjs');
|
|
5
6
|
var PIXI = require('pixi.js');
|
|
6
7
|
var gsap = require('gsap');
|
|
7
8
|
var PixiPlugin = require('gsap/PixiPlugin');
|
|
@@ -88,21 +89,213 @@ async function loadAssetBundle(assets, audioContext) {
|
|
|
88
89
|
async function mixdown(audios, totalDuration, sampleRate = 44100) {
|
|
89
90
|
if (audios.length === 0) return null;
|
|
90
91
|
const ctx = new OfflineAudioContext(2, Math.ceil(sampleRate * totalDuration), sampleRate);
|
|
92
|
+
const synthesised = /* @__PURE__ */ new Map();
|
|
93
|
+
const bufferOf = (a) => {
|
|
94
|
+
if (a.buffer) return a.buffer;
|
|
95
|
+
if (!a.synth) return null;
|
|
96
|
+
let buf = synthesised.get(a.synth.key);
|
|
97
|
+
if (!buf) {
|
|
98
|
+
const [left, right] = a.synth.render(sampleRate);
|
|
99
|
+
buf = ctx.createBuffer(2, left.length, sampleRate);
|
|
100
|
+
buf.getChannelData(0).set(left);
|
|
101
|
+
buf.getChannelData(1).set(right);
|
|
102
|
+
synthesised.set(a.synth.key, buf);
|
|
103
|
+
}
|
|
104
|
+
return buf;
|
|
105
|
+
};
|
|
91
106
|
for (const a of audios) {
|
|
107
|
+
const buffer = bufferOf(a);
|
|
108
|
+
if (!buffer) continue;
|
|
109
|
+
const begin = Math.max(0, a.start);
|
|
110
|
+
const skipped = begin - a.start;
|
|
111
|
+
if (skipped > 0) {
|
|
112
|
+
console.warn(
|
|
113
|
+
`pixi-effects: ${a.layer ?? "an audio layer"} starts at ${a.start.toFixed(2)}s, before the movie starts, so its first ${skipped.toFixed(2)}s are cut off. Start it at 0 or later.`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
92
116
|
const src = ctx.createBufferSource();
|
|
93
|
-
src.buffer =
|
|
117
|
+
src.buffer = buffer;
|
|
94
118
|
src.loop = !!a.loop;
|
|
95
119
|
const gain = ctx.createGain();
|
|
96
|
-
gain.gain.setValueAtTime(a.initialVolume ?? 1,
|
|
120
|
+
gain.gain.setValueAtTime(a.initialVolume ?? 1, begin);
|
|
97
121
|
for (const kf of a.volumeKeyframes ?? []) {
|
|
98
|
-
gain.gain.linearRampToValueAtTime(kf.value, kf.time);
|
|
122
|
+
gain.gain.linearRampToValueAtTime(kf.value, Math.max(0, kf.time));
|
|
99
123
|
}
|
|
100
124
|
src.connect(gain).connect(ctx.destination);
|
|
101
|
-
src.start(
|
|
102
|
-
src.stop(a.end);
|
|
125
|
+
src.start(begin, skipped);
|
|
126
|
+
src.stop(Math.max(begin, a.end));
|
|
103
127
|
}
|
|
104
128
|
return await ctx.startRendering();
|
|
105
129
|
}
|
|
130
|
+
var KNEE = 0.9;
|
|
131
|
+
function limitMix(buffer, audios) {
|
|
132
|
+
let peak = 0;
|
|
133
|
+
let peakIndex = 0;
|
|
134
|
+
for (let ch = 0; ch < buffer.numberOfChannels; ch++) {
|
|
135
|
+
const d = buffer.getChannelData(ch);
|
|
136
|
+
for (let i = 0; i < d.length; i++) {
|
|
137
|
+
const x = Math.abs(d[i]);
|
|
138
|
+
if (x > peak) {
|
|
139
|
+
peak = x;
|
|
140
|
+
peakIndex = i;
|
|
141
|
+
}
|
|
142
|
+
if (x > KNEE) d[i] = Math.sign(d[i]) * (KNEE + (1 - KNEE) * Math.tanh((x - KNEE) / (1 - KNEE)));
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
const peakAt = peakIndex / buffer.sampleRate;
|
|
146
|
+
if (peak > 1) {
|
|
147
|
+
const playing = audios.filter((a) => a.start <= peakAt && peakAt < a.end).map((a) => a.layer ?? "an audio layer");
|
|
148
|
+
console.warn(
|
|
149
|
+
`pixi-effects: the audio mix peaks at ${peak.toFixed(2)} (${(20 * Math.log10(peak)).toFixed(1)} dBFS) at ${peakAt.toFixed(2)}s, so it was limited (it would distort). Playing there: ${[...new Set(playing)].join(", ")}. Lower their volume.`
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return { peak, peakAt };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// src/core/spectrum.ts
|
|
156
|
+
function fft(re, im) {
|
|
157
|
+
const n = re.length;
|
|
158
|
+
for (let i = 1, j = 0; i < n; i++) {
|
|
159
|
+
let bit = n >> 1;
|
|
160
|
+
for (; j & bit; bit >>= 1) j ^= bit;
|
|
161
|
+
j ^= bit;
|
|
162
|
+
if (i < j) {
|
|
163
|
+
[re[i], re[j]] = [re[j], re[i]];
|
|
164
|
+
[im[i], im[j]] = [im[j], im[i]];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
for (let len = 2; len <= n; len <<= 1) {
|
|
168
|
+
const ang = -2 * Math.PI / len;
|
|
169
|
+
for (let i = 0; i < n; i += len) {
|
|
170
|
+
for (let k = 0; k < len / 2; k++) {
|
|
171
|
+
const wr = Math.cos(ang * k), wi = Math.sin(ang * k);
|
|
172
|
+
const a = i + k, b = a + len / 2;
|
|
173
|
+
const xr = re[b] * wr - im[b] * wi, xi = re[b] * wi + im[b] * wr;
|
|
174
|
+
re[b] = re[a] - xr;
|
|
175
|
+
im[b] = im[a] - xi;
|
|
176
|
+
re[a] = re[a] + xr;
|
|
177
|
+
im[a] = im[a] + xi;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
var FRAME = 2048;
|
|
183
|
+
function spectralCentroid(samples, sampleRate, from = 0, to = samples.length) {
|
|
184
|
+
let num = 0;
|
|
185
|
+
let den = 0;
|
|
186
|
+
const re = new Float64Array(FRAME);
|
|
187
|
+
const im = new Float64Array(FRAME);
|
|
188
|
+
const end = Math.min(to, samples.length);
|
|
189
|
+
for (let start = Math.max(0, from); start < end; start += FRAME / 2) {
|
|
190
|
+
for (let i = 0; i < FRAME; i++) {
|
|
191
|
+
const k = start + i;
|
|
192
|
+
const w = 0.5 - 0.5 * Math.cos(2 * Math.PI * i / (FRAME - 1));
|
|
193
|
+
re[i] = k < end ? samples[k] * w : 0;
|
|
194
|
+
im[i] = 0;
|
|
195
|
+
}
|
|
196
|
+
fft(re, im);
|
|
197
|
+
for (let b = 1; b < FRAME / 2; b++) {
|
|
198
|
+
const power = re[b] * re[b] + im[b] * im[b];
|
|
199
|
+
num += power * (b * sampleRate / FRAME);
|
|
200
|
+
den += power;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return den > 1e-9 ? Math.round(num / den / 10) * 10 : 0;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// src/core/inspectAudio.ts
|
|
207
|
+
var INAUDIBLE_DB = -50;
|
|
208
|
+
var db = (x) => Math.round(10 * Math.max(-120, 20 * Math.log10(x))) / 10;
|
|
209
|
+
var mono = (chans) => {
|
|
210
|
+
if (chans.length === 1) return chans[0];
|
|
211
|
+
const out = new Float32Array(chans[0].length);
|
|
212
|
+
for (const d of chans) for (let i = 0; i < out.length; i++) out[i] = out[i] + d[i] / chans.length;
|
|
213
|
+
return out;
|
|
214
|
+
};
|
|
215
|
+
function measure(chans, sampleRate) {
|
|
216
|
+
let peak = 0;
|
|
217
|
+
let at = 0;
|
|
218
|
+
for (const d of chans) for (let i = 0; i < d.length; i++) if (Math.abs(d[i]) > peak) {
|
|
219
|
+
peak = Math.abs(d[i]);
|
|
220
|
+
at = i;
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
length: Math.round(chans[0].length / sampleRate * 1e3) / 1e3,
|
|
224
|
+
peakDb: db(peak),
|
|
225
|
+
loudestAt: Math.round(at / sampleRate * 1e3) / 1e3,
|
|
226
|
+
brightnessHz: spectralCentroid(mono(chans), sampleRate)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function analyzeAudio(mix, sources, stats, movieDuration, opts = {}) {
|
|
230
|
+
if (!mix) {
|
|
231
|
+
return { duration: movieDuration, sampleRate: 0, peakDb: -120, peakAt: 0, sources: [], windows: [], issues: ['no audio: the movie has no audio layers (sound effects need no files: { type: "audio", sfx: "pop", at: 1 })'] };
|
|
232
|
+
}
|
|
233
|
+
const sr = mix.sampleRate;
|
|
234
|
+
const chans = Array.from({ length: mix.numberOfChannels }, (_, c) => mix.getChannelData(c));
|
|
235
|
+
const mixMono = mono(chans);
|
|
236
|
+
const peakIn = (t0, t1) => {
|
|
237
|
+
let p = 0;
|
|
238
|
+
const i1 = Math.min(mix.length, Math.ceil(t1 * sr));
|
|
239
|
+
for (const d of chans) for (let i = Math.max(0, Math.floor(t0 * sr)); i < i1; i++) p = Math.max(p, Math.abs(d[i]));
|
|
240
|
+
return p;
|
|
241
|
+
};
|
|
242
|
+
const win = opts.window && opts.window > 0 ? Math.max(0.01, opts.window) : 0.1;
|
|
243
|
+
const windows2 = [];
|
|
244
|
+
for (let t = 0; t < movieDuration - 1e-9; t += win) {
|
|
245
|
+
const i0 = Math.floor(t * sr);
|
|
246
|
+
const i1 = Math.min(mix.length, Math.floor((t + win) * sr));
|
|
247
|
+
let sum = 0;
|
|
248
|
+
let peak = 0;
|
|
249
|
+
for (const d of chans) {
|
|
250
|
+
for (let i = i0; i < i1; i++) {
|
|
251
|
+
sum += d[i] * d[i];
|
|
252
|
+
peak = Math.max(peak, Math.abs(d[i]));
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const n = Math.max(1, (i1 - i0) * chans.length);
|
|
256
|
+
windows2.push({ t: Math.round(t * 1e3) / 1e3, rmsDb: db(Math.sqrt(sum / n)), peakDb: db(peak), brightnessHz: spectralCentroid(mixMono, sr, i0, i1) });
|
|
257
|
+
}
|
|
258
|
+
const issues = [];
|
|
259
|
+
if (stats && stats.peak > 1) {
|
|
260
|
+
issues.push(`the mix peaks at ${db(stats.peak)} dBFS at ${stats.peakAt.toFixed(2)}s and was limited \u2014 lower the volume of the layers playing there`);
|
|
261
|
+
}
|
|
262
|
+
const rendered = /* @__PURE__ */ new Map();
|
|
263
|
+
const soundOf = (s) => {
|
|
264
|
+
if (s.synth) {
|
|
265
|
+
let m = rendered.get(s.synth.key);
|
|
266
|
+
if (!m) rendered.set(s.synth.key, m = measure(s.synth.render(sr), sr));
|
|
267
|
+
return m;
|
|
268
|
+
}
|
|
269
|
+
const b = s.buffer;
|
|
270
|
+
return measure(Array.from({ length: b.numberOfChannels }, (_, c) => b.getChannelData(c)), b.sampleRate);
|
|
271
|
+
};
|
|
272
|
+
const list = [...sources].sort((a, b) => a.start - b.start).map((s) => {
|
|
273
|
+
const layer = s.layer ?? "an audio layer";
|
|
274
|
+
const source = s.source ?? "audio";
|
|
275
|
+
const peakDb = db(peakIn(s.start, Math.min(s.end, movieDuration)));
|
|
276
|
+
const sound = soundOf(s);
|
|
277
|
+
const topVolume = Math.max(s.initialVolume ?? 1, ...(s.volumeKeyframes ?? []).map((k) => k.value));
|
|
278
|
+
const ownDb = db(Math.pow(10, sound.peakDb / 20) * Math.max(0, topVolume));
|
|
279
|
+
if (s.start >= movieDuration) {
|
|
280
|
+
issues.push(`${layer} (${source}) starts at ${s.start.toFixed(2)}s, after the movie ends (${movieDuration}s)`);
|
|
281
|
+
} else if (ownDb < INAUDIBLE_DB || peakDb < INAUDIBLE_DB) {
|
|
282
|
+
issues.push(`${layer} (${source}) is inaudible from ${s.start.toFixed(2)}s to ${s.end.toFixed(2)}s (its own peak ${ownDb} dBFS at volume ${topVolume}; mix peak there ${peakDb} dBFS) \u2014 check its volume`);
|
|
283
|
+
}
|
|
284
|
+
if (s.synth && s.end > movieDuration + 1e-6 && s.start < movieDuration) {
|
|
285
|
+
issues.push(`${layer} (${source}) is cut off by the end of the movie at ${movieDuration}s (it runs to ${s.end.toFixed(2)}s)`);
|
|
286
|
+
}
|
|
287
|
+
return { layer, source, start: s.start, end: s.end, peakDb, sound };
|
|
288
|
+
});
|
|
289
|
+
return {
|
|
290
|
+
duration: movieDuration,
|
|
291
|
+
sampleRate: sr,
|
|
292
|
+
peakDb: db(stats?.peak ?? peakIn(0, movieDuration)),
|
|
293
|
+
peakAt: stats?.peakAt ?? 0,
|
|
294
|
+
sources: list,
|
|
295
|
+
windows: windows2,
|
|
296
|
+
issues
|
|
297
|
+
};
|
|
298
|
+
}
|
|
106
299
|
var VIDEO_CODEC_BY_FORMAT = {
|
|
107
300
|
mp4: "avc",
|
|
108
301
|
mov: "avc",
|
|
@@ -160,7 +353,7 @@ async function exportFrames(movie, options = {}) {
|
|
|
160
353
|
const audioSource = new mediabunny.AudioBufferSource({
|
|
161
354
|
codec: opts.audio.codec,
|
|
162
355
|
bitrate: opts.audio.bitrate
|
|
163
|
-
});
|
|
356
|
+
}, { startTimestamp: opts.audio.codec === "aac" ? -2112 / movie.audioBuffer.sampleRate : 0 });
|
|
164
357
|
output.addAudioTrack(audioSource);
|
|
165
358
|
await output.start();
|
|
166
359
|
await audioSource.add(movie.audioBuffer);
|
|
@@ -626,16 +819,16 @@ function expandTransitions(spec) {
|
|
|
626
819
|
if (toUses > 1) {
|
|
627
820
|
throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
|
|
628
821
|
}
|
|
629
|
-
const tStart =
|
|
822
|
+
const tStart = chunkKQM2ZZMK_cjs.resolveAt(t.at, parentDuration);
|
|
630
823
|
const tEnd = tStart + t.duration;
|
|
631
824
|
const fromSeq = fromEntry.seq;
|
|
632
|
-
const fromStart =
|
|
825
|
+
const fromStart = chunkKQM2ZZMK_cjs.resolveAt(fromSeq.at, parentDuration);
|
|
633
826
|
const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
|
|
634
827
|
if (tStart < fromStart || tEnd > fromEnd) {
|
|
635
828
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
|
|
636
829
|
}
|
|
637
830
|
const toSeq = toEntry.seq;
|
|
638
|
-
const toStart =
|
|
831
|
+
const toStart = chunkKQM2ZZMK_cjs.resolveAt(toSeq.at, parentDuration);
|
|
639
832
|
const toEnd = toStart + (toSeq.duration ?? parentDuration);
|
|
640
833
|
if (tStart < toStart || tEnd > toEnd) {
|
|
641
834
|
throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
|
|
@@ -946,7 +1139,8 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
946
1139
|
const view = { x: 0, y: 0, width: canvas.width, height: canvas.height };
|
|
947
1140
|
const seen = /* @__PURE__ */ new Map();
|
|
948
1141
|
const scene = /* @__PURE__ */ new Map();
|
|
949
|
-
const
|
|
1142
|
+
const scaledToNothing = /* @__PURE__ */ new Set();
|
|
1143
|
+
const walk = (comp, prefix, insideThreeD, parentVisible, parentScene, parentMoving = false, parentZero = false) => {
|
|
950
1144
|
const blending = /* @__PURE__ */ new Set();
|
|
951
1145
|
for (const w of transitionWindowsOf(comp.spec)) {
|
|
952
1146
|
const start = (comp.absoluteStart ?? 0) + w.start, end = (comp.absoluteStart ?? 0) + w.end;
|
|
@@ -974,8 +1168,10 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
974
1168
|
onCanvas = inter === 0 && area > 0 ? "none" : inter >= area - 1e-6 ? "full" : "partial";
|
|
975
1169
|
if (area === 0) onCanvas = "none";
|
|
976
1170
|
}
|
|
977
|
-
const keys =
|
|
978
|
-
const moving = (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
|
|
1171
|
+
const keys = chunkKQM2ZZMK_cjs.collectPropKeys(seq.spec);
|
|
1172
|
+
const moving = parentMoving || (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
|
|
1173
|
+
const scale = t?.scale;
|
|
1174
|
+
const zero = parentZero || !!scale && (scale.x === 0 || scale.y === 0);
|
|
979
1175
|
const info = { path: prefix + label, name, type: seq.spec.type, threeD, visible, alpha, moving, bounds, onCanvas };
|
|
980
1176
|
layers.push(info);
|
|
981
1177
|
let shown = bounds ? clip(bounds, view) : null;
|
|
@@ -987,7 +1183,8 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
987
1183
|
seen.set(info, shown);
|
|
988
1184
|
const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
|
|
989
1185
|
if (group) scene.set(info, group);
|
|
990
|
-
if (
|
|
1186
|
+
if (zero || seq.showsNothingYet) scaledToNothing.add(info);
|
|
1187
|
+
if (seq instanceof chunk4AGJF5RK_cjs.CompositionSequence) walk(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
|
|
991
1188
|
});
|
|
992
1189
|
};
|
|
993
1190
|
walk(root, "", false, true);
|
|
@@ -997,6 +1194,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
|
|
|
997
1194
|
const b = l.bounds;
|
|
998
1195
|
const who = `text layer "${l.path}"`;
|
|
999
1196
|
if (b.width < 1 || b.height < 1) {
|
|
1197
|
+
if (scaledToNothing.has(l)) continue;
|
|
1000
1198
|
issues.push(`${who} has no size (empty text, or not drawn yet)`);
|
|
1001
1199
|
} else if (l.moving || scene.has(l)) ; else if (l.onCanvas === "none") {
|
|
1002
1200
|
issues.push(`${who} is entirely outside the canvas (at ${Math.round(b.x)},${Math.round(b.y)}, ${Math.round(b.width)}\xD7${Math.round(b.height)})`);
|
|
@@ -1046,63 +1244,34 @@ function sheetLayout(n, columns, cellW, srcW, srcH, labelH) {
|
|
|
1046
1244
|
return { cols, rows, cellW, cellH, width: cols * cellW, height: rows * (cellH + labelH), positions };
|
|
1047
1245
|
}
|
|
1048
1246
|
|
|
1049
|
-
// src/core/
|
|
1050
|
-
function
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
1056
|
-
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) dp[i][j] = Math.min(dp[i][j], dp[i - 2][j - 2] + 1);
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
return dp[a.length][b.length];
|
|
1060
|
-
}
|
|
1061
|
-
var isSubsequence = (small, big) => {
|
|
1062
|
-
let i = 0;
|
|
1063
|
-
for (const ch of big) if (i < small.length && ch === small[i]) i++;
|
|
1064
|
-
return i === small.length;
|
|
1065
|
-
};
|
|
1066
|
-
var COMMON_ALIASES = {
|
|
1067
|
-
fps: "frameRate",
|
|
1068
|
-
framerate: "frameRate",
|
|
1069
|
-
frame_rate: "frameRate",
|
|
1070
|
-
bg: "background",
|
|
1071
|
-
backgroundcolor: "background",
|
|
1072
|
-
bgcolor: "background",
|
|
1073
|
-
seconds: "duration",
|
|
1074
|
-
length: "duration",
|
|
1075
|
-
time: "duration",
|
|
1076
|
-
w: "width",
|
|
1077
|
-
h: "height",
|
|
1078
|
-
cols: "columns",
|
|
1079
|
-
sweep: "degrees",
|
|
1080
|
-
angle: "degrees"
|
|
1081
|
-
};
|
|
1082
|
-
function suggestName(name, valid) {
|
|
1083
|
-
const n = name.toLowerCase();
|
|
1084
|
-
const alias = COMMON_ALIASES[n];
|
|
1085
|
-
if (alias && valid.includes(alias)) return alias;
|
|
1086
|
-
let best = null;
|
|
1087
|
-
for (const v of valid) {
|
|
1088
|
-
const lv = v.toLowerCase();
|
|
1089
|
-
const d = distance(n, lv);
|
|
1090
|
-
const close = d <= Math.max(1, Math.floor(Math.min(n.length, lv.length) / 3));
|
|
1091
|
-
const abbreviation = n.length >= 3 && isSubsequence(n, lv) || lv.length >= 2 && n.length > lv.length && n.includes(lv);
|
|
1092
|
-
if (!close && !abbreviation) continue;
|
|
1093
|
-
const score = close ? d : 3 + (lv.length - n.length) / 100;
|
|
1094
|
-
if (!best || score < best.score) best = { v, score };
|
|
1095
|
-
}
|
|
1096
|
-
return best ? best.v : null;
|
|
1097
|
-
}
|
|
1098
|
-
function warnUnknownOptions(where, opts, valid) {
|
|
1099
|
-
if (!opts || typeof opts !== "object") return;
|
|
1100
|
-
for (const key of Object.keys(opts)) {
|
|
1101
|
-
if (valid.includes(key)) continue;
|
|
1102
|
-
const guess = suggestName(key, valid);
|
|
1103
|
-
console.warn(`pixi-effects: ${where}: unknown option "${key}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (valid: ${valid.join(", ")})`);
|
|
1247
|
+
// src/core/startWhenRunning.ts
|
|
1248
|
+
function startWhenRunning(ctx, start, gesture) {
|
|
1249
|
+
if (ctx.state === "running") {
|
|
1250
|
+
start();
|
|
1251
|
+
return () => {
|
|
1252
|
+
};
|
|
1104
1253
|
}
|
|
1254
|
+
let done = false;
|
|
1255
|
+
const resume = () => {
|
|
1256
|
+
ctx.resume?.()?.catch(() => {
|
|
1257
|
+
});
|
|
1258
|
+
};
|
|
1259
|
+
const stop = () => {
|
|
1260
|
+
done = true;
|
|
1261
|
+
ctx.removeEventListener("statechange", onState);
|
|
1262
|
+
for (const e of GESTURES) gesture?.removeEventListener(e, resume, true);
|
|
1263
|
+
};
|
|
1264
|
+
const onState = () => {
|
|
1265
|
+
if (done || ctx.state !== "running") return;
|
|
1266
|
+
stop();
|
|
1267
|
+
start();
|
|
1268
|
+
};
|
|
1269
|
+
ctx.addEventListener("statechange", onState);
|
|
1270
|
+
for (const e of GESTURES) gesture?.addEventListener(e, resume, true);
|
|
1271
|
+
resume();
|
|
1272
|
+
return stop;
|
|
1105
1273
|
}
|
|
1274
|
+
var GESTURES = ["pointerdown", "mousedown", "touchend", "keydown"];
|
|
1106
1275
|
|
|
1107
1276
|
// src/core/Movie.ts
|
|
1108
1277
|
PIXI.extensions.add(PIXI.CullerPlugin);
|
|
@@ -1116,6 +1285,7 @@ var Movie = class {
|
|
|
1116
1285
|
audioBuffer = null;
|
|
1117
1286
|
audioSource = null;
|
|
1118
1287
|
gainNode = null;
|
|
1288
|
+
_cancelAudioStart = null;
|
|
1119
1289
|
_volume = 1;
|
|
1120
1290
|
_muted = false;
|
|
1121
1291
|
isPlaying = false;
|
|
@@ -1130,6 +1300,9 @@ var Movie = class {
|
|
|
1130
1300
|
_rootSequence = null;
|
|
1131
1301
|
_rootContainer = null;
|
|
1132
1302
|
_raf = null;
|
|
1303
|
+
/** What went into the mix, and its peak before limiting — kept for inspectAudio(). */
|
|
1304
|
+
_audioSources = [];
|
|
1305
|
+
_mixStats = null;
|
|
1133
1306
|
on(event, fn) {
|
|
1134
1307
|
(this._events[event] ??= []).push(fn);
|
|
1135
1308
|
if (event === "ready" && this._initState === "ready") {
|
|
@@ -1162,7 +1335,7 @@ var Movie = class {
|
|
|
1162
1335
|
return this._audioContext;
|
|
1163
1336
|
}
|
|
1164
1337
|
async init(options = {}) {
|
|
1165
|
-
warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition"]);
|
|
1338
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.init()", options, ["width", "height", "duration", "frameRate", "background", "canvas", "assets", "composition"]);
|
|
1166
1339
|
this._initState = "pending";
|
|
1167
1340
|
try {
|
|
1168
1341
|
this.width = options.width ?? 1920;
|
|
@@ -1215,7 +1388,7 @@ var Movie = class {
|
|
|
1215
1388
|
...userComposition
|
|
1216
1389
|
};
|
|
1217
1390
|
if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
|
|
1218
|
-
const composition = new
|
|
1391
|
+
const composition = new chunk4AGJF5RK_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
|
|
1219
1392
|
await composition.build();
|
|
1220
1393
|
this._rootSequence = composition;
|
|
1221
1394
|
if (composition.target) root.addChild(composition.target);
|
|
@@ -1224,7 +1397,9 @@ var Movie = class {
|
|
|
1224
1397
|
composition.collectAudio(audios, 0);
|
|
1225
1398
|
if (audios.length > 0) {
|
|
1226
1399
|
this.audioBuffer = await mixdown(audios, this.duration, audioContext.sampleRate);
|
|
1400
|
+
if (this.audioBuffer) this._mixStats = limitMix(this.audioBuffer, audios);
|
|
1227
1401
|
}
|
|
1402
|
+
this._audioSources = audios;
|
|
1228
1403
|
this.timeline.progress(1).progress(0);
|
|
1229
1404
|
await this._awaitVideoFrames();
|
|
1230
1405
|
this._updateSpace();
|
|
@@ -1262,7 +1437,7 @@ var Movie = class {
|
|
|
1262
1437
|
}));
|
|
1263
1438
|
}
|
|
1264
1439
|
async snapshot(frame = this.currentFrame, opts = {}) {
|
|
1265
|
-
warnUnknownOptions("movie.snapshot()", opts, ["scale", "type", "as"]);
|
|
1440
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.snapshot()", opts, ["scale", "type", "as"]);
|
|
1266
1441
|
this._requireReady("snapshot");
|
|
1267
1442
|
await this.gotoFrame(clampFrame(frame, this.totalFrames), true);
|
|
1268
1443
|
const scale = opts.scale ?? 1;
|
|
@@ -1273,7 +1448,7 @@ var Movie = class {
|
|
|
1273
1448
|
return encodeCanvas(out, opts.type ?? "image/png", opts.as ?? "blob");
|
|
1274
1449
|
}
|
|
1275
1450
|
async contactSheet(opts = {}) {
|
|
1276
|
-
warnUnknownOptions("movie.contactSheet()", opts, ["frames", "times", "count", "columns", "cellWidth", "as"]);
|
|
1451
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.contactSheet()", opts, ["frames", "times", "count", "columns", "cellWidth", "as"]);
|
|
1277
1452
|
this._requireReady("contactSheet");
|
|
1278
1453
|
const frames = (opts.frames ?? opts.times?.map((t) => Math.round(t * this.frameRate)) ?? pickFrames(this.totalFrames, opts.count ?? 6)).map((f) => clampFrame(f, this.totalFrames));
|
|
1279
1454
|
const LABEL_H = 26;
|
|
@@ -1306,12 +1481,21 @@ var Movie = class {
|
|
|
1306
1481
|
* the canvas, cut by an edge, empty, or overlapping other text. Seeks there and stays there.
|
|
1307
1482
|
*/
|
|
1308
1483
|
async inspect(frame = this.currentFrame, opts = { layers: "visible" }) {
|
|
1309
|
-
warnUnknownOptions("movie.inspect()", opts, ["layers"]);
|
|
1484
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.inspect()", opts, ["layers"]);
|
|
1310
1485
|
this._requireReady("inspect");
|
|
1311
1486
|
const f = clampFrame(frame, this.totalFrames);
|
|
1312
1487
|
await this.gotoFrame(f, true);
|
|
1313
1488
|
return inspectScene(this._rootSequence, f, f / this.frameRate, { width: this.width, height: this.height }, opts);
|
|
1314
1489
|
}
|
|
1490
|
+
/**
|
|
1491
|
+
* The soundtrack, measured: when every audio layer plays, how loud the mix is over time, and `issues`
|
|
1492
|
+
* (limiting, inaudible layers, sounds cut off by the end). Use it to CHECK sound you cannot hear.
|
|
1493
|
+
*/
|
|
1494
|
+
inspectAudio(opts = {}) {
|
|
1495
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.inspectAudio()", opts, ["window"]);
|
|
1496
|
+
this._requireReady("inspectAudio");
|
|
1497
|
+
return analyzeAudio(this.audioBuffer, this._audioSources, this._mixStats, this.duration, opts);
|
|
1498
|
+
}
|
|
1315
1499
|
/**
|
|
1316
1500
|
* Draw the stage now. PixiJS's CullerPlugin only culls inside `app.render()` (the ticker), and we render
|
|
1317
1501
|
* by hand — while seeking and especially during `render()`, which stops the ticker — so without this the
|
|
@@ -1339,6 +1523,7 @@ var Movie = class {
|
|
|
1339
1523
|
play() {
|
|
1340
1524
|
if (this._initState !== "ready") return;
|
|
1341
1525
|
if (this.currentFrame >= this.totalFrames) this.currentFrame = 0;
|
|
1526
|
+
const wasPlaying = this.isPlaying;
|
|
1342
1527
|
this.isPlaying = true;
|
|
1343
1528
|
const startTime = performance.now() - this.currentFrame / this.frameRate * 1e3;
|
|
1344
1529
|
let inFlight = false;
|
|
@@ -1368,17 +1553,25 @@ var Movie = class {
|
|
|
1368
1553
|
this._raf = requestAnimationFrame(tick);
|
|
1369
1554
|
if (this.audioBuffer) {
|
|
1370
1555
|
const ctx = this._ensureAudioContext();
|
|
1371
|
-
|
|
1372
|
-
this.
|
|
1373
|
-
this.
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1556
|
+
const buffer = this.audioBuffer;
|
|
1557
|
+
this._cancelAudioStart?.();
|
|
1558
|
+
this._cancelAudioStart = startWhenRunning(ctx, () => {
|
|
1559
|
+
if (!this.isPlaying) return;
|
|
1560
|
+
this.audioSource = ctx.createBufferSource();
|
|
1561
|
+
this.audioSource.buffer = buffer;
|
|
1562
|
+
this.gainNode = ctx.createGain();
|
|
1563
|
+
this.gainNode.gain.value = this._muted ? 0 : this._volume;
|
|
1564
|
+
this.audioSource.connect(this.gainNode).connect(ctx.destination);
|
|
1565
|
+
this.audioSource.start(0, Math.min(this.currentFrame / this.frameRate, buffer.duration));
|
|
1566
|
+
}, typeof window !== "undefined" ? window : void 0);
|
|
1377
1567
|
}
|
|
1568
|
+
if (!wasPlaying) this.emit("play");
|
|
1378
1569
|
}
|
|
1379
1570
|
pause() {
|
|
1380
1571
|
const wasPlaying = this.isPlaying;
|
|
1381
1572
|
this.isPlaying = false;
|
|
1573
|
+
this._cancelAudioStart?.();
|
|
1574
|
+
this._cancelAudioStart = null;
|
|
1382
1575
|
if (this._raf) {
|
|
1383
1576
|
cancelAnimationFrame(this._raf);
|
|
1384
1577
|
this._raf = null;
|
|
@@ -1416,7 +1609,7 @@ var Movie = class {
|
|
|
1416
1609
|
return this.muted;
|
|
1417
1610
|
}
|
|
1418
1611
|
async render(options) {
|
|
1419
|
-
warnUnknownOptions("movie.render()", options, ["format", "video", "audio"]);
|
|
1612
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("movie.render()", options, ["format", "video", "audio"]);
|
|
1420
1613
|
return await exportFrames(this, options);
|
|
1421
1614
|
}
|
|
1422
1615
|
async destroy() {
|
|
@@ -1428,6 +1621,8 @@ var Movie = class {
|
|
|
1428
1621
|
safeRun(() => this.app?.destroy(true, { children: true, texture: true }));
|
|
1429
1622
|
this.app = null;
|
|
1430
1623
|
this.audioBuffer = null;
|
|
1624
|
+
this._audioSources = [];
|
|
1625
|
+
this._mixStats = null;
|
|
1431
1626
|
safeRun(() => this._audioContext?.close().catch(() => {
|
|
1432
1627
|
}));
|
|
1433
1628
|
this._audioContext = null;
|
|
@@ -1455,11 +1650,58 @@ function collectVideoSequences(seq, out) {
|
|
|
1455
1650
|
collectVideoSequences(child, out);
|
|
1456
1651
|
}
|
|
1457
1652
|
}
|
|
1653
|
+
var BY = ["chars", "words", "lines"];
|
|
1654
|
+
var ALIGN = ["left", "center", "right"];
|
|
1655
|
+
var widthOf = (text, style) => PIXI.CanvasTextMetrics.measureText(text, style).width;
|
|
1656
|
+
function measureText(text, style = {}) {
|
|
1657
|
+
const m = PIXI.CanvasTextMetrics.measureText(text, new PIXI.TextStyle(style));
|
|
1658
|
+
return { width: m.width, height: m.height, lines: text.split("\n").length };
|
|
1659
|
+
}
|
|
1660
|
+
function splitText(text, style = {}, opts = {}) {
|
|
1661
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("splitText()", opts, ["by", "x", "y", "align"]);
|
|
1662
|
+
let by = opts.by ?? "chars";
|
|
1663
|
+
if (!BY.includes(by)) {
|
|
1664
|
+
const g = chunkUQBGW5DO_cjs.suggestName(String(by), BY);
|
|
1665
|
+
console.warn(`pixi-effects: splitText(): by "${by}" is not one of ${BY.map((b) => `"${b}"`).join(", ")}${g ? ` \u2014 did you mean "${g}"?` : ""}; using "chars"`);
|
|
1666
|
+
by = "chars";
|
|
1667
|
+
}
|
|
1668
|
+
let align = opts.align ?? "left";
|
|
1669
|
+
if (!ALIGN.includes(align)) {
|
|
1670
|
+
const g = chunkUQBGW5DO_cjs.suggestName(String(align), ALIGN);
|
|
1671
|
+
console.warn(`pixi-effects: splitText(): align "${align}" is not one of ${ALIGN.join(", ")}${g ? ` \u2014 did you mean "${g}"?` : ""}; using "left"`);
|
|
1672
|
+
align = "left";
|
|
1673
|
+
}
|
|
1674
|
+
const x0 = opts.x ?? 0, y0 = opts.y ?? 0;
|
|
1675
|
+
if (text === "") return [];
|
|
1676
|
+
const ts = new PIXI.TextStyle(style);
|
|
1677
|
+
const lineHeight = PIXI.CanvasTextMetrics.measureText("M", ts).lineHeight ?? PIXI.CanvasTextMetrics.measureText("M", ts).height;
|
|
1678
|
+
const sentinel = widthOf("|", ts);
|
|
1679
|
+
const out = [];
|
|
1680
|
+
text.split("\n").forEach((line, lineNo) => {
|
|
1681
|
+
const lineWidth = widthOf(line, ts);
|
|
1682
|
+
const left = align === "center" ? x0 - lineWidth / 2 : align === "right" ? x0 - lineWidth : x0;
|
|
1683
|
+
const y = y0 + lineNo * lineHeight;
|
|
1684
|
+
const advance = (upTo) => upTo === 0 ? 0 : widthOf(line.slice(0, upTo) + "|", ts) - sentinel;
|
|
1685
|
+
const spans = [];
|
|
1686
|
+
if (by === "lines") {
|
|
1687
|
+
if (line.trim() !== "") spans.push([0, line.length]);
|
|
1688
|
+
} else if (by === "words") {
|
|
1689
|
+
for (const m of line.matchAll(/\S+/g)) spans.push([m.index, m.index + m[0].length]);
|
|
1690
|
+
} else {
|
|
1691
|
+
for (let i = 0; i < line.length; i++) if (!/\s/.test(line[i])) spans.push([i, i + 1]);
|
|
1692
|
+
}
|
|
1693
|
+
for (const [a, b] of spans) {
|
|
1694
|
+
const piece = line.slice(a, b);
|
|
1695
|
+
out.push({ text: piece, x: left + advance(a), y, width: widthOf(piece, ts), index: out.length, line: lineNo });
|
|
1696
|
+
}
|
|
1697
|
+
});
|
|
1698
|
+
return out;
|
|
1699
|
+
}
|
|
1458
1700
|
|
|
1459
1701
|
// src/presets/kenBurns.ts
|
|
1460
1702
|
var KEN_BURNS_KEYS = ["asset", "name", "at", "duration", "fit", "ease", "motion", "origin", "zoom", "direction", "angle", "from", "to"];
|
|
1461
1703
|
function kenBurns(opts) {
|
|
1462
|
-
warnUnknownOptions("kenBurns()", opts, KEN_BURNS_KEYS);
|
|
1704
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("kenBurns()", opts, KEN_BURNS_KEYS);
|
|
1463
1705
|
const {
|
|
1464
1706
|
asset,
|
|
1465
1707
|
name,
|
|
@@ -1575,7 +1817,7 @@ function parseEase(name) {
|
|
|
1575
1817
|
// src/presets/orbit.ts
|
|
1576
1818
|
var ORBIT_KEYS = ["duration", "degrees", "start", "radius", "center", "width", "height", "fov", "ease", "dollyZoom", "at", "name", "stepsPerSecond"];
|
|
1577
1819
|
function orbit(opts) {
|
|
1578
|
-
warnUnknownOptions("orbit()", opts, ORBIT_KEYS);
|
|
1820
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("orbit()", opts, ORBIT_KEYS);
|
|
1579
1821
|
const {
|
|
1580
1822
|
duration,
|
|
1581
1823
|
degrees,
|
|
@@ -1591,17 +1833,17 @@ function orbit(opts) {
|
|
|
1591
1833
|
throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
|
|
1592
1834
|
}
|
|
1593
1835
|
const [cx, cy] = opts.center ?? [width / 2, height / 2];
|
|
1594
|
-
const fixedR = opts.radius ??
|
|
1836
|
+
const fixedR = opts.radius ?? chunkKQM2ZZMK_cjs.homeDistance(height, fov ?? chunkKQM2ZZMK_cjs.DEFAULT_FOV);
|
|
1595
1837
|
const start = opts.start ?? -degrees / 2;
|
|
1596
1838
|
const steps = Math.max(1, Math.round(duration * stepsPerSecond));
|
|
1597
1839
|
const easeFn = parseEase(ease);
|
|
1598
1840
|
const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
|
|
1599
1841
|
const pos = (i) => {
|
|
1600
1842
|
const p = i / steps;
|
|
1601
|
-
const a = (start + degrees * easeFn(p)) *
|
|
1843
|
+
const a = (start + degrees * easeFn(p)) * chunkKQM2ZZMK_cjs.DEG;
|
|
1602
1844
|
if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
|
|
1603
1845
|
const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
|
|
1604
|
-
const R =
|
|
1846
|
+
const R = chunkKQM2ZZMK_cjs.homeDistance(height, f);
|
|
1605
1847
|
return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
|
|
1606
1848
|
};
|
|
1607
1849
|
const keyframes = [];
|
|
@@ -1630,7 +1872,7 @@ function orbit(opts) {
|
|
|
1630
1872
|
|
|
1631
1873
|
// src/transforms/withFade.ts
|
|
1632
1874
|
function withFade(spec, opts) {
|
|
1633
|
-
warnUnknownOptions("withFade()", opts, ["in", "out"]);
|
|
1875
|
+
chunkUQBGW5DO_cjs.warnUnknownOptions("withFade()", opts, ["in", "out"]);
|
|
1634
1876
|
if (opts.in != null && opts.in > 0) {
|
|
1635
1877
|
spec.initial = { ...spec.initial ?? {}, alpha: 0 };
|
|
1636
1878
|
const kf = { at: 0, to: { alpha: 1 }, duration: opts.in };
|
|
@@ -1650,11 +1892,13 @@ function withFade(spec, opts) {
|
|
|
1650
1892
|
|
|
1651
1893
|
Object.defineProperty(exports, "registerSequenceType", {
|
|
1652
1894
|
enumerable: true,
|
|
1653
|
-
get: function () { return
|
|
1895
|
+
get: function () { return chunkKQM2ZZMK_cjs.registerSequenceType; }
|
|
1654
1896
|
});
|
|
1655
1897
|
exports.Movie = Movie;
|
|
1656
1898
|
exports.kenBurns = kenBurns;
|
|
1899
|
+
exports.measureText = measureText;
|
|
1657
1900
|
exports.orbit = orbit;
|
|
1901
|
+
exports.splitText = splitText;
|
|
1658
1902
|
exports.withFade = withFade;
|
|
1659
1903
|
//# sourceMappingURL=index.cjs.map
|
|
1660
1904
|
//# sourceMappingURL=index.cjs.map
|