pixi-effects 0.16.3 → 0.18.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 +55 -0
- package/README.md +7 -7
- package/ai/CHAT.md +7 -0
- package/ai/SKILL.md +3 -2
- package/ai/chat-template.html +8 -4
- package/ai/reference/cheatsheet.md +6 -2
- package/ai/reference/pitfalls.md +3 -0
- package/ai/reference/recipes.md +67 -0
- package/ai/template.html +5 -5
- package/ai/tools/check.mjs +119 -59
- package/ai/tools/render.mjs +22 -7
- package/dist/Composition-6JMXWNVV.cjs +14 -0
- package/dist/{Composition-3WWNVRR5.cjs.map → Composition-6JMXWNVV.cjs.map} +1 -1
- package/dist/Composition-MLBHYYFF.js +5 -0
- package/dist/{Composition-VJWY2NDL.js.map → Composition-MLBHYYFF.js.map} +1 -1
- package/dist/Controller.d.cts +1 -1
- package/dist/Controller.d.ts +1 -1
- package/dist/{Movie-DilBC348.d.ts → Movie-DlHQ9C02.d.ts} +126 -2
- package/dist/{Movie-oA0SUAyb.d.cts → Movie-K2YuVAdg.d.cts} +126 -2
- package/dist/Presenter.d.cts +1 -1
- package/dist/Presenter.d.ts +1 -1
- package/dist/{chunk-FJA5VUOF.cjs → chunk-ANO5R2E6.cjs} +25 -3
- package/dist/chunk-ANO5R2E6.cjs.map +1 -0
- package/dist/{chunk-2ROVCPSL.cjs → chunk-JW67MDHQ.cjs} +32 -27
- package/dist/chunk-JW67MDHQ.cjs.map +1 -0
- package/dist/{chunk-ZNKQH356.js → chunk-SG3Y66FN.js} +25 -4
- package/dist/chunk-SG3Y66FN.js.map +1 -0
- package/dist/{chunk-XTIHKODH.js → chunk-UXDR3ZDU.js} +10 -5
- package/dist/chunk-UXDR3ZDU.js.map +1 -0
- package/dist/index.cjs +464 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +442 -21
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/dist/three.cjs +5 -5
- package/dist/three.js +1 -1
- package/docs/dsl.md +2 -1
- package/llms-full.txt +81 -5
- package/llms.txt +1 -1
- package/package.json +6 -3
- package/dist/Composition-3WWNVRR5.cjs +0 -14
- package/dist/Composition-VJWY2NDL.js +0 -5
- package/dist/chunk-2ROVCPSL.cjs.map +0 -1
- package/dist/chunk-FJA5VUOF.cjs.map +0 -1
- package/dist/chunk-XTIHKODH.js.map +0 -1
- package/dist/chunk-ZNKQH356.js.map +0 -1
|
@@ -5,6 +5,12 @@ import { U as Stop, e as AssetSpec, c as CompositionSpec } from './types-SS51lP6
|
|
|
5
5
|
interface AudioInspectOptions {
|
|
6
6
|
/** Width of each loudness window in seconds. Default 0.1. */
|
|
7
7
|
window?: number;
|
|
8
|
+
/** 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. */
|
|
9
|
+
scenes?: Array<{
|
|
10
|
+
name: string;
|
|
11
|
+
start: number;
|
|
12
|
+
end: number;
|
|
13
|
+
}>;
|
|
8
14
|
}
|
|
9
15
|
/** One sound measured ON ITS OWN (not mixed), so overlapping layers do not blur it. */
|
|
10
16
|
interface SoundMeasure {
|
|
@@ -44,8 +50,76 @@ interface AudioReport {
|
|
|
44
50
|
peakDb: number;
|
|
45
51
|
brightnessHz: number;
|
|
46
52
|
}>;
|
|
47
|
-
/** Problems worth fixing: limiting, inaudible layers, sounds cut off by the end of the movie. Read this first. */
|
|
53
|
+
/** 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. */
|
|
48
54
|
issues: string[];
|
|
55
|
+
/** 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). */
|
|
56
|
+
loudness: {
|
|
57
|
+
integratedLufs: number | null;
|
|
58
|
+
truePeakDb: number;
|
|
59
|
+
clippedSamples: number;
|
|
60
|
+
silences: Array<{
|
|
61
|
+
from: number;
|
|
62
|
+
to: number;
|
|
63
|
+
}>;
|
|
64
|
+
};
|
|
65
|
+
/** The same measure for each scene (`silent`: nothing above −60 dBFS). */
|
|
66
|
+
scenes: Array<{
|
|
67
|
+
name: string;
|
|
68
|
+
from: number;
|
|
69
|
+
to: number;
|
|
70
|
+
lufs: number | null;
|
|
71
|
+
peakDb: number;
|
|
72
|
+
silent: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
/** When each sound starts: what a waveform marks. */
|
|
75
|
+
cues: Array<{
|
|
76
|
+
t: number;
|
|
77
|
+
name: string;
|
|
78
|
+
}>;
|
|
79
|
+
/** Advice, not faults: a mix that is quiet or loud for web video, little headroom, silent stretches. */
|
|
80
|
+
notes: string[];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface FontReport {
|
|
84
|
+
/** Text layers none of whose fonts is available here: they are drawn in a fallback. */
|
|
85
|
+
missing: Array<{
|
|
86
|
+
layer: string;
|
|
87
|
+
family: string;
|
|
88
|
+
}>;
|
|
89
|
+
/** Web fonts (`@font-face`) whose file could not be loaded and that a text layer uses. */
|
|
90
|
+
failed: string[];
|
|
91
|
+
/** Web fonts whose file could not be loaded but no text layer uses (an unused face: worth a look, not a fault). */
|
|
92
|
+
failedUnused: string[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** One kind of issue, with how many frames it was seen in. Issues that differ only by numbers are one kind. */
|
|
96
|
+
interface IssueGroup {
|
|
97
|
+
message: string;
|
|
98
|
+
count: number;
|
|
99
|
+
firstFrame: number;
|
|
100
|
+
lastFrame: number;
|
|
101
|
+
}
|
|
102
|
+
interface ReviewOptions {
|
|
103
|
+
/** Moments to resolve and report: `3.5`, `50%`, `f120`, `title@end` (comma-separated). */
|
|
104
|
+
at?: string;
|
|
105
|
+
/** Every layout issue is a problem (by default text overlaps are only listed for review). */
|
|
106
|
+
strict?: boolean;
|
|
107
|
+
}
|
|
108
|
+
interface ReviewReport {
|
|
109
|
+
/** How many frames were inspected. */
|
|
110
|
+
frames: number;
|
|
111
|
+
/** Text cut off by an edge, outside the canvas, or with no size (with `strict`: every issue). */
|
|
112
|
+
problems: IssueGroup[];
|
|
113
|
+
/** Text overlaps and fonts that are not available: often intentional, look at them on the contact sheet. */
|
|
114
|
+
review: IssueGroup[];
|
|
115
|
+
fonts: FontReport;
|
|
116
|
+
/** The sound as numbers (`movie.inspectAudio()`), or null for a movie with no audio. */
|
|
117
|
+
audio: AudioReport | null;
|
|
118
|
+
/** The moments of `at`, as frames with a label that is safe as a file name. */
|
|
119
|
+
at: Array<{
|
|
120
|
+
label: string;
|
|
121
|
+
frame: number;
|
|
122
|
+
}>;
|
|
49
123
|
}
|
|
50
124
|
|
|
51
125
|
interface Rect {
|
|
@@ -107,6 +181,8 @@ interface TimelineRow {
|
|
|
107
181
|
start: number;
|
|
108
182
|
end: number;
|
|
109
183
|
}>;
|
|
184
|
+
/** With `parts`: the name of each layer the row stands for, in the same order (so `render({ range: 'pop-3' })` can find it). */
|
|
185
|
+
partNames?: string[];
|
|
110
186
|
/** A short text for the tooltip (a text layer's words, an asset name). */
|
|
111
187
|
detail?: string;
|
|
112
188
|
}
|
|
@@ -196,6 +272,15 @@ interface RenderOptions {
|
|
|
196
272
|
codec?: string;
|
|
197
273
|
bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
|
|
198
274
|
};
|
|
275
|
+
/**
|
|
276
|
+
* Only part of the movie: `[from, to]` in seconds, or the name of a top-level layer (its start to its end). The file starts at 0
|
|
277
|
+
* and its sound is cut the same way (with a 10 ms fade on a cut edge). Past the end, backwards or an unknown name is an error.
|
|
278
|
+
*/
|
|
279
|
+
range?: [number, number] | string;
|
|
280
|
+
/** Output size relative to the canvas, above 0 and at most 1. Each frame is drawn at full size and copied smaller before it is encoded: the file and the encoding get smaller, the drawing is not faster. */
|
|
281
|
+
scale?: number;
|
|
282
|
+
/** For looking, not for delivering: `scale: 0.5`, `video.bitrate: 'low'` and no motion blur. Anything you set yourself wins. */
|
|
283
|
+
draft?: boolean;
|
|
199
284
|
}
|
|
200
285
|
interface SnapshotOptions {
|
|
201
286
|
/** Motion blur for this picture (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
|
|
@@ -248,6 +333,19 @@ interface ContactSheetOptions {
|
|
|
248
333
|
cellWidth?: number;
|
|
249
334
|
as?: 'blob' | 'dataURL';
|
|
250
335
|
}
|
|
336
|
+
interface OnionSkinOptions {
|
|
337
|
+
/** Where the movement starts, in seconds. Default 0. */
|
|
338
|
+
from?: number;
|
|
339
|
+
/** Where it ends, in seconds. Default: the end of the movie. */
|
|
340
|
+
to?: number;
|
|
341
|
+
/** How many frames are overlaid, 1–64, spread evenly from `from` to `to`. Default 8. */
|
|
342
|
+
count?: number;
|
|
343
|
+
/** Output size relative to the canvas, above 0 and at most 4. Default 1. */
|
|
344
|
+
scale?: number;
|
|
345
|
+
/** Motion blur for these pictures (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
|
|
346
|
+
motionBlur?: MotionBlurSpec;
|
|
347
|
+
as?: 'blob' | 'dataURL';
|
|
348
|
+
}
|
|
251
349
|
interface FrameEvent {
|
|
252
350
|
frame: number;
|
|
253
351
|
totalFrames: number;
|
|
@@ -419,6 +517,17 @@ declare class Movie {
|
|
|
419
517
|
motionBlur?: MotionBlurSpec;
|
|
420
518
|
onImage?: (image: StopImage) => void;
|
|
421
519
|
}): Promise<Blob>;
|
|
520
|
+
/**
|
|
521
|
+
* One picture of a movement: `count` frames from `from` to `to` drawn one over the other, each later one stronger, so a thing that
|
|
522
|
+
* moves leaves a trail (its path and its easing: even steps = constant speed, bunched = slow) and what stays still stays itself.
|
|
523
|
+
* The movie is left where it was.
|
|
524
|
+
*/
|
|
525
|
+
onionSkin(opts?: OnionSkinOptions & {
|
|
526
|
+
as?: 'blob';
|
|
527
|
+
}): Promise<Blob>;
|
|
528
|
+
onionSkin(opts: OnionSkinOptions & {
|
|
529
|
+
as: 'dataURL';
|
|
530
|
+
}): Promise<string>;
|
|
422
531
|
/**
|
|
423
532
|
* Several frames on ONE image, each labelled with its frame number and time — the cheapest way to
|
|
424
533
|
* check a whole animation by eye. Restores the current frame afterwards.
|
|
@@ -447,6 +556,21 @@ declare class Movie {
|
|
|
447
556
|
* The soundtrack, measured: when every audio layer plays, how loud the mix is over time, and `issues`
|
|
448
557
|
* (limiting, inaudible layers, sounds cut off by the end). Use it to CHECK sound you cannot hear.
|
|
449
558
|
*/
|
|
559
|
+
/** The pictures to look at for moments such as `3.5`, `50%`, `f120`, `title@end` (comma-separated). A mistake says what could not be read. */
|
|
560
|
+
resolveAt(list: string): Array<{
|
|
561
|
+
label: string;
|
|
562
|
+
frame: number;
|
|
563
|
+
}>;
|
|
564
|
+
/**
|
|
565
|
+
* One call that looks at everything `pixi-effects-check` looks at inside the page: layout issues over the whole timeline (every
|
|
566
|
+
* scene's first and last frame and a frame every 0.25 s), fonts and the sound. See `ReviewReport`. Page warnings are in `window.__logs`. The movie is left as it was.
|
|
567
|
+
*/
|
|
568
|
+
review(opts?: ReviewOptions): Promise<ReviewReport>;
|
|
569
|
+
/**
|
|
570
|
+
* The fonts of the text layers: `missing` lists layers none of whose `fontFamily` entries is available in this browser (they are
|
|
571
|
+
* drawn in a fallback font), `failed` lists web fonts (`@font-face`) whose file could not be loaded.
|
|
572
|
+
*/
|
|
573
|
+
inspectFonts(): FontReport;
|
|
450
574
|
inspectAudio(opts?: AudioInspectOptions): AudioReport;
|
|
451
575
|
/**
|
|
452
576
|
* Draw the stage now. PixiJS's CullerPlugin only culls inside `app.render()` (the ticker), and we render
|
|
@@ -509,4 +633,4 @@ declare class Movie {
|
|
|
509
633
|
destroy(): Promise<void>;
|
|
510
634
|
}
|
|
511
635
|
|
|
512
|
-
export { type AudioInspectOptions as A, type ContactSheetOptions as C, type
|
|
636
|
+
export { type AudioInspectOptions as A, type ContactSheetOptions as C, type FontReport as F, type InspectOptions as I, type LayerInfo as L, type MotionBlurOptions as M, type OnionSkinOptions as O, type ProgressEvent as P, type RenderOptions as R, type SnapshotOptions as S, type TimelineData 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 LoaderOption as f, type MotionBlurSpec as g, Movie as h, type MovieErrorEvent as i, type MovieOptions as j, type ReviewOptions as k, type ReviewReport as l, type SoundMeasure as m, type StopEvent as n, type StopImage as o, type StopImagesOptions as p, type TimelineHtmlOptions as q, type TimelineRow as r, type TimelineSvgOptions as s, type TimelineTransition as t, dismissLoader as u, failLoader as v, resolveLoader as w };
|
package/dist/Presenter.d.cts
CHANGED
package/dist/Presenter.d.ts
CHANGED
|
@@ -310,6 +310,26 @@ function looksLikeColorString(s) {
|
|
|
310
310
|
if (s.charCodeAt(0) === 35) return true;
|
|
311
311
|
return /^(rgb|hsl|oklab|oklch|lab|lch)\b/i.test(s);
|
|
312
312
|
}
|
|
313
|
+
var FAMILIES = ["power1", "power2", "power3", "power4", "back", "elastic", "bounce", "circ", "expo", "sine"];
|
|
314
|
+
var EASE_NAMES = ["none", ...FAMILIES.flatMap((f) => [`${f}.in`, `${f}.out`, `${f}.inOut`])];
|
|
315
|
+
var warned = /* @__PURE__ */ new Set();
|
|
316
|
+
function checkEase(ease, where) {
|
|
317
|
+
if (typeof ease !== "string") return;
|
|
318
|
+
const found = gsap.gsap.parseEase(ease);
|
|
319
|
+
if (typeof found === "function") return;
|
|
320
|
+
if (warned.has(ease)) return;
|
|
321
|
+
warned.add(ease);
|
|
322
|
+
if (ease === "") {
|
|
323
|
+
console.warn(`pixi-effects: ${where}: an empty ease (GSAP would run its default, power1.out): write 'none' for no easing, or a name such as 'power2.out'`);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
if (found && /^power[1-4]$/i.test(ease)) {
|
|
327
|
+
console.warn(`pixi-effects: ${where}: "${ease}" is a family, not an ease \u2014 write ${ease.toLowerCase()}.out, ${ease.toLowerCase()}.in or ${ease.toLowerCase()}.inOut`);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const guess = chunkUQBGW5DO_cjs.suggestName(ease, EASE_NAMES);
|
|
331
|
+
console.warn(`pixi-effects: ${where}: unknown ease "${ease}"${guess ? ` \u2014 did you mean "${guess}"?` : ""} (GSAP would run it as its default ease, power1.out). Examples: ${EASE_NAMES.slice(0, 7).join(", ")}, back.out(1.7), elastic.out(1, 0.3), steps(8)`);
|
|
332
|
+
}
|
|
313
333
|
|
|
314
334
|
// src/core/Timeline.ts
|
|
315
335
|
function loopVars(kf) {
|
|
@@ -337,6 +357,7 @@ function normalizeKeyframe(kf, parentDuration) {
|
|
|
337
357
|
const at = resolveAt(kf.at, parentDuration);
|
|
338
358
|
const duration = kf.duration ?? 0;
|
|
339
359
|
const ease = kf.ease ?? "none";
|
|
360
|
+
checkEase(ease, "a keyframe");
|
|
340
361
|
const hasSet = !!kf.set;
|
|
341
362
|
const hasFrom = !!kf.from;
|
|
342
363
|
const hasTo = !!kf.to;
|
|
@@ -2754,7 +2775,7 @@ function numOrZero(v, scope) {
|
|
|
2754
2775
|
var _CompositionSequence = null;
|
|
2755
2776
|
async function getCompositionSequence() {
|
|
2756
2777
|
if (!_CompositionSequence) {
|
|
2757
|
-
_CompositionSequence = (await import('./Composition-
|
|
2778
|
+
_CompositionSequence = (await import('./Composition-6JMXWNVV.cjs')).CompositionSequence;
|
|
2758
2779
|
}
|
|
2759
2780
|
return _CompositionSequence;
|
|
2760
2781
|
}
|
|
@@ -2801,6 +2822,7 @@ exports.Sequence = Sequence;
|
|
|
2801
2822
|
exports.buildScope = buildScope;
|
|
2802
2823
|
exports.buildSequenceTree = buildSequenceTree;
|
|
2803
2824
|
exports.cameraBasis = cameraBasis;
|
|
2825
|
+
exports.checkEase = checkEase;
|
|
2804
2826
|
exports.collectPropKeys = collectPropKeys;
|
|
2805
2827
|
exports.describeLayer = describeLayer;
|
|
2806
2828
|
exports.ensureFilterLibrary = ensureFilterLibrary;
|
|
@@ -2817,5 +2839,5 @@ exports.random = random;
|
|
|
2817
2839
|
exports.registerSequenceType = registerSequenceType;
|
|
2818
2840
|
exports.resolveAt = resolveAt;
|
|
2819
2841
|
exports.summarizeWarnings = summarizeWarnings;
|
|
2820
|
-
//# sourceMappingURL=chunk-
|
|
2821
|
-
//# sourceMappingURL=chunk-
|
|
2842
|
+
//# sourceMappingURL=chunk-ANO5R2E6.cjs.map
|
|
2843
|
+
//# sourceMappingURL=chunk-ANO5R2E6.cjs.map
|