@video-editor/renderer 0.0.1-beta.32 → 0.0.1-beta.34

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/dist/index.js CHANGED
@@ -1,434 +1,278 @@
1
- import { createValidator as Wt, createResourceManager as Yt, getResourceKey as W } from "@video-editor/protocol";
2
- import { toRaw as Xt, isRef as Jt, shallowRef as vt, unref as Mt, ref as gt, computed as Ht, effectScope as Qt, watch as Z } from "@vue/reactivity";
3
- import { AudioClip as Tt, renderTxt2ImgBitmap as Zt, MP4Clip as K, Combinator as bt, OffscreenSprite as nt } from "@webav/av-cliper";
4
- import { file as te } from "opfs-tools";
5
- import { Application as kt, Sprite as V, Texture as G, Graphics as Ct, Container as ee } from "pixi.js";
6
- async function oe(e) {
7
- const t = new kt();
1
+ import { createValidator as Ut, createResourceManager as Nt, getResourceKey as z } from "@video-editor/protocol";
2
+ import { toRaw as Dt, isRef as $t, shallowRef as Ge, unref as Le, ref as Be, computed as Kt, effectScope as Gt, watch as fe } from "@vue/reactivity";
3
+ import { renderTxt2ImgBitmap as Lt, MP4Clip as K, Combinator as Je, OffscreenSprite as be, AudioClip as Bt } from "@webav/av-cliper";
4
+ import { file as jt } from "opfs-tools";
5
+ import { Application as Qe, Sprite as U, Texture as $, Graphics as Ze, BlurFilter as et, ColorMatrixFilter as ge, Container as qt } from "pixi.js";
6
+ import { isAudioSegment as tt, isVideoFramesSegment as Ie } from "@video-editor/shared";
7
+ async function _t(e) {
8
+ const t = new Qe();
8
9
  return await t.init({ resizeTo: window, backgroundAlpha: 0, ...e }), t;
9
10
  }
10
- function ie(e, t, o, i, n) {
11
- const a = t || i, c = o || n;
12
- if (!a || !c)
13
- return { width: i, height: n };
14
- const u = a / c, d = i / n;
15
- switch (e) {
16
- case "none":
17
- return { width: a, height: c };
18
- case "cover":
19
- return u > d ? { width: n * u, height: n } : { width: i, height: i / u };
20
- case "stretch":
21
- return { width: i, height: n };
22
- default:
23
- return u > d ? { width: i, height: i / u } : { width: n * u, height: n };
24
- }
25
- }
26
- function re(e, t, o, i, n) {
27
- const a = "fillMode" in e ? e.fillMode : void 0, { width: c, height: u } = ie(
28
- a,
29
- i,
30
- n,
31
- t,
32
- o
33
- ), d = "transform" in e ? e.transform : void 0, [y, h] = d?.position ?? [0, 0], [w, M] = d?.scale ?? [1, 1], p = d?.rotation?.[2] ?? 0, v = c * w, m = u * M, g = t / 2 + y * t / 2, R = o / 2 - h * o / 2;
34
- return {
35
- width: v,
36
- height: m,
37
- centerX: g,
38
- centerY: R,
39
- rotationRad: p / 180 * Math.PI
40
- };
41
- }
42
- function ne(e) {
43
- const t = /* @__PURE__ */ new Set();
44
- for (const o of e.tracks)
45
- for (const i of o.children)
46
- i.url && t.add(i.url);
47
- return t;
48
- }
49
- function Rt(e, t) {
50
- const o = [];
51
- return e.tracks.forEach((i, n) => {
52
- i.children.forEach((a, c) => {
53
- a.startTime <= t && t < a.endTime && o.push({ segment: a, trackIndex: n, childIndex: c });
54
- });
55
- }), o.sort((i, n) => {
56
- const a = e.tracks[i.trackIndex], c = e.tracks[n.trackIndex], u = a?.trackType === "frames" && a.isMain, d = c?.trackType === "frames" && c.isMain, y = e.tracks.length, h = u ? 0 : y - i.trackIndex, w = d ? 0 : y - n.trackIndex;
57
- return h !== w ? h - w : i.trackIndex === n.trackIndex ? i.childIndex - n.childIndex : i.trackIndex - n.trackIndex;
58
- });
59
- }
60
- function ae(e, t, o, i) {
61
- const n = ce(t), a = e instanceof V && e.texture.width || o, c = e instanceof V && e.texture.height || i, u = re(t, o, i, a, c);
62
- e instanceof V ? (e.anchor.set(0.5), e.width = u.width, e.height = u.height, e.position.set(u.centerX, u.centerY), e.rotation = u.rotationRad, e.texture.source?.addEventListener?.("error", () => {
63
- e.texture = G.from(se(o, i));
64
- }, { once: !0 })) : e instanceof Ct && (e.clear(), e.rect(0, 0, u.width, u.height).fill({ color: At("url" in t && typeof t.url == "string" ? t.url : t.segmentType), alpha: Et(t) ? n : 0.35 }), e.pivot.set(u.width / 2, u.height / 2), e.position.set(u.centerX, u.centerY), e.rotation = u.rotationRad), e.alpha = n;
65
- }
66
- function tt(e, t) {
67
- const o = new Ct();
68
- return o.rect(0, 0, 10, 10).fill({ color: At(t ?? e), alpha: 1 }), o;
69
- }
70
- function se(e, t, o) {
71
- const i = `<svg xmlns="http://www.w3.org/2000/svg" width="${e}" height="${t}"><rect width="100%" height="100%" fill="#0f172a" fill-opacity="0.8"/></svg>`;
72
- return `data:image/svg+xml;base64,${btoa(i)}`;
73
- }
74
- function At(e) {
75
- let t = 0;
76
- for (let o = 0; o < e.length; o++)
77
- t = e.charCodeAt(o) + ((t << 5) - t);
78
- return t & 16777215;
79
- }
80
- function it(e) {
81
- const t = e.tracks.flatMap((o) => o.children.map((i) => i.endTime));
82
- return t.length ? Math.max(...t) : 0;
83
- }
84
- function et(e, t, o) {
85
- return Math.min(Math.max(e, t), o);
86
- }
87
- function St(e) {
88
- const t = Xt(e);
89
- return JSON.parse(JSON.stringify(t));
90
- }
91
- function Et(e) {
92
- return "opacity" in e;
93
- }
94
- function ce(e) {
95
- return Et(e) && typeof e.opacity == "number" ? e.opacity : 1;
96
- }
97
- class ue {
11
+ class Wt {
98
12
  protocol;
99
- clips = /* @__PURE__ */ new Map();
100
- loadingClips = /* @__PURE__ */ new Map();
101
- audioLoops = /* @__PURE__ */ new Map();
102
- audioLoopContexts = /* @__PURE__ */ new Map();
103
- mp4Loops = /* @__PURE__ */ new Map();
13
+ options;
104
14
  mp4States = /* @__PURE__ */ new Map();
105
- audioGains = /* @__PURE__ */ new Map();
106
15
  mp4Gains = /* @__PURE__ */ new Map();
16
+ plannedVideoAudioGains = /* @__PURE__ */ new Map();
17
+ plannedVideoAudioRates = /* @__PURE__ */ new Map();
18
+ plannedVoices = /* @__PURE__ */ new Map();
107
19
  audioElements = /* @__PURE__ */ new Map();
108
- useMediaElementForAudio = !0;
109
20
  ctx;
110
- lastTime = 0;
111
- constructor(t) {
112
- this.protocol = t, this.ctx = new (window.AudioContext || window.webkitAudioContext)();
21
+ constructor(t, i = {}) {
22
+ this.protocol = t, this.options = i, this.ctx = new (window.AudioContext || window.webkitAudioContext)();
113
23
  }
114
24
  setProtocol(t) {
115
25
  this.protocol = t;
116
26
  }
117
- async sync(t, o) {
118
- if (!o) {
119
- this.stopAll(), this.lastTime = t;
27
+ applyTimelinePlan(t, i) {
28
+ if (!i) {
29
+ this.stopAll();
120
30
  return;
121
31
  }
122
- this.ctx.state === "suspended" && await this.ctx.resume().catch(() => {
123
- }), Math.abs(t - this.lastTime) > 1e3 && this.stopAll(), this.lastTime = t;
124
- const i = Rt(this.protocol, t), n = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set();
125
- for (const { segment: c } of i)
126
- if (c.segmentType === "audio") {
127
- const u = this.audioKey(c.id);
128
- n.add(u), this.useMediaElementForAudio ? this.syncAudioElement(c, t) : this.ensureAudioLoop(c, t);
129
- } else if (c.segmentType === "frames" && "type" in c && c.type === "video") {
130
- const u = this.videoKey(c.id);
131
- a.add(u);
132
- }
133
- for (const [c, u] of this.audioLoops)
134
- if (!n.has(c)) {
135
- u.stop();
136
- for (const d of u.sources)
137
- try {
138
- d.stop(), d.disconnect();
139
- } catch {
140
- }
141
- this.audioLoops.delete(c), this.audioLoopContexts.delete(c), this.audioGains.delete(c);
142
- }
143
- for (const [c, u] of this.audioElements)
144
- if (!n.has(c)) {
145
- try {
146
- u.el.pause(), u.pendingPlay = void 0, u.lastTimelineMs = void 0, u.lastSourceSec = void 0, u.lastSeekTimelineMs = void 0;
147
- } catch {
148
- }
149
- this.findSegmentInProtocol(u.segmentId) || (this.destroyAudioElement(u.el), this.audioElements.delete(c));
150
- }
151
- for (const [c, u] of this.mp4Loops)
152
- if (!a.has(c)) {
153
- u.stop();
154
- for (const d of u.sources)
155
- try {
156
- d.stop(), d.disconnect();
157
- } catch {
158
- }
159
- this.mp4Loops.delete(c), this.mp4States.delete(c), this.mp4Gains.delete(c);
160
- }
161
- for (const c of this.mp4States.keys())
162
- !a.has(c) && !this.mp4Loops.has(c) && (this.mp4States.delete(c), this.mp4Gains.delete(c));
32
+ this.ctx.state === "suspended" && this.ctx.resume().catch(() => {
33
+ });
34
+ for (const n of t.audioEvents)
35
+ this.applyAudioPlanEvent(n);
36
+ }
37
+ resetTimelineState(t = {}) {
38
+ this.plannedVoices.clear(), this.plannedVideoAudioGains.clear(), this.plannedVideoAudioRates.clear(), t.stop && this.stopAll();
163
39
  }
164
40
  /**
165
41
  * Play audio frames from MP4 video directly.
166
42
  * Called by renderer after it gets audio data from clip.tick()
167
43
  */
168
- playMp4AudioFrames(t, o, i) {
169
- if (!o || o.length === 0 || !o[0]?.length)
44
+ playMp4AudioFrames(t, i, n) {
45
+ const o = this.normalizePcmChannels(i);
46
+ if (!o)
170
47
  return;
171
- const n = this.videoKey(t), a = this.getSegmentVolume(t), c = this.getOrCreateGain(this.mp4Gains, n, a);
48
+ const a = this.videoKey(t), u = this.plannedVideoAudioGains.get(a), d = typeof u == "number" ? this.normalizeVolume(u) : this.getSegmentVolume(t), f = this.plannedVideoAudioRates.get(a), g = typeof f == "number" ? this.normalizePlayRate(f) : 1, m = this.getOrCreateGain(this.mp4Gains, a, d);
172
49
  this.ctx.state === "suspended" && this.ctx.resume().catch(() => {
173
50
  });
174
- let u = this.mp4States.get(n);
175
- u || (u = {
176
- loop: { stop: () => {
177
- }, sources: [], isStopped: () => !1 },
178
- startUs: 0,
179
- startCtxTime: this.ctx.currentTime,
180
- fps: 30,
51
+ let S = this.mp4States.get(a);
52
+ S || (S = {
53
+ sources: [],
181
54
  nextStartAt: 0
182
- }, this.mp4States.set(n, u)), u.nextStartAt = this.playFrames(o, i, u.nextStartAt ?? 0, c, u.loop.sources);
55
+ }, this.mp4States.set(a, S)), S.nextStartAt = this.playFrames(
56
+ o,
57
+ this.normalizeSampleRate(n),
58
+ S.nextStartAt ?? 0,
59
+ m,
60
+ S.sources,
61
+ g
62
+ );
183
63
  }
184
64
  /**
185
65
  * Reset MP4 audio playback state (call when seeking or pausing)
186
66
  */
187
67
  resetMp4Audio(t) {
188
- const o = this.videoKey(t), i = this.mp4States.get(o);
189
- i && (i.nextStartAt = 0);
68
+ const i = this.videoKey(t), n = this.mp4States.get(i);
69
+ n && (n.nextStartAt = 0);
190
70
  }
191
71
  /**
192
72
  * Stop and clean up MP4 audio for a video segment
193
73
  */
194
74
  stopMp4Audio(t) {
195
- const o = this.videoKey(t), i = this.mp4States.get(o);
196
- if (i) {
197
- i.loop.stop();
198
- for (const n of i.loop.sources)
75
+ const i = this.videoKey(t), n = this.mp4States.get(i);
76
+ if (n) {
77
+ for (const o of n.sources)
199
78
  try {
200
- n.stop(), n.disconnect();
79
+ o.stop(), o.disconnect();
201
80
  } catch {
202
81
  }
203
- this.mp4Loops.delete(o), this.mp4States.delete(o), this.mp4Gains.delete(o);
82
+ n.sources.length = 0, this.mp4States.delete(i), this.mp4Gains.delete(i);
204
83
  }
205
84
  }
206
- /**
207
- * @deprecated Use playMp4AudioFrames instead
208
- */
209
- ensureMp4Audio(t, o, i, n) {
210
- const a = this.videoKey(t), c = this.getSegmentVolume(t), u = this.getOrCreateGain(this.mp4Gains, a, c), d = this.mp4States.get(a);
211
- if (d) {
212
- u.gain.value = Math.max(0, c);
213
- const h = (this.ctx.currentTime - d.startCtxTime) * 1e6, w = d.startUs + h;
214
- if (Math.abs(w - i) < 15e4 && d.fps === n)
215
- return;
216
- d.loop.stop();
217
- for (const M of d.loop.sources)
218
- try {
219
- M.stop(), M.disconnect();
220
- } catch {
221
- }
222
- this.mp4Loops.delete(a), this.mp4States.delete(a);
223
- }
224
- this.ctx.state === "suspended" && this.ctx.resume().catch(() => {
225
- });
226
- const y = this.startMp4Loop(o, i, n, u);
227
- this.mp4Loops.set(a, y), this.mp4States.set(a, {
228
- loop: y,
229
- startUs: i,
230
- startCtxTime: this.ctx.currentTime,
231
- fps: n
232
- });
233
- }
234
85
  destroy() {
235
86
  this.stopAll();
236
- for (const t of this.clips.values())
237
- t.clip.destroy();
238
- this.clips.clear();
239
87
  for (const t of this.audioElements.values())
240
88
  this.destroyAudioElement(t.el);
241
89
  this.audioElements.clear();
242
90
  }
243
91
  stopAll() {
244
92
  for (const t of this.audioElements.values())
245
- try {
246
- t.el.pause(), t.pendingPlay = void 0, t.lastTimelineMs = void 0, t.lastSourceSec = void 0, t.lastSeekTimelineMs = void 0;
247
- } catch {
248
- }
249
- for (const t of this.audioLoops.values()) {
250
- t.stop();
251
- for (const o of t.sources)
93
+ this.pauseAudioElementState(t);
94
+ for (const t of this.mp4States.values()) {
95
+ for (const i of t.sources)
252
96
  try {
253
- o.stop(0), o.disconnect();
97
+ i.stop(0), i.disconnect();
254
98
  } catch {
255
99
  }
256
100
  t.sources.length = 0;
257
101
  }
258
- for (const t of this.mp4Loops.values()) {
259
- t.stop();
260
- for (const o of t.sources)
261
- try {
262
- o.stop(0), o.disconnect();
263
- } catch {
264
- }
265
- t.sources.length = 0;
266
- }
267
- for (const t of this.audioGains.values())
268
- try {
269
- t.disconnect();
270
- } catch {
271
- }
272
102
  for (const t of this.mp4Gains.values())
273
103
  try {
274
104
  t.disconnect();
275
105
  } catch {
276
106
  }
277
- this.audioLoops.clear(), this.audioLoopContexts.clear(), this.audioGains.clear(), this.mp4Loops.clear(), this.mp4States.clear(), this.mp4Gains.clear();
107
+ this.mp4States.clear(), this.mp4Gains.clear(), this.plannedVoices.clear(), this.plannedVideoAudioGains.clear(), this.plannedVideoAudioRates.clear();
278
108
  }
279
- async ensureAudioLoop(t, o) {
280
- const i = this.audioKey(t.id), n = await this.loadClip(t);
281
- if (!n)
109
+ applyAudioPlanEvent(t) {
110
+ if (t.segmentKind === "audio") {
111
+ this.applySegmentAudioEvent(t);
282
112
  return;
283
- const a = t.fromTime ?? 0, c = this.normalizePlayRate(t.playRate), u = o - t.startTime, d = a + u * c, y = this.getOrCreateGain(this.audioGains, i, t.volume);
284
- this.applyFadeToGain(t, u, y);
285
- const h = this.audioLoops.get(i);
286
- if (h && !h.isStopped())
287
- return;
288
- h && (this.audioLoops.delete(i), this.audioLoopContexts.delete(i));
289
- const M = (t.endTime - t.startTime) * c, p = a + M, v = this.startAudioLoop(n.clip, Math.max(0, d) * 1e3, y, c, p * 1e3);
290
- this.audioLoops.set(i, v), this.audioLoopContexts.set(i, {
291
- segment: t,
292
- startedAt: this.ctx.currentTime,
293
- segmentRelativeMs: u
294
- });
295
- }
296
- syncAudioElement(t, o) {
297
- const i = this.audioKey(t.id), n = this.getOrCreateAudioElementState(i, t), a = o - t.startTime, c = this.normalizePlayRate(t.playRate), u = t.fromTime ?? 0, d = u + a * c, h = Math.max(0, t.endTime - t.startTime) * c, w = u + h, M = Math.max(0, w) / 1e3, p = Number.isFinite(n.el.duration) ? Math.max(0, n.el.duration) : void 0, v = p === void 0 ? M : Math.min(M, p), m = Math.max(0, Math.min(d / 1e3, v)), g = d / 1e3 >= v - 0.01;
298
- Math.abs(n.el.playbackRate - c) > 1e-3 && (n.el.playbackRate = c);
299
- const R = this.computeSegmentVolume(t, a);
300
- Math.abs(n.el.volume - R) > 1e-3 && (n.el.volume = R);
301
- const P = 0.24, A = 500, E = 300, b = -40, q = n.lastTimelineMs, D = n.lastSourceSec, z = q === void 0 ? 0 : o - q;
302
- let O = !1;
303
- if (q === void 0)
304
- O = !0;
305
- else if (z < b || z > E)
306
- O = !0;
307
- else if (D !== void 0) {
308
- const F = D + z * c / 1e3, Y = Math.abs(F - m), _ = n.lastSeekTimelineMs === void 0 || o - n.lastSeekTimelineMs >= A;
309
- Y > P && _ && (O = !0);
310
113
  }
311
- if (O && Math.abs(n.el.currentTime - m) > 0.06)
312
- try {
313
- n.el.currentTime = m, n.lastSeekTimelineMs = o;
314
- } catch {
114
+ this.applyVideoAudioEvent(t);
115
+ }
116
+ applySegmentAudioEvent(t) {
117
+ const i = this.audioKey(t.segmentId), n = this.getOrCreatePlannedVoice(t);
118
+ if (t.action === "stop") {
119
+ const u = this.audioElements.get(i);
120
+ if (!u) {
121
+ this.plannedVoices.delete(t.voiceId);
122
+ return;
315
123
  }
316
- if (n.lastTimelineMs = o, n.lastSourceSec = m, g) {
317
- if (!n.el.paused)
318
- try {
319
- n.el.pause();
320
- } catch {
321
- }
322
- n.pendingPlay = void 0;
124
+ this.pauseAudioElementState(u), n.phase = "ended", this.plannedVoices.delete(t.voiceId);
323
125
  return;
324
126
  }
325
- if (n.el.paused && !n.pendingPlay) {
326
- const F = n.el.play();
327
- F && typeof F.then == "function" && (n.pendingPlay = F.catch(() => {
328
- }).finally(() => {
329
- n.pendingPlay = void 0;
330
- }));
331
- }
332
- }
333
- applyFadeToGain(t, o, i) {
334
- i.gain.value = this.computeSegmentVolume(t, o);
335
- }
336
- startMp4Loop(t, o, i, n) {
337
- let a = !1, c = o, u = 0, d = !0;
338
- const y = Math.round(1e3 / Math.max(i || 30, 1) * 1e3), h = this.getClipSampleRate(t), w = [], M = window.setInterval(async () => {
339
- if (a)
340
- return;
341
- const { audio: p, state: v } = await t.tick(Math.round(c));
342
- if (c += y, v === "done")
127
+ const o = this.findAudioSegment(t.segmentId);
128
+ if (!o)
129
+ return;
130
+ const a = this.getOrCreateAudioElementState(i, o);
131
+ if (t.action === "start" || t.action === "seek") {
132
+ const u = this.computeSegmentSourceOffsetMs(
133
+ o,
134
+ t.atTimelineMs,
135
+ t.sourceTimeMs
136
+ ), { targetSourceSec: d, isSourceExhausted: f } = this.resolveAudioElementSourceWindow(
137
+ a,
138
+ o,
139
+ u
140
+ );
141
+ if (f) {
142
+ this.pauseAudioElementState(a), n.lastSourceSec = d, n.phase = "ended";
343
143
  return;
344
- if (d) {
345
- d = !1;
144
+ }
145
+ if (d !== void 0 && (n.phase !== "playing" || n.lastSourceSec === void 0 || Math.abs((n.lastSourceSec ?? 0) - d) > 0.02) && !this.seekAudioElement(a, d, t.atTimelineMs) && d > 0.05) {
146
+ this.pauseAudioElementState(a), n.phase = "idle";
346
147
  return;
347
148
  }
348
- (p?.[0]?.length ?? 0) !== 0 && (u = this.playFrames(p, h, u, n, w));
349
- }, Math.round(1e3 / Math.max(i || 30, 1)));
350
- return {
351
- sources: w,
352
- stop: () => {
353
- a = !0, window.clearInterval(M);
354
- },
355
- isStopped: () => a
356
- };
149
+ if (typeof t.gain == "number") {
150
+ const m = this.normalizeVolume(t.gain);
151
+ (n.lastGain === void 0 || Math.abs((n.lastGain ?? 0) - m) > 1e-3) && (a.el.volume = m), n.lastGain = m;
152
+ }
153
+ if (typeof t.rate == "number") {
154
+ const m = this.normalizePlayRate(t.rate);
155
+ (n.lastRate === void 0 || Math.abs((n.lastRate ?? 0) - m) > 1e-3) && (a.el.playbackRate = m), n.lastRate = m;
156
+ }
157
+ d !== void 0 && (n.lastSourceSec = d), this.playAudioElementState(a), n.phase = "playing";
158
+ return;
159
+ }
160
+ if (t.action === "gain") {
161
+ if (typeof t.gain == "number") {
162
+ const u = this.normalizeVolume(t.gain);
163
+ (n.lastGain === void 0 || Math.abs((n.lastGain ?? 0) - u) > 1e-3) && (a.el.volume = u), n.lastGain = u;
164
+ }
165
+ return;
166
+ }
167
+ if (t.action === "rate" && typeof t.rate == "number") {
168
+ const u = this.normalizePlayRate(t.rate);
169
+ (n.lastRate === void 0 || Math.abs((n.lastRate ?? 0) - u) > 1e-3) && (a.el.playbackRate = u), n.lastRate = u;
170
+ }
357
171
  }
358
- startAudioLoop(t, o, i, n = 1, a) {
359
- let c = !1, u = o, d = 0, y = !1;
360
- const h = this.getClipSampleRate(t), w = [], p = Math.round(1e5 * n), v = async () => {
361
- if (c)
362
- return;
363
- if (y || (o > 0 && await t.tick(o), y = !0), u += p, a !== void 0 && u > a) {
364
- c = !0;
172
+ applyVideoAudioEvent(t) {
173
+ const i = this.videoKey(t.segmentId), n = this.getOrCreatePlannedVoice(t);
174
+ if (t.action === "stop") {
175
+ const u = this.audioElements.get(i);
176
+ u && this.pauseAudioElementState(u), this.stopMp4Audio(t.segmentId), this.plannedVideoAudioGains.delete(i), this.plannedVideoAudioRates.delete(i), n.phase = "ended", this.plannedVoices.delete(t.voiceId);
177
+ return;
178
+ }
179
+ const o = this.findVideoSegment(t.segmentId);
180
+ if (!o)
181
+ return;
182
+ const a = this.getOrCreateAudioElementState(i, o);
183
+ if (t.action === "start" || t.action === "seek") {
184
+ this.stopMp4Audio(t.segmentId);
185
+ const u = this.computeSegmentSourceOffsetMs(
186
+ o,
187
+ t.atTimelineMs,
188
+ t.sourceTimeMs
189
+ ), { targetSourceSec: d, isSourceExhausted: f } = this.resolveAudioElementSourceWindow(
190
+ a,
191
+ o,
192
+ u
193
+ );
194
+ if (f) {
195
+ this.pauseAudioElementState(a), n.lastSourceSec = d, n.phase = "ended";
365
196
  return;
366
197
  }
367
- const { audio: m, state: g } = await t.tick(u);
368
- if (c)
369
- return;
370
- if (g === "done") {
371
- c = !0;
198
+ if (d !== void 0 && (n.phase !== "playing" || t.action === "seek" || n.lastSourceSec === void 0 || Math.abs((n.lastSourceSec ?? 0) - d) > 0.02) && !this.seekAudioElement(a, d, t.atTimelineMs) && d > 0.05) {
199
+ this.pauseAudioElementState(a), n.phase = "idle";
372
200
  return;
373
201
  }
374
- if ((m?.[0]?.length ?? 0) === 0) {
375
- c = !0;
376
- return;
202
+ if (typeof t.gain == "number") {
203
+ const m = this.normalizeVolume(t.gain);
204
+ (n.lastGain === void 0 || Math.abs((n.lastGain ?? 0) - m) > 1e-3) && (a.el.volume = m), this.plannedVideoAudioGains.set(i, m), n.lastGain = m;
377
205
  }
378
- d = this.playFrames(m, h, d, i, w, n), c || setTimeout(() => v(), 0);
379
- };
380
- return v(), {
381
- sources: w,
382
- stop: () => {
383
- c = !0;
384
- },
385
- // Treat loop as active while there are still scheduled sources playing.
386
- isStopped: () => c && w.length === 0
387
- };
206
+ if (typeof t.rate == "number") {
207
+ const m = this.normalizePlayRate(t.rate);
208
+ (n.lastRate === void 0 || Math.abs((n.lastRate ?? 0) - m) > 1e-3) && (a.el.playbackRate = m), this.plannedVideoAudioRates.set(i, m), n.lastRate = m;
209
+ }
210
+ d !== void 0 && (n.lastSourceSec = d), this.playAudioElementState(a), n.phase = "playing";
211
+ }
212
+ if (typeof t.gain == "number") {
213
+ const u = this.normalizeVolume(t.gain);
214
+ (n.lastGain === void 0 || Math.abs((n.lastGain ?? 0) - u) > 1e-3) && this.plannedVideoAudioGains.set(i, u), (n.lastGain === void 0 || Math.abs((n.lastGain ?? 0) - u) > 1e-3) && (a.el.volume = u);
215
+ const d = this.mp4Gains.get(i);
216
+ d && (d.gain.value = u), n.lastGain = u;
217
+ }
218
+ if (typeof t.rate == "number") {
219
+ const u = this.normalizePlayRate(t.rate);
220
+ (n.lastRate === void 0 || Math.abs((n.lastRate ?? 0) - u) > 1e-3) && this.plannedVideoAudioRates.set(i, u), (n.lastRate === void 0 || Math.abs((n.lastRate ?? 0) - u) > 1e-3) && (a.el.playbackRate = u), n.lastRate = u;
221
+ }
388
222
  }
389
- playFrames(t, o, i, n, a, c = 1) {
390
- const u = Math.max(t.length, 1), d = t[0]?.length ?? 0;
391
- if (d === 0)
223
+ getOrCreatePlannedVoice(t) {
224
+ const i = this.plannedVoices.get(t.voiceId);
225
+ if (i)
392
226
  return i;
393
- const y = this.ctx.createBuffer(u, d, o);
394
- for (let p = 0; p < u; p++) {
395
- const v = t[p] ?? new Float32Array(d);
396
- y.copyToChannel(new Float32Array(v), p);
227
+ const n = {
228
+ phase: "idle",
229
+ segmentKind: t.segmentKind
230
+ };
231
+ return this.plannedVoices.set(t.voiceId, n), n;
232
+ }
233
+ playFrames(t, i, n, o, a, u = 1) {
234
+ const d = Math.max(t.length, 1), f = t[0]?.length ?? 0;
235
+ if (f === 0)
236
+ return n;
237
+ const g = this.ctx.createBuffer(d, f, i);
238
+ for (let l = 0; l < d; l++) {
239
+ const h = t[l] ?? new Float32Array(f);
240
+ g.copyToChannel(new Float32Array(h), l);
397
241
  }
398
- const h = this.ctx.createBufferSource();
399
- h.buffer = y;
400
- const w = Math.max(0.1, c);
401
- h.playbackRate.value = w, h.connect(n);
402
- const M = Math.max(this.ctx.currentTime, i);
403
- if (h.start(M), a) {
404
- a.push(h);
405
- const p = y.duration / w * 1e3;
242
+ const m = this.ctx.createBufferSource();
243
+ m.buffer = g;
244
+ const S = Math.max(0.1, u);
245
+ m.playbackRate.value = S, m.connect(o);
246
+ const w = Math.max(this.ctx.currentTime, n);
247
+ if (m.start(w), a) {
248
+ a.push(m);
249
+ const l = g.duration / S * 1e3;
406
250
  setTimeout(() => {
407
- const v = a.indexOf(h);
408
- v > -1 && a.splice(v, 1);
409
- }, p + 100);
251
+ const h = a.indexOf(m);
252
+ h > -1 && a.splice(h, 1);
253
+ }, l + 100);
410
254
  }
411
- return M + y.duration / w;
255
+ return w + g.duration / S;
412
256
  }
413
- getOrCreateGain(t, o, i) {
414
- const n = t.get(o);
415
- if (n)
416
- return typeof i == "number" && (n.gain.value = this.normalizeVolume(i)), n;
257
+ getOrCreateGain(t, i, n) {
258
+ const o = t.get(i);
259
+ if (o)
260
+ return typeof n == "number" && (o.gain.value = this.normalizeVolume(n)), o;
417
261
  const a = this.ctx.createGain();
418
- return a.gain.value = this.normalizeVolume(i), a.connect(this.ctx.destination), t.set(o, a), a;
262
+ return a.gain.value = this.normalizeVolume(n), a.connect(this.ctx.destination), t.set(i, a), a;
419
263
  }
420
- getOrCreateAudioElementState(t, o) {
421
- const i = this.audioElements.get(t);
422
- if (i)
423
- return i.url !== o.url && (i.el.pause(), i.el.src = o.url, i.el.currentTime = 0, i.url = o.url, i.pendingPlay = void 0, i.lastTimelineMs = void 0, i.lastSourceSec = void 0, i.lastSeekTimelineMs = void 0), i;
424
- const n = new Audio(o.url);
425
- n.preload = "auto", n.loop = !1, n.volume = this.normalizeVolume(o.volume), n.playbackRate = this.normalizePlayRate(o.playRate);
426
- const a = {
427
- segmentId: o.id,
428
- url: o.url,
429
- el: n
264
+ getOrCreateAudioElementState(t, i) {
265
+ const n = this.options.resolveMediaElementUrl?.(i) ?? i.url, o = this.audioElements.get(t);
266
+ if (o)
267
+ return o.url !== n && (o.el.pause(), o.el.src = n, o.el.currentTime = 0, o.url = n, o.pendingPlay = void 0, o.lastTimelineMs = void 0, o.lastSourceSec = void 0, o.lastSeekTimelineMs = void 0), o;
268
+ const a = new Audio(n);
269
+ a.preload = "auto", a.loop = !1, a.volume = this.normalizeVolume(i.volume), a.playbackRate = this.normalizePlayRate(i.playRate);
270
+ const u = {
271
+ segmentId: i.id,
272
+ url: n,
273
+ el: a
430
274
  };
431
- return this.audioElements.set(t, a), a;
275
+ return this.audioElements.set(t, u), u;
432
276
  }
433
277
  destroyAudioElement(t) {
434
278
  try {
@@ -441,18 +285,63 @@ class ue {
441
285
  } catch {
442
286
  }
443
287
  }
288
+ playAudioElementState(t) {
289
+ if (!t.el.paused || t.pendingPlay)
290
+ return;
291
+ const i = t.el.play();
292
+ i && typeof i.then == "function" && (t.pendingPlay = i.catch(() => {
293
+ }).finally(() => {
294
+ t.pendingPlay = void 0;
295
+ }));
296
+ }
297
+ pauseAudioElementState(t) {
298
+ try {
299
+ t.el.pause();
300
+ } catch {
301
+ }
302
+ t.pendingPlay = void 0, t.lastTimelineMs = void 0, t.lastSourceSec = void 0, t.lastSeekTimelineMs = void 0;
303
+ }
304
+ seekAudioElement(t, i, n) {
305
+ const o = Math.max(0, i);
306
+ if (Math.abs(t.el.currentTime - o) <= 0.02)
307
+ return t.lastTimelineMs = n, t.lastSourceSec = o, !0;
308
+ try {
309
+ return t.el.currentTime = o, t.lastSeekTimelineMs = n, t.lastTimelineMs = n, t.lastSourceSec = o, !0;
310
+ } catch {
311
+ return !1;
312
+ }
313
+ }
444
314
  normalizePlayRate(t) {
445
315
  return typeof t != "number" || !Number.isFinite(t) ? 1 : Math.max(0.1, Math.min(100, t));
446
316
  }
447
317
  normalizeVolume(t) {
448
318
  return typeof t != "number" || !Number.isFinite(t) ? 1 : Math.max(0, Math.min(1, t));
449
319
  }
450
- computeSegmentVolume(t, o) {
451
- const i = this.normalizeVolume(t.volume), n = Math.max(0, t.endTime - t.startTime), a = Math.max(0, t.fadeInDuration ?? 0), c = Math.max(0, t.fadeOutDuration ?? 0);
452
- let u = 1;
453
- a > 0 && o < a && (u = Math.max(0, o / a));
454
- const d = n - o;
455
- return c > 0 && d < c && (u = Math.min(u, Math.max(0, d / c))), i * u;
320
+ computeSegmentSourceOffsetMs(t, i, n) {
321
+ if (typeof n == "number" && Number.isFinite(n))
322
+ return Math.max(0, n);
323
+ const o = Math.max(0, i - t.startTime), a = Math.max(0, t.fromTime ?? 0), u = this.normalizePlayRate(t.playRate);
324
+ return Math.max(0, a + o * u);
325
+ }
326
+ resolveAudioElementSourceWindow(t, i, n) {
327
+ const o = this.normalizePlayRate(i.playRate), a = Math.max(0, i.fromTime ?? 0), d = Math.max(0, i.endTime - i.startTime) * o, f = Math.max(0, a + d) / 1e3, g = Number.isFinite(t.el.duration) ? Math.max(0, t.el.duration) : void 0, m = g === void 0 ? f : Math.min(f, g), S = Math.max(0, n / 1e3), w = Math.max(0, Math.min(S, m)), l = S >= m - 0.01;
328
+ return { targetSourceSec: w, isSourceExhausted: l };
329
+ }
330
+ normalizeSampleRate(t) {
331
+ return !Number.isFinite(t) || t <= 0 ? 48e3 : Math.round(t);
332
+ }
333
+ normalizePcmChannels(t) {
334
+ if (!t)
335
+ return;
336
+ if (t instanceof Float32Array)
337
+ return t.length > 0 ? [t] : void 0;
338
+ if (!Array.isArray(t) || t.length === 0)
339
+ return;
340
+ const i = [];
341
+ for (const n of t)
342
+ !(n instanceof Float32Array) || n.length === 0 || i.push(n);
343
+ if (i.length !== 0)
344
+ return i;
456
345
  }
457
346
  audioKey(t) {
458
347
  return `audio:${t}`;
@@ -460,400 +349,1203 @@ class ue {
460
349
  videoKey(t) {
461
350
  return `video:${t}`;
462
351
  }
463
- async loadClip(t) {
464
- const o = this.clips.get(t.id);
465
- if (o)
466
- return o;
467
- const i = this.loadingClips.get(t.id);
468
- if (i)
469
- return i;
470
- const n = (async () => {
471
- try {
472
- const a = await fetch(t.url);
473
- if (!a.body) {
474
- this.loadingClips.delete(t.id);
475
- return;
476
- }
477
- const c = new Tt(a.body), u = { clip: c, ready: c.ready };
478
- if (await c.ready, !this.findSegmentInProtocol(t.id)) {
479
- c.destroy(), this.loadingClips.delete(t.id);
480
- return;
481
- }
482
- return this.clips.set(t.id, u), this.loadingClips.delete(t.id), u;
483
- } catch (a) {
484
- console.error(`[AudioManager] Failed to load audio ${t.url}`, a), this.loadingClips.delete(t.id);
485
- return;
486
- }
487
- })();
488
- return this.loadingClips.set(t.id, n), n;
352
+ findAudioSegment(t) {
353
+ for (const i of this.protocol.tracks)
354
+ for (const n of i.children)
355
+ if (n.id === t && n.segmentType === "audio")
356
+ return n;
489
357
  }
490
- findSegmentInProtocol(t) {
491
- for (const o of this.protocol.tracks)
492
- for (const i of o.children)
493
- if (i.id === t) return !0;
494
- return !1;
358
+ findVideoSegment(t) {
359
+ for (const i of this.protocol.tracks)
360
+ for (const n of i.children)
361
+ if (n.id === t && n.segmentType === "frames" && n.type === "video")
362
+ return n;
495
363
  }
496
364
  getSegmentVolume(t) {
497
- for (const o of this.protocol.tracks)
498
- for (const i of o.children) {
499
- if (i.id !== t)
365
+ for (const i of this.protocol.tracks)
366
+ for (const n of i.children) {
367
+ if (n.id !== t)
500
368
  continue;
501
- const n = i.volume;
502
- return this.normalizeVolume(n);
369
+ const o = n.volume;
370
+ return this.normalizeVolume(o);
503
371
  }
504
372
  return 1;
505
373
  }
506
- getClipSampleRate(t) {
507
- const o = t.meta;
508
- if (!o)
509
- return 48e3;
510
- const i = o.audioSampleRate;
511
- if (typeof i == "number" && i > 0)
512
- return i;
513
- const n = o.sampleRate;
514
- return typeof n == "number" && n > 0 ? n : 48e3;
374
+ }
375
+ function Yt(e, t, i, n, o) {
376
+ const a = t || n, u = i || o;
377
+ if (!a || !u)
378
+ return { width: n, height: o };
379
+ const d = a / u, f = n / o;
380
+ switch (e) {
381
+ case "none":
382
+ return { width: a, height: u };
383
+ case "cover":
384
+ return d > f ? { width: o * d, height: o } : { width: n, height: n / d };
385
+ case "stretch":
386
+ return { width: n, height: o };
387
+ default:
388
+ return d > f ? { width: n, height: n / d } : { width: o * d, height: o };
515
389
  }
516
390
  }
517
- const le = 100, $ = /* @__PURE__ */ new Map();
518
- let de = le;
519
- function fe(e, t) {
520
- $.delete(e), $.set(e, t);
391
+ function Xt(e, t, i, n, o) {
392
+ const a = "fillMode" in e ? e.fillMode : void 0, { width: u, height: d } = Yt(
393
+ a,
394
+ n,
395
+ o,
396
+ t,
397
+ i
398
+ ), f = "transform" in e ? e.transform : void 0, [g, m] = f?.position ?? [0, 0], [S, w] = f?.scale ?? [1, 1], l = f?.rotation?.[2] ?? 0, h = u * S, b = d * w, T = t / 2 + g * t / 2, I = i / 2 - m * i / 2;
399
+ return {
400
+ width: h,
401
+ height: b,
402
+ centerX: T,
403
+ centerY: I,
404
+ rotationRad: l / 180 * Math.PI
405
+ };
406
+ }
407
+ function Ht(e) {
408
+ const t = /* @__PURE__ */ new Set();
409
+ for (const i of e.tracks)
410
+ for (const n of i.children)
411
+ n.url && t.add(n.url);
412
+ return t;
413
+ }
414
+ function Jt(e, t, i, n, o = {}) {
415
+ const a = en(o.opacity ?? Zt(t)), u = e instanceof U && e.texture.width || i, d = e instanceof U && e.texture.height || n, f = Xt(t, i, n, u, d);
416
+ e instanceof U ? (e.anchor.set(0.5), e.width = f.width, e.height = f.height, e.position.set(f.centerX, f.centerY), e.rotation = f.rotationRad, e.texture.source?.addEventListener?.("error", () => {
417
+ e.texture = $.from(Qt(i, n));
418
+ }, { once: !0 })) : e instanceof Ze && (e.clear(), e.rect(0, 0, f.width, f.height).fill({ color: nt("url" in t && typeof t.url == "string" ? t.url : t.segmentType), alpha: it(t) ? a : 0.35 }), e.pivot.set(f.width / 2, f.height / 2), e.position.set(f.centerX, f.centerY), e.rotation = f.rotationRad), e.alpha = a;
419
+ }
420
+ function me(e, t) {
421
+ const i = new Ze();
422
+ return i.rect(0, 0, 10, 10).fill({ color: nt(t ?? e), alpha: 1 }), i;
423
+ }
424
+ function Qt(e, t, i) {
425
+ const n = `<svg xmlns="http://www.w3.org/2000/svg" width="${e}" height="${t}"><rect width="100%" height="100%" fill="#0f172a" fill-opacity="0.8"/></svg>`;
426
+ return `data:image/svg+xml;base64,${btoa(n)}`;
427
+ }
428
+ function nt(e) {
429
+ let t = 0;
430
+ for (let i = 0; i < e.length; i++)
431
+ t = e.charCodeAt(i) + ((t << 5) - t);
432
+ return t & 16777215;
433
+ }
434
+ function ve(e) {
435
+ const t = e.tracks.flatMap((i) => i.children.map((n) => n.endTime));
436
+ return t.length ? Math.max(...t) : 0;
437
+ }
438
+ function pe(e, t, i) {
439
+ return Math.min(Math.max(e, t), i);
440
+ }
441
+ function je(e) {
442
+ const t = Dt(e);
443
+ return JSON.parse(JSON.stringify(t));
444
+ }
445
+ function it(e) {
446
+ return "opacity" in e;
447
+ }
448
+ function Zt(e) {
449
+ return it(e) && typeof e.opacity == "number" ? e.opacity : 1;
450
+ }
451
+ function en(e) {
452
+ return Number.isFinite(e) ? Math.min(Math.max(e, 0), 1) : 1;
453
+ }
454
+ const tn = 0.1, nn = 100;
455
+ function rn(e = {}) {
456
+ const t = e.now ?? on;
457
+ let i = !!e.playing, n = qe(e.initialRate), o = 0, a = C(void 0, t), u = he(e.initialTimelineMs);
458
+ const d = /* @__PURE__ */ new Set();
459
+ i && (a = C(void 0, t));
460
+ const f = (w) => i ? u + (w - a) * n : u, g = (w) => ({
461
+ playing: i,
462
+ timelineMs: he(f(w)),
463
+ rate: n,
464
+ epochWallMs: a,
465
+ epochTimelineMs: u,
466
+ discontinuitySeq: o
467
+ }), m = (w) => {
468
+ for (const l of d)
469
+ l(w);
470
+ }, S = (w, l) => {
471
+ u = he(w), a = l;
472
+ };
473
+ return {
474
+ getSnapshot(w) {
475
+ return g(C(w, t));
476
+ },
477
+ play(w) {
478
+ const l = C(w, t);
479
+ if (!i) {
480
+ const b = f(l);
481
+ i = !0, S(b, l);
482
+ }
483
+ const h = g(l);
484
+ return m(h), h;
485
+ },
486
+ pause(w) {
487
+ const l = C(w, t);
488
+ if (i) {
489
+ const b = f(l);
490
+ i = !1, S(b, l);
491
+ }
492
+ const h = g(l);
493
+ return m(h), h;
494
+ },
495
+ seek(w, l) {
496
+ const h = C(l, t);
497
+ S(w, h), o += 1;
498
+ const b = g(h);
499
+ return m(b), b;
500
+ },
501
+ setRate(w, l) {
502
+ const h = C(l, t), b = qe(w), T = f(h);
503
+ S(T, h), Math.abs(n - b) > 1e-4 && (n = b, o += 1);
504
+ const I = g(h);
505
+ return m(I), I;
506
+ },
507
+ subscribe(w) {
508
+ return d.add(w), () => {
509
+ d.delete(w);
510
+ };
511
+ }
512
+ };
513
+ }
514
+ function C(e, t) {
515
+ return typeof e == "number" && Number.isFinite(e) ? e : t();
516
+ }
517
+ function he(e) {
518
+ return typeof e != "number" || !Number.isFinite(e) ? 0 : Math.max(0, e);
519
+ }
520
+ function qe(e) {
521
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.min(nn, Math.max(tn, e));
522
+ }
523
+ function on() {
524
+ return typeof globalThis.performance < "u" && typeof globalThis.performance.now == "function" ? globalThis.performance.now() : Date.now();
525
+ }
526
+ function an(e) {
527
+ const t = /* @__PURE__ */ new Map(), i = un(e);
528
+ for (const n of e.transitions ?? [])
529
+ !cn(n) || i.get(n.fromSegmentId) !== n.toSegmentId || t.set(n.fromSegmentId, {
530
+ id: n.id,
531
+ name: n.name,
532
+ duration: n.duration,
533
+ fromSegmentId: n.fromSegmentId,
534
+ toSegmentId: n.toSegmentId
535
+ });
536
+ return t;
537
+ }
538
+ function sn(e) {
539
+ return !e || typeof e != "object" || typeof e.id != "string" || typeof e.name != "string" ? !1 : Number.isFinite(e.duration) && e.duration > 0;
540
+ }
541
+ function cn(e) {
542
+ return !e || typeof e != "object" || typeof e.fromSegmentId != "string" || typeof e.toSegmentId != "string" ? !1 : sn(e);
521
543
  }
522
- function he() {
523
- for (; $.size > de; ) {
524
- const [e, t] = $.entries().next().value;
525
- $.delete(e), t.close?.();
544
+ function un(e) {
545
+ const t = /* @__PURE__ */ new Map();
546
+ for (const i of e.tracks) {
547
+ if (i.trackType !== "frames")
548
+ continue;
549
+ const n = i.children;
550
+ for (let o = 0; o < n.length - 1; o++) {
551
+ const a = n[o], u = n[o + 1];
552
+ !a || !u || t.set(a.id, u.id);
553
+ }
554
+ }
555
+ return t;
556
+ }
557
+ function ne() {
558
+ return {
559
+ activeVoices: []
560
+ };
561
+ }
562
+ function rt(e, t, i = ne()) {
563
+ const n = te(t.atMs), o = te(t.windowStartMs), a = Math.max(o, te(t.windowEndMs)), u = [], d = /* @__PURE__ */ new Map(), f = wn(e, n), g = an(e);
564
+ for (let l = 0; l < e.tracks.length; l++) {
565
+ const h = e.tracks[l], b = yn(e.tracks.length, l, h);
566
+ for (let T = 0; T < h.children.length; T++) {
567
+ const I = h.children[T];
568
+ if (!ot(I, n) || I.segmentType === "effect" || I.segmentType === "filter")
569
+ continue;
570
+ I.segmentType !== "audio" && u.push(dn({
571
+ segment: I,
572
+ track: h,
573
+ trackOrder: b,
574
+ childIndex: T,
575
+ atMs: n,
576
+ transition: g.get(I.id),
577
+ effects: f
578
+ }));
579
+ const E = ln(I, h, n);
580
+ E && d.set(E.voiceId, E);
581
+ }
582
+ }
583
+ u.sort((l, h) => l.zOrder !== h.zOrder ? l.zOrder - h.zOrder : l.segmentId.localeCompare(h.segmentId));
584
+ const m = /* @__PURE__ */ new Map();
585
+ for (const l of i.activeVoices)
586
+ m.set(l.voiceId, l);
587
+ const S = [];
588
+ for (const [l, h] of m)
589
+ d.has(l) || S.push({
590
+ voiceId: l,
591
+ segmentId: h.segmentId,
592
+ trackId: h.trackId,
593
+ segmentKind: h.segmentKind,
594
+ action: "stop",
595
+ atTimelineMs: n
596
+ });
597
+ const w = [];
598
+ for (const l of d.values())
599
+ w.push({
600
+ voiceId: l.voiceId,
601
+ segmentId: l.segmentId,
602
+ trackId: l.trackId,
603
+ segmentKind: l.segmentKind
604
+ }), m.has(l.voiceId) ? t.discontinuity && S.push({
605
+ voiceId: l.voiceId,
606
+ segmentId: l.segmentId,
607
+ trackId: l.trackId,
608
+ segmentKind: l.segmentKind,
609
+ action: "seek",
610
+ atTimelineMs: n,
611
+ sourceTimeMs: l.sourceTimeMs
612
+ }) : S.push({
613
+ voiceId: l.voiceId,
614
+ segmentId: l.segmentId,
615
+ trackId: l.trackId,
616
+ segmentKind: l.segmentKind,
617
+ action: "start",
618
+ atTimelineMs: n,
619
+ sourceTimeMs: l.sourceTimeMs,
620
+ gain: l.gain,
621
+ rate: l.rate
622
+ }), S.push({
623
+ voiceId: l.voiceId,
624
+ segmentId: l.segmentId,
625
+ trackId: l.trackId,
626
+ segmentKind: l.segmentKind,
627
+ action: "gain",
628
+ atTimelineMs: n,
629
+ gain: l.gain
630
+ }), S.push({
631
+ voiceId: l.voiceId,
632
+ segmentId: l.segmentId,
633
+ trackId: l.trackId,
634
+ segmentKind: l.segmentKind,
635
+ action: "rate",
636
+ atTimelineMs: n,
637
+ rate: l.rate
638
+ });
639
+ return {
640
+ plan: {
641
+ atMs: n,
642
+ windowStartMs: o,
643
+ windowEndMs: a,
644
+ visuals: u,
645
+ audioEvents: S
646
+ },
647
+ state: {
648
+ activeVoices: w
649
+ }
650
+ };
651
+ }
652
+ function dn(e) {
653
+ const {
654
+ segment: t,
655
+ track: i,
656
+ trackOrder: n,
657
+ childIndex: o,
658
+ atMs: a,
659
+ transition: u,
660
+ effects: d
661
+ } = e;
662
+ return {
663
+ segmentId: t.id,
664
+ trackId: i.trackId,
665
+ trackType: i.trackType,
666
+ segmentType: t.segmentType,
667
+ zOrder: n * 1e4 + o,
668
+ sourceTimeMs: fn(t, a),
669
+ opacity: pn(t),
670
+ transition: mn(t, u, a),
671
+ effects: d.length ? d : void 0
672
+ };
673
+ }
674
+ function ln(e, t, i) {
675
+ if (tt(e)) {
676
+ const n = Math.max(0, i - e.startTime);
677
+ return {
678
+ voiceId: `audio:${e.id}`,
679
+ segmentId: e.id,
680
+ trackId: t.trackId,
681
+ segmentKind: "audio",
682
+ sourceTimeMs: Me(e, i),
683
+ gain: hn(e, n),
684
+ rate: Se(e.playRate)
685
+ };
686
+ }
687
+ if (Ie(e)) {
688
+ const n = ke(e.volume);
689
+ return n <= 0 ? void 0 : {
690
+ voiceId: `video:${e.id}`,
691
+ segmentId: e.id,
692
+ trackId: t.trackId,
693
+ segmentKind: "video",
694
+ sourceTimeMs: Me(e, i),
695
+ gain: n,
696
+ rate: Se(e.playRate)
697
+ };
526
698
  }
527
699
  }
528
- function pe(e) {
700
+ function fn(e, t) {
701
+ return tt(e) || Ie(e) ? Me(e, t) : Math.max(0, t - e.startTime);
702
+ }
703
+ function Me(e, t) {
704
+ const i = Math.max(0, t - e.startTime), n = te(e.fromTime ?? 0), o = Se(e.playRate);
705
+ return Math.max(0, n + i * o);
706
+ }
707
+ function mn(e, t, i) {
708
+ if (e.segmentType !== "frames" || !t || t.fromSegmentId !== e.id)
709
+ return;
710
+ const n = e.endTime - t.duration;
711
+ if (i < n || i >= e.endTime)
712
+ return;
713
+ const o = (i - n) / t.duration;
714
+ return {
715
+ fromSegmentId: e.id,
716
+ toSegmentId: t.toSegmentId,
717
+ progress: ie(o, 0, 1),
718
+ transitionId: t.id,
719
+ transitionName: t.name,
720
+ durationMs: t.duration
721
+ };
722
+ }
723
+ function ot(e, t) {
724
+ return e.startTime <= t && t < e.endTime;
725
+ }
726
+ function pn(e) {
727
+ return "opacity" in e && typeof e.opacity == "number" && Number.isFinite(e.opacity) ? ie(e.opacity, 0, 1) : 1;
728
+ }
729
+ function hn(e, t) {
730
+ const i = ke(e.volume), n = Math.max(0, e.endTime - e.startTime), o = Math.max(0, e.fadeInDuration ?? 0), a = Math.max(0, e.fadeOutDuration ?? 0);
731
+ let u = 1;
732
+ o > 0 && t < o && (u = Math.max(0, t / o));
733
+ const d = n - t;
734
+ return a > 0 && d < a && (u = Math.min(u, Math.max(0, d / a))), i * u;
735
+ }
736
+ function yn(e, t, i) {
737
+ return i.trackType === "frames" && "isMain" in i && i.isMain ? 0 : e - t;
738
+ }
739
+ function wn(e, t) {
740
+ const i = [];
741
+ for (const n of e.tracks)
742
+ for (const o of n.children)
743
+ ot(o, t) && (o.segmentType === "effect" ? i.push({
744
+ segmentType: "effect",
745
+ segmentId: o.id,
746
+ effectId: o.effectId,
747
+ name: o.name
748
+ }) : o.segmentType === "filter" && i.push({
749
+ segmentType: "filter",
750
+ segmentId: o.id,
751
+ filterId: o.filterId,
752
+ name: o.name,
753
+ intensity: ke(o.intensity)
754
+ }));
755
+ return i;
756
+ }
757
+ function te(e) {
758
+ return Number.isFinite(e) ? Math.max(0, e) : 0;
759
+ }
760
+ function ke(e) {
761
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : ie(e, 0, 1);
762
+ }
763
+ function Se(e) {
764
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : ie(e, 0.1, 100);
765
+ }
766
+ function ie(e, t, i) {
767
+ return Math.min(Math.max(e, t), i);
768
+ }
769
+ function at() {
770
+ let e = ne();
771
+ return {
772
+ evaluate(t, i) {
773
+ const n = rt(t, i, e);
774
+ return e = n.state, n.plan;
775
+ },
776
+ reset() {
777
+ e = ne();
778
+ },
779
+ getState() {
780
+ return e;
781
+ }
782
+ };
783
+ }
784
+ const gn = 20, vn = 100;
785
+ function Mn(e) {
786
+ const t = _e(e.lookbackMs, gn), i = _e(e.lookaheadMs, vn), n = at();
787
+ let o = e.transport.getSnapshot().discontinuitySeq;
788
+ return {
789
+ evaluate(a, u) {
790
+ const d = e.transport.getSnapshot(), f = Sn(typeof u == "number" ? u : d.timelineMs), g = d.discontinuitySeq !== o;
791
+ return g && (o = d.discontinuitySeq), n.evaluate(a, {
792
+ atMs: f,
793
+ windowStartMs: Math.max(0, f - t),
794
+ windowEndMs: f + i,
795
+ fps: Math.max(a.fps || 30, 1),
796
+ discontinuity: g
797
+ });
798
+ },
799
+ reset() {
800
+ n.reset(), o = e.transport.getSnapshot().discontinuitySeq;
801
+ },
802
+ getState() {
803
+ return n.getState();
804
+ }
805
+ };
806
+ }
807
+ function _e(e, t) {
808
+ return typeof e != "number" || !Number.isFinite(e) ? t : Math.max(0, e);
809
+ }
810
+ function Sn(e) {
811
+ return Number.isFinite(e) ? Math.max(0, e) : 0;
812
+ }
813
+ function Tn() {
814
+ const e = at();
815
+ let t;
816
+ return {
817
+ evaluateAt(i, n, o = {}) {
818
+ const a = ye(n), u = ye(o.windowStartMs ?? a), d = Math.max(
819
+ u,
820
+ ye(o.windowEndMs ?? a)
821
+ ), f = {
822
+ atMs: a,
823
+ windowStartMs: u,
824
+ windowEndMs: d,
825
+ fps: Math.max(i.fps || 30, 1),
826
+ discontinuity: typeof o.discontinuity == "boolean" ? o.discontinuity : t !== void 0 && a < t
827
+ };
828
+ return t = a, e.evaluate(i, f);
829
+ },
830
+ evaluateSequence(i, n) {
831
+ const o = [];
832
+ for (const a of n)
833
+ o.push(this.evaluateAt(i, a));
834
+ return o;
835
+ },
836
+ reset() {
837
+ e.reset(), t = void 0;
838
+ },
839
+ getState() {
840
+ return e.getState();
841
+ }
842
+ };
843
+ }
844
+ function ye(e) {
845
+ return typeof e != "number" || !Number.isFinite(e) ? 0 : Math.max(0, e);
846
+ }
847
+ const bn = 20;
848
+ function In(e) {
849
+ const t = kn(e.intervalMs, bn), i = e.setInterval ?? ((u, d) => globalThis.setInterval(u, d)), n = e.clearInterval ?? ((u) => {
850
+ globalThis.clearInterval(u);
851
+ });
852
+ let o;
853
+ const a = () => {
854
+ const u = e.transport.getSnapshot(), d = e.runner.evaluate(e.getProtocol(), u.timelineMs);
855
+ return e.onPlan(d, u), d;
856
+ };
857
+ return {
858
+ start() {
859
+ o === void 0 && (a(), o = i(() => {
860
+ a();
861
+ }, t));
862
+ },
863
+ stop() {
864
+ o !== void 0 && (n(o), o = void 0);
865
+ },
866
+ tick: a,
867
+ isRunning() {
868
+ return o !== void 0;
869
+ }
870
+ };
871
+ }
872
+ function kn(e, t) {
873
+ return typeof e != "number" || !Number.isFinite(e) ? t : Math.max(1, e);
874
+ }
875
+ function xn(e, t) {
876
+ const i = An(e), n = /* @__PURE__ */ new Set();
877
+ for (const a of t)
878
+ n.add(a.segmentId);
879
+ const o = [];
880
+ for (const a of t) {
881
+ const u = i.get(a.segmentId);
882
+ if (!u)
883
+ continue;
884
+ const d = Te(a.transition?.progress ?? 0), f = Te(a.opacity) * (a.transition ? 1 - d : 1);
885
+ if (o.push({
886
+ segment: u,
887
+ sourceTimeMs: Math.max(0, a.sourceTimeMs),
888
+ opacity: f,
889
+ includeAudio: !0,
890
+ effects: a.effects
891
+ }), !a.transition || d <= 0 || n.has(a.transition.toSegmentId))
892
+ continue;
893
+ const g = i.get(a.transition.toSegmentId);
894
+ if (!g)
895
+ continue;
896
+ const m = st(a.transition.durationMs);
897
+ if (m <= 0)
898
+ continue;
899
+ const S = m * d, w = En(g, S), l = Rn(g) * d;
900
+ o.push({
901
+ segment: g,
902
+ sourceTimeMs: w,
903
+ opacity: l,
904
+ includeAudio: !1,
905
+ effects: a.effects
906
+ });
907
+ }
908
+ return o;
909
+ }
910
+ function An(e) {
911
+ const t = /* @__PURE__ */ new Map();
912
+ for (const i of e.tracks)
913
+ for (const n of i.children)
914
+ t.set(n.id, n);
915
+ return t;
916
+ }
917
+ function En(e, t) {
918
+ if (Ie(e)) {
919
+ const i = st(e.fromTime), n = Vn(e.playRate);
920
+ return Math.max(0, i + t * n);
921
+ }
922
+ return Math.max(0, t);
923
+ }
924
+ function Rn(e) {
925
+ return "opacity" in e && typeof e.opacity == "number" && Number.isFinite(e.opacity) ? Te(e.opacity) : 1;
926
+ }
927
+ function st(e) {
928
+ return typeof e != "number" || !Number.isFinite(e) ? 0 : Math.max(0, e);
929
+ }
930
+ function Vn(e) {
931
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.min(Math.max(e, 0.1), 100);
932
+ }
933
+ function Te(e) {
934
+ return Number.isFinite(e) ? Math.min(Math.max(e, 0), 1) : 0;
935
+ }
936
+ function Fn(e) {
937
+ if (!e?.length)
938
+ return [];
939
+ const t = [];
940
+ for (const i of e) {
941
+ const n = i.segmentType === "filter" ? Pn(i) : On(i);
942
+ n && t.push(n);
943
+ }
944
+ return t;
945
+ }
946
+ function Pn(e) {
947
+ const t = ut(e.name, e.filterId), i = Cn(e.intensity);
948
+ if (ct(t))
949
+ return new et({ strength: 1 + i * 14, quality: 2, kernelSize: 5 });
950
+ const n = new ge();
951
+ return zn(t) ? n.grayscale(i, !1) : t.includes("sepia") || t.includes("warm") ? n.sepia(!1) : t.includes("negative") || t.includes("invert") ? n.negative(!1) : t.includes("vintage") || t.includes("retro") ? n.vintage(!1) : t.includes("contrast") ? n.contrast(0.5 + i * 0.5, !1) : t.includes("brightness") || t.includes("bright") ? n.brightness(0.5 + i, !1) : t.includes("saturate") || t.includes("vivid") ? n.saturate(i, !1) : t.includes("cool") ? n.hue(-20 * i, !1) : n.saturate(-0.3 * i, !1), n;
952
+ }
953
+ function On(e) {
954
+ const t = ut(e.name, e.effectId);
955
+ if (ct(t) || t.includes("glow") || t.includes("dream") || t.includes("soft"))
956
+ return new et({ strength: 4, quality: 2, kernelSize: 5 });
957
+ if (t.includes("vintage") || t.includes("retro")) {
958
+ const i = new ge();
959
+ return i.vintage(!1), i;
960
+ }
961
+ if (t.includes("sharpen") || t.includes("clarity")) {
962
+ const i = new ge();
963
+ return i.contrast(0.75, !1), i;
964
+ }
965
+ }
966
+ function ct(e) {
967
+ return e.includes("blur") || e.includes("gaussian");
968
+ }
969
+ function zn(e) {
970
+ return e.includes("grayscale") || e.includes("grey") || e.includes("gray") || e.includes("mono") || e.includes("blackwhite") || e.includes("bw");
971
+ }
972
+ function ut(...e) {
973
+ return e.join(" ").toLowerCase().replace(/[^a-z0-9]+/g, "");
974
+ }
975
+ function Cn(e) {
976
+ return Number.isFinite(e) ? Math.min(Math.max(e, 0), 1) : 1;
977
+ }
978
+ function Un(e) {
979
+ const t = Dn(e), i = $n(t);
980
+ if (!i.length)
981
+ return [];
982
+ const n = [], o = /* @__PURE__ */ new Map(), u = Tn().evaluateSequence(e, i);
983
+ for (const d of u)
984
+ for (const f of d.audioEvents)
985
+ Nn(f, t, o, n);
986
+ for (const d of o.values()) {
987
+ const f = dt(d, t, Kn(d, t));
988
+ f && n.push(f);
989
+ }
990
+ return n.sort((d, f) => d.startTime !== f.startTime ? d.startTime - f.startTime : d.endTime !== f.endTime ? d.endTime - f.endTime : d.segmentId.localeCompare(f.segmentId));
991
+ }
992
+ function Nn(e, t, i, n) {
993
+ if (e.action === "start") {
994
+ const u = xe(e.segmentKind, e.segmentId, t);
995
+ if (!u || lt(u) <= 0)
996
+ return;
997
+ const f = {
998
+ voiceId: e.voiceId,
999
+ segmentKind: e.segmentKind,
1000
+ segmentId: e.segmentId,
1001
+ startTime: e.atTimelineMs,
1002
+ fromTime: Math.max(0, e.sourceTimeMs ?? Gn(u)),
1003
+ playRate: ft(e.rate ?? Ln(u))
1004
+ };
1005
+ i.set(e.voiceId, f);
1006
+ return;
1007
+ }
1008
+ if (e.action !== "stop")
1009
+ return;
1010
+ const o = i.get(e.voiceId);
1011
+ if (!o)
1012
+ return;
1013
+ i.delete(e.voiceId);
1014
+ const a = dt(o, t, e.atTimelineMs);
1015
+ a && n.push(a);
1016
+ }
1017
+ function dt(e, t, i) {
1018
+ const n = xe(e.segmentKind, e.segmentId, t);
1019
+ if (!n)
1020
+ return;
1021
+ const o = Xe(e.startTime, n.startTime, n.endTime), a = Xe(i, o, n.endTime);
1022
+ if (a <= o)
1023
+ return;
1024
+ const u = {
1025
+ segmentId: n.id,
1026
+ segmentKind: e.segmentKind,
1027
+ url: n.url,
1028
+ startTime: o,
1029
+ endTime: a,
1030
+ fromTime: e.fromTime,
1031
+ playRate: e.playRate,
1032
+ volume: lt(n)
1033
+ };
1034
+ if (n.segmentType === "audio") {
1035
+ const d = Math.max(0, a - o);
1036
+ return {
1037
+ ...u,
1038
+ fadeInDuration: Ye(n.fadeInDuration, d),
1039
+ fadeOutDuration: Ye(n.fadeOutDuration, d)
1040
+ };
1041
+ }
1042
+ return u;
1043
+ }
1044
+ function Dn(e) {
1045
+ const t = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
1046
+ for (const n of e.tracks)
1047
+ for (const o of n.children)
1048
+ o.segmentType === "audio" ? t.set(o.id, o) : o.segmentType === "frames" && o.type === "video" && i.set(o.id, o);
1049
+ return { audioById: t, videoById: i };
1050
+ }
1051
+ function $n(e) {
1052
+ const t = /* @__PURE__ */ new Set([0]);
1053
+ for (const i of e.audioById.values())
1054
+ We(t, i.startTime, i.endTime);
1055
+ for (const i of e.videoById.values())
1056
+ We(t, i.startTime, i.endTime);
1057
+ return [...t].sort((i, n) => i - n);
1058
+ }
1059
+ function We(e, t, i) {
1060
+ !Number.isFinite(t) || !Number.isFinite(i) || i <= t || (e.add(Math.max(0, t)), e.add(Math.max(0, i)));
1061
+ }
1062
+ function xe(e, t, i) {
1063
+ return e === "audio" ? i.audioById.get(t) : i.videoById.get(t);
1064
+ }
1065
+ function Kn(e, t) {
1066
+ const i = xe(e.segmentKind, e.segmentId, t);
1067
+ return i ? i.endTime : e.startTime;
1068
+ }
1069
+ function Gn(e) {
1070
+ return typeof e.fromTime != "number" || !Number.isFinite(e.fromTime) ? 0 : Math.max(0, e.fromTime);
1071
+ }
1072
+ function Ln(e) {
1073
+ return ft(e.playRate);
1074
+ }
1075
+ function lt(e) {
1076
+ return Bn(e.volume);
1077
+ }
1078
+ function Ye(e, t) {
1079
+ return typeof e != "number" || !Number.isFinite(e) ? 0 : Math.max(0, Math.min(e, t));
1080
+ }
1081
+ function ft(e) {
1082
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(0.1, Math.min(100, e));
1083
+ }
1084
+ function Bn(e) {
1085
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(0, Math.min(1, e));
1086
+ }
1087
+ function Xe(e, t, i) {
1088
+ return Math.min(Math.max(e, t), i);
1089
+ }
1090
+ const jn = 100, N = /* @__PURE__ */ new Map();
1091
+ let qn = jn;
1092
+ function _n(e, t) {
1093
+ N.delete(e), N.set(e, t);
1094
+ }
1095
+ function Wn() {
1096
+ for (; N.size > qn; ) {
1097
+ const [e, t] = N.entries().next().value;
1098
+ N.delete(e), t.close?.();
1099
+ }
1100
+ }
1101
+ function Yn(e) {
529
1102
  return e.map((t) => t.content).filter(Boolean).join(`
530
1103
  `);
531
1104
  }
532
- function me(e) {
533
- const t = Array.isArray(e.fontFamily) ? e.fontFamily.join(", ") : e.fontFamily, o = e.fontSize ?? 32, i = e.fontWeight ?? "normal", n = e.fontStyle ?? "normal", a = e.fill ?? "#ffffff", c = e.align ?? "left", u = [
534
- `font-size: ${o}px`,
535
- `font-weight: ${i}`,
536
- `font-style: ${n}`,
1105
+ function Xn(e) {
1106
+ const t = Array.isArray(e.fontFamily) ? e.fontFamily.join(", ") : e.fontFamily, i = e.fontSize ?? 32, n = e.fontWeight ?? "normal", o = e.fontStyle ?? "normal", a = e.fill ?? "#ffffff", u = e.align ?? "left", d = [
1107
+ `font-size: ${i}px`,
1108
+ `font-weight: ${n}`,
1109
+ `font-style: ${o}`,
537
1110
  `color: ${a}`,
538
- `text-align: ${c}`,
1111
+ `text-align: ${u}`,
539
1112
  "white-space: pre-wrap"
540
1113
  ];
541
- if (t && u.push(`font-family: ${t}`), typeof e.letterSpacing == "number" && u.push(`letter-spacing: ${e.letterSpacing}px`), typeof e.leading == "number" && u.push(`line-height: ${e.leading}px`), e.background?.color && u.push(`background: ${e.background.color}`), e.stroke?.color && typeof e.stroke.width == "number" && u.push(`-webkit-text-stroke: ${e.stroke.width}px ${e.stroke.color}`), e.underline && u.push("text-decoration: underline"), e.dropShadow?.color && typeof e.dropShadow.distance == "number") {
542
- const d = (e.dropShadow.angle ?? 45) * (Math.PI / 180), y = Math.cos(d) * e.dropShadow.distance, h = Math.sin(d) * e.dropShadow.distance, w = e.dropShadow.blur ?? 0;
543
- u.push(`text-shadow: ${y}px ${h}px ${w}px ${e.dropShadow.color}`);
544
- }
545
- return u.join("; ");
546
- }
547
- async function ye(e, t) {
548
- const o = `${t}::${e}`, i = $.get(o);
549
- if (i)
550
- return fe(o, i), i;
551
- const n = await Zt(e, t);
552
- return $.set(o, n), he(), n;
553
- }
554
- const we = "/video-editor-res";
555
- async function ve(e) {
556
- const t = Wt(), o = Jt(e.protocol) ? e.protocol : vt(e.protocol), i = vt(
557
- t.verify(St(Mt(o)))
558
- ), n = e.app ?? await oe(e.appOptions), a = new ee();
559
- n.stage.addChild(a);
560
- const c = Yt({ dir: e.resourceDir }), u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Map(), y = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Set(), w = /* @__PURE__ */ new Set(), M = e.videoSourceMode ?? "auto", p = /* @__PURE__ */ new Map(), v = /* @__PURE__ */ new Map(), m = gt(0), g = gt(!1), R = Ht(() => it(i.value)), P = new ue(i.value);
561
- let A, E = 0, b = 0;
562
- async function q(r) {
563
- const l = b, { protocol: s, at: f, layer: S } = r, x = Kt(s, f), T = Rt(s, x), k = r.app.renderer.width, C = r.app.renderer.height;
564
- P.sync(f, g.value);
565
- const I = [];
566
- for (const { segment: N } of T) {
567
- if (l !== b)
1114
+ if (t && d.push(`font-family: ${t}`), typeof e.letterSpacing == "number" && d.push(`letter-spacing: ${e.letterSpacing}px`), typeof e.leading == "number" && d.push(`line-height: ${e.leading}px`), e.background?.color && d.push(`background: ${e.background.color}`), e.stroke?.color && typeof e.stroke.width == "number" && d.push(`-webkit-text-stroke: ${e.stroke.width}px ${e.stroke.color}`), e.underline && d.push("text-decoration: underline"), e.dropShadow?.color && typeof e.dropShadow.distance == "number") {
1115
+ const f = (e.dropShadow.angle ?? 45) * (Math.PI / 180), g = Math.cos(f) * e.dropShadow.distance, m = Math.sin(f) * e.dropShadow.distance, S = e.dropShadow.blur ?? 0;
1116
+ d.push(`text-shadow: ${g}px ${m}px ${S}px ${e.dropShadow.color}`);
1117
+ }
1118
+ return d.join("; ");
1119
+ }
1120
+ async function Hn(e, t) {
1121
+ const i = `${t}::${e}`, n = N.get(i);
1122
+ if (n)
1123
+ return _n(i, n), n;
1124
+ const o = await Lt(e, t);
1125
+ return N.set(i, o), Wn(), o;
1126
+ }
1127
+ const Jn = "/video-editor-res", Qn = 1500, Zn = 2;
1128
+ async function ei(e) {
1129
+ const t = Ut(), i = $t(e.protocol) ? e.protocol : Ge(e.protocol), n = Ge(
1130
+ t.verify(je(Le(i)))
1131
+ ), o = e.app ?? await _t(e.appOptions), a = new qt();
1132
+ o.stage.addChild(a);
1133
+ const u = Nt({ dir: e.resourceDir }), d = /* @__PURE__ */ new Set(), f = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map(), m = /* @__PURE__ */ new Set(), S = /* @__PURE__ */ new Set(), w = e.videoSourceMode ?? "auto", l = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Set(), T = Be(0), I = Be(!1), E = Kt(() => ve(n.value)), A = /* @__PURE__ */ new Map(), R = /* @__PURE__ */ new Map(), x = new Wt(n.value, {
1134
+ resolveMediaElementUrl: Ft
1135
+ }), O = rn({
1136
+ initialTimelineMs: T.value,
1137
+ initialRate: 1,
1138
+ playing: !1
1139
+ }), re = Mn({
1140
+ transport: O
1141
+ }), G = In({
1142
+ transport: O,
1143
+ runner: re,
1144
+ getProtocol: () => n.value,
1145
+ onPlan: (r) => {
1146
+ Re(r);
1147
+ }
1148
+ });
1149
+ let L, W = 0, P = 0;
1150
+ function Y() {
1151
+ re.reset(), x.resetTimelineState({ stop: !0 });
1152
+ }
1153
+ function Re(r) {
1154
+ x.applyTimelinePlan(r, I.value);
1155
+ }
1156
+ function pt(r, c) {
1157
+ if (I.value)
1158
+ return;
1159
+ const s = re.evaluate(r, c);
1160
+ Re(s);
1161
+ }
1162
+ async function ht(r) {
1163
+ const c = P, { protocol: s, at: p, layer: v } = r, M = Vt(s, p), y = r.app.renderer.width, k = r.app.renderer.height;
1164
+ pt(s, p), It(s, M);
1165
+ const V = rt(s, {
1166
+ atMs: M,
1167
+ windowStartMs: M,
1168
+ windowEndMs: M,
1169
+ fps: Math.max(s.fps || 30, 1)
1170
+ }, ne()).plan.visuals, F = xn(s, V), D = /* @__PURE__ */ new Map(), Q = [];
1171
+ for (const Z of F) {
1172
+ const { segment: ee } = Z;
1173
+ if (c !== P)
568
1174
  return;
569
- const L = await r.getDisplay(N);
570
- if (l !== b)
1175
+ const q = await r.getDisplay(ee);
1176
+ if (c !== P)
571
1177
  return;
572
- if (L && !L.destroyed) {
573
- if (ae(L, N, k, C), Gt(N) && await H(N, x), l !== b)
1178
+ if (q && !q.destroyed) {
1179
+ if (yt(q, Z.effects, D), Jt(q, ee, y, k, {
1180
+ opacity: Z.opacity
1181
+ }), H(ee) && await X(ee, Z.sourceTimeMs), c !== P)
574
1182
  return;
575
- I.push(L);
1183
+ Q.push(q);
576
1184
  }
577
1185
  }
578
- if (l !== b)
1186
+ if (c !== P)
579
1187
  return;
580
- S.removeChildren();
581
- const U = I.filter(Boolean);
582
- U.length && S.addChild(...U), l === b && r.app.render();
1188
+ v.removeChildren();
1189
+ const j = Q.filter(Boolean);
1190
+ j.length && v.addChild(...j), c === P && r.app.render();
1191
+ }
1192
+ function yt(r, c, s) {
1193
+ const p = c?.length ? JSON.stringify(c) : "";
1194
+ let v = s.get(p);
1195
+ v === void 0 && (v = c?.length ? Fn(c) : null, s.set(p, v)), r.filters = v;
583
1196
  }
584
- const D = Me(() => q({
585
- app: n,
1197
+ const oe = ti(() => ht({
1198
+ app: o,
586
1199
  layer: a,
587
- protocol: i.value,
588
- at: m.value,
589
- getDisplay: Lt
590
- })), z = Qt();
591
- z.run(() => {
592
- Z(
593
- () => Mt(o),
1200
+ protocol: n.value,
1201
+ at: T.value,
1202
+ getDisplay: bt
1203
+ })), Ve = Gt();
1204
+ Ve.run(() => {
1205
+ fe(
1206
+ () => Le(i),
594
1207
  (r) => {
595
1208
  try {
596
- i.value = t.verify(St(r));
597
- } catch (l) {
598
- console.error("[renderer] invalid protocol update", l);
1209
+ n.value = t.verify(je(r));
1210
+ } catch (c) {
1211
+ console.error("[renderer] invalid protocol update", c);
599
1212
  return;
600
1213
  }
601
- P.setProtocol(i.value), b += 1, _(), e.warmUpResources !== !1 && F(i.value), Y(i.value), O(), e.manualRender || D();
1214
+ x.setProtocol(n.value), Y(), I.value && G.tick(), P += 1, Fe(), e.warmUpResources !== !1 && (wt(n.value), gt(n.value)), vt(n.value), Mt(n.value), ae(), e.manualRender || oe();
602
1215
  },
603
1216
  { deep: !0, immediate: !0 }
604
- ), e.manualRender || Z(m, () => {
605
- O(), D();
606
- }), Z(R, () => O());
1217
+ ), e.manualRender || fe(T, () => {
1218
+ ae(), oe();
1219
+ }), fe(E, () => ae());
607
1220
  });
608
- function O() {
609
- const r = R.value;
610
- r <= 0 ? m.value = 0 : m.value > r ? m.value = r : m.value < 0 && (m.value = 0);
1221
+ function ae() {
1222
+ const r = E.value;
1223
+ r <= 0 ? T.value = 0 : T.value > r ? T.value = r : T.value < 0 && (T.value = 0);
611
1224
  }
612
- function F(r) {
613
- for (const l of ne(r))
614
- u.has(l) || (u.add(l), mt(l) !== "video" && ft(l) && c.add(l).catch(() => {
1225
+ function wt(r) {
1226
+ for (const c of Ht(r))
1227
+ d.has(c) || (d.add(c), De(c) !== "video" && de(c) && u.add(c).catch(() => {
615
1228
  }));
616
1229
  }
617
- function Y(r) {
618
- const l = /* @__PURE__ */ new Set();
1230
+ function gt(r) {
1231
+ for (const c of r.tracks)
1232
+ for (const s of c.children)
1233
+ H(s) && ((s.volume ?? 1) <= 0 || ue(s.url));
1234
+ }
1235
+ function vt(r) {
1236
+ const c = /* @__PURE__ */ new Set();
1237
+ for (const s of r.tracks)
1238
+ for (const p of s.children)
1239
+ c.add(p.id);
1240
+ for (const [s, p] of f)
1241
+ c.has(s) || (p.destroy(), f.delete(s));
1242
+ for (const [s, p] of l)
1243
+ c.has(s) || (Ue(p), l.delete(s));
1244
+ }
1245
+ function Mt(r) {
1246
+ const c = /* @__PURE__ */ new Set();
619
1247
  for (const s of r.tracks)
620
- for (const f of s.children)
621
- l.add(f.id);
622
- for (const [s, f] of d)
623
- l.has(s) || (f.destroy(), d.delete(s));
624
- for (const [s, f] of p)
625
- l.has(s) || (ht(f), p.delete(s));
626
- }
627
- function _() {
1248
+ for (const p of s.children) {
1249
+ if (!H(p))
1250
+ continue;
1251
+ const v = z(p.url);
1252
+ v && c.add(v);
1253
+ }
1254
+ for (const [s, p] of A)
1255
+ c.has(s) || (URL.revokeObjectURL(p), A.delete(s));
1256
+ }
1257
+ function Fe() {
628
1258
  a.removeChildren();
629
- for (const r of d.values())
1259
+ for (const r of f.values())
630
1260
  r.destroy();
631
- d.clear(), y.clear();
632
- for (const r of p.values())
633
- ht(r);
634
- p.clear();
1261
+ f.clear(), g.clear();
1262
+ for (const r of l.values())
1263
+ Ue(r);
1264
+ l.clear();
635
1265
  }
636
- function ct() {
637
- g.value || (g.value = !0, E = performance.now(), A = requestAnimationFrame(ut));
1266
+ function Pe() {
1267
+ if (I.value)
1268
+ return;
1269
+ I.value = !0;
1270
+ const r = performance.now();
1271
+ O.seek(T.value, r), O.play(r), G.start(), W = r, L = requestAnimationFrame(Oe);
638
1272
  }
639
- function X() {
640
- g.value = !1, A !== void 0 && cancelAnimationFrame(A), A = void 0, P.sync(m.value, !1), e.freezeOnPause !== !1 && qt();
1273
+ function se() {
1274
+ I.value = !1;
1275
+ const r = performance.now();
1276
+ O.pause(r), G.stop(), Y(), L !== void 0 && cancelAnimationFrame(L), L = void 0, e.freezeOnPause !== !1 && Pt();
641
1277
  }
642
- function ut() {
643
- lt(), g.value && (A = requestAnimationFrame(ut));
1278
+ function Oe() {
1279
+ ze(), I.value && (L = requestAnimationFrame(Oe));
644
1280
  }
645
- function lt(r) {
646
- if (!g.value && r === void 0)
1281
+ function ze(r) {
1282
+ if (!I.value && r === void 0)
647
1283
  return;
648
- const l = performance.now(), s = r ?? (E ? l - E : 0);
649
- E = l, s !== 0 && (m.value = et(
650
- m.value + s,
1284
+ const c = performance.now(), s = r ?? (W ? c - W : 0);
1285
+ W = c, s !== 0 && (T.value = pe(
1286
+ T.value + s,
651
1287
  0,
652
- R.value || Number.POSITIVE_INFINITY
653
- ), R.value > 0 && m.value >= R.value && X());
1288
+ E.value || Number.POSITIVE_INFINITY
1289
+ ), E.value > 0 && T.value >= E.value && se());
654
1290
  }
655
- function Ut(r) {
656
- m.value = et(r, 0, R.value || Number.POSITIVE_INFINITY);
1291
+ function St(r) {
1292
+ T.value = pe(r, 0, E.value || Number.POSITIVE_INFINITY), O.seek(T.value, performance.now()), Y(), I.value && G.tick();
657
1293
  }
658
- async function Ot(r) {
659
- m.value = et(r, 0, R.value || Number.POSITIVE_INFINITY), await D();
1294
+ async function Tt(r) {
1295
+ T.value = pe(r, 0, E.value || Number.POSITIVE_INFINITY), O.seek(T.value, performance.now()), Y(), I.value && G.tick(), await oe();
660
1296
  }
661
- async function Lt(r) {
662
- const l = d.get(r.id);
663
- if (l)
664
- return l;
665
- const s = y.get(r.id);
1297
+ async function bt(r) {
1298
+ const c = f.get(r.id);
1299
+ if (c)
1300
+ return c;
1301
+ const s = g.get(r.id);
666
1302
  if (s)
667
1303
  return s;
668
- const f = Vt(r);
669
- y.set(r.id, f);
670
- const S = await f;
671
- return S && d.set(r.id, S), y.delete(r.id), S;
1304
+ const p = Ce(r);
1305
+ g.set(r.id, p);
1306
+ const v = await p;
1307
+ return v && f.set(r.id, v), g.delete(r.id), v;
672
1308
  }
673
- async function Vt(r) {
1309
+ function It(r, c) {
1310
+ const s = Zn - b.size;
1311
+ if (s <= 0)
1312
+ return;
1313
+ const p = c + Qn, v = [];
1314
+ for (const M of r.tracks)
1315
+ for (const y of M.children)
1316
+ H(y) && (y.startTime <= c || y.startTime > p || f.has(y.id) || g.has(y.id) || b.has(y.id) || v.push(y));
1317
+ v.sort((M, y) => M.startTime - y.startTime);
1318
+ for (const M of v.slice(0, s))
1319
+ kt(M);
1320
+ }
1321
+ async function kt(r) {
1322
+ b.add(r.id);
1323
+ try {
1324
+ const c = await Ce(r);
1325
+ c && !f.has(r.id) && f.set(r.id, c), await X(r, Math.max(r.fromTime ?? 0, 0));
1326
+ } catch (c) {
1327
+ console.error("[renderer] failed to preload upcoming video segment", r.url, c);
1328
+ } finally {
1329
+ b.delete(r.id);
1330
+ }
1331
+ }
1332
+ async function Ce(r) {
674
1333
  if (r.segmentType === "frames" || r.segmentType === "sticker") {
675
1334
  if (!r.url)
676
- return tt(r.segmentType);
677
- if ("type" in r && r.type === "video" && yt(r.url)) {
678
- const s = await zt(r);
679
- return s || tt(r.segmentType, r.url);
1335
+ return me(r.segmentType);
1336
+ if ("type" in r && r.type === "video" && $e(r.url)) {
1337
+ const s = await Et(r);
1338
+ return s || me(r.segmentType, r.url);
680
1339
  }
681
- const l = await Dt(r.url);
682
- return l ? new V(l) : tt(r.segmentType, r.url);
1340
+ const c = await At(r.url);
1341
+ return c ? new U(c) : me(r.segmentType, r.url);
683
1342
  }
684
1343
  if (r.segmentType === "text")
685
- return await $t(r);
1344
+ return await xt(r);
686
1345
  r.segmentType === "effect" || r.segmentType;
687
1346
  }
688
- async function $t(r) {
689
- const l = pe(r.texts);
690
- if (!l)
1347
+ async function xt(r) {
1348
+ const c = Yn(r.texts);
1349
+ if (!c)
691
1350
  return;
692
1351
  const [s] = r.texts;
693
1352
  if (!s)
694
1353
  return;
695
- const f = await ye(l, me(s)), S = G.from(f);
696
- return new V(S);
1354
+ const p = await Hn(c, Xn(s)), v = $.from(p);
1355
+ return new U(v);
697
1356
  }
698
- async function Dt(r) {
699
- const l = r.startsWith("data:"), s = /^https?:\/\//.test(r);
700
- if (!l && !s)
1357
+ async function At(r) {
1358
+ const c = r.startsWith("data:"), s = /^https?:\/\//.test(r);
1359
+ if (!c && !s)
701
1360
  try {
702
- await c.add(r);
703
- const f = await c.get(r);
704
- if (f instanceof HTMLImageElement)
705
- return G.from(f);
1361
+ await u.add(r);
1362
+ const p = await u.get(r);
1363
+ if (p instanceof HTMLImageElement)
1364
+ return $.from(p);
706
1365
  } catch {
707
1366
  }
708
- return await jt(r);
709
- }
710
- async function zt(r) {
711
- const l = p.get(r.id);
712
- if (l)
713
- return l.sprite;
714
- const s = W(r.url), f = M !== "element", S = M !== "mp4clip";
715
- if (s && h.has(s)) {
716
- if (!S)
1367
+ return await zt(r);
1368
+ }
1369
+ async function Et(r) {
1370
+ const c = l.get(r.id);
1371
+ if (c)
1372
+ return c.sprite;
1373
+ ue(r.url);
1374
+ const s = z(r.url), p = w !== "element", v = w !== "mp4clip";
1375
+ if (s && m.has(s)) {
1376
+ if (!v)
717
1377
  throw new Error(`[renderer] MP4Clip unsupported for ${r.url}`);
718
- const x = await B(r.url).catch((T) => {
719
- console.warn("[renderer] failed to load video via <video>", r.url, T);
1378
+ const M = await B(r.url).catch((y) => {
1379
+ console.warn("[renderer] failed to load video via <video>", r.url, y);
720
1380
  });
721
- return x ? (p.set(r.id, x), x.sprite) : void 0;
1381
+ return M ? (l.set(r.id, M), M.sprite) : void 0;
722
1382
  }
723
- if (f) {
724
- const x = await pt(r.url).catch((T) => {
725
- if (s && J(T) && h.add(s), (!s || !w.has(s)) && (s && w.add(s), console.warn("[renderer] failed to load video via MP4Clip", r.url, T)), !S)
726
- throw T;
1383
+ if (p) {
1384
+ const M = await Ne(r.url).catch((y) => {
1385
+ if (s && ce(y) && m.add(s), (!s || !S.has(s)) && (s && S.add(s), console.warn("[renderer] failed to load video via MP4Clip", r.url, y)), !v)
1386
+ throw y;
727
1387
  });
728
- if (x)
729
- return console.info("[renderer] video source: mp4clip", r.url), p.set(r.id, x), x.sprite;
1388
+ if (M)
1389
+ return console.info("[renderer] video source: mp4clip", r.url), l.set(r.id, M), M.sprite;
730
1390
  }
731
- if (S) {
732
- const x = await B(r.url).catch((T) => {
733
- console.warn("[renderer] failed to load video via <video>", r.url, T);
1391
+ if (v) {
1392
+ const M = await B(r.url).catch((y) => {
1393
+ console.warn("[renderer] failed to load video via <video>", r.url, y);
734
1394
  });
735
- if (x)
736
- return console.info("[renderer] video source: element", r.url), p.set(r.id, x), x.sprite;
1395
+ if (M)
1396
+ return console.info("[renderer] video source: element", r.url), l.set(r.id, M), M.sprite;
737
1397
  }
738
1398
  }
739
- function J(r) {
1399
+ function ce(r) {
740
1400
  if (!(r instanceof Error))
741
1401
  return !1;
742
- const l = r.message || "";
743
- return l.includes("stream is done") || l.includes("not emit ready") || l.includes("tick video timeout");
1402
+ const c = r.message || "";
1403
+ return c.includes("stream is done") || c.includes("not emit ready") || c.includes("tick video timeout");
744
1404
  }
745
- async function H(r, l) {
746
- const s = p.get(r.id);
1405
+ async function X(r, c) {
1406
+ const s = l.get(r.id);
747
1407
  if (s)
748
1408
  try {
749
- const f = r.fromTime ?? 0, S = Math.max(0, l - r.startTime + f), x = Math.floor(S * 1e3);
1409
+ const p = Math.max(0, c), v = Math.floor(p * 1e3);
750
1410
  if (s.kind === "frozen") {
751
- const k = W(r.url);
752
- if (!k)
1411
+ const y = z(r.url);
1412
+ if (!y)
753
1413
  return;
754
- const C = await Nt(r.url, k, { sprite: s.sprite, oldTexture: s.texture });
755
- return C ? (p.set(r.id, C), await H(r, l)) : void 0;
1414
+ const k = await Rt(r.url, y, { sprite: s.sprite, oldTexture: s.texture });
1415
+ return k ? (l.set(r.id, k), await X(r, c)) : void 0;
756
1416
  }
757
1417
  if (s.kind === "mp4clip")
758
1418
  try {
759
- const k = await s.clip.tick(x);
760
- if (k.video) {
761
- const C = s.canvas.getContext("2d");
762
- C && (C.drawImage(k.video, 0, 0, s.canvas.width, s.canvas.height), wt(s.texture)), k.video.close();
763
- }
764
- if (g.value && k.audio && k.audio.length > 0) {
765
- const C = s.clip.meta?.audioSampleRate ?? 48e3;
766
- P.playMp4AudioFrames(r.id, k.audio, C);
1419
+ const y = await s.clip.tick(v);
1420
+ if (y.video) {
1421
+ const k = s.canvas.getContext("2d");
1422
+ k && (k.drawImage(y.video, 0, 0, s.canvas.width, s.canvas.height), Ke(s.texture)), y.video.close();
767
1423
  }
768
1424
  return;
769
- } catch (k) {
770
- const C = W(r.url);
771
- if (C && J(k) && (h.add(C), s.clip.destroy(), M !== "mp4clip")) {
772
- const I = await B(r.url, { sprite: s.sprite, oldTexture: s.texture }).catch((U) => {
773
- console.warn("[renderer] failed to fallback to <video> after MP4Clip error", r.url, U);
1425
+ } catch (y) {
1426
+ const k = z(r.url);
1427
+ if (k && ce(y) && (m.add(k), s.clip.destroy(), w !== "mp4clip")) {
1428
+ const V = await B(r.url, { sprite: s.sprite, oldTexture: s.texture }).catch((F) => {
1429
+ console.warn("[renderer] failed to fallback to <video> after MP4Clip error", r.url, F);
774
1430
  });
775
- if (I)
776
- return p.set(r.id, I), await H(r, l);
1431
+ if (V)
1432
+ return l.set(r.id, V), await X(r, c);
777
1433
  }
778
- C && !w.has(C) && (w.add(C), console.warn("[renderer] MP4Clip tick failed", r.url, k));
1434
+ k && !S.has(k) && (S.add(k), console.warn("[renderer] MP4Clip tick failed", r.url, y));
779
1435
  return;
780
1436
  }
781
- const T = S / 1e3;
782
- if (!Number.isFinite(T) || s.kind !== "element")
1437
+ const M = p / 1e3;
1438
+ if (!Number.isFinite(M) || s.kind !== "element")
783
1439
  return;
784
- await Bt(s, {
785
- targetSec: T,
786
- playbackRate: r.playRate ?? 1,
787
- volume: r.volume ?? 1
1440
+ await Ot(s, {
1441
+ targetSec: M,
1442
+ playbackRate: r.playRate ?? 1
788
1443
  });
789
- } catch (f) {
790
- console.warn("[renderer] update video frame failed", f);
1444
+ } catch (p) {
1445
+ console.warn("[renderer] update video frame failed", p);
791
1446
  }
792
1447
  }
793
- async function Nt(r, l, s) {
794
- const f = M !== "element", S = M !== "mp4clip";
795
- if (h.has(l)) {
796
- if (!S)
1448
+ async function Rt(r, c, s) {
1449
+ const p = w !== "element", v = w !== "mp4clip";
1450
+ if (m.has(c)) {
1451
+ if (!v)
797
1452
  throw new Error(`[renderer] MP4Clip unsupported for ${r}`);
798
1453
  return await B(r, s).catch(() => {
799
1454
  });
800
1455
  }
801
- if (f) {
802
- const x = await pt(r, s).catch((T) => {
803
- if (J(T) && h.add(l), !S)
804
- throw T;
1456
+ if (p) {
1457
+ const M = await Ne(r, s).catch((y) => {
1458
+ if (ce(y) && m.add(c), !v)
1459
+ throw y;
805
1460
  });
806
- if (x)
807
- return x;
1461
+ if (M)
1462
+ return M;
808
1463
  }
809
- if (S)
1464
+ if (v)
810
1465
  return await B(r, s).catch(() => {
811
1466
  });
812
1467
  }
813
- function Gt(r) {
814
- return r.segmentType === "frames" && r.type === "video" && typeof r.url == "string" && yt(r.url);
1468
+ function H(r) {
1469
+ return r.segmentType === "frames" && r.type === "video" && typeof r.url == "string" && $e(r.url);
815
1470
  }
816
- function Kt(r, l) {
817
- const s = it(r);
1471
+ function Vt(r, c) {
1472
+ const s = ve(r);
818
1473
  if (s <= 0)
819
1474
  return 0;
820
- if (l < s)
821
- return l;
822
- const f = Math.max(1e3 / Math.max(r.fps || 30, 1), 1);
823
- return Math.max(s - f, 0);
1475
+ if (c < s)
1476
+ return c;
1477
+ const p = Math.max(1e3 / Math.max(r.fps || 30, 1), 1);
1478
+ return Math.max(s - p, 0);
824
1479
  }
825
- async function dt(r) {
826
- const l = e.resourceDir ?? we;
1480
+ async function J(r) {
1481
+ const c = e.resourceDir ?? Jn;
827
1482
  try {
828
- const s = W(r);
1483
+ const s = z(r);
829
1484
  if (!s)
830
1485
  return;
831
- const f = te(`${l}/${s}`, "r");
832
- if (await f.exists())
833
- return f;
1486
+ const p = jt(`${c}/${s}`, "r");
1487
+ if (await p.exists())
1488
+ return p;
834
1489
  } catch {
835
1490
  return;
836
1491
  }
837
1492
  }
838
- function ft(r) {
1493
+ function Ft(r) {
1494
+ if (r.segmentType !== "frames" || r.type !== "video")
1495
+ return;
1496
+ const c = z(r.url);
1497
+ if (c)
1498
+ return ue(r.url), A.get(c);
1499
+ }
1500
+ async function ue(r) {
1501
+ if (!de(r))
1502
+ return;
1503
+ const c = z(r);
1504
+ if (!c)
1505
+ return;
1506
+ const s = A.get(c);
1507
+ if (s)
1508
+ return s;
1509
+ const p = R.get(c);
1510
+ if (p)
1511
+ return await p;
1512
+ const v = (async () => {
1513
+ let M = await J(r);
1514
+ if (M || (await u.add(r).catch(() => {
1515
+ }), M = await J(r)), !M)
1516
+ return;
1517
+ const y = await M.getOriginFile();
1518
+ if (!y)
1519
+ return;
1520
+ const k = URL.createObjectURL(y);
1521
+ return A.set(c, k), k;
1522
+ })();
1523
+ R.set(c, v);
1524
+ try {
1525
+ return await v;
1526
+ } finally {
1527
+ R.delete(c);
1528
+ }
1529
+ }
1530
+ function de(r) {
839
1531
  return !(!r || r.startsWith("data:") || r.startsWith("blob:"));
840
1532
  }
841
- function qt() {
842
- for (const [r, l] of p) {
843
- if (l.kind === "mp4clip") {
844
- l.clip.destroy(), p.set(r, {
1533
+ function Pt() {
1534
+ for (const [r, c] of l) {
1535
+ if (c.kind === "mp4clip") {
1536
+ c.clip.destroy(), l.set(r, {
845
1537
  kind: "frozen",
846
- canvas: l.canvas,
847
- texture: l.texture,
848
- sprite: l.sprite,
849
- meta: l.meta
1538
+ canvas: c.canvas,
1539
+ texture: c.texture,
1540
+ sprite: c.sprite,
1541
+ meta: c.meta
850
1542
  });
851
1543
  continue;
852
1544
  }
853
- l.kind === "element" && l.video.pause();
1545
+ c.kind === "element" && c.video.pause();
854
1546
  }
855
1547
  }
856
- function ht(r) {
1548
+ function Ue(r) {
857
1549
  if (r.kind === "mp4clip") {
858
1550
  r.clip.destroy();
859
1551
  return;
@@ -861,156 +1553,159 @@ async function ve(e) {
861
1553
  if (r.kind === "frozen")
862
1554
  return;
863
1555
  r.video.pause();
864
- const l = v.get(r.video);
865
- l && (URL.revokeObjectURL(l), v.delete(r.video)), r.video.removeAttribute("src"), r.video.load();
866
- }
867
- function Q(r, l, s = 1e3) {
868
- return new Promise((f, S) => {
869
- const x = window.setTimeout(() => {
870
- C(), S(new Error(`Timed out waiting for media event: ${l}`));
871
- }, s), T = () => {
872
- C(), f();
1556
+ const c = h.get(r.video);
1557
+ c && (URL.revokeObjectURL(c), h.delete(r.video)), r.video.removeAttribute("src"), r.video.load();
1558
+ }
1559
+ function le(r, c, s = 1e3) {
1560
+ return new Promise((p, v) => {
1561
+ const M = window.setTimeout(() => {
1562
+ V(), v(new Error(`Timed out waiting for media event: ${c}`));
1563
+ }, s), y = () => {
1564
+ V(), p();
873
1565
  }, k = () => {
874
- C();
875
- const I = r.error ? `${r.error.code}` : "unknown";
876
- S(new Error(`Media error (${I}) while waiting for ${l}`));
877
- }, C = () => {
878
- window.clearTimeout(x), r.removeEventListener(l, T), r.removeEventListener("error", k);
1566
+ V();
1567
+ const F = r.error ? `${r.error.code}` : "unknown";
1568
+ v(new Error(`Media error (${F}) while waiting for ${c}`));
1569
+ }, V = () => {
1570
+ window.clearTimeout(M), r.removeEventListener(c, y), r.removeEventListener("error", k);
879
1571
  };
880
- r.addEventListener(l, T, { once: !0 }), r.addEventListener("error", k, { once: !0 });
1572
+ r.addEventListener(c, y, { once: !0 }), r.addEventListener("error", k, { once: !0 });
881
1573
  });
882
1574
  }
883
- async function pt(r, l) {
1575
+ async function Ne(r, c) {
884
1576
  let s;
885
- ft(r) && (s = await dt(r), s || (await c.add(r).catch(() => {
886
- }), s = await dt(r)));
887
- let f;
1577
+ de(r) && (s = await J(r), s || (await u.add(r).catch(() => {
1578
+ }), s = await J(r)));
1579
+ let p;
888
1580
  try {
889
1581
  if (s)
890
- f = new K(s);
1582
+ p = new K(s, { audio: !1 });
891
1583
  else {
892
- const I = await fetch(r);
893
- if (I.body)
894
- f = new K(I.body);
1584
+ const F = await fetch(r);
1585
+ if (F.body)
1586
+ p = new K(F.body, { audio: !1 });
895
1587
  else {
896
- const U = await I.arrayBuffer(), N = new ReadableStream({
897
- start(L) {
898
- L.enqueue(new Uint8Array(U)), L.close();
1588
+ const D = await F.arrayBuffer(), Q = new ReadableStream({
1589
+ start(j) {
1590
+ j.enqueue(new Uint8Array(D)), j.close();
899
1591
  }
900
1592
  });
901
- f = new K(N);
1593
+ p = new K(Q, { audio: !1 });
902
1594
  }
903
1595
  }
904
- await f.ready;
905
- const { width: S, height: x } = f.meta, T = document.createElement("canvas");
906
- T.width = S || 1, T.height = x || 1;
907
- const k = G.from(T), C = l?.sprite ?? new V(k);
908
- return l?.sprite && (l.sprite.texture = k, l.oldTexture?.destroy(!0)), { kind: "mp4clip", clip: f, canvas: T, texture: k, sprite: C, meta: { width: S, height: x } };
909
- } catch (S) {
910
- throw f?.destroy(), S;
1596
+ await p.ready;
1597
+ const { width: v, height: M } = p.meta, y = document.createElement("canvas");
1598
+ y.width = v || 1, y.height = M || 1;
1599
+ const k = $.from(y), V = c?.sprite ?? new U(k);
1600
+ return c?.sprite && (c.sprite.texture = k, c.oldTexture?.destroy(!0)), { kind: "mp4clip", clip: p, canvas: y, texture: k, sprite: V, meta: { width: v, height: M } };
1601
+ } catch (v) {
1602
+ throw p?.destroy(), v;
911
1603
  }
912
1604
  }
913
- function mt(r) {
1605
+ function De(r) {
914
1606
  const s = r.split("#")[0].split("?")[0].split("/").pop()?.split(".").pop()?.toLowerCase() ?? "";
915
1607
  return ["mp4", "m4v", "mov", "webm"].includes(s) ? "video" : ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg", "avif"].includes(s) ? "image" : ["mp3", "wav", "aac", "m4a", "ogg", "flac"].includes(s) ? "audio" : "unknown";
916
1608
  }
917
- function yt(r) {
918
- const l = mt(r);
919
- return !(l === "image" || l === "audio");
1609
+ function $e(r) {
1610
+ const c = De(r);
1611
+ return !(c === "image" || c === "audio");
920
1612
  }
921
- async function B(r, l) {
1613
+ async function B(r, c) {
922
1614
  const s = document.createElement("video");
923
- s.crossOrigin = "anonymous", s.muted = !1, s.playsInline = !0, s.preload = "metadata", s.src = r, s.load();
1615
+ s.crossOrigin = "anonymous", s.muted = !0, s.playsInline = !0, s.preload = "metadata", s.src = r, s.load();
924
1616
  try {
925
- await Q(s, "loadedmetadata", 15e3);
926
- } catch (C) {
1617
+ await le(s, "loadedmetadata", 15e3);
1618
+ } catch (V) {
927
1619
  s.pause();
928
- const I = v.get(s);
929
- throw I && (URL.revokeObjectURL(I), v.delete(s)), s.removeAttribute("src"), s.load(), C;
1620
+ const F = h.get(s);
1621
+ throw F && (URL.revokeObjectURL(F), h.delete(s)), s.removeAttribute("src"), s.load(), V;
930
1622
  }
931
- const f = s.videoWidth || 1, S = s.videoHeight || 1, x = document.createElement("canvas");
932
- x.width = f, x.height = S;
933
- const T = G.from(x), k = l?.sprite ?? new V(T);
934
- return l?.sprite && (l.sprite.texture = T, l.oldTexture?.destroy(!0)), { kind: "element", video: s, canvas: x, texture: T, sprite: k, meta: { width: f, height: S } };
935
- }
936
- async function Bt(r, l) {
937
- const { video: s, canvas: f, texture: S } = r;
938
- s.playbackRate = Number.isFinite(l.playbackRate) && l.playbackRate > 0 ? l.playbackRate : 1, s.volume = Math.max(0, Math.min(1, l.volume ?? 1)), g.value ? s.play().catch(() => {
1623
+ const p = s.videoWidth || 1, v = s.videoHeight || 1, M = document.createElement("canvas");
1624
+ M.width = p, M.height = v;
1625
+ const y = $.from(M), k = c?.sprite ?? new U(y);
1626
+ return c?.sprite && (c.sprite.texture = y, c.oldTexture?.destroy(!0)), { kind: "element", video: s, canvas: M, texture: y, sprite: k, meta: { width: p, height: v } };
1627
+ }
1628
+ async function Ot(r, c) {
1629
+ const { video: s, canvas: p, texture: v } = r;
1630
+ s.playbackRate = Number.isFinite(c.playbackRate) && c.playbackRate > 0 ? c.playbackRate : 1, s.muted = !0, s.volume = 0, I.value ? s.play().catch(() => {
939
1631
  }) : s.pause();
940
- const x = Number.isFinite(s.duration) && s.duration > 0 ? s.duration : null, T = x ? Math.min(l.targetSec, Math.max(x - 0.03, 0)) : l.targetSec, k = s.currentTime, C = Math.abs(k - T), I = g.value ? 0.25 : 0.03;
941
- if (Number.isFinite(k) && C > I) {
1632
+ const M = Number.isFinite(s.duration) && s.duration > 0 ? s.duration : null, y = M ? Math.min(c.targetSec, Math.max(M - 0.03, 0)) : c.targetSec, k = s.currentTime, V = Math.abs(k - y), F = I.value ? 0.25 : 0.03;
1633
+ if (Number.isFinite(k) && V > F) {
942
1634
  try {
943
- s.currentTime = T;
1635
+ s.currentTime = y;
944
1636
  } catch {
945
1637
  }
946
- await Q(s, "seeked", 250).catch(() => {
1638
+ await le(s, "seeked", 250).catch(() => {
947
1639
  });
948
1640
  }
949
- if (s.readyState < 2 && (await Q(s, "canplay", 250).catch(() => {
1641
+ if (s.readyState < 2 && (await le(s, "canplay", 250).catch(() => {
950
1642
  }), s.readyState < 2))
951
1643
  return;
952
- const U = f.getContext("2d");
953
- U && (U.drawImage(s, 0, 0, f.width, f.height), wt(S));
1644
+ const D = p.getContext("2d");
1645
+ D && (D.drawImage(s, 0, 0, p.width, p.height), Ke(v));
954
1646
  }
955
- function jt(r) {
956
- return new Promise((l) => {
1647
+ function zt(r) {
1648
+ return new Promise((c) => {
957
1649
  const s = new Image();
958
- s.crossOrigin = "anonymous", s.onload = () => l(G.from(s)), s.onerror = () => {
959
- console.warn("[renderer] failed to load image", r), l(void 0);
1650
+ s.crossOrigin = "anonymous", s.onload = () => c($.from(s)), s.onerror = () => {
1651
+ console.warn("[renderer] failed to load image", r), c(void 0);
960
1652
  }, s.src = r;
961
1653
  });
962
1654
  }
963
- function wt(r) {
964
- const l = r.source;
965
- if ("update" in l && typeof l.update == "function") {
966
- l.update();
1655
+ function Ke(r) {
1656
+ const c = r.source;
1657
+ if ("update" in c && typeof c.update == "function") {
1658
+ c.update();
967
1659
  return;
968
1660
  }
969
1661
  typeof r.update == "function" && r.update();
970
1662
  }
971
- function _t() {
972
- X(), b += 1, z.stop(), _(), a.destroy({ children: !0 }), d.clear(), y.clear(), u.clear(), e.app || n.destroy(), P.destroy();
1663
+ function Ct() {
1664
+ se(), P += 1, Ve.stop(), Fe(), a.destroy({ children: !0 }), f.clear(), g.clear(), d.clear();
1665
+ for (const r of A.values())
1666
+ URL.revokeObjectURL(r);
1667
+ A.clear(), R.clear(), e.app || o.destroy(), x.destroy();
973
1668
  }
974
- return e.autoPlay && ct(), {
975
- app: n,
1669
+ return e.autoPlay && Pe(), {
1670
+ app: o,
976
1671
  layer: a,
977
- currentTime: m,
978
- duration: R,
979
- isPlaying: g,
980
- play: ct,
981
- pause: X,
982
- tick: lt,
983
- seek: Ut,
984
- renderAt: Ot,
985
- destroy: _t
1672
+ currentTime: T,
1673
+ duration: E,
1674
+ isPlaying: I,
1675
+ play: Pe,
1676
+ pause: se,
1677
+ tick: ze,
1678
+ seek: St,
1679
+ renderAt: Tt,
1680
+ destroy: Ct
986
1681
  };
987
1682
  }
988
- function Me(e) {
989
- let t = !1, o = !1, i = null, n = null;
1683
+ function ti(e) {
1684
+ let t = !1, i = !1, n = null, o = null;
990
1685
  return async () => {
991
- i || (i = new Promise((u) => {
992
- n = u;
1686
+ n || (n = new Promise((d) => {
1687
+ o = d;
993
1688
  }));
994
- const c = i;
995
- if (o)
996
- return t = !0, c;
997
- o = !0;
1689
+ const u = n;
1690
+ if (i)
1691
+ return t = !0, u;
1692
+ i = !0;
998
1693
  do
999
1694
  t = !1, await e();
1000
1695
  while (t);
1001
- return o = !1, n?.(), i = null, n = null, c;
1696
+ return i = !1, o?.(), n = null, o = null, u;
1002
1697
  };
1003
1698
  }
1004
- function ge(e) {
1699
+ function ni(e) {
1005
1700
  return typeof e == "object" && e !== null && "createReader" in e && "getSize" in e;
1006
1701
  }
1007
- function Se(e) {
1702
+ function ii(e) {
1008
1703
  return typeof ReadableStream < "u" && e instanceof ReadableStream;
1009
1704
  }
1010
- function xe(e) {
1011
- return typeof e == "string" || e instanceof Blob || ge(e) || Se(e) ? { source: e } : e;
1705
+ function ri(e) {
1706
+ return typeof e == "string" || e instanceof Blob || ni(e) || ii(e) ? { source: e } : e;
1012
1707
  }
1013
- async function xt(e) {
1708
+ async function He(e) {
1014
1709
  if (typeof e == "string") {
1015
1710
  const t = await fetch(e);
1016
1711
  if (!t.body)
@@ -1019,81 +1714,81 @@ async function xt(e) {
1019
1714
  }
1020
1715
  return e instanceof Blob ? e.stream() : e;
1021
1716
  }
1022
- function Te(e, t) {
1023
- let o = !1;
1024
- const i = () => {
1025
- o || (o = !0, t());
1026
- }, n = e.getReader();
1717
+ function oi(e, t) {
1718
+ let i = !1;
1719
+ const n = () => {
1720
+ i || (i = !0, t());
1721
+ }, o = e.getReader();
1027
1722
  return new ReadableStream({
1028
1723
  async pull(a) {
1029
- const { done: c, value: u } = await n.read();
1030
- if (c) {
1031
- i(), a.close();
1724
+ const { done: u, value: d } = await o.read();
1725
+ if (u) {
1726
+ n(), a.close();
1032
1727
  return;
1033
1728
  }
1034
- a.enqueue(u);
1729
+ a.enqueue(d);
1035
1730
  },
1036
1731
  async cancel(a) {
1037
1732
  try {
1038
- await n.cancel(a);
1733
+ await o.cancel(a);
1039
1734
  } finally {
1040
- i();
1735
+ n();
1041
1736
  }
1042
1737
  }
1043
1738
  });
1044
1739
  }
1045
- async function Ne(e, t = {}) {
1740
+ async function bi(e, t = {}) {
1046
1741
  if (e.length === 0)
1047
1742
  throw new Error("concatVideos: expected at least one source");
1048
1743
  const {
1049
- onProgress: o,
1050
- width: i,
1051
- height: n,
1744
+ onProgress: i,
1745
+ width: n,
1746
+ height: o,
1052
1747
  ...a
1053
- } = t, c = e.map(xe), [u, ...d] = c, y = await xt(u.source), h = new K(y);
1054
- await h.ready;
1055
- const w = i ?? Math.round(h.meta.width || 0), M = n ?? Math.round(h.meta.height || 0);
1056
- if (!w || !M)
1057
- throw h.destroy(), new Error("concatVideos: output width/height is required");
1058
- const p = new bt({
1748
+ } = t, u = e.map(ri), [d, ...f] = u, g = await He(d.source), m = new K(g);
1749
+ await m.ready;
1750
+ const S = n ?? Math.round(m.meta.width || 0), w = o ?? Math.round(m.meta.height || 0);
1751
+ if (!S || !w)
1752
+ throw m.destroy(), new Error("concatVideos: output width/height is required");
1753
+ const l = new Je({
1059
1754
  ...a,
1060
- width: w,
1061
- height: M
1755
+ width: S,
1756
+ height: w
1062
1757
  });
1063
- o && p.on("OutputProgress", o);
1064
- let v = 0;
1065
- const m = async (A) => {
1066
- const E = A.meta.duration;
1067
- if (!Number.isFinite(E) || E <= 0)
1758
+ i && l.on("OutputProgress", i);
1759
+ let h = 0;
1760
+ const b = async (A) => {
1761
+ const R = A.meta.duration;
1762
+ if (!Number.isFinite(R) || R <= 0)
1068
1763
  throw A.destroy(), new Error("concatVideos: invalid clip duration");
1069
- const b = new nt(A);
1764
+ const x = new be(A);
1070
1765
  try {
1071
- await b.ready, b.rect.x = 0, b.rect.y = 0, b.rect.w = w, b.rect.h = M, b.time.offset = v, b.time.duration = E, await p.addSprite(b), v += E;
1766
+ await x.ready, x.rect.x = 0, x.rect.y = 0, x.rect.w = S, x.rect.h = w, x.time.offset = h, x.time.duration = R, await l.addSprite(x), h += R;
1072
1767
  } finally {
1073
- b.destroy();
1768
+ x.destroy();
1074
1769
  }
1075
1770
  };
1076
1771
  try {
1077
- await m(h);
1078
- for (const A of d) {
1079
- const E = await xt(A.source), b = new K(E);
1080
- await b.ready, await m(b);
1772
+ await b(m);
1773
+ for (const A of f) {
1774
+ const R = await He(A.source), x = new K(R);
1775
+ await x.ready, await b(x);
1081
1776
  }
1082
1777
  } catch (A) {
1083
- throw p.destroy(), A;
1778
+ throw l.destroy(), A;
1084
1779
  }
1085
- const g = v, R = p.output({ maxTime: g }), P = () => {
1086
- p.destroy();
1780
+ const T = h, I = l.output({ maxTime: T }), E = () => {
1781
+ l.destroy();
1087
1782
  };
1088
1783
  return {
1089
- stream: Te(R, P),
1090
- width: w,
1091
- height: M,
1092
- durationMs: Math.round(g / 1e3),
1093
- destroy: P
1784
+ stream: oi(I, E),
1785
+ width: S,
1786
+ height: w,
1787
+ durationMs: Math.round(T / 1e3),
1788
+ destroy: E
1094
1789
  };
1095
1790
  }
1096
- class at {
1791
+ class Ae {
1097
1792
  ready;
1098
1793
  meta;
1099
1794
  protocol;
@@ -1101,90 +1796,90 @@ class at {
1101
1796
  renderer;
1102
1797
  app;
1103
1798
  destroyed = !1;
1104
- constructor(t, o = {}) {
1105
- this.protocol = t, this.options = o;
1106
- const i = o.width ?? t.width, n = o.height ?? t.height, a = it(t);
1799
+ constructor(t, i = {}) {
1800
+ this.protocol = t, this.options = i;
1801
+ const n = i.width ?? t.width, o = i.height ?? t.height, a = ve(t);
1107
1802
  this.meta = {
1108
- width: i,
1109
- height: n,
1803
+ width: n,
1804
+ height: o,
1110
1805
  duration: Math.max(0, Math.round(a * 1e3))
1111
1806
  }, this.ready = this.init();
1112
1807
  }
1113
1808
  async init() {
1114
- const t = this.options.width ?? this.protocol.width, o = this.options.height ?? this.protocol.height;
1115
- if (!t || !o)
1809
+ const t = this.options.width ?? this.protocol.width, i = this.options.height ?? this.protocol.height;
1810
+ if (!t || !i)
1116
1811
  throw new Error("ProtocolVideoClip: output width/height is required");
1117
- const i = new kt();
1118
- await i.init({
1812
+ const n = new Qe();
1813
+ await n.init({
1119
1814
  width: t,
1120
- height: o,
1815
+ height: i,
1121
1816
  backgroundAlpha: 0,
1122
1817
  ...this.options.appOptions
1123
- }), i.ticker.stop(), this.app = i;
1124
- const n = this.options.rendererOptions ?? {}, a = await ve({
1818
+ }), n.ticker.stop(), this.app = n;
1819
+ const o = this.options.rendererOptions ?? {}, a = await ei({
1125
1820
  protocol: this.protocol,
1126
- app: i,
1127
- ...n,
1821
+ app: n,
1822
+ ...o,
1128
1823
  autoPlay: !1,
1129
1824
  freezeOnPause: !1,
1130
1825
  manualRender: !0,
1131
- videoSourceMode: n.videoSourceMode ?? "mp4clip"
1826
+ videoSourceMode: o.videoSourceMode ?? "mp4clip"
1132
1827
  });
1133
1828
  this.renderer = a;
1134
- const c = a.duration.value;
1829
+ const u = a.duration.value;
1135
1830
  return this.meta = {
1136
- width: i.renderer.width,
1137
- height: i.renderer.height,
1138
- duration: Math.max(0, Math.round(c * 1e3))
1831
+ width: n.renderer.width,
1832
+ height: n.renderer.height,
1833
+ duration: Math.max(0, Math.round(u * 1e3))
1139
1834
  }, this.meta;
1140
1835
  }
1141
1836
  async tick(t) {
1142
- const o = [];
1837
+ const i = [];
1143
1838
  if (this.destroyed)
1144
- return { audio: o, state: "done" };
1839
+ return { audio: i, state: "done" };
1145
1840
  if (await this.ready, !this.renderer)
1146
- return { audio: o, state: "done" };
1147
- const i = this.meta.duration;
1148
- if (t >= i)
1149
- return { audio: o, state: "done" };
1150
- const n = Math.max(0, Math.min(t, i));
1151
- return await this.renderer.renderAt(n / 1e3), {
1841
+ return { audio: i, state: "done" };
1842
+ const n = this.meta.duration;
1843
+ if (t >= n)
1844
+ return { audio: i, state: "done" };
1845
+ const o = Math.max(0, Math.min(t, n));
1846
+ return await this.renderer.renderAt(o / 1e3), {
1152
1847
  video: new VideoFrame(this.renderer.app.canvas, {
1153
1848
  timestamp: t
1154
1849
  }),
1155
- audio: o,
1850
+ audio: i,
1156
1851
  state: "success"
1157
1852
  };
1158
1853
  }
1159
1854
  async clone() {
1160
- const t = new at(this.protocol, this.options);
1855
+ const t = new Ae(this.protocol, this.options);
1161
1856
  return await t.ready, t;
1162
1857
  }
1163
1858
  destroy() {
1164
1859
  this.destroyed || (this.destroyed = !0, this.renderer?.destroy(), this.app?.destroy(!0));
1165
1860
  }
1166
1861
  }
1167
- const It = 12e3;
1168
- function be(e, t, o) {
1169
- return new Promise((i, n) => {
1862
+ const mt = 12e3;
1863
+ function ai(e, t, i) {
1864
+ return new Promise((n, o) => {
1170
1865
  const a = globalThis.setTimeout(() => {
1171
- n(new Error(`composeProtocol: ${o} timed out (${t}ms)`));
1866
+ o(new Error(`composeProtocol: ${i} timed out (${t}ms)`));
1172
1867
  }, t);
1173
- e.then((c) => {
1174
- globalThis.clearTimeout(a), i(c);
1175
- }).catch((c) => {
1176
- globalThis.clearTimeout(a), n(c);
1868
+ e.then((u) => {
1869
+ globalThis.clearTimeout(a), n(u);
1870
+ }).catch((u) => {
1871
+ globalThis.clearTimeout(a), o(u);
1177
1872
  });
1178
1873
  });
1179
1874
  }
1180
- class st {
1181
- constructor(t, o) {
1182
- this.sourceClip = t, this.config = o, this.ready = this.sourceClip.ready.then((i) => {
1183
- const n = Math.round(this.config.segmentDurationUs * this.config.playRate), a = Math.max(0, i.duration - this.config.fromUs);
1875
+ class Ee {
1876
+ constructor(t, i) {
1877
+ this.sourceClip = t, this.config = i, this.ready = this.sourceClip.ready.then((n) => {
1878
+ const o = Math.round(this.config.segmentDurationUs * this.config.playRate), a = Math.max(0, n.duration - this.config.fromUs);
1184
1879
  return this.clipMeta = {
1185
- width: i.width,
1186
- height: i.height,
1187
- duration: Math.max(0, Math.min(n, a))
1880
+ width: n.width,
1881
+ height: n.height,
1882
+ duration: Math.max(0, Math.min(o, a))
1188
1883
  }, this.meta;
1189
1884
  });
1190
1885
  }
@@ -1198,217 +1893,200 @@ class st {
1198
1893
  return { ...this.clipMeta };
1199
1894
  }
1200
1895
  async tick(t) {
1201
- const o = Math.max(0, Math.round(t)), i = Math.round(o / this.config.playRate);
1202
- if (i >= this.config.segmentDurationUs)
1896
+ const i = Math.max(0, Math.round(t)), n = Math.round(i / this.config.playRate);
1897
+ if (n >= this.config.segmentDurationUs)
1203
1898
  return {
1204
1899
  audio: [],
1205
1900
  state: "done"
1206
1901
  };
1207
- const n = this.config.fromUs + o, a = await this.sourceClip.tick(n);
1208
- ke(a.video);
1209
- const c = this.resolveGain(i);
1902
+ const o = this.config.fromUs + i, a = await this.sourceClip.tick(o);
1903
+ si(a.video);
1904
+ const u = this.resolveGain(n);
1210
1905
  return {
1211
- audio: Ce(a.audio ?? [], c),
1906
+ audio: ci(a.audio ?? [], u),
1212
1907
  state: a.state
1213
1908
  };
1214
1909
  }
1215
1910
  async clone() {
1216
- const t = await this.sourceClip.clone(), o = new st(t, this.config);
1217
- return await o.ready, o;
1911
+ const t = await this.sourceClip.clone(), i = new Ee(t, this.config);
1912
+ return await i.ready, i;
1218
1913
  }
1219
1914
  destroy() {
1220
1915
  this.sourceClip.destroy();
1221
1916
  }
1222
1917
  resolveGain(t) {
1223
- let o = 1;
1224
- this.config.fadeInUs > 0 && t < this.config.fadeInUs && (o = Math.max(0, t / this.config.fadeInUs));
1225
- const i = this.config.segmentDurationUs - t;
1226
- return this.config.fadeOutUs > 0 && i < this.config.fadeOutUs && (o = Math.min(o, Math.max(0, i / this.config.fadeOutUs))), this.config.baseVolume * o;
1918
+ let i = 1;
1919
+ this.config.fadeInUs > 0 && t < this.config.fadeInUs && (i = Math.max(0, t / this.config.fadeInUs));
1920
+ const n = this.config.segmentDurationUs - t;
1921
+ return this.config.fadeOutUs > 0 && n < this.config.fadeOutUs && (i = Math.min(i, Math.max(0, n / this.config.fadeOutUs))), this.config.baseVolume * i;
1227
1922
  }
1228
1923
  }
1229
- function ke(e) {
1924
+ function si(e) {
1230
1925
  if (!e || typeof e != "object")
1231
1926
  return;
1232
1927
  const t = e.close;
1233
1928
  typeof t == "function" && t.call(e);
1234
1929
  }
1235
- function Ce(e, t) {
1236
- return !e.length || t >= 0.999 ? e : t <= 0 ? e.map((o) => new Float32Array(o.length)) : e.map((o) => {
1237
- const i = new Float32Array(o.length);
1238
- for (let n = 0; n < o.length; n++)
1239
- i[n] = o[n] * t;
1240
- return i;
1930
+ function ci(e, t) {
1931
+ return !e.length || t >= 0.999 ? e : t <= 0 ? e.map((i) => new Float32Array(i.length)) : e.map((i) => {
1932
+ const n = new Float32Array(i.length);
1933
+ for (let o = 0; o < i.length; o++)
1934
+ n[o] = i[o] * t;
1935
+ return n;
1241
1936
  });
1242
1937
  }
1243
- function j(e) {
1938
+ function _(e) {
1244
1939
  return Number.isFinite(e) ? Math.max(0, Math.round(e * 1e3)) : 0;
1245
1940
  }
1246
- function rt(e) {
1941
+ function ui(e) {
1247
1942
  return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(0, Math.min(1, e));
1248
1943
  }
1249
- function Re(e) {
1944
+ function di(e) {
1250
1945
  return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(0.1, Math.min(100, e));
1251
1946
  }
1252
- function Ae(e) {
1253
- const t = Math.max(0, e.endTime - e.startTime), o = Math.max(0, Math.min(e.fadeInDuration ?? 0, t)), i = Math.max(0, Math.min(e.fadeOutDuration ?? 0, t));
1947
+ function li(e) {
1948
+ const t = Math.max(0, e.endTime - e.startTime), i = Math.max(0, Math.min(e.fadeInDuration ?? 0, t)), n = Math.max(0, Math.min(e.fadeOutDuration ?? 0, t));
1254
1949
  return {
1255
- fromUs: j(e.fromTime ?? 0),
1256
- segmentDurationUs: j(t),
1257
- playRate: Re(e.playRate),
1258
- baseVolume: rt(e.volume),
1259
- fadeInUs: j(o),
1260
- fadeOutUs: j(i)
1950
+ fromUs: _(e.fromTime ?? 0),
1951
+ segmentDurationUs: _(t),
1952
+ playRate: di(e.playRate),
1953
+ baseVolume: ui(e.volume),
1954
+ fadeInUs: _(i),
1955
+ fadeOutUs: _(n)
1261
1956
  };
1262
1957
  }
1263
- function Ee(e) {
1264
- return e.segmentType === "audio";
1265
- }
1266
- function Ie(e) {
1267
- return e.segmentType === "frames" && e.type === "video";
1268
- }
1269
- async function Pt(e, t = It) {
1270
- const o = new AbortController(), i = globalThis.setTimeout(() => o.abort(), t);
1958
+ async function fi(e, t = mt) {
1959
+ const i = new AbortController(), n = globalThis.setTimeout(() => i.abort(), t);
1271
1960
  try {
1272
- const n = await fetch(e, { signal: o.signal });
1273
- if (!n.body)
1961
+ const o = await fetch(e, { signal: i.signal });
1962
+ if (!o.body)
1274
1963
  throw new Error(`composeProtocol: unable to read resource stream: ${e}`);
1275
- return n.body;
1276
- } catch (n) {
1277
- throw o.signal.aborted ? new Error(`composeProtocol: loading resource timed out (${t}ms): ${e}`) : n;
1964
+ return o.body;
1965
+ } catch (o) {
1966
+ throw i.signal.aborted ? new Error(`composeProtocol: loading resource timed out (${t}ms): ${e}`) : o;
1278
1967
  } finally {
1279
- globalThis.clearTimeout(i);
1968
+ globalThis.clearTimeout(n);
1280
1969
  }
1281
1970
  }
1282
- async function Ft(e, t) {
1283
- const o = Ae(t), i = new st(e, o), n = new nt(i);
1971
+ async function mi(e, t) {
1972
+ const i = li(t), n = new Ee(e, i), o = new be(n);
1284
1973
  try {
1285
- await be(n.ready, It, "prepare audio sprite");
1974
+ await ai(o.ready, mt, "prepare audio sprite");
1286
1975
  } catch (a) {
1287
- throw n.destroy(), a;
1976
+ throw o.destroy(), a;
1288
1977
  }
1289
- return n.time.offset = j(t.startTime), n.time.duration = o.segmentDurationUs, n.time.playbackRate = o.playRate, n;
1290
- }
1291
- async function Pe(e) {
1292
- const t = await Pt(e.url), o = new Tt(t);
1293
- return await Ft(o, e);
1978
+ return o.time.offset = _(t.startTime), o.time.duration = i.segmentDurationUs, o.time.playbackRate = i.playRate, o;
1294
1979
  }
1295
- async function Fe(e) {
1296
- const t = await Pt(e.url), o = new K(t, { audio: !0 });
1297
- return await Ft(o, e);
1980
+ async function pi(e) {
1981
+ const t = await fi(e.url), i = e.segmentKind === "audio" ? new Bt(t) : new K(t, { audio: !0 });
1982
+ return await mi(i, e);
1298
1983
  }
1299
- async function Ue(e) {
1300
- const t = [];
1301
- for (const n of e.tracks)
1302
- for (const a of n.children)
1303
- if (!(a.endTime <= a.startTime)) {
1304
- if (Ee(a)) {
1305
- if (rt(a.volume) <= 0)
1306
- continue;
1307
- t.push(Pe(a));
1308
- continue;
1309
- }
1310
- if (Ie(a)) {
1311
- if (rt(a.volume) <= 0)
1312
- continue;
1313
- t.push(Fe(a));
1314
- }
1315
- }
1316
- if (!t.length)
1984
+ async function hi(e) {
1985
+ const i = Un(e).map((a) => pi(a));
1986
+ if (!i.length)
1317
1987
  return [];
1318
- const o = await Promise.allSettled(t), i = [];
1319
- for (const n of o) {
1320
- if (n.status === "fulfilled") {
1321
- i.push(n.value);
1988
+ const n = await Promise.allSettled(i), o = [];
1989
+ for (const a of n) {
1990
+ if (a.status === "fulfilled") {
1991
+ o.push(a.value);
1322
1992
  continue;
1323
1993
  }
1324
- console.warn("[compose] skip audio sprite due to load failure", n.reason);
1994
+ console.warn("[compose] skip audio sprite due to load failure", a.reason);
1325
1995
  }
1326
- return i;
1996
+ return o;
1327
1997
  }
1328
- function ot(e) {
1998
+ function we(e) {
1329
1999
  for (const t of e)
1330
2000
  t.destroy();
1331
2001
  }
1332
- function Oe(e, t) {
1333
- let o = !1;
1334
- const i = () => {
1335
- o || (o = !0, t());
1336
- }, n = e.getReader();
2002
+ function yi(e, t) {
2003
+ let i = !1;
2004
+ const n = () => {
2005
+ i || (i = !0, t());
2006
+ }, o = e.getReader();
1337
2007
  return new ReadableStream({
1338
2008
  async pull(a) {
1339
- const { done: c, value: u } = await n.read();
1340
- if (c) {
1341
- i(), a.close();
2009
+ const { done: u, value: d } = await o.read();
2010
+ if (u) {
2011
+ n(), a.close();
1342
2012
  return;
1343
2013
  }
1344
- a.enqueue(u);
2014
+ a.enqueue(d);
1345
2015
  },
1346
2016
  async cancel(a) {
1347
2017
  try {
1348
- await n.cancel(a);
2018
+ await o.cancel(a);
1349
2019
  } finally {
1350
- i();
2020
+ n();
1351
2021
  }
1352
2022
  }
1353
2023
  });
1354
2024
  }
1355
- async function Ge(e, t = {}) {
2025
+ async function Ii(e, t = {}) {
1356
2026
  const {
1357
- width: o,
1358
- height: i,
1359
- fps: n,
2027
+ width: i,
2028
+ height: n,
2029
+ fps: o,
1360
2030
  onProgress: a,
1361
- clipOptions: c,
1362
- audioSprites: u,
1363
- ...d
1364
- } = t, y = o ?? e.width, h = i ?? e.height;
1365
- if (!y || !h)
2031
+ clipOptions: u,
2032
+ audioSprites: d,
2033
+ ...f
2034
+ } = t, g = i ?? e.width, m = n ?? e.height;
2035
+ if (!g || !m)
1366
2036
  throw new Error("composeProtocol: output width/height is required");
1367
- const w = n ?? e.fps, M = d.audio === !1 ? [] : typeof u == "function" ? await u(e) : await Ue(e), p = d.audio ?? (M.length > 0 ? void 0 : !1), v = new bt({
1368
- ...d,
1369
- audio: p,
1370
- width: y,
1371
- height: h,
1372
- fps: w
2037
+ const S = o ?? e.fps, w = f.audio === !1 ? [] : typeof d == "function" ? await d(e) : await hi(e), l = f.audio ?? (w.length > 0 ? void 0 : !1), h = new Je({
2038
+ ...f,
2039
+ audio: l,
2040
+ width: g,
2041
+ height: m,
2042
+ fps: S
1373
2043
  });
1374
- a && v.on("OutputProgress", a);
1375
- let m, g;
2044
+ a && h.on("OutputProgress", a);
2045
+ let b, T;
1376
2046
  try {
1377
- m = new at(e, {
1378
- width: y,
1379
- height: h,
1380
- fps: w,
1381
- ...c,
2047
+ b = new Ae(e, {
2048
+ width: g,
2049
+ height: m,
2050
+ fps: S,
2051
+ ...u,
1382
2052
  rendererOptions: {
1383
2053
  warmUpResources: !1,
1384
- ...c?.rendererOptions
2054
+ ...u?.rendererOptions
1385
2055
  }
1386
- }), await m.ready, g = new nt(m), await g.ready, g.time.offset = 0, g.time.duration = m.meta.duration, g.rect.x = 0, g.rect.y = 0, g.rect.w = m.meta.width, g.rect.h = m.meta.height, await v.addSprite(g, { main: !0 });
1387
- for (const b of M)
1388
- await v.addSprite(b);
1389
- } catch (b) {
1390
- throw ot(M), g?.destroy(), m?.destroy(), v.destroy(), b;
1391
- }
1392
- const R = m?.meta.duration ?? 0;
1393
- if (!R)
1394
- throw ot(M), g?.destroy(), m?.destroy(), v.destroy(), new Error("composeProtocol: protocol has no duration");
1395
- const P = v.output({ maxTime: R });
2056
+ }), await b.ready, T = new be(b), await T.ready, T.time.offset = 0, T.time.duration = b.meta.duration, T.rect.x = 0, T.rect.y = 0, T.rect.w = b.meta.width, T.rect.h = b.meta.height, await h.addSprite(T, { main: !0 });
2057
+ for (const x of w)
2058
+ await h.addSprite(x);
2059
+ } catch (x) {
2060
+ throw we(w), T?.destroy(), b?.destroy(), h.destroy(), x;
2061
+ }
2062
+ const I = b?.meta.duration ?? 0;
2063
+ if (!I)
2064
+ throw we(w), T?.destroy(), b?.destroy(), h.destroy(), new Error("composeProtocol: protocol has no duration");
2065
+ const E = h.output({ maxTime: I });
1396
2066
  let A = !1;
1397
- const E = () => {
1398
- A || (A = !0, ot(M), g?.destroy(), m?.destroy(), v.destroy());
2067
+ const R = () => {
2068
+ A || (A = !0, we(w), T?.destroy(), b?.destroy(), h.destroy());
1399
2069
  };
1400
2070
  return {
1401
- stream: Oe(P, E),
1402
- width: y,
1403
- height: h,
1404
- durationMs: Math.round(R / 1e3),
1405
- destroy: E
2071
+ stream: yi(E, R),
2072
+ width: g,
2073
+ height: m,
2074
+ durationMs: Math.round(I / 1e3),
2075
+ destroy: R
1406
2076
  };
1407
2077
  }
1408
2078
  export {
1409
- at as ProtocolVideoClip,
1410
- Ge as composeProtocol,
1411
- Ne as concatVideos,
1412
- ve as createRenderer
2079
+ Ae as ProtocolVideoClip,
2080
+ an as collectTransitionByFromSegmentId,
2081
+ Ii as composeProtocol,
2082
+ bi as concatVideos,
2083
+ Un as createComposeAudioInputs,
2084
+ Tn as createComposeRunner,
2085
+ ne as createEmptyEvaluatorState,
2086
+ Fn as createPixiFiltersFromVisualEffects,
2087
+ ei as createRenderer,
2088
+ rn as createTimelineTransport,
2089
+ xn as createVisualRenderItems,
2090
+ rt as evaluateTimelinePlan
1413
2091
  };
1414
2092
  //# sourceMappingURL=index.js.map