pixi-effects 0.26.2 → 0.27.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +8 -10
  3. package/ai/CHAT.md +1 -1
  4. package/ai/chat-template.html +4 -6
  5. package/ai/tools/render.mjs +16 -11
  6. package/dist/{Base-CpdDs4HT.d.ts → Base-CVezIEdo.d.ts} +2 -4
  7. package/dist/{Base-TbBhHPrG.d.cts → Base-DzC3i919.d.cts} +2 -4
  8. package/dist/Composition-4TYDRRRY.js +7 -0
  9. package/dist/{Composition-H4QA24MV.js.map → Composition-4TYDRRRY.js.map} +1 -1
  10. package/dist/Composition-QCOWQSDB.cjs +16 -0
  11. package/dist/{Composition-HM4YT5L7.cjs.map → Composition-QCOWQSDB.cjs.map} +1 -1
  12. package/dist/Controller.d.cts +2 -3
  13. package/dist/Controller.d.ts +2 -3
  14. package/dist/{Movie-i05Oh9mJ.d.cts → Movie-CQ0Nz62a.d.cts} +12 -6
  15. package/dist/{Movie-DVeDTdnc.d.ts → Movie-M9dKm9dI.d.ts} +12 -6
  16. package/dist/Presenter.d.cts +2 -3
  17. package/dist/Presenter.d.ts +2 -3
  18. package/dist/{blendModes-YV43K6E7.cjs → blendModes-HDOP6R7T.cjs} +5 -5
  19. package/dist/{blendModes-YV43K6E7.cjs.map → blendModes-HDOP6R7T.cjs.map} +1 -1
  20. package/dist/{blendModes-G3NOAU3T.js → blendModes-PAVTW3BO.js} +4 -4
  21. package/dist/{blendModes-G3NOAU3T.js.map → blendModes-PAVTW3BO.js.map} +1 -1
  22. package/dist/{chunk-TLYTYBWX.js → chunk-45QKLD6M.js} +9 -11
  23. package/dist/chunk-45QKLD6M.js.map +1 -0
  24. package/dist/{chunk-GBUM7X2S.js → chunk-CKTS6G6I.js} +7 -11
  25. package/dist/chunk-CKTS6G6I.js.map +1 -0
  26. package/dist/{chunk-555URQHQ.cjs → chunk-NDR2VQFV.cjs} +91 -95
  27. package/dist/chunk-NDR2VQFV.cjs.map +1 -0
  28. package/dist/{chunk-3DLYAPK7.cjs → chunk-P4GY3Z4G.cjs} +5 -5
  29. package/dist/{chunk-3DLYAPK7.cjs.map → chunk-P4GY3Z4G.cjs.map} +1 -1
  30. package/dist/{chunk-WPXDRSGN.cjs → chunk-RQMI7EJT.cjs} +1170 -280
  31. package/dist/chunk-RQMI7EJT.cjs.map +1 -0
  32. package/dist/{chunk-X3HB4DSR.js → chunk-TGJACVLD.js} +1150 -263
  33. package/dist/chunk-TGJACVLD.js.map +1 -0
  34. package/dist/{chunk-AXZUKNXF.js → chunk-TYWFKCPY.js} +4 -4
  35. package/dist/{chunk-AXZUKNXF.js.map → chunk-TYWFKCPY.js.map} +1 -1
  36. package/dist/{chunk-ECA2WNRX.cjs → chunk-ZMAD3KJU.cjs} +9 -11
  37. package/dist/chunk-ZMAD3KJU.cjs.map +1 -0
  38. package/dist/index.cjs +189 -116
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +16 -14
  41. package/dist/index.d.ts +16 -14
  42. package/dist/index.js +136 -45
  43. package/dist/index.js.map +1 -1
  44. package/dist/loader.css +1 -1
  45. package/dist/three.cjs +6 -6
  46. package/dist/three.d.cts +2 -3
  47. package/dist/three.d.ts +2 -3
  48. package/dist/three.js +2 -2
  49. package/dist/{types-DSGwN5w1.d.ts → types-DUVefWiB.d.cts} +128 -3
  50. package/dist/{types-DSGwN5w1.d.cts → types-DUVefWiB.d.ts} +128 -3
  51. package/docs/api.md +16 -6
  52. package/docs/dsl.md +14 -14
  53. package/llms-full.txt +38 -28
  54. package/llms.txt +1 -1
  55. package/package.json +3 -4
  56. package/skills/pixi-effects/SKILL.md +1 -1
  57. package/skills/pixi-effects/reference/cheatsheet.md +3 -3
  58. package/skills/pixi-effects/reference/pitfalls.md +3 -3
  59. package/skills/pixi-effects/reference/recipes.md +1 -1
  60. package/skills/pixi-effects/template.html +6 -8
  61. package/dist/Composition-H4QA24MV.js +0 -7
  62. package/dist/Composition-HM4YT5L7.cjs +0 -16
  63. package/dist/chunk-555URQHQ.cjs.map +0 -1
  64. package/dist/chunk-ECA2WNRX.cjs.map +0 -1
  65. package/dist/chunk-GBUM7X2S.js.map +0 -1
  66. package/dist/chunk-TLYTYBWX.js.map +0 -1
  67. package/dist/chunk-WPXDRSGN.cjs.map +0 -1
  68. package/dist/chunk-X3HB4DSR.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,41 +1,19 @@
1
1
  'use strict';
2
2
 
3
- var chunk555URQHQ_cjs = require('./chunk-555URQHQ.cjs');
4
- var chunkWPXDRSGN_cjs = require('./chunk-WPXDRSGN.cjs');
5
- var chunk3DLYAPK7_cjs = require('./chunk-3DLYAPK7.cjs');
6
- var chunkECA2WNRX_cjs = require('./chunk-ECA2WNRX.cjs');
3
+ var chunkNDR2VQFV_cjs = require('./chunk-NDR2VQFV.cjs');
4
+ var chunkRQMI7EJT_cjs = require('./chunk-RQMI7EJT.cjs');
5
+ var chunkP4GY3Z4G_cjs = require('./chunk-P4GY3Z4G.cjs');
6
+ var chunkZMAD3KJU_cjs = require('./chunk-ZMAD3KJU.cjs');
7
7
  var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
