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/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var chunk555URQHQ_cjs = require('./chunk-555URQHQ.cjs');
4
- var chunkWPXDRSGN_cjs = require('./chunk-WPXDRSGN.cjs');
3
+ var chunkIIDBEYQH_cjs = require('./chunk-IIDBEYQH.cjs');
4
+ var chunkA225HYSY_cjs = require('./chunk-A225HYSY.cjs');
5
5
  var chunk3DLYAPK7_cjs = require('./chunk-3DLYAPK7.cjs');
6
6
  var chunkECA2WNRX_cjs = require('./chunk-ECA2WNRX.cjs');
7
7
  var chunkTWZNOUM7_cjs = require('./chunk-TWZNOUM7.cjs');
@@ -779,24 +779,70 @@ function resolveRenderOptions(o) {
779
779
  };
780
780
  }
781
781
 
782
- // src/core/Renderer.ts
783
- var VIDEO_CODEC_BY_FORMAT = {
784
- mp4: "avc",
785
- mov: "avc",
786
- webm: "vp9",
787
- mkv: "vp9"
782
+ // src/core/renderOptions.ts
783
+ var QUALITY_NAMES = ["very-low", "low", "medium", "high", "very-high"];
784
+ function parseBitrate(v) {
785
+ if (v === void 0 || v === null) return {};
786
+ if (typeof v === "string" && QUALITY_NAMES.includes(v)) return { quality: v };
787
+ if (typeof v === "number" && Number.isFinite(v) && v > 0) return { bps: Math.round(v) };
788
+ const m = typeof v === "string" ? /^\s*(\d+(?:\.\d+)?)\s*([kKmM]?)\s*$/.exec(v) : null;
789
+ if (m) {
790
+ const n = Number(m[1]) * { "": 1, k: 1e3, m: 1e6 }[m[2].toLowerCase()];
791
+ if (n > 0) return { bps: Math.round(n) };
792
+ }
793
+ throw new Error(`pixi-effects: bitrate ${JSON.stringify(v)}: use a quality (${QUALITY_NAMES.join(", ")}) or bits a second (8000000, '8M', '800k')`);
794
+ }
795
+ var AUDIO_FORMATS = ["wav", "ogg"];
796
+ var isAudioFormat = (f) => AUDIO_FORMATS.includes(f);
797
+ var VIDEO_CODEC_PREFERENCE = {
798
+ mp4: ["avc", "hevc", "vp9", "av1"],
799
+ mov: ["avc", "hevc"],
800
+ webm: ["vp9", "av1", "vp8"],
801
+ mkv: ["vp9", "avc", "hevc", "av1", "vp8"]
788
802
  };
789
- var AUDIO_CODEC_BY_FORMAT = {
790
- mp4: "aac",
791
- mov: "aac",
792
- webm: "opus",
793
- mkv: "opus"
803
+ var CODEC_ALIASES = {
804
+ h264: "avc",
805
+ "h.264": "avc",
806
+ x264: "avc",
807
+ avc1: "avc",
808
+ h265: "hevc",
809
+ "h.265": "hevc",
810
+ x265: "hevc",
811
+ hvc1: "hevc",
812
+ hev1: "hevc",
813
+ vp09: "vp9",
814
+ "vp-9": "vp9",
815
+ av01: "av1",
816
+ vp80: "vp8",
817
+ "vp-8": "vp8"
794
818
  };
819
+ async function chooseVideoCodec(a) {
820
+ const held = a.supported ?? VIDEO_CODEC_PREFERENCE[a.fmt];
821
+ const order = VIDEO_CODEC_PREFERENCE[a.fmt].filter((c) => held.includes(c));
822
+ const firstThatWorks = async (list) => {
823
+ for (const c of list) if (await a.canEncode(c)) return c;
824
+ return null;
825
+ };
826
+ if (a.requested) {
827
+ const alias = CODEC_ALIASES[a.requested.toLowerCase()];
828
+ if (alias) throw new Error(`pixi-effects: render({ video: { codec: "${a.requested}" } }): "${a.requested}" is not a codec name here; did you mean "${alias}"?`);
829
+ if (!order.includes(a.requested)) throw new Error(`pixi-effects: render(): "${a.requested}" cannot go in ${a.fmt} (${a.fmt} holds ${order.join(", ")})`);
830
+ if (await a.canEncode(a.requested)) return { codec: a.requested };
831
+ const alt = await firstThatWorks(order.filter((c) => c !== a.requested));
832
+ 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(", ") + "."));
833
+ }
834
+ const chosen = await firstThatWorks(order);
835
+ 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`);
836
+ return chosen === order[0] ? { codec: chosen } : { codec: chosen, fellBackFrom: order[0] };
837
+ }
838
+
839
+ // src/core/Renderer.ts
795
840
  var AUDIO_PREFERENCE = {
796
841
  mp4: ["aac", "opus", "mp3", "flac"],
797
842
  mov: ["aac", "mp3"],
798
843
  webm: ["opus", "vorbis"],
799
- mkv: ["opus", "vorbis", "aac", "flac", "mp3"]
844
+ mkv: ["opus", "vorbis", "aac", "flac", "mp3"],
845
+ ogg: ["opus", "vorbis", "flac"]
800
846
  };
801
847
  async function chooseAudioCodec(fmt, requested, container, audio, bitrate) {
802
848
  const supported = container.getSupportedAudioCodecs?.();
@@ -821,6 +867,10 @@ var qualityMap = {
821
867
  "high": mediabunny.QUALITY_HIGH,
822
868
  "very-high": mediabunny.QUALITY_VERY_HIGH
823
869
  };
870
+ function bitrateOf(v, fallback) {
871
+ const b = parseBitrate(v);
872
+ return b.bps ?? (b.quality ? qualityMap[b.quality] : fallback);
873
+ }
824
874
  function makeOutputFormat(name) {
825
875
  switch (name) {
826
876
  case "mp4":
@@ -840,19 +890,47 @@ function sliceAudio(buffer, fromSec, toSec, fadeIn, fadeOut) {
840
890
  cut.forEach((data, c) => out.copyToChannel(data, c));
841
891
  return out;
842
892
  }
893
+ async function exportAudioOnly(movie, options, fmt, range2) {
894
+ if (!movie.audioBuffer) {
895
+ 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`);
896
+ }
897
+ if (options.video) console.warn(`pixi-effects: render({ format: '${fmt}' }): video options are ignored, only the sound is written`);
898
+ const audio = range2.partial ? sliceAudio(movie.audioBuffer, range2.fromSec, range2.toSec, range2.fromFrame > 0, range2.toFrame < movie.totalFrames) : movie.audioBuffer;
899
+ const container = fmt === "wav" ? new mediabunny.WavOutputFormat() : new mediabunny.OggOutputFormat();
900
+ let codec;
901
+ if (fmt === "wav") {
902
+ codec = options.audio?.codec ?? "pcm-s16";
903
+ const held = container.getSupportedAudioCodecs();
904
+ if (!held.includes(codec)) throw new Error(`pixi-effects: render({ format: 'wav', audio: { codec: "${codec}" } }): wav holds ${held.join(", ")} (the usual is pcm-s16)`);
905
+ } else {
906
+ codec = await chooseAudioCodec("ogg", options.audio?.codec, container, audio, bitrateOf(options.audio?.bitrate, mediabunny.QUALITY_HIGH));
907
+ }
908
+ const output = new mediabunny.Output({ format: container, target: new mediabunny.BufferTarget() });
909
+ const source = new mediabunny.AudioBufferSource({ codec, ...fmt === "wav" ? {} : { bitrate: bitrateOf(options.audio?.bitrate, mediabunny.QUALITY_HIGH) } });
910
+ output.addAudioTrack(source);
911
+ movie.emit("progress", { progress: 0, frame: range2.fromFrame, totalFrames: movie.totalFrames });
912
+ await output.start();
913
+ await source.add(audio);
914
+ await source.close();
915
+ await output.finalize();
916
+ movie.emit("progress", { progress: 100, frame: range2.toFrame, totalFrames: movie.totalFrames });
917
+ return new Blob([output.target.buffer], { type: output.format.mimeType });
918
+ }
843
919
  async function exportFrames(movie, options = {}) {
844
920
  const fmt = options.format ?? "mp4";
845
921
  const eff = resolveRenderOptions(options);
846
922
  const range2 = resolveRange(options.range, { frameRate: movie.frameRate, totalFrames: movie.totalFrames, duration: movie.duration, rows: typeof options.range === "string" ? movie.timelineData().rows : void 0 });
923
+ if (isAudioFormat(fmt)) return exportAudioOnly(movie, options, fmt, range2);
924
+ 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)`);
925
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.render({ video })", options.video, ["codec", "bitrate", "hardware", "keyFrameInterval"]);
926
+ chunkTWZNOUM7_cjs.warnUnknownOptions("movie.render({ audio })", options.audio, ["codec", "bitrate"]);
927
+ const videoBitrate = bitrateOf(eff.bitrate ?? "high", mediabunny.QUALITY_HIGH);
847
928
  const opts = {
848
929
  format: fmt,
849
- video: {
850
- codec: options.video?.codec ?? VIDEO_CODEC_BY_FORMAT[fmt],
851
- bitrate: qualityMap[eff.bitrate ?? "high"] ?? mediabunny.QUALITY_HIGH
852
- },
930
+ video: { codec: "", bitrate: videoBitrate },
853
931
  audio: {
854
- codec: options.audio?.codec ?? AUDIO_CODEC_BY_FORMAT[fmt],
855
- bitrate: qualityMap[options.audio?.bitrate ?? "high"] ?? mediabunny.QUALITY_HIGH
932
+ codec: options.audio?.codec ?? (fmt === "mp4" || fmt === "mov" ? "aac" : "opus"),
933
+ bitrate: bitrateOf(options.audio?.bitrate, mediabunny.QUALITY_HIGH)
856
934
  }
857
935
  };
858
936
  const container = makeOutputFormat(opts.format);
@@ -867,9 +945,23 @@ async function exportFrames(movie, options = {}) {
867
945
  const blurCanvas = mb ? Object.assign(document.createElement("canvas"), { width: stage.width, height: stage.height }) : null;
868
946
  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
947
  const smallCtx = small?.getContext("2d") ?? null;
870
- const canvasSource = new mediabunny.CanvasSource(small ?? blurCanvas ?? stage, {
948
+ const picture = small ?? blurCanvas ?? stage;
949
+ const chosen = await chooseVideoCodec({
950
+ fmt,
951
+ requested: options.video?.codec,
952
+ supported: container.getSupportedVideoCodecs(),
953
+ canEncode: (c) => mediabunny.canEncodeVideo(c, { width: picture.width, height: picture.height, bitrate: opts.video.bitrate })
954
+ });
955
+ 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).`);
956
+ opts.video.codec = chosen.codec;
957
+ const hardware = options.video?.hardware;
958
+ if (hardware !== void 0 && !["no-preference", "prefer-hardware", "prefer-software"].includes(hardware)) {
959
+ throw new Error(`pixi-effects: render({ video: { hardware: "${String(hardware)}" } }): use 'prefer-hardware', 'prefer-software' or 'no-preference'`);
960
+ }
961
+ const canvasSource = new mediabunny.CanvasSource(picture, {
871
962
  codec: opts.video.codec,
872
- bitrate: opts.video.bitrate
963
+ bitrate: opts.video.bitrate,
964
+ ...hardware ? { hardwareAcceleration: hardware } : {}
873
965
  });
