pixi-effects 0.26.2 → 0.26.3

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.
Files changed (42) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +5 -5
  3. package/ai/chat-template.html +3 -3
  4. package/ai/tools/render.mjs +16 -11
  5. package/dist/Composition-3O7L2VL5.js +7 -0
  6. package/dist/{Composition-H4QA24MV.js.map → Composition-3O7L2VL5.js.map} +1 -1
  7. package/dist/Composition-EE3KEE2L.cjs +16 -0
  8. package/dist/{Composition-HM4YT5L7.cjs.map → Composition-EE3KEE2L.cjs.map} +1 -1
  9. package/dist/Controller.d.cts +1 -1
  10. package/dist/Controller.d.ts +1 -1
  11. package/dist/{Movie-i05Oh9mJ.d.cts → Movie-BWLLWRRe.d.cts} +10 -3
  12. package/dist/{Movie-DVeDTdnc.d.ts → Movie-BkP82KXS.d.ts} +10 -3
  13. package/dist/Presenter.d.cts +1 -1
  14. package/dist/Presenter.d.ts +1 -1
  15. package/dist/{chunk-WPXDRSGN.cjs → chunk-A225HYSY.cjs} +205 -27
  16. package/dist/chunk-A225HYSY.cjs.map +1 -0
  17. package/dist/{chunk-X3HB4DSR.js → chunk-FXAHNPBP.js} +205 -27
  18. package/dist/chunk-FXAHNPBP.js.map +1 -0
  19. package/dist/{chunk-555URQHQ.cjs → chunk-IIDBEYQH.cjs} +59 -59
  20. package/dist/{chunk-555URQHQ.cjs.map → chunk-IIDBEYQH.cjs.map} +1 -1
  21. package/dist/{chunk-GBUM7X2S.js → chunk-WMMZDPWK.js} +3 -3
  22. package/dist/{chunk-GBUM7X2S.js.map → chunk-WMMZDPWK.js.map} +1 -1
  23. package/dist/index.cjs +142 -48
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +119 -25
  28. package/dist/index.js.map +1 -1
  29. package/dist/loader.css +1 -1
  30. package/dist/three.cjs +5 -5
  31. package/dist/three.js +1 -1
  32. package/docs/api.md +11 -5
  33. package/docs/dsl.md +2 -0
  34. package/llms-full.txt +17 -9
  35. package/package.json +1 -1
  36. package/skills/pixi-effects/SKILL.md +1 -1
  37. package/skills/pixi-effects/reference/cheatsheet.md +3 -3
  38. package/skills/pixi-effects/template.html +6 -6
  39. package/dist/Composition-H4QA24MV.js +0 -7
  40. package/dist/Composition-HM4YT5L7.cjs +0 -16
  41. package/dist/chunk-WPXDRSGN.cjs.map +0 -1
  42. package/dist/chunk-X3HB4DSR.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.26.3
4
+
5
+ **Added**
6
+
7
+ - **Sound-only export.** `render({ format: 'wav' })` (16-bit PCM) and `render({ format: 'ogg' })` (Opus) write the movie's mixed sound without drawing a frame, with `range` cutting it; `pixi-effects render page.html -o mix.wav` does it from a script. A movie with no sound says so instead of writing an empty file.
8
+ - **Video codec and bitrate options.** `render({ video: { codec, bitrate, hardware, keyFrameInterval } })`: `codec` is `avc`, `hevc`, `vp9`, `av1` or `vp8` (checked against the container and against what this browser can encode: the usual one falls back to the next that works with a warning, a codec you name is used or the error names the one that would work, and `h264` gets a did-you-mean); `bitrate` is a quality name or bits a second (`8_000_000`, `'8M'`, `'800k'`); `hardware` picks the encoder; `keyFrameInterval` (seconds, default 2). The render command gains `--video-bitrate`.
9
+ - **Relative keyframe values.** `to`, `from` and `set` accept `'+=36'` / `'-=36'`, measured from where the layer stands, with an expression on the right (`'-=GW*0.1'`): `from: { x: '-=36' }` is the usual slide-in, `to: { y: '+=40' }` a nudge, and keyframes one after another stack in any order of seeking. Until now `'+=36'` was evaluated as an expression and became **0 with no warning**; in `initial`, a style or the start of a `from` + `to` it now warns and is read as the number. (GSAP supported relative values all along; the keyframe pipeline did not let them through.)
10
+
11
+ **Changed**
12
+
13
+ - **Video: the pauses of reverse play and of a loop are read ahead.** A looping layer reads the first frames of the file (and a pass behind them) before the end comes, so the wrap shows no pause (a 30 s loop of two heavy layers: 0 pauses, it had 3). Reverse play reads the next window in the background while the held frames last, and each window now just fits what is held: one heavy layer played backwards shows 29.3 distinct frames a second with 1 pause in 6 s (24.8 and 6 pauses without the read-ahead, 14.1 and 31 before 0.26.2); four heavy layers, each reading its own window, reach 18 a second. Frames are now let go by where the playhead is (the ones it has passed first), not by age. Measured with the on-screen frame-number method of 0.26.2, on an M1 Pro.
14
+
3
15
  ## 0.26.2