8
- var PIXI = require('pixi.js');
9
- var gsap = require('gsap');
10
- var PixiPlugin = require('gsap/PixiPlugin');
8
+ var pixi_js = require('pixi.js');
11
9
  var mediabunny = require('mediabunny');
12
10
 
13
- function _interopNamespace(e) {
14
- if (e && e.__esModule) return e;
15
- var n = Object.create(null);
16
- if (e) {
17
- Object.keys(e).forEach(function (k) {
18
- if (k !== 'default') {
19
- var d = Object.getOwnPropertyDescriptor(e, k);
20
- Object.defineProperty(n, k, d.get ? d : {
21
- enumerable: true,
22
- get: function () { return e[k]; }
23
- });
24
- }
25
- });
26
- }
27
- n.default = e;
28
- return Object.freeze(n);
29
- }
30
-
31
- var PIXI__namespace = /*#__PURE__*/_interopNamespace(PIXI);
32
-
33
11
  var registered = false;
34
12
  function ensureLoadersRegistered(audioContext) {
35
13
  if (registered) return;
36
14
  registered = true;
37
- PIXI.extensions.add({
38
- extension: { type: PIXI.ExtensionType.LoadParser, name: "pixi-effects-audio" },
15
+ pixi_js.extensions.add({
16
+ extension: { type: pixi_js.ExtensionType.LoadParser, name: "pixi-effects-audio" },
39
17
  test: (url) => /\.(mp3|wav|ogg)$/i.test(url),
40
18
  async load(url) {
41
19
  const res = await fetch(url);
@@ -45,8 +23,8 @@ function ensureLoadersRegistered(audioContext) {
45
23
  return { audioBuffer, duration: audioBuffer.duration };
46
24
  }
47
25
  });
48
- PIXI.extensions.add({
49
- extension: { type: PIXI.ExtensionType.LoadParser, name: "pixi-effects-video", priority: 1 },
26
+ pixi_js.extensions.add({
27
+ extension: { type: pixi_js.ExtensionType.LoadParser, name: "pixi-effects-video", priority: 1 },
50
28
  test: (url) => /\.(mp4|webm|mov|mkv)$/i.test(url),
51
29
  async load(url) {
52
30
  const blob = await fetch(url).then((r) => r.blob());
@@ -83,8 +61,8 @@ function ensureLoadersRegistered(audioContext) {
83
61
  async function loadAssetBundle(assets, audioContext, onProgress) {
84
62
  ensureLoadersRegistered(audioContext);
85
63
  const bundle = assets.map((a) => ({ alias: a.name, src: a.src }));
86
- PIXI.Assets.addBundle("pixi-effects", bundle);
87
- return await PIXI.Assets.loadBundle("pixi-effects", onProgress);
64
+ pixi_js.Assets.addBundle("pixi-effects", bundle);
65
+ return await pixi_js.Assets.loadBundle("pixi-effects", onProgress);
88
66
  }
89
67
 
90
68
  // src/core/audioRemap.ts
@@ -779,24 +757,70 @@ function resolveRenderOptions(o) {
779
757
  };
780
758
  }
781
759
 
782
- // src/core/Renderer.ts
783
- var VIDEO_CODEC_BY_FORMAT = {
784
- mp4: "avc",
785
- mov: "avc",
786
- webm: "vp9",
787
- mkv: "vp9"
760
+ // src/core/renderOptions.ts
761
+ var QUALITY_NAMES = ["very-low", "low", "medium", "high", "very-high"];
762
+ function parseBitrate(v) {
763
+ if (v === void 0 || v === null) return {};
764
+ if (typeof v === "string" && QUALITY_NAMES.includes(v)) return { quality: v };
765
+ if (typeof v === "number" && Number.isFinite(v) && v > 0) return { bps: Math.round(v) };
766
+ const m = typeof v === "string" ? /^\s*(\d+(?:\.\d+)?)\s*([kKmM]?)\s*$/.exec(v) : null;
767
+ if (m) {
768
+ const n = Number(m[1]) * { "": 1, k: 1e3, m: 1e6 }[m[2].toLowerCase()];
769
+ if (n > 0) return { bps: Math.round(n) };
770
+ }
771
+ throw new Error(`pixi-effects: bitrate ${JSON.stringify(v)}: use a quality (${QUALITY_NAMES.join(", ")}) or bits a second (8000000, '8M', '800k')`);
772
+ }
773
+ var AUDIO_FORMATS = ["wav", "ogg"];
774
+ var isAudioFormat = (f) => AUDIO_FORMATS.includes(f);
775
+ var VIDEO_CODEC_PREFERENCE = {
776
+ mp4: ["avc", "hevc", "vp9", "av1"],
777
+ mov: ["avc", "hevc"],
778
+ webm: ["vp9", "av1", "vp8"],
779
+ mkv: ["vp9", "avc", "hevc", "av1", "vp8"]
788
780
  };
789
- var AUDIO_CODEC_BY_FORMAT = {
790
- mp4: "aac",
791
- mov: "aac",
792
- webm: "opus",
793
- mkv: "opus"
781
+ var CODEC_ALIASES = {
782
+ h264: "avc",
783
+ "h.264": "avc",
784
+ x264: "avc",
785
+ avc1: "avc",
786
+ h265: "hevc",
787
+ "h.265": "hevc",
788
+ x265: "hevc",
789
+ hvc1: "hevc",
790
+ hev1: "hevc",
791
+ vp09: "vp9",
792
+ "vp-9": "vp9",
793
+ av01: "av1",
794
+ vp80: "vp8",
795
+ "vp-8": "vp8"
794
796
  };
797
+ async function chooseVideoCodec(a) {
798
+ const held = a.supported ?? VIDEO_CODEC_PREFERENCE[a.fmt];
799
+ const order = VIDEO_CODEC_PREFERENCE[a.fmt].filter((c) => held.includes(c));
800
+ const firstThatWorks = async (list) => {
801
+ for (const c of list) if (await a.canEncode(c)) return c;
802
+ return null;
803
+ };
804
+ if (a.requested) {
805
+ const alias = CODEC_ALIASES[a.requested.toLowerCase()];
806
+ if (alias) throw new Error(`pixi-effects: render({ video: { codec: "${a.requested}" } }): "${a.requested}" is not a codec name here; did you mean "${alias}"?`);
807
+ if (!order.includes(a.requested)) throw new Error(`pixi-effects: render(): "${a.requested}" cannot go in ${a.fmt} (${a.fmt} holds ${order.join(", ")})`);
808
+ if (await a.canEncode(a.requested)) return { codec: a.requested };
809
+ const alt = await firstThatWorks(order.filter((c) => c !== a.requested));
810
+ throw new Error(`pixi-effects: this browser cannot encode "${a.requested}" video for ${a.fmt}` + (alt ? `; "${alt}" would work: render({ format: '${a.fmt}', video: { codec: '${alt}' } }), or leave video.codec out and the best one is chosen.` : "; it can encode none of " + order.join(", ") + "."));
811
+ }
812
+ const chosen = await firstThatWorks(order);
813
+ if (!chosen) throw new Error(`pixi-effects: this browser has no video encoder for ${a.fmt} (it tried ${order.join(", ")}): try another browser, or another format`);
814
+ return chosen === order[0] ? { codec: chosen } : { codec: chosen, fellBackFrom: order[0] };
815
+ }
816
+
817
+ // src/core/Renderer.ts
795
818
  var AUDIO_PREFERENCE = {
796
819
  mp4: ["aac", "opus", "mp3", "flac"],
797
820
  mov: ["aac", "mp3"],
798
821
  webm: ["opus", "vorbis"],
799
- mkv: ["opus", "vorbis", "aac", "flac", "mp3"]
822
+ mkv: ["opus", "vorbis", "aac", "flac", "mp3"],
823
+ ogg: ["opus", "vorbis", "flac"]
800
824
  };
801
825
  async function chooseAudioCodec(fmt, requested, container, audio, bitrate) {
802
826
  const supported = container.getSupportedAudioCodecs?.();
@@ -821,6 +845,10 @@ var qualityMap = {
821
845
  "high": mediabunny.QUALITY_HIGH,
822
846
  "very-high": mediabunny.QUALITY_VERY_HIGH
823
847
  };
848
+ function bitrateOf(v, fallback) {
849
+ const b = parseBitrate(v);
850
+ return b.bps ?? (b.quality ? qualityMap[b.quality] : fallback);
851
+ }
824
852
  function makeOutputFormat(name) {
825
853
  switch (name) {
826
854
  case "mp4":
@@ -840,19 +868,47 @@ function sliceAudio(buffer, fromSec, toSec, fadeIn, fadeOut) {
840
868
  cut.forEach((data, c) => out.copyToChannel(data, c));
841
869
  return out;
842
870
  }
871
+ async function exportAudioOnly(movie, options, fmt, range2) {
872
+ if (!movie.audioBuffer) {
873
+ throw new Error(`pixi-effects: render({ format: '${fmt}' }): this movie has no sound to export (add an audio layer, an sfx or a music score); for the picture use mp4, webm, mov or mkv`);
874
+ }
875
+ if (options.video) console.warn(`pixi-effects: render({ format: '${fmt}' }): video options are ignored, only the sound is written`);
876
+ const audio = range2.partial ? sliceAudio(movie.audioBuffer, range2.fromSec, range2.toSec, range2.fromFrame > 0, range2.toFrame < movie.totalFrames) : movie.audioBuffer;
877
+ const container = fmt === "wav" ? new mediabunny.WavOutputFormat() : new mediabunny.OggOutputFormat();
878
+ let codec;
879
+ if (fmt === "wav") {
880
+ codec = options.audio?.codec ?? "pcm-s16";
881
+ const held = container.getSupportedAudioCodecs();
882
+ if (!held.includes(codec)) throw new Error(`pixi-effects: render({ format: 'wav', audio: { codec: "${codec}" } }): wav holds ${held.join(", ")} (the usual is pcm-s16)`);
883
+ } else {
884
+ codec = await chooseAudioCodec("ogg", options.audio?.codec, container, audio, bitrateOf(options.audio?.bitrate, mediabunny.QUALITY_HIGH));
885
+ }
886
+ const output = new mediabunny.Output({ format: container, target: new mediabunny.BufferTarget() });
887
+ const source = new mediabunny.AudioBufferSource({ codec, ...fmt === "wav" ? {} : { bitrate: bitrateOf(options.audio?.bitrate, mediabunny.QUALITY_HIGH) } });
888
+ output.addAudioTrack(source);
889
+ movie.emit("progress", { progress: 0, frame: range2.fromFrame, totalFrames: movie.totalFrames });
890
+ await output.start();
891
+ await source.add(audio);
892
+ await source.close();
893
+ await output.finalize();
894
+ movie.emit("progress", { progress: 100, frame: range2.toFrame, totalFrames: movie.totalFrames });
895
+ return new Blob([output.target.buffer], { type: output.format.mimeType });
896
+ }
843
897
  async function exportFrames(movie, options = {}) {
844
898
  const fmt = options.format ?? "mp4";
845
899
  const eff = resolveRenderOptions(options);
846
900
  const range2 = resolveRange(options.range, { frameRate: movie.frameRate, totalFrames: movie.totalFrames, duration: movie.duration, rows: typeof options.range === "string" ? movie.timelineData().rows : void 0 });
901
+ if (isAudioFormat(fmt)) return exportAudioOnly(movie, options, fmt, range2);
902
+ if (!["mp4", "mov", "webm", "mkv"].includes(fmt)) throw new Error(`pixi-effects: render({ format: "${String(fmt)}" }): use mp4, mov, webm, mkv (a picture) or wav, ogg (only the sound)`);
903
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.render({ video })", options.video, ["codec", "bitrate", "hardware", "keyFrameInterval"]);
904
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.render({ audio })", options.audio, ["codec", "bitrate"]);
905
+ const videoBitrate = bitrateOf(eff.bitrate ?? "high", mediabunny.QUALITY_HIGH);
847
906
  const opts = {
848
907
  format: fmt,
849
- video: {
850
- codec: options.video?.codec ?? VIDEO_CODEC_BY_FORMAT[fmt],
851
- bitrate: qualityMap[eff.bitrate ?? "high"] ?? mediabunny.QUALITY_HIGH
852
- },
908
+ video: { codec: "", bitrate: videoBitrate },
853
909
  audio: {
854
- codec: options.audio?.codec ?? AUDIO_CODEC_BY_FORMAT[fmt],
855
- bitrate: qualityMap[options.audio?.bitrate ?? "high"] ?? mediabunny.QUALITY_HIGH
910
+ codec: options.audio?.codec ?? (fmt === "mp4" || fmt === "mov" ? "aac" : "opus"),
911
+ bitrate: bitrateOf(options.audio?.bitrate, mediabunny.QUALITY_HIGH)
856
912
  }
857
913
  };
858
914
  const container = makeOutputFormat(opts.format);
@@ -867,9 +923,23 @@ async function exportFrames(movie, options = {}) {
867
923
  const blurCanvas = mb ? Object.assign(document.createElement("canvas"), { width: stage.width, height: stage.height }) : null;
868
924
  const small = eff.scale < 1 ? Object.assign(document.createElement("canvas"), { width: Math.max(2, Math.round(stage.width * eff.scale / 2) * 2), height: Math.max(2, Math.round(stage.height * eff.scale / 2) * 2) }) : null;
869
925
  const smallCtx = small?.getContext("2d") ?? null;
870
- const canvasSource = new mediabunny.CanvasSource(small ?? blurCanvas ?? stage, {
926
+ const picture = small ?? blurCanvas ?? stage;
927
+ const chosen = await chooseVideoCodec({
928
+ fmt,
929
+ requested: options.video?.codec,
930
+ supported: container.getSupportedVideoCodecs(),
931
+ canEncode: (c) => mediabunny.canEncodeVideo(c, { width: picture.width, height: picture.height, bitrate: opts.video.bitrate })
932
+ });
933
+ if (chosen.fellBackFrom) console.warn(`pixi-effects: this browser cannot encode ${chosen.fellBackFrom.toUpperCase()} video, so the ${fmt} carries ${chosen.codec.toUpperCase()} instead (name a codec with render({ video: { codec } }) to choose yourself).`);
934
+ opts.video.codec = chosen.codec;
935
+ const hardware = options.video?.hardware;
936
+ if (hardware !== void 0 && !["no-preference", "prefer-hardware", "prefer-software"].includes(hardware)) {
937
+ throw new Error(`pixi-effects: render({ video: { hardware: "${String(hardware)}" } }): use 'prefer-hardware', 'prefer-software' or 'no-preference'`);
938
+ }
939
+ const canvasSource = new mediabunny.CanvasSource(picture, {
871
940
  codec: opts.video.codec,
872
- bitrate: opts.video.bitrate
941
+ bitrate: opts.video.bitrate,
942
+ ...hardware ? { hardwareAcceleration: hardware } : {}
873
943
  });
874
944
  output.addVideoTrack(canvasSource, { frameRate: movie.frameRate });
875
945
  if (audio) {
@@ -885,7 +955,9 @@ async function exportFrames(movie, options = {}) {
885
955
  await output.start();
886
956
  }
887
957
  movie.app.ticker.stop();
888
- const keyframeIntervalFrames = Math.max(1, Math.round(2 * movie.frameRate));
958
+ const interval = options.video?.keyFrameInterval ?? 2;
959
+ if (!(typeof interval === "number" && Number.isFinite(interval) && interval > 0)) throw new Error(`pixi-effects: render({ video: { keyFrameInterval: ${String(interval)} } }): seconds between keyframes, above 0 (default 2)`);
960
+ const keyframeIntervalFrames = Math.max(1, Math.round(interval * movie.frameRate));
889
961
  try {
890
962
  const count = Math.max(1, range2.toFrame - range2.fromFrame);
891
963
  for (let frame = range2.fromFrame; frame <= range2.toFrame; frame++) {
@@ -1173,7 +1245,7 @@ fn mainFragment(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
1173
1245
  return raw * reveal;
1174
1246
  }
1175
1247
  `;
1176
- var TransitionMaskFilter = class extends PIXI.Filter {
1248
+ var TransitionMaskFilter = class extends pixi_js.Filter {
1177
1249
  constructor(options = {}) {
1178
1250
  const mode = options.mode ?? "wipe-left";
1179
1251
  const smoothing = options.smoothing ?? 0.02;
@@ -1182,17 +1254,17 @@ var TransitionMaskFilter = class extends PIXI.Filter {
1182
1254
  const scale = options.scale ?? 30;
1183
1255
  const seed = options.seed ?? 0;
1184
1256
  super({
1185
- glProgram: PIXI.GlProgram.from({
1186
- vertex: PIXI.defaultFilterVert,
1257
+ glProgram: pixi_js.GlProgram.from({
1258
+ vertex: pixi_js.defaultFilterVert,
1187
1259
  fragment: GL_FRAGMENT,
1188
1260
  name: "transition-mask-filter"
1189
1261
  }),
1190
- gpuProgram: PIXI.GpuProgram.from({
1262
+ gpuProgram: pixi_js.GpuProgram.from({
1191
1263
  vertex: { source: WGSL_SOURCE, entryPoint: "mainVertex" },
1192
1264
  fragment: { source: WGSL_SOURCE, entryPoint: "mainFragment" }
1193
1265
  }),
1194
1266
  resources: {
1195
- transitionUniforms: new PIXI.UniformGroup({
1267
+ transitionUniforms: new pixi_js.UniformGroup({
1196
1268
  uProgress: { value: progress, type: "f32" },
1197
1269
  uMode: { value: MODE_CODES[mode], type: "f32" },
1198
1270
  uSmoothing: { value: smoothing, type: "f32" },
@@ -1319,19 +1391,19 @@ fn mainFragment(@location(0) uv : vec2<f32>) -> @location(0) vec4<f32> {
1319
1391
  if (lumaUniforms.uInvert > 0.5) { reveal = 1.0 - step(0.99, reveal); }
1320
1392
  return raw * reveal;
1321
1393
  }`;
1322
- var LumaWipeFilter = class extends PIXI.Filter {
1394
+ var LumaWipeFilter = class extends pixi_js.Filter {
1323
1395
  _mapName;
1324
1396
  _builtIn;
1325
1397
  _resolved = false;
1326
1398
  _warned = false;
1327
1399
  constructor({ map, softness = 0.1, progress = 0, invert = false, flip = false }) {
1328
- const t = PIXI.Texture.WHITE;
1400
+ const t = pixi_js.Texture.WHITE;
1329
1401
  const mode = LUMA_MAPS.indexOf(map) + 1;
1330
1402
  super({
1331
- glProgram: PIXI.GlProgram.from({ vertex: PIXI.defaultFilterVert, fragment: GL, name: "pe-luma-wipe" }),
1332
- gpuProgram: PIXI.GpuProgram.from({ vertex: { source: WGSL, entryPoint: "mainVertex" }, fragment: { source: WGSL, entryPoint: "mainFragment" } }),
1403
+ glProgram: pixi_js.GlProgram.from({ vertex: pixi_js.defaultFilterVert, fragment: GL, name: "pe-luma-wipe" }),
1404
+ gpuProgram: pixi_js.GpuProgram.from({ vertex: { source: WGSL, entryPoint: "mainVertex" }, fragment: { source: WGSL, entryPoint: "mainFragment" } }),
1333
1405
  resources: {
1334
- lumaUniforms: new PIXI.UniformGroup({
1406
+ lumaUniforms: new pixi_js.UniformGroup({
1335
1407
  uProgress: { value: progress, type: "f32" },
1336
1408
  uSoftness: { value: softness, type: "f32" },
1337
1409
  uInvert: { value: invert ? 1 : 0, type: "f32" },
@@ -1353,7 +1425,7 @@ var LumaWipeFilter = class extends PIXI.Filter {
1353
1425
  }
1354
1426
  apply(fm, input, output, clear) {
1355
1427
  if (!this._builtIn && !this._resolved) {
1356
- const t = PIXI.Assets.get(this._mapName);
1428
+ const t = pixi_js.Assets.get(this._mapName);
1357
1429
  if (t) {
1358
1430
  this.resources.uMap = t.source;
1359
1431
  this.resources.uMapSampler = t.source.style;
@@ -1407,8 +1479,8 @@ function expandTransitions(spec) {
1407
1479
  }
1408
1480
  const transitions = out.transitions;
1409
1481
  const sequences = out.sequences ?? [];
1410
- const remap = out.duration !== void 0 ? chunkWPXDRSGN_cjs.timeRemapOf(out) : null;
1411
- const parentDuration = remap ? chunkWPXDRSGN_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
1482
+ const remap = out.duration !== void 0 ? chunkRQMI7EJT_cjs.timeRemapOf(out) : null;
1483
+ const parentDuration = remap ? chunkRQMI7EJT_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
1412
1484
  const compW = out.width;
1413
1485
  const compH = out.height;
1414
1486
  const threeDByName = new Set(sequences.filter((s) => s.name && s.threeD).map((s) => s.name));
@@ -1476,16 +1548,16 @@ function expandTransitions(spec) {
1476
1548
  if (toUses > 1) {
1477
1549
  throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
1478
1550
  }
1479
- const tStart = chunkWPXDRSGN_cjs.resolveAt(t.at, parentDuration);
1551
+ const tStart = chunkRQMI7EJT_cjs.resolveAt(t.at, parentDuration);
1480
1552
  const tEnd = tStart + t.duration;
1481
1553
  const fromSeq = fromEntry.seq;
1482
- const fromStart = chunkWPXDRSGN_cjs.resolveAt(fromSeq.at, parentDuration);
1554
+ const fromStart = chunkRQMI7EJT_cjs.resolveAt(fromSeq.at, parentDuration);
1483
1555
  const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
1484
1556
  if (tStart < fromStart - EPS || tEnd > fromEnd + EPS) {
1485
1557
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`from\` "${t.from}" (lives [${fromStart}, ${fromEnd}], so it ends at ${fromEnd})`);
1486
1558
  }
1487
1559
  const toSeq = toEntry.seq;
1488
- const toStart = chunkWPXDRSGN_cjs.resolveAt(toSeq.at, parentDuration);
1560
+ const toStart = chunkRQMI7EJT_cjs.resolveAt(toSeq.at, parentDuration);
1489
1561
  const toEnd = toStart + (toSeq.duration ?? parentDuration);
1490
1562
  if (tStart < toStart - EPS || tEnd > toEnd + EPS) {
1491
1563
  throw new Error(`pixi-effects: ${tag} window [${tStart}, ${tEnd}] is not covered by \`to\` "${t.to}" (lives [${toStart}, ${toEnd}], so it starts at ${toStart})`);
@@ -1545,7 +1617,7 @@ function wrapAsFullComposition(seq, compW, compH) {
1545
1617
  delete inner.at;
1546
1618
  delete inner.duration;
1547
1619
  const m = inner.mask;
1548
- const carriesMatte = m !== void 0 && chunk555URQHQ_cjs.maskSourceOf(m).kind === "refs";
1620
+ const carriesMatte = m !== void 0 && chunkNDR2VQFV_cjs.maskSourceOf(m).kind === "refs";
1549
1621
  if (carriesMatte) delete inner.mask;
1550
1622
  return {
1551
1623
  ...carriesMatte ? { mask: m } : {},
@@ -1847,9 +1919,9 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1847
1919
  onCanvas = inter === 0 && area > 0 ? "none" : inter >= area - 1e-6 ? "full" : "partial";
1848
1920
  if (area === 0) onCanvas = "none";
1849
1921
  }
1850
- const keys = chunkECA2WNRX_cjs.collectPropKeys(seq.spec);
1922
+ const keys = chunkZMAD3KJU_cjs.collectPropKeys(seq.spec);
1851
1923
  const carried = carriers.some((c) => {
1852
- const k = chunkECA2WNRX_cjs.collectPropKeys(c.spec);
1924
+ const k = chunkZMAD3KJU_cjs.collectPropKeys(c.spec);
1853
1925
  return (c.spec.keyframes ?? []).length > 0 && (k.has("x") || k.has("y") || k.has("rotation") || k.has("scale"));
1854
1926
  });
1855
1927
  const moving = parentMoving || carried || (seq.spec.keyframes ?? []).length > 0 && (keys.has("x") || keys.has("y"));
@@ -1872,7 +1944,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1872
1944
  const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
1873
1945
  if (group) scene.set(info, group);
1874
1946
  if (zero || seq.showsNothingYet) scaledToNothing.add(info);
1875
- if (seq instanceof chunk555URQHQ_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1947
+ if (seq instanceof chunkNDR2VQFV_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1876
1948
  });
1877
1949
  };
1878
1950
  walk2(root, "", false, true);
@@ -1933,10 +2005,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions, lo
1933
2005
  const start = parentStart + (seq.at ?? 0);
1934
2006
  const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
1935
2007
  const span = end - start;
1936
- const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkWPXDRSGN_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
2008
+ const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkRQMI7EJT_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
1937
2009
  const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq), ...local ? { local } : {} };
1938
2010
  const inner = [];
1939
- const isComp = seq instanceof chunk555URQHQ_cjs.CompositionSequence;
2011
+ const isComp = seq instanceof chunkNDR2VQFV_cjs.CompositionSequence;
1940
2012
  if (isComp) {
1941
2013
  const label = seq.remapLabel();
1942
2014
  walk(seq, label ? 0 : start, label ? seq.contentSpan : end, depth + 1, prefix + name + "/", inner, transitions, label ? `${name} ${label}` : local);
@@ -2448,9 +2520,7 @@ function setLoaderProgress(loader, state) {
2448
2520
  }
2449
2521
 
2450
2522
  // src/core/Movie.ts
2451
- PIXI.extensions.add(PIXI.CullerPlugin);
2452
- gsap.gsap.registerPlugin(PixiPlugin.PixiPlugin);
2453
- PixiPlugin.PixiPlugin.registerPIXI(PIXI__namespace);
2523
+ pixi_js.extensions.add(pixi_js.CullerPlugin);
2454
2524
  var Movie = class {
2455
2525
  _events = {};
2456
2526
  _initState = "idle";
@@ -2586,8 +2656,8 @@ var Movie = class {
2586
2656
  this.stops = normalizeStops(options.composition?.stops, this.duration, this.frameRate);
2587
2657
  this._posterFrame = poster.frame;
2588
2658
  this.background = options.background ?? "#000000";
2589
- this.timeline = gsap.gsap.timeline({ paused: true, defaults: { ease: "none" } });
2590
- this.timeline.add(gsap.gsap.to({}, { duration: this.duration }));
2659
+ this.timeline = chunkRQMI7EJT_cjs.createTimeline({ paused: true, defaults: { ease: "none" } });
2660
+ chunkRQMI7EJT_cjs.lengthen(this.timeline, this.duration);
2591
2661
  const baseAppOptions = {
2592
2662
  width: this.width,
2593
2663
  height: this.height,
@@ -2598,19 +2668,19 @@ var Movie = class {
2598
2668
  preserveDrawingBuffer: true,
2599
2669
  canvas: options.canvas
2600
2670
  };
2601
- this.app = new PIXI.Application();
2671
+ this.app = new pixi_js.Application();
2602
2672
  try {
2603
2673
  await this.app.init({ ...baseAppOptions, preference: "webgpu" });
2604
2674
  } catch (err) {
2605
2675
  console.warn("pixi-effects: WebGPU init failed, falling back to WebGL \u2014", err);
2606
- this.app = new PIXI.Application();
2676
+ this.app = new pixi_js.Application();
2607
2677
  await this.app.init({ ...baseAppOptions, preference: "webgl" });
2608
2678
  }
2609
- if (chunk3DLYAPK7_cjs.usesAdvancedBlend(options.composition)) await chunk3DLYAPK7_cjs.enableAdvancedBlend(this.app.renderer);
2610
- const root = new PIXI.Container();
2679
+ if (chunkP4GY3Z4G_cjs.usesAdvancedBlend(options.composition)) await chunkP4GY3Z4G_cjs.enableAdvancedBlend(this.app.renderer);
2680
+ const root = new pixi_js.Container();
2611
2681
  root.cullable = true;
2612
2682
  root.cullableChildren = true;
2613
- root.cullArea = new PIXI.Rectangle(0, 0, this.width, this.height);
2683
+ root.cullArea = new pixi_js.Rectangle(0, 0, this.width, this.height);
2614
2684
  this.app.stage.addChild(root);
2615
2685
  this._rootContainer = root;
2616
2686
  const audioContext = this._ensureAudioContext();
@@ -2646,7 +2716,7 @@ var Movie = class {
2646
2716
  height: options.composition.height ?? this.height,
2647
2717
  duration: options.composition.duration ?? this.duration
2648
2718
  } : void 0;
2649
- await chunkWPXDRSGN_cjs.ensureFilterLibrary(seededComposition);
2719
+ await chunkRQMI7EJT_cjs.ensureFilterLibrary(seededComposition);
2650
2720
  const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
2651
2721
  const rootSeqSpec = {
2652
2722
  type: "composition",
@@ -2656,7 +2726,7 @@ var Movie = class {
2656
2726
  ...userComposition
2657
2727
  };
2658
2728
  if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
2659
- const composition = new chunk555URQHQ_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
2729
+ const composition = new chunkNDR2VQFV_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
2660
2730
  lp.begin("build", countLayers(rootSeqSpec));
2661
2731
  await composition.build();
2662
2732
  this._rootSequence = composition;
@@ -2672,8 +2742,8 @@ var Movie = class {
2672
2742
  if (this.audioBuffer) this._mixStats = limitMix(this.audioBuffer, audios);
2673
2743
  }
2674
2744
  this._audioSources = audios;
2675
- this.timeline.progress(1).progress(0);
2676
2745
  lp.begin("frames", 0);
2746
+ this.timeline.time(this._timeOf(0));
2677
2747
  await this._awaitVideoFrames();
2678
2748
  this._updateSpace();
2679
2749
  this._renderNow();
@@ -3008,7 +3078,7 @@ var Movie = class {
3008
3078
  if (!this._synced) this._rootSequence?.syncFrame();
3009
3079
  this._synced = false;
3010
3080
  this._feedTimeFilters();
3011
- PIXI.Culler.shared.cull(app.stage, app.renderer.screen, false);
3081
+ pixi_js.Culler.shared.cull(app.stage, app.renderer.screen, false);
3012
3082
  app.renderer.render({ container: app.stage });
3013
3083
  }
3014
3084
  _requireReady(what) {
@@ -3329,9 +3399,9 @@ function countLayers(spec) {
3329
3399
  }
3330
3400
  var BY = ["chars", "words", "lines"];
3331
3401
  var ALIGN = ["left", "center", "right"];
3332
- var widthOf = (text, style) => PIXI.CanvasTextMetrics.measureText(text, style).width;
3402
+ var widthOf = (text, style) => pixi_js.CanvasTextMetrics.measureText(text, style).width;
3333
3403
  function measureText(text, style = {}) {
3334
- const m = PIXI.CanvasTextMetrics.measureText(text, new PIXI.TextStyle(style));
3404
+ const m = pixi_js.CanvasTextMetrics.measureText(text, new pixi_js.TextStyle(style));
3335
3405
  return { width: m.width, height: m.height, lines: text.split("\n").length };
3336
3406
  }
3337
3407
  function splitText(text, style = {}, opts = {}) {
@@ -3353,8 +3423,8 @@ function splitText(text, style = {}, opts = {}) {
3353
3423
  if (typeof v !== "number" || !Number.isFinite(v)) throw new Error(`splitText(): ${n} must be a number of pixels (e.g. ${n}: 640), got ${JSON.stringify(v)}: the pieces are placed by measuring, so an expression such as 'GW/2' cannot be used here. \`y\` is the top of the line.`);
3354
3424
  }
3355
3425
  if (text === "") return [];
3356
- const ts = new PIXI.TextStyle(style);
3357
- const lineHeight = PIXI.CanvasTextMetrics.measureText("M", ts).lineHeight ?? PIXI.CanvasTextMetrics.measureText("M", ts).height;
3426
+ const ts = new pixi_js.TextStyle(style);
3427
+ const lineHeight = pixi_js.CanvasTextMetrics.measureText("M", ts).lineHeight ?? pixi_js.CanvasTextMetrics.measureText("M", ts).height;
3358
3428
  const sentinel = widthOf("|", ts);
3359
3429
  const out = [];
3360
3430
  text.split("\n").forEach((line, lineNo) => {
@@ -3378,6 +3448,12 @@ function splitText(text, style = {}, opts = {}) {
3378
3448
  return out;
3379
3449
  }
3380
3450
 
3451
+ // src/presets/_ease.ts
3452
+ function parseEase2(name) {
3453
+ chunkRQMI7EJT_cjs.checkEase(name, "a preset");
3454
+ return chunkRQMI7EJT_cjs.parseEase(name);
3455
+ }
3456
+
3381
3457
  // src/presets/kenBurns.ts
3382
3458
  var KEN_BURNS_KEYS = ["asset", "name", "at", "duration", "fit", "ease", "motion", "origin", "zoom", "direction", "angle", "from", "to"];
3383
3459
  function kenBurns(opts) {
@@ -3490,10 +3566,6 @@ function kenBurns(opts) {
3490
3566
  function clamp(v, lo, hi) {
3491
3567
  return Math.max(lo, Math.min(hi, v));
3492
3568
  }
3493
- function parseEase(name) {
3494
- chunkWPXDRSGN_cjs.checkEase(name, "a preset");
3495
- return gsap.gsap.parseEase(name);
3496
- }
3497
3569
 
3498
3570
  // src/presets/orbit.ts
3499
3571
  var ORBIT_KEYS = ["duration", "degrees", "start", "radius", "center", "width", "height", "fov", "ease", "dollyZoom", "at", "name", "stepsPerSecond"];
@@ -3514,17 +3586,17 @@ function orbit(opts) {
3514
3586
  throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
3515
3587
  }
3516
3588
  const [cx, cy] = opts.center ?? [width / 2, height / 2];
3517
- const fixedR = opts.radius ?? chunkWPXDRSGN_cjs.homeDistance(height, fov ?? chunkWPXDRSGN_cjs.DEFAULT_FOV);
3589
+ const fixedR = opts.radius ?? chunkRQMI7EJT_cjs.homeDistance(height, fov ?? chunkRQMI7EJT_cjs.DEFAULT_FOV);
3518
3590
  const start = opts.start ?? -degrees / 2;
3519
3591
  const steps = Math.max(1, Math.round(duration * stepsPerSecond));
3520
- const easeFn = parseEase(ease);
3521
- const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
3592
+ const easeFn = parseEase2(ease);
3593
+ const dollyEase = dolly ? parseEase2(dolly.ease ?? ease) : null;
3522
3594
  const pos = (i) => {
3523
3595
  const p = i / steps;
3524
- const a = (start + degrees * easeFn(p)) * chunkWPXDRSGN_cjs.DEG;
3596
+ const a = (start + degrees * easeFn(p)) * chunkRQMI7EJT_cjs.DEG;
3525
3597
  if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
3526
3598
  const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
3527
- const R = chunkWPXDRSGN_cjs.homeDistance(height, f);
3599
+ const R = chunkRQMI7EJT_cjs.homeDistance(height, f);
3528
3600
  return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
3529
3601
  };
3530
3602
  const keyframes = [];
@@ -3579,7 +3651,7 @@ function particles(opts) {
3579
3651
  const round3 = (v) => Math.round(v * 1e6) / 1e6;
3580
3652
  const out = [];
3581
3653
  for (let i = 0; i < count; i++) {
3582
- const r = chunkWPXDRSGN_cjs.random(seed * 1000003 + i * 7919 + 17);
3654
+ const r = chunkRQMI7EJT_cjs.random(seed * 1000003 + i * 7919 + 17);
3583
3655
  const pick = ([a2, b]) => a2 + r() * (b - a2);
3584
3656
  const born = at + r() * emit;
3585
3657
  const lifetime = pick(life);
@@ -3592,7 +3664,7 @@ function particles(opts) {
3592
3664
  const turn = spin ? pick(spin) : 0;
3593
3665
  const startAngle = spin ? r() * 360 : 0;
3594
3666
  const swayAmp = sway?.amp ?? 0, swayFreq = sway?.freq ?? 1;
3595
- const n0 = sway ? chunkWPXDRSGN_cjs.noise(0, seed * 1000003 + i) : 0;
3667
+ const n0 = sway ? chunkRQMI7EJT_cjs.noise(0, seed * 1000003 + i) : 0;
3596
3668
  const at_ = (t) => {
3597
3669
  const axis = (p0, v0, acc) => {
3598
3670
  if (drag > 0) {
@@ -3601,7 +3673,7 @@ function particles(opts) {
3601
3673
  }
3602
3674
  return p0 + v0 * t + 0.5 * acc * t * t;
3603
3675
  };
3604
- const sw = sway ? swayAmp * (chunkWPXDRSGN_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
3676
+ const sw = sway ? swayAmp * (chunkRQMI7EJT_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
3605
3677
  return { x: axis(x0, vx, wind) + sw, y: axis(y0, vy, gravity) };
3606
3678
  };
3607
3679
  const kfs = [];
@@ -3663,7 +3735,7 @@ function followPath(opts) {
3663
3735
  if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
3664
3736
  const segments = [];
3665
3737
  let total = 0;
3666
- for (const line of chunkWPXDRSGN_cjs.flattenSvgPath(d)) {
3738
+ for (const line of chunkRQMI7EJT_cjs.flattenSvgPath(d)) {
3667
3739
  const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
3668
3740
  for (let i = 2; i < p.length; i += 2) {
3669
3741
  const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
@@ -3688,7 +3760,7 @@ function followPath(opts) {
3688
3760
  const t = Math.min(Math.max((s - g.start) / g.len, 0), 1);
3689
3761
  return { x: g.x0 + (g.x1 - g.x0) * t, y: g.y0 + (g.y1 - g.y0) * t, heading: Math.atan2(g.y1 - g.y0, g.x1 - g.x0) * 180 / Math.PI };
3690
3762
  };
3691
- const shape = parseEase(ease);
3763
+ const shape = parseEase2(ease);
3692
3764
  const round3 = (v) => Math.round(v * 1e6) / 1e6;
3693
3765
  let turn = 0;
3694
3766
  const sample = (k) => {
@@ -3765,7 +3837,7 @@ function cameraPath(opts) {
3765
3837
  const a = curve[i], b = curve[i + 1];
3766
3838
  return [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
3767
3839
  };
3768
- const shape = parseEase(ease);
3840
+ const shape = parseEase2(ease);
3769
3841
  const round3 = (v) => Math.round(v * 1e6) / 1e6;
3770
3842
  const sample = (k) => {
3771
3843
  const p = from + (to - from) * shape(k / steps);
@@ -3807,7 +3879,7 @@ function stagger(items, options = {}) {
3807
3879
  const dist2 = distances(n, from, grid, seed);
3808
3880
  const max = dist2.reduce((m, d) => Math.max(m, d), 0);
3809
3881
  const total = amount !== void 0 ? amount : (each ?? 0.1) * max;
3810
- const shape = parseEase(ease);
3882
+ const shape = parseEase2(ease);
3811
3883
  const clamp01 = (v) => Math.min(1, Math.max(0, v));
3812
3884
  const delays = dist2.map((d) => max === 0 ? 0 : Math.round(total * clamp01(shape(d / max)) * 1e6) / 1e6);
3813
3885
  if (isCount) return delays;
@@ -3817,7 +3889,7 @@ function distances(n, from, grid, seed) {
3817
3889
  if (n === 0) return [];
3818
3890
  if (from === "random") {
3819
3891
  const order = Array.from({ length: n }, (_, i) => i);
3820
- const r = chunkWPXDRSGN_cjs.random(seed);
3892
+ const r = chunkRQMI7EJT_cjs.random(seed);
3821
3893
  for (let i = n - 1; i > 0; i--) {
3822
3894
  const j = Math.floor(r() * (i + 1));
3823
3895
  [order[i], order[j]] = [order[j], order[i]];
@@ -3879,7 +3951,7 @@ function wiggle(opts) {
3879
3951
  to[n] = p.around;
3880
3952
  return;
3881
3953
  }
3882
- const off = (chunkWPXDRSGN_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
3954
+ const off = (chunkRQMI7EJT_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
3883
3955
  to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
3884
3956
  });
3885
3957
  out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
@@ -4354,19 +4426,19 @@ function withFade(spec, opts) {
4354
4426
 
4355
4427
  Object.defineProperty(exports, "noise", {
4356
4428
  enumerable: true,
4357
- get: function () { return chunkWPXDRSGN_cjs.noise; }
4429
+ get: function () { return chunkRQMI7EJT_cjs.noise; }
4358
4430
  });
4359
4431
  Object.defineProperty(exports, "rand", {
4360
4432
  enumerable: true,
4361
- get: function () { return chunkWPXDRSGN_cjs.rand; }
4433
+ get: function () { return chunkRQMI7EJT_cjs.rand; }
4362
4434
  });
4363
4435
  Object.defineProperty(exports, "random", {
4364
4436
  enumerable: true,
4365
- get: function () { return chunkWPXDRSGN_cjs.random; }
4437
+ get: function () { return chunkRQMI7EJT_cjs.random; }
4366
4438
  });
4367
4439
  Object.defineProperty(exports, "registerSequenceType", {
4368
4440
  enumerable: true,
4369
- get: function () { return chunkWPXDRSGN_cjs.registerSequenceType; }
4441
+ get: function () { return chunkRQMI7EJT_cjs.registerSequenceType; }
4370
4442
  });
4371
4443
  exports.Movie = Movie;
4372
4444
  exports.animateText = animateText;
@@ -4376,6 +4448,7 @@ exports.cameraPath = cameraPath;
4376
4448
  exports.computeEnvelope = computeEnvelope;
4377
4449
  exports.deck = deck;
4378
4450
  exports.dismissLoader = dismissLoader;
4451
+ exports.ease = parseEase2;
4379
4452
  exports.failLoader = failLoader;
4380
4453
  exports.followPath = followPath;
4381
4454
  exports.kenBurns = kenBurns;