pixi-effects 0.16.2 → 0.17.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 +39 -0
- package/README.md +6 -6
- package/ai/CHAT.md +4 -0
- package/ai/SKILL.md +2 -1
- package/ai/chat-template.html +3 -3
- package/ai/reference/cheatsheet.md +4 -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 +162 -18
- package/ai/tools/render.mjs +21 -7
- package/dist/Composition-HYAOYPAX.js +5 -0
- package/dist/{Composition-VJWY2NDL.js.map → Composition-HYAOYPAX.js.map} +1 -1
- package/dist/Composition-LMVEASHF.cjs +14 -0
- package/dist/{Composition-3WWNVRR5.cjs.map → Composition-LMVEASHF.cjs.map} +1 -1
- package/dist/Controller.cjs +9 -3
- package/dist/Controller.cjs.map +1 -1
- package/dist/Controller.d.cts +1 -1
- package/dist/Controller.d.ts +1 -1
- package/dist/Controller.js +9 -3
- package/dist/Controller.js.map +1 -1
- package/dist/{Movie-oA0SUAyb.d.cts → Movie-CoxF2Z7t.d.cts} +82 -2
- package/dist/{Movie-DilBC348.d.ts → Movie-DHJRrUfI.d.ts} +82 -2
- package/dist/Presenter.d.cts +1 -1
- package/dist/Presenter.d.ts +1 -1
- package/dist/{chunk-2ROVCPSL.cjs → chunk-ETAIVOHP.cjs} +32 -27
- package/dist/chunk-ETAIVOHP.cjs.map +1 -0
- package/dist/{chunk-FJA5VUOF.cjs → chunk-LBJRXU7N.cjs} +15 -3
- package/dist/chunk-LBJRXU7N.cjs.map +1 -0
- package/dist/{chunk-ZNKQH356.js → chunk-ORTYBA42.js} +15 -4
- package/dist/chunk-ORTYBA42.js.map +1 -0
- package/dist/{chunk-XTIHKODH.js → chunk-Q3IVBYT7.js} +10 -5
- package/dist/chunk-Q3IVBYT7.js.map +1 -0
- package/dist/index.cjs +351 -41
- 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 +329 -19
- 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 +78 -4
- 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
package/ai/tools/render.mjs
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
*
|
|
14
14
|
* Options: -o, --out FILE (default ./<page name>.<format>; the container follows the extension: mp4 webm mov mkv) ·
|
|
15
15
|
* --format mp4|webm|mov|mkv|pdf (a .pdf is the deck as pages: one picture per page of a movie with `stops`; --all-stops makes a page of every stop) · --quality very-low|low|medium|high|very-high (video and audio bitrate, default high) ·
|
|
16
|
+
* --range A:B (only seconds A to B; 2: runs to the end, :5 starts at the beginning) · --scene NAME (the span of a top-level layer: a movie's scene) · --scale S (output size, 0 < S <= 1: smaller picture, smaller file) ·
|
|
17
|
+
* --draft (for looking: half size, low quality, no motion blur; a --quality you give still wins) ·
|
|
16
18
|
* --motion-blur SAMPLES (2-64: each frame is drawn that many times over the shutter and averaged; overrides the page's own motionBlur) ·
|
|
17
19
|
* --shutter FRACTION (with --motion-blur: how long the shutter is open, 0-1 of a frame, default 0.5) ·
|
|
18
20
|
* --video-codec C · --audio-codec C · --query "a=1&b=2" (added to the page URL) · --fail-on-warn (exit 1 when the page
|
|
@@ -41,7 +43,7 @@ export function defaultOutput(page, format) {
|
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
export function parseRenderArgs(argv) {
|
|
44
|
-
const o = { page: null, out: null, format: null, quality: 'high', videoCodec: null, audioCodec: null, allStops: false, motionBlur: null, shutter: null, query: null, failOnWarn: false, quiet: false, timeout: 900, root: null, chrome: null };
|
|
46
|
+
const o = { range: null, scene: null, scale: null, draft: false, qualityGiven: false, page: null, out: null, format: null, quality: 'high', videoCodec: null, audioCodec: null, allStops: false, motionBlur: null, shutter: null, query: null, failOnWarn: false, quiet: false, timeout: 900, root: null, chrome: null };
|
|
45
47
|
const need = (i, name) => { if (i + 1 >= argv.length) throw new Error(`${name} needs a value`); return argv[i + 1]; };
|
|
46
48
|
for (let i = 0; i < argv.length; i++) {
|
|
47
49
|
const a = argv[i];
|
|
@@ -50,6 +52,7 @@ export function parseRenderArgs(argv) {
|
|
|
50
52
|
o.format = need(i++, a).toLowerCase();
|
|
51
53
|
if (!FORMATS.includes(o.format)) throw new Error(`--format must be mp4, webm, mov, mkv or pdf (got "${o.format}")`);
|
|
52
54
|
} else if (a === '--quality') {
|
|
55
|
+
o.qualityGiven = true;
|
|
53
56
|
o.quality = need(i++, a);
|
|
54
57
|
if (!QUALITIES.includes(o.quality)) throw new Error(`--quality must be very-low, low, medium, high or very-high (got "${o.quality}")`);
|
|
55
58
|
} else if (a === '--video-codec') o.videoCodec = need(i++, a);
|
|
@@ -60,7 +63,16 @@ export function parseRenderArgs(argv) {
|
|
|
60
63
|
} else if (a === '--shutter') {
|
|
61
64
|
o.shutter = Number(need(i++, a));
|
|
62
65
|
if (!(o.shutter > 0 && o.shutter <= 1)) throw new Error(`--shutter must be above 0 and at most 1 (0.5 is a 180° shutter), got "${argv[i]}"`);
|
|
63
|
-
} else if (a === '--
|
|
66
|
+
} else if (a === '--range') {
|
|
67
|
+
const m = need(i++, a).match(/^(\d+(?:\.\d+)?)?:(\d+(?:\.\d+)?)?$/);
|
|
68
|
+
if (!m || (m[1] === undefined && m[2] === undefined)) throw new Error(`--range must look like 2:5 (seconds; 2: runs to the end, :5 starts at the beginning), got "${argv[i]}"`);
|
|
69
|
+
o.range = [m[1] === undefined ? null : Number(m[1]), m[2] === undefined ? null : Number(m[2])];
|
|
70
|
+
} else if (a === '--scene') o.scene = need(i++, a);
|
|
71
|
+
else if (a === '--scale') {
|
|
72
|
+
o.scale = Number(need(i++, a));
|
|
73
|
+
if (!(o.scale > 0 && o.scale <= 1)) throw new Error(`--scale must be above 0 and at most 1 (0.5 is half size), got "${argv[i]}"`);
|
|
74
|
+
} else if (a === '--draft') o.draft = true;
|
|
75
|
+
else if (a === '--query') o.query = need(i++, a).replace(/^\?/, '');
|
|
64
76
|
else if (a === '--all-stops') o.allStops = true;
|
|
65
77
|
else if (a === '--fail-on-warn') o.failOnWarn = true;
|
|
66
78
|
else if (a === '--quiet') o.quiet = true;
|
|
@@ -74,6 +86,8 @@ export function parseRenderArgs(argv) {
|
|
|
74
86
|
if (o.shutter !== null && o.motionBlur === null) throw new Error('--shutter goes with --motion-blur SAMPLES');
|
|
75
87
|
if (o.allStops && o.format !== 'pdf' && !(o.out && formatFromPath(o.out) === 'pdf')) throw new Error('--all-stops goes with a PDF (-o deck.pdf)');
|
|
76
88
|
o.format ??= (o.out ? formatFromPath(o.out) : null) ?? 'mp4';
|
|
89
|
+
if (o.range && o.scene !== null) throw new Error('--range and --scene cannot be used together: a scene is a range');
|
|
90
|
+
if (o.format === 'pdf' && (o.range || o.scene !== null || o.scale !== null || o.draft)) throw new Error('--range, --scene, --scale and --draft are not for a PDF (a PDF is the pages of a deck)');
|
|
77
91
|
return o;
|
|
78
92
|
}
|
|
79
93
|
|
|
@@ -81,16 +95,16 @@ const UPLOAD = '/__pixi_effects_out';
|
|
|
81
95
|
const kb = n => (n >= 1048576 ? `${(n / 1048576).toFixed(2)} MB` : `${Math.max(1, Math.round(n / 1024))} KB`);
|
|
82
96
|
|
|
83
97
|
/** The page's side: render, and PUT the Blob to our server (so a long video never goes through base64). */
|
|
84
|
-
const renderScript = (format, quality, videoCodec, audioCodec, motionBlur, shutter, allStops) => `(() => {
|
|
98
|
+
const renderScript = (format, quality, videoCodec, audioCodec, motionBlur, shutter, allStops, part = {}) => `(() => {
|
|
85
99
|
window.__r = { state: 'running', progress: 0 };
|
|
86
100
|
movie.on('progress', e => { window.__r.progress = e.progress; });
|
|
87
101
|
(async () => {
|
|
88
102
|
try {
|
|
89
|
-
const video = { bitrate: ${JSON.stringify(quality)}
|
|
103
|
+
const video = { ${[part.draft && !part.qualityGiven ? null : `bitrate: ${JSON.stringify(quality)}`, videoCodec ? `codec: ${JSON.stringify(videoCodec)}` : null].filter(Boolean).join(', ')} };
|
|
90
104
|
const audio = { bitrate: ${JSON.stringify(quality)}${audioCodec ? `, codec: ${JSON.stringify(audioCodec)}` : ''} };
|
|
91
105
|
const blob = ${JSON.stringify(format)} === 'pdf'
|
|
92
106
|
? await movie.exportPDF({ which: ${allStops ? "'stops'" : "'pages'"}, title: document.title })
|
|
93
|
-
: await movie.render({ format: ${JSON.stringify(format)}, video, audio${motionBlur ? `, motionBlur: { samples: ${motionBlur}${shutter ? `, shutter: ${shutter}` : ''} }` : ''} });
|
|
107
|
+
: await movie.render({ format: ${JSON.stringify(format)}, video, audio${part.range ? `, range: [${part.range[0] ?? 0}, ${part.range[1] ?? 'movie.duration'}]` : ''}${part.scene ? `, range: ${JSON.stringify(part.scene)}` : ''}${part.scale ? `, scale: ${part.scale}` : ''}${part.draft ? ', draft: true' : ''}${motionBlur ? `, motionBlur: { samples: ${motionBlur}${shutter ? `, shutter: ${shutter}` : ''} }` : ''} });
|
|
94
108
|
const res = await fetch(${JSON.stringify(UPLOAD)}, { method: 'PUT', body: blob });
|
|
95
109
|
if (!res.ok) throw new Error('could not hand the file to the command (' + res.status + ')');
|
|
96
110
|
window.__r = { state: 'done', bytes: blob.size, type: blob.type };
|
|
@@ -156,7 +170,7 @@ export async function runRender(opts, log = console.log, progress = () => {}) {
|
|
|
156
170
|
}
|
|
157
171
|
Object.assign(result, { duration: info.duration, frames: info.totalFrames, width: info.width, height: info.height, frameRate: info.frameRate });
|
|
158
172
|
|
|
159
|
-
await cdp.eval(renderScript(opts.format, opts.quality, opts.videoCodec, opts.audioCodec, opts.motionBlur, opts.shutter, opts.allStops));
|
|
173
|
+
await cdp.eval(renderScript(opts.format, opts.quality, opts.videoCodec, opts.audioCodec, opts.motionBlur, opts.shutter, opts.allStops, { range: opts.range, scene: opts.scene, scale: opts.scale, draft: opts.draft, qualityGiven: opts.qualityGiven }));
|
|
160
174
|
let state;
|
|
161
175
|
for (;;) {
|
|
162
176
|
left();
|
|
@@ -190,7 +204,7 @@ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href)
|
|
|
190
204
|
if (typeof WebSocket === 'undefined') throw new Error('Node >= 22 is needed (built-in WebSocket)');
|
|
191
205
|
const opts = parseRenderArgs(process.argv.slice(2));
|
|
192
206
|
if (!opts.page) {
|
|
193
|
-
console.error('usage: node ai/tools/render.mjs <page.html> [-o out.mp4] [--format mp4|webm|mov|mkv|pdf] [--quality very-low|low|medium|high|very-high] [--query a=1] [--fail-on-warn] [--quiet] [--timeout S] [--root DIR] [--chrome PATH]');
|
|
207
|
+
console.error('usage: node ai/tools/render.mjs <page.html> [-o out.mp4] [--format mp4|webm|mov|mkv|pdf] [--range A:B | --scene NAME] [--scale S] [--draft] [--quality very-low|low|medium|high|very-high] [--query a=1] [--fail-on-warn] [--quiet] [--timeout S] [--root DIR] [--chrome PATH]');
|
|
194
208
|
process.exit(2);
|
|
195
209
|
}
|
|
196
210
|
let last = -1;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-HYAOYPAX.js"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkETAIVOHP_cjs = require('./chunk-ETAIVOHP.cjs');
|
|
4
|
+
require('./chunk-LBJRXU7N.cjs');
|
|
5
|
+
require('./chunk-UQBGW5DO.cjs');
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Object.defineProperty(exports, "CompositionSequence", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () { return chunkETAIVOHP_cjs.CompositionSequence; }
|
|
12
|
+
});
|
|
13
|
+
//# sourceMappingURL=Composition-LMVEASHF.cjs.map
|
|
14
|
+
//# sourceMappingURL=Composition-LMVEASHF.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-LMVEASHF.cjs"}
|
package/dist/Controller.cjs
CHANGED
|
@@ -919,6 +919,11 @@ var Controller = class _Controller {
|
|
|
919
919
|
async handleExport() {
|
|
920
920
|
if (this.isExporting) return;
|
|
921
921
|
this.isExporting = true;
|
|
922
|
+
this.setVisible(true);
|
|
923
|
+
if (this.hideTimer) {
|
|
924
|
+
clearTimeout(this.hideTimer);
|
|
925
|
+
this.hideTimer = null;
|
|
926
|
+
}
|
|
922
927
|
const wasPlaying = this.movie.isPlaying;
|
|
923
928
|
if (wasPlaying) {
|
|
924
929
|
this.movie.pause();
|
|
@@ -951,6 +956,7 @@ var Controller = class _Controller {
|
|
|
951
956
|
} finally {
|
|
952
957
|
this.hideExportOverlay();
|
|
953
958
|
this.isExporting = false;
|
|
959
|
+
this.kickIdleTimer();
|
|
954
960
|
if (wasPlaying) {
|
|
955
961
|
void this.startPlaying();
|
|
956
962
|
this.refreshPlayIcon();
|
|
@@ -1014,7 +1020,7 @@ var Controller = class _Controller {
|
|
|
1014
1020
|
const wrap = this.wrapper;
|
|
1015
1021
|
this.onWrapPointerMove = () => this.kickIdleTimer();
|
|
1016
1022
|
this.onWrapMouseLeave = () => {
|
|
1017
|
-
if (!this.settingsOpen && !this.isScrubbing && !this.isVolumeScrubbing) this.setVisible(false);
|
|
1023
|
+
if (!this.settingsOpen && !this.isScrubbing && !this.isVolumeScrubbing && !this.isExporting) this.setVisible(false);
|
|
1018
1024
|
};
|
|
1019
1025
|
wrap.addEventListener("pointermove", this.onWrapPointerMove);
|
|
1020
1026
|
wrap.addEventListener("mouseleave", this.onWrapMouseLeave);
|
|
@@ -1032,9 +1038,9 @@ var Controller = class _Controller {
|
|
|
1032
1038
|
clearTimeout(this.hideTimer);
|
|
1033
1039
|
this.hideTimer = null;
|
|
1034
1040
|
}
|
|
1035
|
-
if (this.settingsOpen) return;
|
|
1041
|
+
if (this.settingsOpen || this.isExporting) return;
|
|
1036
1042
|
this.hideTimer = setTimeout(() => {
|
|
1037
|
-
if (!this.isScrubbing && !this.isVolumeScrubbing && !this.settingsOpen) this.setVisible(false);
|
|
1043
|
+
if (!this.isScrubbing && !this.isVolumeScrubbing && !this.settingsOpen && !this.isExporting) this.setVisible(false);
|
|
1038
1044
|
}, _Controller.HIDE_DELAY_MS);
|
|
1039
1045
|
}
|
|
1040
1046
|
setVisible(v) {
|