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.
- package/CHANGELOG.md +12 -0
- package/README.md +5 -5
- package/ai/chat-template.html +3 -3
- package/ai/tools/render.mjs +16 -11
- package/dist/Composition-3O7L2VL5.js +7 -0
- package/dist/{Composition-H4QA24MV.js.map → Composition-3O7L2VL5.js.map} +1 -1
- package/dist/Composition-EE3KEE2L.cjs +16 -0
- package/dist/{Composition-HM4YT5L7.cjs.map → Composition-EE3KEE2L.cjs.map} +1 -1
- package/dist/Controller.d.cts +1 -1
- package/dist/Controller.d.ts +1 -1
- package/dist/{Movie-i05Oh9mJ.d.cts → Movie-BWLLWRRe.d.cts} +10 -3
- package/dist/{Movie-DVeDTdnc.d.ts → Movie-BkP82KXS.d.ts} +10 -3
- package/dist/Presenter.d.cts +1 -1
- package/dist/Presenter.d.ts +1 -1
- package/dist/{chunk-WPXDRSGN.cjs → chunk-A225HYSY.cjs} +205 -27
- package/dist/chunk-A225HYSY.cjs.map +1 -0
- package/dist/{chunk-X3HB4DSR.js → chunk-FXAHNPBP.js} +205 -27
- package/dist/chunk-FXAHNPBP.js.map +1 -0
- package/dist/{chunk-555URQHQ.cjs → chunk-IIDBEYQH.cjs} +59 -59
- package/dist/{chunk-555URQHQ.cjs.map → chunk-IIDBEYQH.cjs.map} +1 -1
- package/dist/{chunk-GBUM7X2S.js → chunk-WMMZDPWK.js} +3 -3
- package/dist/{chunk-GBUM7X2S.js.map → chunk-WMMZDPWK.js.map} +1 -1
- package/dist/index.cjs +142 -48
- 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 +119 -25
- 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/api.md +11 -5
- package/docs/dsl.md +2 -0
- package/llms-full.txt +17 -9
- package/package.json +1 -1
- package/skills/pixi-effects/SKILL.md +1 -1
- package/skills/pixi-effects/reference/cheatsheet.md +3 -3
- package/skills/pixi-effects/template.html +6 -6
- package/dist/Composition-H4QA24MV.js +0 -7
- package/dist/Composition-HM4YT5L7.cjs +0 -16
- package/dist/chunk-WPXDRSGN.cjs.map +0 -1
- package/dist/chunk-X3HB4DSR.js.map +0 -1
|
@@ -373,19 +373,29 @@ function evaluateExpr(source, scope) {
|
|
|
373
373
|
// src/expr/normalizeProps.ts
|
|
374
374
|
function normalizeProps(input, scope, options = {}) {
|
|
375
375
|
const skip = new Set(options.skipKeys ?? []);
|
|
376
|
-
return walk(input, scope, skip, null);
|
|
376
|
+
return walk(input, scope, skip, null, options);
|
|
377
377
|
}
|
|
378
|
-
|
|
378
|
+
var RELATIVE = /^\s*([+-])=([\s\S]*)$/;
|
|
379
|
+
function walk(value, scope, skip, currentKey, options) {
|
|
379
380
|
if (Array.isArray(value)) {
|
|
380
|
-
return value.map((v) => walk(v, scope, skip, currentKey));
|
|
381
|
+
return value.map((v) => walk(v, scope, skip, currentKey, options));
|
|
381
382
|
}
|
|
382
383
|
if (value !== null && typeof value === "object") {
|
|
383
384
|
const out = {};
|
|
384
385
|
for (const k of Object.keys(value)) {
|
|
385
|
-
out[k] = walk(value[k], scope, skip, k);
|
|
386
|
+
out[k] = walk(value[k], scope, skip, k, options);
|
|
386
387
|
}
|
|
387
388
|
return out;
|
|
388
389
|
}
|
|
390
|
+
if (typeof value === "string" && !(currentKey !== null && skip.has(currentKey))) {
|
|
391
|
+
const rel = RELATIVE.exec(value);
|
|
392
|
+
if (rel) {
|
|
393
|
+
const n = evaluateExpr(rel[2].trim(), scope);
|
|
394
|
+
if (options.relative === "allow") return `${rel[1]}=${n}`;
|
|
395
|
+
console.warn(`pixi-effects: "${value.trim()}"${currentKey ? ` (${currentKey})` : ""} is a relative value (measured from where the layer is): it works in a keyframe's to / from / set, not in ${options.where ?? "an initial or a style"}; it is read as the number ${rel[1] === "-" ? -n : n}`);
|
|
396
|
+
return rel[1] === "-" ? -n : n;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
389
399
|
if (isExpr(value) && !(currentKey !== null && skip.has(currentKey))) {
|
|
390
400
|
if (looksLikeColorString(value)) return value;
|
|
391
401
|
return evaluateExpr(value, scope);
|
|
@@ -616,7 +626,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
616
626
|
const kf = normalizeKeyframe(raw, parentDuration);
|
|
617
627
|
const at = offset + kf.at;
|
|
618
628
|
if (kf.kind === "set") {
|
|
619
|
-
const resolved = normalizeProps(kf.set, scope, { skipKeys });
|
|
629
|
+
const resolved = normalizeProps(kf.set, scope, { skipKeys, relative: "allow" });
|
|
620
630
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
621
631
|
for (const r of routed) timeline.set(r.target, { [r.prop]: r.value }, at);
|
|
622
632
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
@@ -627,7 +637,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
627
637
|
timeline.set(f, props, at);
|
|
628
638
|
}
|
|
629
639
|
} else if (kf.kind === "to") {
|
|
630
|
-
const resolved = normalizeProps(kf.to, scope, { skipKeys });
|
|
640
|
+
const resolved = normalizeProps(kf.to, scope, { skipKeys, relative: "allow" });
|
|
631
641
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
632
642
|
for (const r of routed)
|
|
633
643
|
timeline.to(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
@@ -640,7 +650,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
640
650
|
timeline.to(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
641
651
|
}
|
|
642
652
|
} else if (kf.kind === "from") {
|
|
643
|
-
const resolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
653
|
+
const resolved = normalizeProps(kf.from, scope, { skipKeys, relative: "allow" });
|
|
644
654
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
645
655
|
for (const r of routed)
|
|
646
656
|
timeline.from(r.target, { [r.prop]: r.value, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
@@ -653,8 +663,8 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
653
663
|
timeline.from(f, { ...props, duration: kf.duration, ease: kf.ease, ...kf.loop }, at);
|
|
654
664
|
}
|
|
655
665
|
} else {
|
|
656
|
-
const fromResolved = normalizeProps(kf.from, scope, { skipKeys });
|
|
657
|
-
const toResolved = normalizeProps(kf.to, scope, { skipKeys });
|
|
666
|
+
const fromResolved = normalizeProps(kf.from, scope, { skipKeys, where: "the from side of a from + to keyframe" });
|
|
667
|
+
const toResolved = normalizeProps(kf.to, scope, { skipKeys, relative: "allow" });
|
|
658
668
|
const fromRouted = splitRouted(fromResolved, routers);
|
|
659
669
|
const toRouted = splitRouted(toResolved, routers);
|
|
660
670
|
const fromByKey = new Map(fromRouted.routed.map((r) => [r.key, r]));
|
|
@@ -704,7 +714,7 @@ function applyKeyframes(timeline, target, keyframes, parentDuration, scope, skip
|
|
|
704
714
|
}
|
|
705
715
|
function applyInitial(target, initial, scope, skipKeys = [], routers) {
|
|
706
716
|
if (!initial) return;
|
|
707
|
-
const resolved = normalizeProps(initial, scope, { skipKeys });
|
|
717
|
+
const resolved = normalizeProps(initial, scope, { skipKeys, where: "initial" });
|
|
708
718
|
const { rest, routed } = splitRouted(resolved, routers);
|
|
709
719
|
for (const r of routed) gsap.set(r.target, { [r.prop]: r.value });
|
|
710
720
|
const { ownProps, filterProps } = partitionProps(rest);
|
|
@@ -3046,6 +3056,9 @@ var BUDGET_BYTES = 96 * 1024 * 1024;
|
|
|
3046
3056
|
var MIN_HELD = 3;
|
|
3047
3057
|
var JUMP_SECONDS = 1;
|
|
3048
3058
|
var EPS = 1e-6;
|
|
3059
|
+
var LOW_BEHIND = 14;
|
|
3060
|
+
var MIN_HELD_TO_READ_BACK = 20;
|
|
3061
|
+
var MIN_HELD_TO_READ_START = 9;
|
|
3049
3062
|
function reportDecodeError(err, time) {
|
|
3050
3063
|
const isTransient = err instanceof DOMException && (err.name === "EncodingError" || err.name === "NotSupportedError");
|
|
3051
3064
|
if (isTransient) console.debug("pixi-effects: transient video decode failure at", time, "s \u2014", err.name);
|
|
@@ -3064,9 +3077,22 @@ var FrameCache = class {
|
|
|
3064
3077
|
_held = 0;
|
|
3065
3078
|
_lock = Promise.resolve();
|
|
3066
3079
|
_lastTime = null;
|
|
3080
|
+
_dir = 0;
|
|
3081
|
+
_gen = 0;
|
|
3082
|
+
_backBusy = false;
|
|
3083
|
+
_backGen = 0;
|
|
3084
|
+
_standbyBusy = false;
|
|
3085
|
+
/** A second pass at the start of the file, ready for the moment a looping video comes round. */
|
|
3086
|
+
_standby = null;
|
|
3087
|
+
_duration;
|
|
3088
|
+
_loop;
|
|
3089
|
+
/** How often it had to wait for a decoder (`restarts`, `singles`) and how many reads ahead it made: for tests and for `check`. */
|
|
3090
|
+
stats = { restarts: 0, singles: 0, prefetches: 0 };
|
|
3067
3091
|
constructor(sink, options = {}) {
|
|
3068
3092
|
this.sink = sink;
|
|
3069
3093
|
this.capacity = options.capacity ?? 30;
|
|
3094
|
+
this._duration = options.duration ?? null;
|
|
3095
|
+
this._loop = !!options.loop;
|
|
3070
3096
|
}
|
|
3071
3097
|
/** How many decoded frames are held right now (the sequential reader's own list, plus the exact-time cache of the old path). */
|
|
3072
3098
|
get heldFrames() {
|
|
@@ -3136,24 +3162,157 @@ var FrameCache = class {
|
|
|
3136
3162
|
return null;
|
|
3137
3163
|
}
|
|
3138
3164
|
async _sequentialAt(time) {
|
|
3165
|
+
const last = this._lastTime;
|
|
3166
|
+
this._lastTime = time;
|
|
3167
|
+
if (last !== null && Math.abs(time - last) <= JUMP_SECONDS) this._dir = time > last + EPS ? 1 : time < last - EPS ? -1 : this._dir;
|
|
3168
|
+
let frame;
|
|
3139
3169
|
try {
|
|
3140
|
-
|
|
3141
|
-
this._lastTime = time;
|
|
3142
|
-
const hit = this._covering(time);
|
|
3143
|
-
if (hit) return hit.frame;
|
|
3144
|
-
if (last === null || Math.abs(time - last) > JUMP_SECONDS) return await this._single(time);
|
|
3145
|
-
const cur = this._cur;
|
|
3146
|
-
if (this._iter && cur && time >= cur.ts && time - cur.ts <= JUMP_SECONDS) return await this._advance(time);
|
|
3147
|
-
const backwards = !!cur && time < cur.ts;
|
|
3148
|
-
return await this._restart(time, backwards ? Math.max(0, time - this._held / 30) : time);
|
|
3170
|
+
frame = await this._serve(time, last);
|
|
3149
3171
|
} catch (err) {
|
|
3150
3172
|
reportDecodeError(err, time);
|
|
3151
3173
|
await this._closeIter();
|
|
3152
3174
|
return null;
|
|
3153
3175
|
}
|
|
3176
|
+
this._maybeReadAhead(time);
|
|
3177
|
+
return frame;
|
|
3178
|
+
}
|
|
3179
|
+
async _serve(time, last) {
|
|
3180
|
+
const hit = this._covering(time);
|
|
3181
|
+
if (hit) return hit.frame;
|
|
3182
|
+
const sb = this._standby;
|
|
3183
|
+
if (sb && time >= sb.cur.ts - EPS && time - sb.cur.ts <= JUMP_SECONDS && (!this._iter || !this._cur || this._cur.ts > time + JUMP_SECONDS)) return await this._adoptStandby(time);
|
|
3184
|
+
if (last === null || Math.abs(time - last) > JUMP_SECONDS) return await this._single(time);
|
|
3185
|
+
const cur = this._cur;
|
|
3186
|
+
if (this._iter && cur && time >= cur.ts && time - cur.ts <= JUMP_SECONDS) return await this._advance(time);
|
|
3187
|
+
const backwards = !!cur && time < cur.ts;
|
|
3188
|
+
return await this._restart(time, backwards ? Math.max(0, time - Math.max(1, this._held - 1) / 30) : time);
|
|
3189
|
+
}
|
|
3190
|
+
// ── reading ahead ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
|
|
3191
|
+
_maybeReadAhead(time) {
|
|
3192
|
+
if (this._held === 0) return;
|
|
3193
|
+
if (this._dir === -1) {
|
|
3194
|
+
this._dropStandby();
|
|
3195
|
+
let behind = 0, passed = 0, earliest = Infinity;
|
|
3196
|
+
for (const e of this._frames) {
|
|
3197
|
+
if (e.ts < time - EPS) behind++;
|
|
3198
|
+
else if (e.ts > time + EPS) passed++;
|
|
3199
|
+
if (e.ts < earliest) earliest = e.ts;
|
|
3200
|
+
}
|
|
3201
|
+
if (this._held >= MIN_HELD_TO_READ_BACK && behind < LOW_BEHIND && passed >= 3 && earliest > EPS && !this._backBusy) void this._readBack(earliest, passed);
|
|
3202
|
+
} else if (this._held >= MIN_HELD_TO_READ_START && this._dir === 1 && this._loop && this._duration !== null && time >= this._duration - JUMP_SECONDS && !this._standby && !this._standbyBusy) {
|
|
3203
|
+
void this._readStart();
|
|
3204
|
+
}
|
|
3205
|
+
}
|
|
3206
|
+
/** In the background: the window of frames before the earliest one held (reverse play comes to it next). */
|
|
3207
|
+
async _readBack(earliest, room) {
|
|
3208
|
+
this._backBusy = true;
|
|
3209
|
+
this.stats.prefetches++;
|
|
3210
|
+
const gen = this._gen, bg = this._backGen;
|
|
3211
|
+
const want = Math.max(3, Math.min(Math.floor(this._held * 0.6), room));
|
|
3212
|
+
let iter = null;
|
|
3213
|
+
const got = [];
|
|
3214
|
+
try {
|
|
3215
|
+
iter = this.sink.samples(Math.max(0, earliest - want / 30));
|
|
3216
|
+
for (; ; ) {
|
|
3217
|
+
const r = await iter.next();
|
|
3218
|
+
if (r.done) break;
|
|
3219
|
+
if (gen !== this._gen || r.value.timestamp >= earliest - EPS) {
|
|
3220
|
+
r.value.close?.();
|
|
3221
|
+
break;
|
|
3222
|
+
}
|
|
3223
|
+
got.push(r.value);
|
|
3224
|
+
if (bg !== this._backGen) break;
|
|
3225
|
+
}
|
|
3226
|
+
if (gen === this._gen && bg === this._backGen) {
|
|
3227
|
+
for (let k = 0; k < got.length; k++) {
|
|
3228
|
+
const s = got[k];
|
|
3229
|
+
const frame = s.toVideoFrame();
|
|
3230
|
+
this._keep({ ts: s.timestamp, end: got[k + 1]?.timestamp ?? earliest, frame }, frame);
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
} catch (err) {
|
|
3234
|
+
reportDecodeError(err, earliest);
|
|
3235
|
+
} finally {
|
|
3236
|
+
for (const s of got) s.close?.();
|
|
3237
|
+
this._backBusy = false;
|
|
3238
|
+
try {
|
|
3239
|
+
await iter?.return?.(void 0);
|
|
3240
|
+
} catch {
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
}
|
|
3244
|
+
/** In the background: the first frames of the file and a pass that stands behind them; held (pinned) until the loop comes round. */
|
|
3245
|
+
async _readStart() {
|
|
3246
|
+
this._standbyBusy = true;
|
|
3247
|
+
this.stats.prefetches++;
|
|
3248
|
+
const gen = this._gen;
|
|
3249
|
+
const want = Math.max(3, Math.min(10, Math.floor(this._held / 3)));
|
|
3250
|
+
let iter = null;
|
|
3251
|
+
const got = [];
|
|
3252
|
+
let keep = false;
|
|
3253
|
+
try {
|
|
3254
|
+
iter = this.sink.samples(0);
|
|
3255
|
+
for (; got.length < want + 1; ) {
|
|
3256
|
+
const r = await iter.next();
|
|
3257
|
+
if (r.done) break;
|
|
3258
|
+
if (gen !== this._gen) {
|
|
3259
|
+
r.value.close?.();
|
|
3260
|
+
break;
|
|
3261
|
+
}
|
|
3262
|
+
got.push(r.value);
|
|
3263
|
+
}
|
|
3264
|
+
if (gen === this._gen && got.length >= 2) {
|
|
3265
|
+
const next = got.pop();
|
|
3266
|
+
let cur = null;
|
|
3267
|
+
got.forEach((s, k) => {
|
|
3268
|
+
const frame = s.toVideoFrame();
|
|
3269
|
+
s.close?.();
|
|
3270
|
+
const entry = { ts: s.timestamp, end: (got[k + 1] ?? next).timestamp, frame, pinned: true };
|
|
3271
|
+
this._keep(entry, frame);
|
|
3272
|
+
cur = entry;
|
|
3273
|
+
});
|
|
3274
|
+
got.length = 0;
|
|
3275
|
+
if (cur) {
|
|
3276
|
+
this._standby = { iter, cur, next };
|
|
3277
|
+
keep = true;
|
|
3278
|
+
}
|
|
3279
|
+
}
|
|
3280
|
+
} catch (err) {
|
|
3281
|
+
reportDecodeError(err, 0);
|
|
3282
|
+
} finally {
|
|
3283
|
+
for (const s of got) s.close?.();
|
|
3284
|
+
this._standbyBusy = false;
|
|
3285
|
+
if (!keep) {
|
|
3286
|
+
try {
|
|
3287
|
+
await iter?.return?.(void 0);
|
|
3288
|
+
} catch {
|
|
3289
|
+
}
|
|
3290
|
+
}
|
|
3291
|
+
}
|
|
3292
|
+
}
|
|
3293
|
+
async _adoptStandby(time) {
|
|
3294
|
+
const sb = this._standby;
|
|
3295
|
+
this._standby = null;
|
|
3296
|
+
await this._closeIter();
|
|
3297
|
+
for (const e of this._frames) e.pinned = false;
|
|
3298
|
+
this._iter = sb.iter;
|
|
3299
|
+
this._next = sb.next;
|
|
3300
|
+
this._cur = sb.cur;
|
|
3301
|
+
return this._advance(time);
|
|
3302
|
+
}
|
|
3303
|
+
_dropStandby() {
|
|
3304
|
+
const sb = this._standby;
|
|
3305
|
+
if (!sb) return;
|
|
3306
|
+
this._standby = null;
|
|
3307
|
+
sb.next?.close?.();
|
|
3308
|
+
for (const e of this._frames.filter((x) => x.pinned)) {
|
|
3309
|
+
e.pinned = false;
|
|
3310
|
+
}
|
|
3311
|
+
void sb.iter.return?.(void 0);
|
|
3154
3312
|
}
|
|
3155
3313
|
/** One frame by itself (a seek): getSample, kept so that asking again for the same time costs nothing. The running pass, if any, is closed: it no longer follows the playhead. */
|
|
3156
3314
|
async _single(time) {
|
|
3315
|
+
this.stats.singles++;
|
|
3157
3316
|
await this._closeIter();
|
|
3158
3317
|
this._cur = null;
|
|
3159
3318
|
const sample = await this.sink.getSample(time);
|
|
@@ -3165,6 +3324,8 @@ var FrameCache = class {
|
|
|
3165
3324
|
}
|
|
3166
3325
|
/** Start a pass at `time` (a seek and the frames of one group of pictures), keeping what is still held for a step back. */
|
|
3167
3326
|
async _restart(time, from = time) {
|
|
3327
|
+
this.stats.restarts++;
|
|
3328
|
+
this._backGen++;
|
|
3168
3329
|
await this._closeIter();
|
|
3169
3330
|
this._cur = null;
|
|
3170
3331
|
const iter = this.sink.samples(from);
|
|
@@ -3228,12 +3389,27 @@ var FrameCache = class {
|
|
|
3228
3389
|
}
|
|
3229
3390
|
this._frames.push(entry);
|
|
3230
3391
|
while (this._frames.length > this._held) {
|
|
3231
|
-
const
|
|
3232
|
-
if (!
|
|
3233
|
-
this._frames.splice(this._frames.indexOf(
|
|
3234
|
-
|
|
3392
|
+
const victim = this._victim(entry);
|
|
3393
|
+
if (!victim) break;
|
|
3394
|
+
this._frames.splice(this._frames.indexOf(victim), 1);
|
|
3395
|
+
victim.frame.close?.();
|
|
3235
3396
|
}
|
|
3236
3397
|
}
|
|
3398
|
+
/**
|
|
3399
|
+
* The frame to let go: one the playhead has already passed (going forward those before it, going back those after it), the furthest
|
|
3400
|
+
* behind first; when there is none, the one furthest ahead of the playhead (the last to be needed). Least recently used when the
|
|
3401
|
+
* direction is not known. Frames of the standby (pinned) and the frame the pass stands on are never chosen.
|
|
3402
|
+
*/
|
|
3403
|
+
_victim(except) {
|
|
3404
|
+
const cand = this._frames.filter((e) => e !== this._cur && e !== except && !e.pinned);
|
|
3405
|
+
if (cand.length === 0) return null;
|
|
3406
|
+
if (this._dir === 0) return cand[0];
|
|
3407
|
+
const at = this._lastTime ?? 0;
|
|
3408
|
+
const passed = cand.filter((e) => this._dir === 1 ? e.ts < at - EPS : e.ts > at + EPS);
|
|
3409
|
+
const farthest = (list, sign) => list.reduce((a, b) => sign * (b.ts - a.ts) > 0 ? b : a);
|
|
3410
|
+
if (passed.length) return farthest(passed, this._dir === 1 ? -1 : 1);
|
|
3411
|
+
return farthest(cand, this._dir === 1 ? 1 : -1);
|
|
3412
|
+
}
|
|
3237
3413
|
async _closeIter() {
|
|
3238
3414
|
const iter = this._iter;
|
|
3239
3415
|
this._iter = null;
|
|
@@ -3256,6 +3432,8 @@ var FrameCache = class {
|
|
|
3256
3432
|
}
|
|
3257
3433
|
}
|
|
3258
3434
|
dispose() {
|
|
3435
|
+
this._gen++;
|
|
3436
|
+
this._dropStandby();
|
|
3259
3437
|
for (const f of this.cache.values()) f?.close?.();
|
|
3260
3438
|
this.cache.clear();
|
|
3261
3439
|
this._pending.clear();
|
|
@@ -3297,7 +3475,7 @@ var VideoSequence = class extends Sequence {
|
|
|
3297
3475
|
this._sourceDuration = data.duration;
|
|
3298
3476
|
this._remap = remapOf(this.spec, "currentTime", this._sourceDuration);
|
|
3299
3477
|
this._audioBuffer = this.spec.audio !== false ? data.audioBuffer : null;
|
|
3300
|
-
this._cache = new FrameCache(data.sink, { capacity: 30 });
|
|
3478
|
+
this._cache = new FrameCache(data.sink, { capacity: 30, duration: data.duration, loop: !!this.spec.loop });
|
|
3301
3479
|
const probeFrame = await this._cache.getFrameAt(0);
|
|
3302
3480
|
const w = probeFrame?.displayWidth ?? 1920;
|
|
3303
3481
|
const h = probeFrame?.displayHeight ?? 1080;
|
|
@@ -4497,7 +4675,7 @@ function resolveDim(v, scope) {
|
|
|
4497
4675
|
var _CompositionSequence = null;
|
|
4498
4676
|
async function getCompositionSequence() {
|
|
4499
4677
|
if (!_CompositionSequence) {
|
|
4500
|
-
_CompositionSequence = (await import('./Composition-
|
|
4678
|
+
_CompositionSequence = (await import('./Composition-3O7L2VL5.js')).CompositionSequence;
|
|
4501
4679
|
}
|
|
4502
4680
|
return _CompositionSequence;
|
|
4503
4681
|
}
|
|
@@ -4540,5 +4718,5 @@ async function buildSequenceTree(specs, parent, root) {
|
|
|
4540
4718
|
}
|
|
4541
4719
|
|
|
4542
4720
|
export { CameraSequence, DEFAULT_FOV, DEG2 as DEG, FALLOFFS, LIGHT_KINDS, LIGHT_PROPS, LightSequence, MANY_BLURRED, MAX_BLUR, MAX_CASTERS, MAX_LIGHTS, MIN_BLUR, NEAR, NullSequence, SHADOW_TAPS, Sequence, bindClock, blurRadius, buildScope, buildSequenceTree, cameraBasis, checkEase, clockTable, contentLength, ensureFilterLibrary, evaluateExpr, flattenSvgPath, focusProblems, homeCamera, homeDistance, layerInitialZ, layerToWorld, lightLevel, noise, packLights, projectLayer, projectPoint, rand, random, registerSequenceType, remapOf, resolveAt, timeRemapOf };
|
|
4543
|
-
//# sourceMappingURL=chunk-
|
|
4544
|
-
//# sourceMappingURL=chunk-
|
|
4721
|
+
//# sourceMappingURL=chunk-FXAHNPBP.js.map
|
|
4722
|
+
//# sourceMappingURL=chunk-FXAHNPBP.js.map
|