pixi-effects 0.46.0 → 0.47.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 +12 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/ai/tools/check.mjs +2 -2
- package/ai/tools/lookup.mjs +6 -1
- package/ai/tools/pixi-effects.mjs +1 -0
- package/ai/tools/render.mjs +17 -1
- package/dist/{chunk-O66JGPVV.cjs → chunk-23SXKSUI.cjs} +18 -4
- package/dist/chunk-23SXKSUI.cjs.map +1 -0
- package/dist/{chunk-K24FF4BT.js → chunk-4SEL6W7H.js} +18 -4
- package/dist/chunk-4SEL6W7H.js.map +1 -0
- package/dist/{chunk-7M63Y6MO.cjs → chunk-I6VUQ2CR.cjs} +105 -25
- package/dist/chunk-I6VUQ2CR.cjs.map +1 -0
- package/dist/{chunk-2E74SP63.js → chunk-W46VWAZC.js} +101 -21
- package/dist/chunk-W46VWAZC.js.map +1 -0
- package/dist/index.cjs +27 -27
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -2
- package/dist/loader.css +1 -1
- package/dist/present.cjs +2 -2
- package/dist/present.js +2 -2
- package/dist/sound.cjs +2 -2
- package/dist/sound.js +1 -1
- package/docs/api.md +1 -1
- package/docs/dsl.md +2 -2
- package/llms-full.txt +7 -7
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/reference/cheatsheet.md +2 -2
- package/skills/pixi-effects/reference/recipes.md +1 -1
- package/skills/pixi-effects/template.html +6 -6
- package/dist/chunk-2E74SP63.js.map +0 -1
- package/dist/chunk-7M63Y6MO.cjs.map +0 -1
- package/dist/chunk-K24FF4BT.js.map +0 -1
- package/dist/chunk-O66JGPVV.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CompositionSequence, maskSourceOf } from './chunk-FPV3NPYC.js';
|
|
2
2
|
import { EXPRESSION_NAMES, createTimeline, lengthen, ensureFilterLibrary, checkEase, parseEase, homeDistance, DEFAULT_FOV, random, noise, flattenSvgPath, trimPolylines, rand, DEG, timeRemapOf, contentLength, resolveAt, parseSpring, springDuration, spansMeta } from './chunk-DM2OLQOJ.js';
|
|
3
|
-
import { analyzeAudio, fft, resampleThrough, measureLoudness, playSpan } from './chunk-
|
|
3
|
+
import { analyzeAudio, fft, resampleThrough, measureLoudness, playSpan } from './chunk-4SEL6W7H.js';
|
|
4
4
|
import { usesAdvancedBlend, enableAdvancedBlend } from './chunk-VNP7QCJE.js';
|
|
5
5
|
import { describeLayer } from './chunk-32MMNDDN.js';
|
|
6
6
|
import { warnUnknownOptions, suggestName } from './chunk-BXOCEZ4U.js';
|
|
@@ -141,18 +141,86 @@ async function mixdown(audios, totalDuration, sampleRate = 44100, pace) {
|
|
|
141
141
|
}
|
|
142
142
|
var KNEE = 0.9;
|
|
143
143
|
var LOUDNESS_CEILING_DB = -1;
|
|
144
|
+
var MAX_LIMIT_DB = 10;
|
|
145
|
+
function limitInto(source, out, gain, ceil, sampleRate) {
|
|
146
|
+
const n = source[0]?.length ?? 0;
|
|
147
|
+
const req = new Float32Array(n);
|
|
148
|
+
for (let i = 0; i < n; i++) {
|
|
149
|
+
let p = 0;
|
|
150
|
+
for (const c of source) {
|
|
151
|
+
const a = Math.abs(c[i]) * gain;
|
|
152
|
+
if (a > p) p = a;
|
|
153
|
+
}
|
|
154
|
+
req[i] = p > ceil ? ceil / p : 1;
|
|
155
|
+
}
|
|
156
|
+
const L = Math.max(1, Math.round(3e-3 * sampleRate));
|
|
157
|
+
const mn = new Float32Array(n), dq = new Int32Array(n);
|
|
158
|
+
let head = 0, tail = 0;
|
|
159
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
160
|
+
while (tail > head && req[dq[tail - 1]] >= req[i]) tail--;
|
|
161
|
+
dq[tail++] = i;
|
|
162
|
+
while (dq[head] > i + L) head++;
|
|
163
|
+
mn[i] = req[dq[head]];
|
|
164
|
+
}
|
|
165
|
+
const release = 1 - Math.exp(-1 / (0.08 * sampleRate));
|
|
166
|
+
let run = 0, prev = 1, lowest = 1, lowestAt = 0;
|
|
167
|
+
const gains = new Float32Array(n);
|
|
168
|
+
for (let i = 0; i < n; i++) {
|
|
169
|
+
run += mn[i];
|
|
170
|
+
if (i > L) run -= mn[i - L - 1];
|
|
171
|
+
const avg = run / Math.min(i + 1, L + 1);
|
|
172
|
+
const g = Math.min(avg, prev + (1 - prev) * release);
|
|
173
|
+
gains[i] = g;
|
|
174
|
+
prev = g;
|
|
175
|
+
if (g < lowest) {
|
|
176
|
+
lowest = g;
|
|
177
|
+
lowestAt = i;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
for (let ch = 0; ch < source.length; ch++) {
|
|
181
|
+
const s = source[ch], o = out[ch];
|
|
182
|
+
for (let i = 0; i < n; i++) {
|
|
183
|
+
const v = s[i] * gain * gains[i];
|
|
184
|
+
o[i] = v > ceil ? ceil : v < -ceil ? -ceil : v;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return { reductionDb: lowest < 1 ? -20 * Math.log10(lowest) : 0, at: lowestAt / sampleRate };
|
|
188
|
+
}
|
|
144
189
|
function normalizeMix(buffer, target) {
|
|
145
190
|
const chans = [];
|
|
146
191
|
for (let ch = 0; ch < buffer.numberOfChannels; ch++) chans.push(buffer.getChannelData(ch));
|
|
147
|
-
const
|
|
192
|
+
const sr = buffer.sampleRate;
|
|
193
|
+
const m = measureLoudness(chans, sr, { truePeak: false });
|
|
148
194
|
if (m.integratedLufs === null) return { target, gainDb: 0, reachedLufs: null, limited: false };
|
|
195
|
+
const original = chans.map((c) => Float32Array.from(c));
|
|
149
196
|
let gainDb = target - m.integratedLufs;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
197
|
+
let ceilDb = LOUDNESS_CEILING_DB;
|
|
198
|
+
let applied = { reductionDb: 0, at: 0 }, measured = m;
|
|
199
|
+
for (let round2 = 0; round2 < 8; round2++) {
|
|
200
|
+
const cap = MAX_LIMIT_DB + ceilDb - m.samplePeakDb;
|
|
201
|
+
if (gainDb > cap) gainDb = cap;
|
|
202
|
+
applied = limitInto(original, chans, 10 ** (gainDb / 20), 10 ** (ceilDb / 20), sr);
|
|
203
|
+
measured = measureLoudness(chans, sr);
|
|
204
|
+
const overTp = measured.truePeakDb - LOUDNESS_CEILING_DB;
|
|
205
|
+
if (overTp > 0.02) {
|
|
206
|
+
ceilDb -= overTp + 0.02;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const deficit = target - measured.integratedLufs;
|
|
210
|
+
if (Math.abs(deficit) <= 0.15) break;
|
|
211
|
+
const next = Math.min(gainDb + deficit, cap);
|
|
212
|
+
if (Math.abs(next - gainDb) < 0.05) break;
|
|
213
|
+
gainDb = next;
|
|
214
|
+
}
|
|
215
|
+
const limited = measured.integratedLufs < target - 0.15;
|
|
216
|
+
const reduction = Math.round(applied.reductionDb * 10) / 10;
|
|
217
|
+
return {
|
|
218
|
+
target,
|
|
219
|
+
gainDb: Math.round(gainDb * 10) / 10,
|
|
220
|
+
reachedLufs: measured.integratedLufs,
|
|
221
|
+
limited,
|
|
222
|
+
...reduction >= 0.1 ? { limiterDb: reduction, limiterAt: Math.round(applied.at * 100) / 100 } : {}
|
|
223
|
+
};
|
|
156
224
|
}
|
|
157
225
|
function limitMix(buffer, audios) {
|
|
158
226
|
let peak = 0;
|
|
@@ -4446,20 +4514,25 @@ function animateText(text, style, options) {
|
|
|
4446
4514
|
const pieces = splitText(text, style, { by, x, y, align, ...vertical ? { vertical } : {} });
|
|
4447
4515
|
if (pieces.length === 0) return [];
|
|
4448
4516
|
const lineHeight = measureText("M", style).height;
|
|
4449
|
-
const
|
|
4450
|
-
const
|
|
4517
|
+
const given = (v) => v === false || v === "none" ? void 0 : v;
|
|
4518
|
+
const inSpec = options.in === void 0 ? "rise" : given(options.in), outSpec = given(options.out);
|
|
4519
|
+
const inTween = inSpec === void 0 ? null : resolveTween(inSpec, "in");
|
|
4520
|
+
const outTween = outSpec === void 0 ? null : resolveTween(outSpec, "out");
|
|
4451
4521
|
const delays = stagger(pieces.length, options.stagger ?? { each: 0.04 });
|
|
4452
4522
|
const wave = Math.max(...delays);
|
|
4453
|
-
const
|
|
4523
|
+
const outDelays = outTween?.stagger ? stagger(pieces.length, outTween.stagger) : delays;
|
|
4524
|
+
const outWave = Math.max(...outDelays);
|
|
4525
|
+
const lead = Math.max(...delays.map((d, i) => d - outDelays[i]));
|
|
4526
|
+
const need = (inTween?.duration ?? 0) + (outTween ? outTween.duration + outWave + lead : wave);
|
|
4454
4527
|
if (duration < need - 1e-9) {
|
|
4455
4528
|
throw new Error(`animateText(): duration ${duration} is too short for this wave: the entrance${outTween ? ", the exit" : ""} and the stagger need at least ${+need.toFixed(3)} s`);
|
|
4456
4529
|
}
|
|
4457
4530
|
const end = at + duration;
|
|
4458
4531
|
if (outTween?.at !== void 0) {
|
|
4459
4532
|
if (outTween.at < at - 1e-9) console.warn(`pixi-effects: animateText(): out.at ${outTween.at} is before the layer starts (at ${at}): the exit starts with the piece; use out.at \u2265 ${at}`);
|
|
4460
|
-
const latest = end - outTween.duration -
|
|
4461
|
-
if (outTween.at > latest + 1e-9) console.warn(`pixi-effects: animateText(): out.at ${outTween.at} leaves after the layer ends (the exit and the wave take ${+(outTween.duration +
|
|
4462
|
-
if (inTween && outTween.at - at < inTween.duration - 1e-9) console.warn(`pixi-effects: animateText(): out.at ${outTween.at} is before the entrance has finished (it takes ${inTween.duration} s from at ${at}): use out.at \u2265 ${+(at + inTween.duration).toFixed(3)}`);
|
|
4533
|
+
const latest = end - outTween.duration - outWave;
|
|
4534
|
+
if (outTween.at > latest + 1e-9) console.warn(`pixi-effects: animateText(): out.at ${outTween.at} leaves after the layer ends (the exit and the wave take ${+(outTween.duration + outWave).toFixed(3)} s and the layer ends at ${+end.toFixed(3)} s): use out.at \u2264 ${+latest.toFixed(3)}, or a longer duration`);
|
|
4535
|
+
if (inTween && outTween.at - at < inTween.duration + lead - 1e-9) console.warn(`pixi-effects: animateText(): out.at ${outTween.at} is before the entrance has finished (it takes ${inTween.duration} s from at ${at}): use out.at \u2265 ${+(at + inTween.duration + lead).toFixed(3)}`);
|
|
4463
4536
|
}
|
|
4464
4537
|
return pieces.map((p, i) => {
|
|
4465
4538
|
const cx = p.cx ?? p.x + p.width / 2, cy = p.cy ?? p.y + lineHeight / 2;
|
|
@@ -4479,8 +4552,8 @@ function animateText(text, style, options) {
|
|
|
4479
4552
|
}
|
|
4480
4553
|
let idleEnd = len;
|
|
4481
4554
|
if (outTween) {
|
|
4482
|
-
const begin = outTween.at !== void 0 ? void 0 : outTween.duration + (
|
|
4483
|
-
const local = outTween.at !== void 0 ? Math.max(0, outTween.at -
|
|
4555
|
+
const begin = outTween.at !== void 0 ? void 0 : outTween.duration + (outWave - outDelays[i]);
|
|
4556
|
+
const local = outTween.at !== void 0 ? Math.max(0, outTween.at + outDelays[i] - start) : -begin;
|
|
4484
4557
|
idleEnd = outTween.at !== void 0 ? local : len - begin;
|
|
4485
4558
|
keyframes.push({
|
|
4486
4559
|
at: local,
|
|
@@ -4516,6 +4589,10 @@ function resolveTween(spec, which) {
|
|
|
4516
4589
|
if (typeof spec === "object" && spec) {
|
|
4517
4590
|
for (const key of Object.keys(spec)) {
|
|
4518
4591
|
if (TWEEN_KEYS.includes(key)) continue;
|
|
4592
|
+
if (key === "stagger") {
|
|
4593
|
+
if (which === "in") console.warn("pixi-effects: animateText(): in.stagger is ignored: the entrance wave is the options' `stagger` (only `out` can have a wave of its own: out: { stagger: 0 } leaves all at once)");
|
|
4594
|
+
continue;
|
|
4595
|
+
}
|
|
4519
4596
|
if (which === "out" && key === "at") {
|
|
4520
4597
|
if (typeof spec.at !== "number" || !Number.isFinite(spec.at)) console.warn(`pixi-effects: animateText(): out.at must be a number of seconds (the composition second the exit starts at), got ${JSON.stringify(spec.at)}; ignored`);
|
|
4521
4598
|
continue;
|
|
@@ -4527,7 +4604,7 @@ function resolveTween(spec, which) {
|
|
|
4527
4604
|
}
|
|
4528
4605
|
if (t.preset !== void 0 && !(t.preset in PRESETS)) {
|
|
4529
4606
|
const guess = suggestName(String(t.preset), PRESET_NAMES);
|
|
4530
|
-
throw new Error(`animateText(): ${which} "${t.preset}" is not a preset${guess ? `; did you mean "${guess}"?` : ""} (presets: ${PRESET_NAMES.map((n) => `"${n}"`).join(", ")})`);
|
|
4607
|
+
throw new Error(`animateText(): ${which} "${t.preset}" is not a preset${guess ? `; did you mean "${guess}"?` : ""} (presets: ${PRESET_NAMES.map((n) => `"${n}"`).join(", ")}; for no ${which === "out" ? "exit: omit `out` or write out: false (the pieces stay until the layer ends)" : "entrance: in: false"})`);
|
|
4531
4608
|
}
|
|
4532
4609
|
const base = t.preset ? PRESETS[t.preset] : void 0;
|
|
4533
4610
|
const from = { ...base?.from ?? {}, ...t.from ?? {} };
|
|
@@ -4536,11 +4613,14 @@ function resolveTween(spec, which) {
|
|
|
4536
4613
|
for (const k of Object.keys(from)) {
|
|
4537
4614
|
if (!known.has(k) && to[k] === void 0) throw new Error(`animateText(): ${which}.from has "${k}", which has no resting value; give ${which}.to: { ${k}: \u2026 }`);
|
|
4538
4615
|
}
|
|
4539
|
-
if (Object.keys(from).length === 0)
|
|
4616
|
+
if (Object.keys(from).length === 0) {
|
|
4617
|
+
throw new Error(`animateText(): ${which} needs a preset or a from${which === "out" && Object.keys(to).length ? ` \u2014 ${which} takes \`from\`: the state the piece leaves to (out: { from: { y: 18, alpha: 0 } }); \`to\` is only the resting value of a property that has none` : ""}`);
|
|
4618
|
+
}
|
|
4540
4619
|
let ease = t.ease ?? base?.ease ?? "power2.out";
|
|
4541
4620
|
if (which === "out" && t.ease === void 0) ease = ease.replace(".out", ".in");
|
|
4542
4621
|
const at = which === "out" && typeof t.at === "number" && Number.isFinite(t.at) ? t.at : void 0;
|
|
4543
|
-
|
|
4622
|
+
const wave = which === "out" && t.stagger !== void 0 ? t.stagger === 0 ? { each: 0 } : t.stagger : void 0;
|
|
4623
|
+
return { from, to: { ...to }, duration: t.duration ?? base?.duration ?? 0.5, ease, ...at !== void 0 ? { at } : {}, ...wave ? { stagger: wave } : {} };
|
|
4544
4624
|
}
|
|
4545
4625
|
|
|
4546
4626
|
// src/presets/react.ts
|
|
@@ -4848,5 +4928,5 @@ function withFade(spec, opts) {
|
|
|
4848
4928
|
}
|
|
4849
4929
|
|
|
4850
4930
|
export { Movie, animateText, audioEnvelope, bpmEnvelope, cameraPath, computeEnvelope, dismissLoader, failLoader, followPath, kenBurns, measureText, musicBuffer, musicEnvelope, musicEvents, orbit, parseEase2 as parseEase, particles, react, resolveLoader, samplePath, splitText, stagger, wiggle, withFade };
|
|
4851
|
-
//# sourceMappingURL=chunk-
|
|
4852
|
-
//# sourceMappingURL=chunk-
|
|
4931
|
+
//# sourceMappingURL=chunk-W46VWAZC.js.map
|
|
4932
|
+
//# sourceMappingURL=chunk-W46VWAZC.js.map
|