4
16
 
5
17
  **Fixed**
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # pixi-effects
2
2
 
3
- > **Status**: experimental — current release `0.26.2`. The API may still change between minor versions; see the [CHANGELOG](./CHANGELOG.md) for what each release changed.
3
+ > **Status**: experimental — current release `0.26.3`. The API may still change between minor versions; see the [CHANGELOG](./CHANGELOG.md) for what each release changed.
4
4
 
5
5
  **[Guide →](https://yjmtmtk.github.io/pixi-effects/guide/)** · **[Gallery →](https://yjmtmtk.github.io/pixi-effects/examples/gallery/)** · 50 portfolio pieces written as plain data by AI models · **[Examples →](https://yjmtmtk.github.io/pixi-effects/examples/)** · 15 numbered examples, a music lab + an in-browser playground.
6
6
 
@@ -51,8 +51,8 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
51
51
  "gsap": "https://esm.sh/gsap@3.12.5",
52
52
  "gsap/PixiPlugin": "https://esm.sh/gsap@3.12.5/PixiPlugin",
53
53
  "mediabunny": "https://esm.sh/mediabunny",
54
- "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/index.js",
55
- "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/Controller.js"
54
+ "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.3/dist/index.js",
55
+ "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.3/dist/Controller.js"
56
56
  }
57
57
  }
58
58
  </script>
@@ -63,7 +63,7 @@ Drop the imports into an [importmap](https://developer.mozilla.org/docs/Web/HTML
63
63
  </script>
64
64
  ```
65
65
 
66
- Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.26.2/dist/index.js`) rather than a CDN-rebundled build such as `esm.sh/pixi-effects` or jsDelivr's `+esm`: the entries (`pixi-effects`, `…/controller`, `…/three`) share internal chunks, which only works when each file is served untouched.
66
+ Load the `dist/` files **as they are** (jsDelivr's `/npm/…/dist/…`, or unpkg's `https://unpkg.com/pixi-effects@0.26.3/dist/index.js`) rather than a CDN-rebundled build such as `esm.sh/pixi-effects` or jsDelivr's `+esm`: the entries (`pixi-effects`, `…/controller`, `…/three`) share internal chunks, which only works when each file is served untouched.
67
67
 