874
966
  output.addVideoTrack(canvasSource, { frameRate: movie.frameRate });
875
967
  if (audio) {
@@ -885,7 +977,9 @@ async function exportFrames(movie, options = {}) {
885
977
  await output.start();
886
978
  }
887
979
  movie.app.ticker.stop();
888
- const keyframeIntervalFrames = Math.max(1, Math.round(2 * movie.frameRate));
980
+ const interval = options.video?.keyFrameInterval ?? 2;
981
+ 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)`);
982
+ const keyframeIntervalFrames = Math.max(1, Math.round(interval * movie.frameRate));
889
983
  try {
890
984
  const count = Math.max(1, range2.toFrame - range2.fromFrame);
891
985
  for (let frame = range2.fromFrame; frame <= range2.toFrame; frame++) {
@@ -1407,8 +1501,8 @@ function expandTransitions(spec) {
1407
1501
  }
1408
1502
  const transitions = out.transitions;
1409
1503
  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;
1504
+ const remap = out.duration !== void 0 ? chunkA225HYSY_cjs.timeRemapOf(out) : null;
1505
+ const parentDuration = remap ? chunkA225HYSY_cjs.contentLength(remap, out.duration) : out.duration ?? Infinity;
1412
1506
  const compW = out.width;
1413
1507
  const compH = out.height;
1414
1508
  const threeDByName = new Set(sequences.filter((s) => s.name && s.threeD).map((s) => s.name));
@@ -1476,16 +1570,16 @@ function expandTransitions(spec) {
1476
1570
  if (toUses > 1) {
1477
1571
  throw new Error(`pixi-effects: ${tag} sequence "${t.to}" is used as \`to\` in more than one transition`);
