pixi-effects 0.13.0 → 0.14.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 +20 -0
- package/README.md +5 -5
- package/ai/SKILL.md +1 -1
- package/ai/reference/cheatsheet.md +1 -0
- package/ai/reference/pitfalls.md +1 -1
- package/ai/template.html +5 -5
- package/ai/tools/check.mjs +15 -2
- package/dist/Controller.cjs +2 -3
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +2 -2
- package/dist/Controller.d.ts +2 -2
- package/dist/Controller.js +2 -3
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-DnR4H1OO.d.ts → Movie-BwT6XtGz.d.ts} +23 -0
- package/dist/{Movie-Tl5dRLJl.d.cts → Movie-qmgOU4in.d.cts} +23 -0
- package/dist/Presenter.d.cts +1 -1
- package/dist/Presenter.d.ts +1 -1
- package/dist/index.cjs +59 -5
- 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 +59 -5
- package/dist/index.js.map +1 -1
- package/dist/loader.css +1 -1
- package/docs/api.md +4 -0
- package/llms-full.txt +7 -2
- package/package.json +1 -1
package/dist/loader.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* pixi-effects loader: one line of HTML on the page, a few lines of CSS, no JavaScript of your own.
|
|
3
3
|
*
|
|
4
|
-
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.
|
|
4
|
+
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/pixi-effects@0.14.0/dist/loader.css">
|
|
5
5
|
* <div class="stage" style="position: relative"> <!-- any box the canvas sits in, with position: relative -->
|
|
6
6
|
* <canvas id="stage" width="1280" height="720"></canvas>
|
|
7
7
|
* <div class="pe-loader" data-label="LOADING"></div> <!-- or class="pe-loader pe-loader--bar" -->
|
package/docs/api.md
CHANGED
|
@@ -289,6 +289,10 @@ const presenter = new Presenter(movie, { canvas }); // instead of Controller
|
|
|
289
289
|
|
|
290
290
|
`presenter.start()`, `presenter.openPresenterView()`, `presenter.closePresenterView()`, `presenter.next()`, `presenter.prev()`, `presenter.setCover('black' \| 'white' \| 'off')`, `presenter.exit()`, `presenter.destroy()`. It uses the canvas's positioned parent, or wraps the canvas like `Controller` does. A movie with stops shown through a **`Controller`** gets a mark per stop on the seek bar and a Present button (`present: false` leaves the marks only) that hands the page to a `Presenter` (fullscreen, keys, click and swipe move through the stops; Esc gives the bar back).
|
|
291
291
|
|
|
292
|
+
### `movie.inspectStops(options?)`
|
|
293
|
+
|
|
294
|
+
Is the picture at each stop still changing? Each stop is compared with the picture `lookback` frames before it (default 3); when more than `tolerance` (default 0.004, a share of the pixels) differs, the audience, the page overview and a PDF would see a half-finished animation. Returns `{ stops: [{ index, page, at, frame, moving, settled }], issues: string[] }`; each issue names the stop and the page and says what to do (move the stop to after the animation has ended, or flag a settled stop of the page `pdf: true`). Leaves the playhead where it was. `pixi-effects-check` runs it for any page with `stops`.
|
|
295
|
+
|
|
292
296
|
### Pictures of the stops and the deck as a PDF: `movie.stopImages()`, `movie.exportPDF()`
|
|
293
297
|
|
|
294
298
|
```ts
|
package/llms-full.txt
CHANGED
|
@@ -22,7 +22,7 @@ You describe a video as a tree of plain objects; the library plays it in a canva
|
|
|
22
22
|
- `await movie.inspect(frame)` → every layer's canvas bounds and visibility, plus `issues` (text off the canvas, cut off by an edge, empty, or overlapping other text). Run it at several frames; fix every issue it names.
|
|
23
23
|
- `await movie.snapshot(frame, { as: 'dataURL' })` → one frame, canvas only (no player bar).
|
|
24
24
|
- `movie.inspectAudio()` → **hear with numbers**: for every sound its `start`, `sound.length`, `sound.peakDb`, `sound.loudestAt` (line this up with the picture) and `sound.brightnessHz` (< 500 dark, > 8000 airy), plus `issues` (limited mix, inaudible or cut-off sounds). Check it whenever the movie has audio; `render()` encodes this same mix.
|
|
25
|
-
- **A deck** (`composition.stops`, `deck()`): `await movie.contactSheet({ frames: movie.stops.map(s => s.frame), as: 'dataURL' })` is one picture of every stop (the check writes it as `stops.png`); what the audience reads while a page waits is that picture, so check every one. `await movie.stopImages({ which: 'pages' })` / `movie.exportPDF()` give the pages themselves.
|
|
25
|
+
- **A deck** (`composition.stops`, `deck()`): `await movie.contactSheet({ frames: movie.stops.map(s => s.frame), as: 'dataURL' })` is one picture of every stop (the check writes it as `stops.png`); what the audience reads while a page waits is that picture, so check every one. `await movie.inspectStops()` lists the stops where the picture is still changing (a stop landing before its animation ends); the check prints it as a review list: move the stop later or flag a settled one `pdf: true`. `await movie.stopImages({ which: 'pages' })` / `movie.exportPDF()` give the pages themselves.
|
|
26
26
|
From a browser tool the result is a `data:` URL string: `agent-browser eval "movie.contactSheet({ count: 6, as: 'dataURL' })" | python3 ai/tools/save-image.py /absolute/sheet.png`, then open the PNG. Sheet tiles are small (~480 px): use `snapshot` for detail. `inspect` output is long on busy scenes: pass `{ layers: 'none' }` and read `issues` first. Give layers a `name` so inspect paths are readable. A moving ticker is not flagged as cut off.
|
|
27
27
|
6. **Iterate** on what you saw (clipped text, collisions, wrong timing). Fast motion looks choppy: add `motionBlur: true` to `movie.init` (render, snapshot and contact sheet then show a film-style blur; renders take ~8× longer). Then export: `const blob = await movie.render({ format: 'mp4' })` (about real time; `movie.on('progress', …)` reports 0–100).
|
|
28
28
|
|
|
@@ -189,6 +189,7 @@ new Presenter(movie, { canvas }); // import { Presenter } from 'pixi-eff
|
|
|
189
189
|
movie.next() / prev() / goToStop(i) / goToPage(n) / movie.stops / movie.on('stop', …) // Controller: marks on the seek bar, play / Space / click = play to the next stop (pauseAtStops: false = straight through), a Present button, PDF in the download panel
|
|
190
190
|
// Presenter extras: G = page overview (pictures), P = presenter view (a second window: live picture, next picture, notes, timer); start() makes the pictures before the audience sees anything
|
|
191
191
|
await movie.stopImages({ as: 'dataURL', scale: 0.25 }) // [{ stop, page, image }] one per page (its last stop); { which: 'stops' } one per stop (a page's picture honours `pdf` flags)
|
|
192
|
+
await movie.inspectStops() // { stops, issues }: stops whose picture is still changing (a stop landing before its animation ends); the check lists them
|
|
192
193
|
await movie.exportPDF({ title }) // Blob: a PDF page per page of the deck; CLI: pixi-effects-render talk.html -o talk.pdf (--all-stops)
|
|
193
194
|
const env = await audioEnvelope('music.mp3', { frameRate: 30 }) // BEFORE movie.init: .series.level|bass|mid|treble (0–1 per frame), .beats [s], .bpm, .at(t, band); bands: { name: [Hz, Hz] }
|
|
194
195
|
const env = bpmEnvelope(120, { duration: 12 }) // no audio file: kick / snare / hats exactly on a tempo
|
|
@@ -312,7 +313,7 @@ A good habit that catches most of these: after `init`, read `window.__logs` (see
|
|
|
312
313
|
54. **A deck page lasts until its last stop plus the transition.** `deck()` lays pages out one after another in page-local time and a `transition` overlaps them: a page shorter than its last stop (or shorter than the transition) loses its final step or flashes. A step is a layer that starts at the previous stop (`at: <previous stop>`), so the thing that appears on a press is fully visible when the movie stops. The transition option is `kind`, not `type`. If the last stop is mid-exit on paper, flag the stop you want in the PDF: `{ at, pdf: true }` (in `deck()`: `stops: [1.2, { at: 3, pdf: true }]`), and `pdf: false` keeps one out.
|
|
313
314
|
55. **Presenter and Controller both listen to click and keys.** Use the `Presenter` for a talk (or let the Controller's Present button start one); do not run both on the same canvas yourself. `movie.play()` ignores stops, but the Controller's play button / Space / click-on-picture play to the next stop and pause (`pauseAtStops: false` plays through); `movie.next()` plays to the next stop (a second press skips to it), `prev()` jumps back (nothing plays in reverse).
|
|
314
315
|
56. **Analyse audio before `init`, and give it the movie's frame rate.** `const env = await audioEnvelope('music.mp3', { frameRate })` is async; `react()` is pure and bakes the keyframes, so there is no per-frame callback. A custom `bands` list replaces the defaults (include `bass` if you want it; beats are picked there). No file yet: `bpmEnvelope(120, { duration })` is a stand-in with a kick on every beat. Offset the music with `audioOffset` when the audio layer does not start at 0.
|
|
315
|
-
57. **Review a deck by its stops, not by its timeline.** `pixi-effects-check` writes `stops.png` (one picture per stop, in order) for a page with `stops`; the picture at a stop is what the audience reads while it waits.
|
|
316
|
+
57. **Review a deck by its stops, not by its timeline.** `pixi-effects-check` writes `stops.png` (one picture per stop, in order) for a page with `stops`; the picture at a stop is what the audience reads while it waits. A stop that lands a few frames before an animation ends shows it half-finished (also in the PDF): `movie.inspectStops()` / the check's review list names such stops; give an animation a little more time than its step (e.g. the next stop 0.3 s after it ends).
|
|
316
317
|
|
|
317
318
|
|
|
318
319
|
<!-- ===== ai/reference/recipes.md ===== -->
|
|
@@ -2660,6 +2661,10 @@ const presenter = new Presenter(movie, { canvas }); // instead of Controller
|
|
|
2660
2661
|
|
|
2661
2662
|
`presenter.start()`, `presenter.openPresenterView()`, `presenter.closePresenterView()`, `presenter.next()`, `presenter.prev()`, `presenter.setCover('black' \| 'white' \| 'off')`, `presenter.exit()`, `presenter.destroy()`. It uses the canvas's positioned parent, or wraps the canvas like `Controller` does. A movie with stops shown through a **`Controller`** gets a mark per stop on the seek bar and a Present button (`present: false` leaves the marks only) that hands the page to a `Presenter` (fullscreen, keys, click and swipe move through the stops; Esc gives the bar back).
|
|
2662
2663
|
|
|
2664
|
+
### `movie.inspectStops(options?)`
|
|
2665
|
+
|
|
2666
|
+
Is the picture at each stop still changing? Each stop is compared with the picture `lookback` frames before it (default 3); when more than `tolerance` (default 0.004, a share of the pixels) differs, the audience, the page overview and a PDF would see a half-finished animation. Returns `{ stops: [{ index, page, at, frame, moving, settled }], issues: string[] }`; each issue names the stop and the page and says what to do (move the stop to after the animation has ended, or flag a settled stop of the page `pdf: true`). Leaves the playhead where it was. `pixi-effects-check` runs it for any page with `stops`.
|
|
2667
|
+
|
|
2663
2668
|
### Pictures of the stops and the deck as a PDF: `movie.stopImages()`, `movie.exportPDF()`
|
|
2664
2669
|
|
|
2665
2670
|
```ts
|