68
68
  > **Using three.js?** Add two more entries (`three` and `pixi-effects/three`) to this importmap — see [Adding three.js](#adding-threejs-optional) below.
69
69
  >
@@ -79,7 +79,7 @@ Add two more entries to the importmap above: three.js itself, and the `pixi-effe
79
79
  "imports": {
80
80
  "...": "(everything from the importmap above)",
81
81
  "three": "https://esm.sh/three@0.178.0",
82
- "pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/three.js"
82
+ "pixi-effects/three": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.3/dist/three.js"
83
83
  }
84
84
  }
85
85
  </script>
@@ -61,9 +61,9 @@
61
61
  "gsap": "https://cdn.jsdelivr.net/npm/gsap@3.12.5/+esm",
62
62
  "gsap/PixiPlugin": "https://cdn.jsdelivr.net/npm/gsap@3.12.5/PixiPlugin/+esm",
63
63
  "mediabunny": "https://cdn.jsdelivr.net/npm/mediabunny@1.61.3/+esm",
64
- "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/index.js",
65
- "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/Controller.js",
66
- "pixi-effects/presenter": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.2/dist/Presenter.js"
64
+ "pixi-effects": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.3/dist/index.js",
65
+ "pixi-effects/controller": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.3/dist/Controller.js",
66
+ "pixi-effects/presenter": "https://cdn.jsdelivr.net/npm/pixi-effects@0.26.3/dist/Presenter.js"
67
67
  }
68
68
  }
69
69
  </script>
@@ -12,12 +12,12 @@
12
12
  * Exit code: 0 = the file was written, 1 = the page or the render failed (no file), 2 = bad usage.
13
13
  *
14
14
  * Options: -o, --out FILE (default ./<page name>.<format>; the container follows the extension: mp4 webm mov mkv) ·
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) ·
15
+ * --format mp4|webm|mov|mkv|wav|ogg|pdf (wav / ogg: only the movie's sound, no picture; 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
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
17
  * --draft (for looking: half size, low quality, no motion blur; a --quality you give still wins) ·
18
18
  * --motion-blur SAMPLES (2-64: each frame is drawn that many times over the shutter and averaged; overrides the page's own motionBlur) ·
19
19
  * --shutter FRACTION (with --motion-blur: how long the shutter is open, 0-1 of a frame, default 0.5) ·
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
20
+ * --video-codec C (avc hevc vp9 av1 vp8) · --video-bitrate B (a quality or bits a second: 8M, 800k) · --audio-codec C · --query "a=1&b=2" (added to the page URL) · --fail-on-warn (exit 1 when the page
21
21
  * logged a warning; the file is still written) · --quiet (no progress line) · --timeout SECONDS (default 900) ·
22
22
  * --root DIR (static server root; default: the nearest folder above the page with dist/) · --chrome PATH
23
23
  */
@@ -27,14 +27,15 @@ import path from 'node:path';
27
27
  import { pathToFileURL } from 'node:url';
28
28
  import { findChrome, findRoot, serve, launchChrome, shown, sleep } from './check.mjs';
29
29
 
30
- const FORMATS = ['mp4', 'webm', 'mov', 'mkv', 'pdf'];
30
+ const FORMATS = ['mp4', 'webm', 'mov', 'mkv', 'wav', 'ogg', 'pdf'];
31
+ const SOUND_ONLY = ['wav', 'ogg'];
31
32
  const QUALITIES = ['very-low', 'low', 'medium', 'high', 'very-high'];
32
33
 
33
34
  /** 'clip.WEBM' → 'webm'; no extension → null; any other extension is an error. */
34
35
  export function formatFromPath(file) {
35
36
  const ext = path.extname(file).slice(1).toLowerCase();
36
37
  if (!ext) return null;
37
- if (!FORMATS.includes(ext)) throw new Error(`cannot tell the container from ".${ext}": use an output ending in mp4, webm, mov, mkv or pdf (or --format)`);
38
+ if (!FORMATS.includes(ext)) throw new Error(`cannot tell the container from ".${ext}": use an output ending in mp4, webm, mov, mkv, wav, ogg or pdf (or --format)`);
38
39
  return ext;
39
40
  }
40
41
 
@@ -43,18 +44,21 @@ export function defaultOutput(page, format) {
43
44
  }
44
45
 
45
46
  export function parseRenderArgs(argv) {
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 };
47
+ const o = { range: null, scene: null, scale: null, draft: false, qualityGiven: false, page: null, out: null, format: null, quality: 'high', videoCodec: null, videoBitrate: null, audioCodec: null, allStops: false, motionBlur: null, shutter: null, query: null, failOnWarn: false, quiet: false, timeout: 900, root: null, chrome: null };
47
48
  const need = (i, name) => { if (i + 1 >= argv.length) throw new Error(`${name} needs a value`); return argv[i + 1]; };
48
49
  for (let i = 0; i < argv.length; i++) {
49
50
  const a = argv[i];
50
51
  if (a === '-o' || a === '--out') o.out = need(i++, a);
51
52
  else if (a === '--format') {
52
53
  o.format = need(i++, a).toLowerCase();
53
- if (!FORMATS.includes(o.format)) throw new Error(`--format must be mp4, webm, mov, mkv or pdf (got "${o.format}")`);
54
+ if (!FORMATS.includes(o.format)) throw new Error(`--format must be mp4, webm, mov, mkv, wav, ogg or pdf (got "${o.format}")`);
54
55
  } else if (a === '--quality') {
55
56
  o.qualityGiven = true;
56
57
  o.quality = need(i++, a);
57
58
  if (!QUALITIES.includes(o.quality)) throw new Error(`--quality must be very-low, low, medium, high or very-high (got "${o.quality}")`);
59
+ } else if (a === '--video-bitrate') {
60
+ o.videoBitrate = need(i++, a);
61
+ if (!/^(very-low|low|medium|high|very-high|\d+(\.\d+)?\s*[kKmM]?)$/.test(o.videoBitrate)) throw new Error(`--video-bitrate must be a quality (very-low, low, medium, high, very-high) or bits a second (8000000, 8M, 800k), got "${o.videoBitrate}"`);
58
62
  } else if (a === '--video-codec') o.videoCodec = need(i++, a);
59
63
  else if (a === '--audio-codec') o.audioCodec = need(i++, a);
60
64
  else if (a === '--motion-blur') {
@@ -88,6 +92,7 @@ export function parseRenderArgs(argv) {
88
92
  if (o.allStops && o.format !== 'pdf' && !(o.out && formatFromPath(o.out) === 'pdf')) throw new Error('--all-stops goes with a PDF (-o deck.pdf)');
89
93
  o.format ??= (o.out ? formatFromPath(o.out) : null) ?? 'mp4';
90
94
  if (o.range && o.scene !== null) throw new Error('--range and --scene cannot be used together: a scene is a range');
95
+ if (SOUND_ONLY.includes(o.format) && (o.scale !== null || o.draft || o.motionBlur !== null || o.videoCodec || o.videoBitrate)) throw new Error(`--scale, --draft, --motion-blur, --video-codec and --video-bitrate are for a picture: ${o.format} writes only the sound`);
91
96
  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)');
92
97
  return o;
93
98
  }
@@ -96,16 +101,16 @@ const UPLOAD = '/__pixi_effects_out';
96
101
  const kb = n => (n >= 1048576 ? `${(n / 1048576).toFixed(2)} MB` : `${Math.max(1, Math.round(n / 1024))} KB`);
97
102
 
98
103
  /** The page's side: render, and PUT the Blob to our server (so a long video never goes through base64). */
99
- const renderScript = (format, quality, videoCodec, audioCodec, motionBlur, shutter, allStops, part = {}) => `(() => {
104
+ const renderScript = (format, quality, videoCodec, audioCodec, motionBlur, shutter, allStops, part = {}, videoBitrate = null) => `(() => {
100
105
  window.__r = { state: 'running', progress: 0 };
101
106
  movie.on('progress', e => { window.__r.progress = e.progress; });
102
107
  (async () => {
103
108
  try {
104
- const video = { ${[part.draft && !part.qualityGiven ? null : `bitrate: ${JSON.stringify(quality)}`, videoCodec ? `codec: ${JSON.stringify(videoCodec)}` : null].filter(Boolean).join(', ')} };
109
+ const video = { ${[videoBitrate ? `bitrate: ${JSON.stringify(/^\d+(\.\d+)?$/.test(videoBitrate) ? Number(videoBitrate) : videoBitrate)}` : part.draft && !part.qualityGiven ? null : `bitrate: ${JSON.stringify(quality)}`, videoCodec ? `codec: ${JSON.stringify(videoCodec)}` : null].filter(Boolean).join(', ')} };
105
110
  const audio = { bitrate: ${JSON.stringify(quality)}${audioCodec ? `, codec: ${JSON.stringify(audioCodec)}` : ''} };
106
111
  const blob = ${JSON.stringify(format)} === 'pdf'
107
112
  ? await movie.exportPDF({ which: ${allStops ? "'stops'" : "'pages'"}, title: document.title })
108
- : 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}` : ''} }` : ''} });
113
+ : await movie.render({ format: ${JSON.stringify(format)}, ${SOUND_ONLY.includes(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}` : ''} }` : ''} });
109
114
  const res = await fetch(${JSON.stringify(UPLOAD)}, { method: 'PUT', body: blob });
110
115
  if (!res.ok) throw new Error('could not hand the file to the command (' + res.status + ')');
111
116
  window.__r = { state: 'done', bytes: blob.size, type: blob.type };
@@ -171,7 +176,7 @@ export async function runRender(opts, log = console.log, progress = () => {}) {
171
176
  }
172
177
  Object.assign(result, { duration: info.duration, frames: info.totalFrames, width: info.width, height: info.height, frameRate: info.frameRate });
173
178
 
174
- 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 }));
179
+ 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 }, opts.videoBitrate));
175
180
  let state;
176
181
  for (;;) {
177
182
  left();
@@ -221,7 +226,7 @@ if (process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process
221
226
  console.error(`pixi-effects render failed: ${r.problems.join('; ') || 'no file written'}`);
222
227
  process.exit(1);
223
228
  }
224
- console.log(`${shown(r.file)} ${kb(r.bytes)} · ${r.duration} s · ${r.width}×${r.height} @ ${r.frameRate} fps · ${opts.format} · rendered in ${r.seconds} s`);
229
+ console.log(`${shown(r.file)} ${kb(r.bytes)} · ${r.duration} s · ${SOUND_ONLY.includes(opts.format) ? 'sound only' : `${r.width}×${r.height} @ ${r.frameRate} fps`} · ${opts.format} · rendered in ${r.seconds} s`);
225
230
  process.exit(opts.failOnWarn && r.logs.length ? 1 : 0);
226
231
  } catch (e) {
227
232
  console.error(`pixi-effects render failed: ${e.message}`);
@@ -0,0 +1,7 @@
1
+ export { CompositionSequence } from './chunk-WMMZDPWK.js';
2
+ import './chunk-FXAHNPBP.js';
3
+ import './chunk-AXZUKNXF.js';
4
+ import './chunk-TLYTYBWX.js';
5
+ import './chunk-BXOCEZ4U.js';
6
+ //# sourceMappingURL=Composition-3O7L2VL5.js.map
7
+ //# sourceMappingURL=Composition-3O7L2VL5.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-H4QA24MV.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-3O7L2VL5.js"}
@@ -0,0 +1,16 @@
1
+ 'use strict';
2
+
3
+ var chunkIIDBEYQH_cjs = require('./chunk-IIDBEYQH.cjs');
4
+ require('./chunk-A225HYSY.cjs');
5
+ require('./chunk-3DLYAPK7.cjs');
6
+ require('./chunk-ECA2WNRX.cjs');
7
+ require('./chunk-TWZNOUM7.cjs');
8
+
9
+
10
+
11
+ Object.defineProperty(exports, "CompositionSequence", {
12
+ enumerable: true,
13
+ get: function () { return chunkIIDBEYQH_cjs.CompositionSequence; }
14
+ });
15
+ //# sourceMappingURL=Composition-EE3KEE2L.cjs.map
16
+ //# sourceMappingURL=Composition-EE3KEE2L.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-HM4YT5L7.cjs"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"Composition-EE3KEE2L.cjs"}
@@ -1,4 +1,4 @@
1
- import { j as Movie } from './Movie-i05Oh9mJ.cjs';
1
+ import { j as Movie } from './Movie-BWLLWRRe.cjs';
2
2
  import 'pixi.js';
3
3
  import 'gsap';
4
4
  import './types-DSGwN5w1.cjs';
@@ -1,4 +1,4 @@
1
- import { j as Movie } from './Movie-DVeDTdnc.js';
1
+ import { j as Movie } from './Movie-BkP82KXS.js';
2
2
  import 'pixi.js';
3
3
  import 'gsap';
4
4
  import './types-DSGwN5w1.js';
@@ -289,14 +289,21 @@ interface MovieOptions {
289
289
  interface RenderOptions {
290
290
  /** Motion blur for this export (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
291
291
  motionBlur?: MotionBlurSpec;
292
- format?: 'mp4' | 'mov' | 'webm' | 'mkv';
292
+ /** `mp4`, `mov`, `webm`, `mkv`: the picture with its sound. `wav`, `ogg`: only the sound of the movie (an error when it has none). */
293
+ format?: 'mp4' | 'mov' | 'webm' | 'mkv' | 'wav' | 'ogg';
293
294
  video?: {
295
+ /** `'avc'` (H.264), `'hevc'`, `'vp9'`, `'av1'`, `'vp8'`: default the usual one for the format, the next that works if this browser cannot encode it; a name you give is never swapped. */
294
296
  codec?: string;
295
- bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
297
+ /** A quality name, or bits a second: `8_000_000` or `'8M'`, `'800k'`. */
298
+ bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high' | number | string;
299
+ /** Where to encode: `'prefer-hardware'`, `'prefer-software'` or `'no-preference'` (default). */
300
+ hardware?: 'no-preference' | 'prefer-hardware' | 'prefer-software';
301
+ /** Seconds between keyframes (default 2): shorter seeks faster and makes a bigger file. */
302
+ keyFrameInterval?: number;
296
303
  };
297
304
  audio?: {
298
305
  codec?: string;
299
- bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
306
+ bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high' | number | string;
300
307
  };
301
308
  /**
302
309
  * 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
@@ -289,14 +289,21 @@ interface MovieOptions {
289
289
  interface RenderOptions {
290
290
  /** Motion blur for this export (see `MovieOptions.motionBlur`); overrides the movie's own setting, `false` turns it off. */
291
291
  motionBlur?: MotionBlurSpec;
292
- format?: 'mp4' | 'mov' | 'webm' | 'mkv';
292
+ /** `mp4`, `mov`, `webm`, `mkv`: the picture with its sound. `wav`, `ogg`: only the sound of the movie (an error when it has none). */
293
+ format?: 'mp4' | 'mov' | 'webm' | 'mkv' | 'wav' | 'ogg';
293
294
  video?: {
295
+ /** `'avc'` (H.264), `'hevc'`, `'vp9'`, `'av1'`, `'vp8'`: default the usual one for the format, the next that works if this browser cannot encode it; a name you give is never swapped. */
294
296
  codec?: string;
295
- bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
297
+ /** A quality name, or bits a second: `8_000_000` or `'8M'`, `'800k'`. */
298
+ bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high' | number | string;
299
+ /** Where to encode: `'prefer-hardware'`, `'prefer-software'` or `'no-preference'` (default). */
300
+ hardware?: 'no-preference' | 'prefer-hardware' | 'prefer-software';
301
+ /** Seconds between keyframes (default 2): shorter seeks faster and makes a bigger file. */
302
+ keyFrameInterval?: number;
296
303
  };
297
304
  audio?: {
298
305
  codec?: string;
299
- bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high';
306
+ bitrate?: 'very-low' | 'low' | 'medium' | 'high' | 'very-high' | number | string;
300
307
  };
301
308
  /**
302
309
  * 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
@@ -1,4 +1,4 @@
1
- import { j as Movie } from './Movie-i05Oh9mJ.cjs';
1
+ import { j as Movie } from './Movie-BWLLWRRe.cjs';
2
2
  import 'pixi.js';
3
3
  import 'gsap';
4
4
  import './types-DSGwN5w1.cjs';
@@ -1,4 +1,4 @@
1
- import { j as Movie } from './Movie-DVeDTdnc.js';
1
+ import { j as Movie } from './Movie-BkP82KXS.js';
2
2
  import 'pixi.js';
3
3
  import 'gsap';
4
4
  import './types-DSGwN5w1.js';