1478
1572
  }
1479
- const tStart = chunkWPXDRSGN_cjs.resolveAt(t.at, parentDuration);
1573
+ const tStart = chunkA225HYSY_cjs.resolveAt(t.at, parentDuration);
1480
1574
  const tEnd = tStart + t.duration;
1481
1575
  const fromSeq = fromEntry.seq;
1482
- const fromStart = chunkWPXDRSGN_cjs.resolveAt(fromSeq.at, parentDuration);
1576
+ const fromStart = chunkA225HYSY_cjs.resolveAt(fromSeq.at, parentDuration);
1483
1577
  const fromEnd = fromStart + (fromSeq.duration ?? parentDuration);
1484
1578
  if (tStart < fromStart - EPS || tEnd > fromEnd + EPS) {
1485
1579
  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
1580
  }
1487
1581
  const toSeq = toEntry.seq;
1488
- const toStart = chunkWPXDRSGN_cjs.resolveAt(toSeq.at, parentDuration);
1582
+ const toStart = chunkA225HYSY_cjs.resolveAt(toSeq.at, parentDuration);
1489
1583
  const toEnd = toStart + (toSeq.duration ?? parentDuration);
1490
1584
  if (tStart < toStart - EPS || tEnd > toEnd + EPS) {
1491
1585
  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 +1639,7 @@ function wrapAsFullComposition(seq, compW, compH) {
1545
1639
  delete inner.at;
1546
1640
  delete inner.duration;
1547
1641
  const m = inner.mask;
1548
- const carriesMatte = m !== void 0 && chunk555URQHQ_cjs.maskSourceOf(m).kind === "refs";
1642
+ const carriesMatte = m !== void 0 && chunkIIDBEYQH_cjs.maskSourceOf(m).kind === "refs";
1549
1643
  if (carriesMatte) delete inner.mask;
1550
1644
  return {
1551
1645
  ...carriesMatte ? { mask: m } : {},
@@ -1872,7 +1966,7 @@ function inspectScene(root, frame, time, canvas, opts = {}) {
1872
1966
  const group = parentScene ?? (name !== void 0 && blending.has(name) ? name : void 0);
1873
1967
  if (group) scene.set(info, group);
1874
1968
  if (zero || seq.showsNothingYet) scaledToNothing.add(info);
1875
- if (seq instanceof chunk555URQHQ_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1969
+ if (seq instanceof chunkIIDBEYQH_cjs.CompositionSequence) walk2(seq, prefix + label + "/", insideThreeD || threeD, visible, group, moving, zero);
1876
1970
  });
1877
1971
  };
1878
1972
  walk2(root, "", false, true);
@@ -1933,10 +2027,10 @@ function walk(comp, parentStart, parentEnd, depth, prefix, rows, transitions, lo
1933
2027
  const start = parentStart + (seq.at ?? 0);
1934
2028
  const end = Math.min(parentEnd, seq.duration !== void 0 ? start + seq.duration : parentEnd);
1935
2029
  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);
2030
+ const keys = (seq.spec.keyframes ?? []).map((kf) => round(start + chunkA225HYSY_cjs.resolveAt(kf.at, span))).sort((a, b) => a - b).slice(0, MAX_KEYS);
1937
2031
  const row = { path: prefix + name, name, type: seq.spec.type, depth, start: round(start), end: round(end), keys, detail: detailOf(seq), ...local ? { local } : {} };
1938
2032
  const inner = [];
1939
- const isComp = seq instanceof chunk555URQHQ_cjs.CompositionSequence;
2033
+ const isComp = seq instanceof chunkIIDBEYQH_cjs.CompositionSequence;
1940
2034
  if (isComp) {
1941
2035
  const label = seq.remapLabel();
1942
2036
  walk(seq, label ? 0 : start, label ? seq.contentSpan : end, depth + 1, prefix + name + "/", inner, transitions, label ? `${name} ${label}` : local);
@@ -2646,7 +2740,7 @@ var Movie = class {
2646
2740
  height: options.composition.height ?? this.height,
2647
2741
  duration: options.composition.duration ?? this.duration
2648
2742
  } : void 0;
2649
- await chunkWPXDRSGN_cjs.ensureFilterLibrary(seededComposition);
2743
+ await chunkA225HYSY_cjs.ensureFilterLibrary(seededComposition);
2650
2744
  const userComposition = seededComposition ? expandTransitions(seededComposition) : void 0;
2651
2745
  const rootSeqSpec = {
2652
2746
  type: "composition",
@@ -2656,7 +2750,7 @@ var Movie = class {
2656
2750
  ...userComposition
2657
2751
  };
2658
2752
  if (userComposition) carryTransitionWindows(userComposition, rootSeqSpec);
2659
- const composition = new chunk555URQHQ_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
2753
+ const composition = new chunkIIDBEYQH_cjs.CompositionSequence(rootSeqSpec, null, rootShape);
2660
2754
  lp.begin("build", countLayers(rootSeqSpec));
2661
2755
  await composition.build();
2662
2756
  this._rootSequence = composition;
@@ -3491,7 +3585,7 @@ function clamp(v, lo, hi) {
3491
3585
  return Math.max(lo, Math.min(hi, v));
3492
3586
  }
3493
3587
  function parseEase(name) {
3494
- chunkWPXDRSGN_cjs.checkEase(name, "a preset");
3588
+ chunkA225HYSY_cjs.checkEase(name, "a preset");
3495
3589
  return gsap.gsap.parseEase(name);
3496
3590
  }
3497
3591
 
@@ -3514,17 +3608,17 @@ function orbit(opts) {
3514
3608
  throw new Error("pixi-effects: orbit() cannot combine `radius` with `dollyZoom` \u2014 the radius follows the animated fov");
3515
3609
  }
3516
3610
  const [cx, cy] = opts.center ?? [width / 2, height / 2];
3517
- const fixedR = opts.radius ?? chunkWPXDRSGN_cjs.homeDistance(height, fov ?? chunkWPXDRSGN_cjs.DEFAULT_FOV);
3611
+ const fixedR = opts.radius ?? chunkA225HYSY_cjs.homeDistance(height, fov ?? chunkA225HYSY_cjs.DEFAULT_FOV);
3518
3612
  const start = opts.start ?? -degrees / 2;
3519
3613
  const steps = Math.max(1, Math.round(duration * stepsPerSecond));
3520
3614
  const easeFn = parseEase(ease);
3521
3615
  const dollyEase = dolly ? parseEase(dolly.ease ?? ease) : null;
3522
3616
  const pos = (i) => {
3523
3617
  const p = i / steps;
3524
- const a = (start + degrees * easeFn(p)) * chunkWPXDRSGN_cjs.DEG;
3618
+ const a = (start + degrees * easeFn(p)) * chunkA225HYSY_cjs.DEG;
3525
3619
  if (!dolly) return { x: cx + fixedR * Math.sin(a), z: fixedR * Math.cos(a) };
3526
3620
  const f = dolly.from + (dolly.to - dolly.from) * dollyEase(p);
3527
- const R = chunkWPXDRSGN_cjs.homeDistance(height, f);
3621
+ const R = chunkA225HYSY_cjs.homeDistance(height, f);
3528
3622
  return { x: cx + R * Math.sin(a), z: R * Math.cos(a), fov: f };
3529
3623
  };
3530
3624
  const keyframes = [];
@@ -3579,7 +3673,7 @@ function particles(opts) {
3579
3673
  const round3 = (v) => Math.round(v * 1e6) / 1e6;
3580
3674
  const out = [];
3581
3675
  for (let i = 0; i < count; i++) {
3582
- const r = chunkWPXDRSGN_cjs.random(seed * 1000003 + i * 7919 + 17);
3676
+ const r = chunkA225HYSY_cjs.random(seed * 1000003 + i * 7919 + 17);
3583
3677
  const pick = ([a2, b]) => a2 + r() * (b - a2);
3584
3678
  const born = at + r() * emit;
3585
3679
  const lifetime = pick(life);
@@ -3592,7 +3686,7 @@ function particles(opts) {
3592
3686
  const turn = spin ? pick(spin) : 0;
3593
3687
  const startAngle = spin ? r() * 360 : 0;
3594
3688
  const swayAmp = sway?.amp ?? 0, swayFreq = sway?.freq ?? 1;
3595
- const n0 = sway ? chunkWPXDRSGN_cjs.noise(0, seed * 1000003 + i) : 0;
3689
+ const n0 = sway ? chunkA225HYSY_cjs.noise(0, seed * 1000003 + i) : 0;
3596
3690
  const at_ = (t) => {
3597
3691
  const axis = (p0, v0, acc) => {
3598
3692
  if (drag > 0) {
@@ -3601,7 +3695,7 @@ function particles(opts) {
3601
3695
  }
3602
3696
  return p0 + v0 * t + 0.5 * acc * t * t;
3603
3697
  };
3604
- const sw = sway ? swayAmp * (chunkWPXDRSGN_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
3698
+ const sw = sway ? swayAmp * (chunkA225HYSY_cjs.noise(t * swayFreq, seed * 1000003 + i) - n0) : 0;
3605
3699
  return { x: axis(x0, vx, wind) + sw, y: axis(y0, vy, gravity) };
3606
3700
  };
3607
3701
  const kfs = [];
@@ -3663,7 +3757,7 @@ function followPath(opts) {
3663
3757
  if (steps > MAX_STEPS) throw new Error(`followPath(): ${steps} samples is too many (max ${MAX_STEPS}); lower frameRate or duration`);
3664
3758
  const segments = [];
3665
3759
  let total = 0;
3666
- for (const line of chunkWPXDRSGN_cjs.flattenSvgPath(d)) {
3760
+ for (const line of chunkA225HYSY_cjs.flattenSvgPath(d)) {
3667
3761
  const p = line.closed ? [...line.pts, line.pts[0], line.pts[1]] : line.pts;
3668
3762
  for (let i = 2; i < p.length; i += 2) {
3669
3763
  const len = Math.hypot(p[i] - p[i - 2], p[i + 1] - p[i - 1]);
@@ -3817,7 +3911,7 @@ function distances(n, from, grid, seed) {
3817
3911
  if (n === 0) return [];
3818
3912
  if (from === "random") {
3819
3913
  const order = Array.from({ length: n }, (_, i) => i);
3820
- const r = chunkWPXDRSGN_cjs.random(seed);
3914
+ const r = chunkA225HYSY_cjs.random(seed);
3821
3915
  for (let i = n - 1; i > 0; i--) {
3822
3916
  const j = Math.floor(r() * (i + 1));
3823
3917
  [order[i], order[j]] = [order[j], order[i]];
@@ -3879,7 +3973,7 @@ function wiggle(opts) {
3879
3973
  to[n] = p.around;
3880
3974
  return;
3881
3975
  }
3882
- const off = (chunkWPXDRSGN_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
3976
+ const off = (chunkA225HYSY_cjs.rand(seed * 7919 + pi * 104729 + s * 31 + 1) * 2 - 1) * p.amp;
3883
3977
  to[n] = typeof p.around === "number" ? p.around + off : `(${p.around}) ${off < 0 ? "-" : "+"} ${Math.abs(off)}`;
3884
3978
  });
3885
3979
  out.push({ at: at + s * stepLen, to, duration: stepLen, ease });
@@ -4354,19 +4448,19 @@ function withFade(spec, opts) {
4354
4448
 
4355
4449
  Object.defineProperty(exports, "noise", {
4356
4450
  enumerable: true,
4357
- get: function () { return chunkWPXDRSGN_cjs.noise; }
4451
+ get: function () { return chunkA225HYSY_cjs.noise; }
4358
4452
  });
4359
4453
  Object.defineProperty(exports, "rand", {
4360
4454
  enumerable: true,
4361
- get: function () { return chunkWPXDRSGN_cjs.rand; }
4455
+ get: function () { return chunkA225HYSY_cjs.rand; }
4362
4456
  });
4363
4457
  Object.defineProperty(exports, "random", {
4364
4458
  enumerable: true,
4365
- get: function () { return chunkWPXDRSGN_cjs.random; }
4459
+ get: function () { return chunkA225HYSY_cjs.random; }
4366
4460
  });
4367
4461
  Object.defineProperty(exports, "registerSequenceType", {
4368
4462
  enumerable: true,
4369
- get: function () { return chunkWPXDRSGN_cjs.registerSequenceType; }
4463
+ get: function () { return chunkA225HYSY_cjs.registerSequenceType; }
4370
4464
  });
4371
4465
  exports.Movie = Movie;
4372
4466
  exports.animateText = animateText;