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

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,100 +1,100 @@
1
- import { createValidator as Gt, createResourceManager as Nt, getResourceKey as N } from "@video-editor/protocol";
2
- import { toRaw as zt, isRef as Kt, shallowRef as ut, unref as lt, ref as ft, computed as qt, effectScope as Bt, watch as W } from "@vue/reactivity";
3
- import { AudioClip as jt, renderTxt2ImgBitmap as _t, MP4Clip as G, Combinator as mt, OffscreenSprite as wt } from "@webav/av-cliper";
4
- import { file as Wt } from "opfs-tools";
5
- import { Application as yt, Sprite as O, Texture as V, Graphics as vt, Container as Yt } from "pixi.js";
6
- async function Xt(o) {
7
- const t = new yt();
8
- return await t.init({ resizeTo: window, backgroundAlpha: 0, ...o }), t;
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();
8
+ return await t.init({ resizeTo: window, backgroundAlpha: 0, ...e }), t;
9
9
  }
10
- function Jt(o, t, i, r, a) {
11
- const u = t || r, c = i || a;
12
- if (!u || !c)
13
- return { width: r, height: a };
14
- const d = u / c, l = r / a;
15
- switch (o) {
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
16
  case "none":
17
- return { width: u, height: c };
17
+ return { width: a, height: c };
18
18
  case "cover":
19
- return d > l ? { width: a * d, height: a } : { width: r, height: r / d };
19
+ return u > d ? { width: n * u, height: n } : { width: i, height: i / u };
20
20
  case "stretch":
21
- return { width: r, height: a };
21
+ return { width: i, height: n };
22
22
  default:
23
- return d > l ? { width: r, height: r / d } : { width: a * d, height: a };
23
+ return u > d ? { width: i, height: i / u } : { width: n * u, height: n };
24
24
  }
25
25
  }
26
- function Ht(o, t, i, r, a) {
27
- const u = "fillMode" in o ? o.fillMode : void 0, { width: c, height: d } = Jt(
28
- u,
29
- r,
26
+ function re(e, t, o, i, n) {
27
+ const a = "fillMode" in e ? e.fillMode : void 0, { width: c, height: u } = ie(
30
28
  a,
29
+ i,
30
+ n,
31
31
  t,
32
- i
33
- ), l = "transform" in o ? o.transform : void 0, [p, h] = l?.position ?? [0, 0], [m, S] = l?.scale ?? [1, 1], M = l?.rotation?.[2] ?? 0, k = c * m, w = d * S, x = t / 2 + p * t / 2, R = i / 2 - h * i / 2;
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
34
  return {
35
- width: k,
36
- height: w,
37
- centerX: x,
35
+ width: v,
36
+ height: m,
37
+ centerX: g,
38
38
  centerY: R,
39
- rotationRad: M / 180 * Math.PI
39
+ rotationRad: p / 180 * Math.PI
40
40
  };
41
41
  }
42
- function Qt(o) {
42
+ function ne(e) {
43
43
  const t = /* @__PURE__ */ new Set();
44
- for (const i of o.tracks)
45
- for (const r of i.children)
46
- r.url && t.add(r.url);
44
+ for (const o of e.tracks)
45
+ for (const i of o.children)
46
+ i.url && t.add(i.url);
47
47
  return t;
48
48
  }
49
- function Mt(o, t) {
50
- const i = [];
51
- return o.tracks.forEach((r, a) => {
52
- r.children.forEach((u, c) => {
53
- u.startTime <= t && t < u.endTime && i.push({ segment: u, trackIndex: a, childIndex: c });
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
54
  });
55
- }), i.sort((r, a) => {
56
- const u = o.tracks[r.trackIndex], c = o.tracks[a.trackIndex], d = u?.trackType === "frames" && u.isMain, l = c?.trackType === "frames" && c.isMain, p = o.tracks.length, h = d ? 0 : p - r.trackIndex, m = l ? 0 : p - a.trackIndex;
57
- return h !== m ? h - m : r.trackIndex === a.trackIndex ? r.childIndex - a.childIndex : r.trackIndex - a.trackIndex;
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
58
  });
59
59
  }
60
- function Zt(o, t, i, r) {
61
- const a = ee(t), u = o instanceof O && o.texture.width || i, c = o instanceof O && o.texture.height || r, d = Ht(t, i, r, u, c);
62
- o instanceof O ? (o.anchor.set(0.5), o.width = d.width, o.height = d.height, o.position.set(d.centerX, d.centerY), o.rotation = d.rotationRad, o.texture.source?.addEventListener?.("error", () => {
63
- o.texture = V.from(te(i, r));
64
- }, { once: !0 })) : o instanceof vt && (o.clear(), o.rect(0, 0, d.width, d.height).fill({ color: gt("url" in t && typeof t.url == "string" ? t.url : t.segmentType), alpha: xt(t) ? a : 0.35 }), o.pivot.set(d.width / 2, d.height / 2), o.position.set(d.centerX, d.centerY), o.rotation = d.rotationRad), o.alpha = a;
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
65
  }
66
- function Y(o, t) {
67
- const i = new vt();
68
- return i.rect(0, 0, 10, 10).fill({ color: gt(t ?? o), alpha: 1 }), i;
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
69
  }
70
- function te(o, t, i) {
71
- const r = `<svg xmlns="http://www.w3.org/2000/svg" width="${o}" height="${t}"><rect width="100%" height="100%" fill="#0f172a" fill-opacity="0.8"/></svg>`;
72
- return `data:image/svg+xml;base64,${btoa(r)}`;
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
73
  }
74
- function gt(o) {
74
+ function At(e) {
75
75
  let t = 0;
76
- for (let i = 0; i < o.length; i++)
77
- t = o.charCodeAt(i) + ((t << 5) - t);
76
+ for (let o = 0; o < e.length; o++)
77
+ t = e.charCodeAt(o) + ((t << 5) - t);
78
78
  return t & 16777215;
79
79
  }
80
- function J(o) {
81
- const t = o.tracks.flatMap((i) => i.children.map((r) => r.endTime));
80
+ function it(e) {
81
+ const t = e.tracks.flatMap((o) => o.children.map((i) => i.endTime));
82
82
  return t.length ? Math.max(...t) : 0;
83
83
  }
84
- function X(o, t, i) {
85
- return Math.min(Math.max(o, t), i);
84
+ function et(e, t, o) {
85
+ return Math.min(Math.max(e, t), o);
86
86
  }
87
- function pt(o) {
88
- const t = zt(o);
87
+ function St(e) {
88
+ const t = Xt(e);
89
89
  return JSON.parse(JSON.stringify(t));
90
90
  }
91
- function xt(o) {
92
- return "opacity" in o;
91
+ function Et(e) {
92
+ return "opacity" in e;
93
93
  }
94
- function ee(o) {
95
- return xt(o) && typeof o.opacity == "number" ? o.opacity : 1;
94
+ function ce(e) {
95
+ return Et(e) && typeof e.opacity == "number" ? e.opacity : 1;
96
96
  }
97
- class oe {
97
+ class ue {
98
98
  protocol;
99
99
  clips = /* @__PURE__ */ new Map();
100
100
  loadingClips = /* @__PURE__ */ new Map();
@@ -104,6 +104,8 @@ class oe {
104
104
  mp4States = /* @__PURE__ */ new Map();
105
105
  audioGains = /* @__PURE__ */ new Map();
106
106
  mp4Gains = /* @__PURE__ */ new Map();
107
+ audioElements = /* @__PURE__ */ new Map();
108
+ useMediaElementForAudio = !0;
107
109
  ctx;
108
110
  lastTime = 0;
109
111
  constructor(t) {
@@ -112,113 +114,121 @@ class oe {
112
114
  setProtocol(t) {
113
115
  this.protocol = t;
114
116
  }
115
- async sync(t, i) {
116
- if (!i) {
117
+ async sync(t, o) {
118
+ if (!o) {
117
119
  this.stopAll(), this.lastTime = t;
118
120
  return;
119
121
  }
120
122
  this.ctx.state === "suspended" && await this.ctx.resume().catch(() => {
121
123
  }), Math.abs(t - this.lastTime) > 1e3 && this.stopAll(), this.lastTime = t;
122
- const r = Mt(this.protocol, t), a = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set();
123
- for (const { segment: c } of r)
124
+ const i = Rt(this.protocol, t), n = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set();
125
+ for (const { segment: c } of i)
124
126
  if (c.segmentType === "audio") {
125
- const d = this.audioKey(c.id);
126
- a.add(d), this.ensureAudioLoop(c, t);
127
+ const u = this.audioKey(c.id);
128
+ n.add(u), this.useMediaElementForAudio ? this.syncAudioElement(c, t) : this.ensureAudioLoop(c, t);
127
129
  } else if (c.segmentType === "frames" && "type" in c && c.type === "video") {
128
- const d = this.videoKey(c.id);
129
- u.add(d);
130
+ const u = this.videoKey(c.id);
131
+ a.add(u);
130
132
  }
131
- for (const [c, d] of this.audioLoops)
132
- if (!a.has(c)) {
133
- d.stop();
134
- for (const l of d.sources)
133
+ for (const [c, u] of this.audioLoops)
134
+ if (!n.has(c)) {
135
+ u.stop();
136
+ for (const d of u.sources)
135
137
  try {
136
- l.stop(), l.disconnect();
138
+ d.stop(), d.disconnect();
137
139
  } catch {
138
140
  }
139
141
  this.audioLoops.delete(c), this.audioLoopContexts.delete(c), this.audioGains.delete(c);
140
142
  }
141
- for (const [c, d] of this.mp4Loops)
142
- if (!u.has(c)) {
143
- d.stop();
144
- for (const l of d.sources)
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)
145
155
  try {
146
- l.stop(), l.disconnect();
156
+ d.stop(), d.disconnect();
147
157
  } catch {
148
158
  }
149
159
  this.mp4Loops.delete(c), this.mp4States.delete(c), this.mp4Gains.delete(c);
150
160
  }
151
161
  for (const c of this.mp4States.keys())
152
- !u.has(c) && !this.mp4Loops.has(c) && (this.mp4States.delete(c), this.mp4Gains.delete(c));
162
+ !a.has(c) && !this.mp4Loops.has(c) && (this.mp4States.delete(c), this.mp4Gains.delete(c));
153
163
  }
154
164
  /**
155
165
  * Play audio frames from MP4 video directly.
156
166
  * Called by renderer after it gets audio data from clip.tick()
157
167
  */
158
- playMp4AudioFrames(t, i, r) {
159
- if (!i || i.length === 0 || !i[0]?.length)
168
+ playMp4AudioFrames(t, o, i) {
169
+ if (!o || o.length === 0 || !o[0]?.length)
160
170
  return;
161
- const a = this.videoKey(t), u = this.getSegmentVolume(t), c = this.getOrCreateGain(this.mp4Gains, a, u);
171
+ const n = this.videoKey(t), a = this.getSegmentVolume(t), c = this.getOrCreateGain(this.mp4Gains, n, a);
162
172
  this.ctx.state === "suspended" && this.ctx.resume().catch(() => {
163
173
  });
164
- let d = this.mp4States.get(a);
165
- d || (d = {
174
+ let u = this.mp4States.get(n);
175
+ u || (u = {
166
176
  loop: { stop: () => {
167
177
  }, sources: [], isStopped: () => !1 },
168
178
  startUs: 0,
169
179
  startCtxTime: this.ctx.currentTime,
170
180
  fps: 30,
171
181
  nextStartAt: 0
172
- }, this.mp4States.set(a, d)), d.nextStartAt = this.playFrames(i, r, d.nextStartAt ?? 0, c, d.loop.sources);
182
+ }, this.mp4States.set(n, u)), u.nextStartAt = this.playFrames(o, i, u.nextStartAt ?? 0, c, u.loop.sources);
173
183
  }
174
184
  /**
175
185
  * Reset MP4 audio playback state (call when seeking or pausing)
176
186
  */
177
187
  resetMp4Audio(t) {
178
- const i = this.videoKey(t), r = this.mp4States.get(i);
179
- r && (r.nextStartAt = 0);
188
+ const o = this.videoKey(t), i = this.mp4States.get(o);
189
+ i && (i.nextStartAt = 0);
180
190
  }
181
191
  /**
182
192
  * Stop and clean up MP4 audio for a video segment
183
193
  */
184
194
  stopMp4Audio(t) {
185
- const i = this.videoKey(t), r = this.mp4States.get(i);
186
- if (r) {
187
- r.loop.stop();
188
- for (const a of r.loop.sources)
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)
189
199
  try {
190
- a.stop(), a.disconnect();
200
+ n.stop(), n.disconnect();
191
201
  } catch {
192
202
  }
193
- this.mp4Loops.delete(i), this.mp4States.delete(i), this.mp4Gains.delete(i);
203
+ this.mp4Loops.delete(o), this.mp4States.delete(o), this.mp4Gains.delete(o);
194
204
  }
195
205
  }
196
206
  /**
197
207
  * @deprecated Use playMp4AudioFrames instead
198
208
  */
199
- ensureMp4Audio(t, i, r, a) {
200
- const u = this.videoKey(t), c = this.getSegmentVolume(t), d = this.getOrCreateGain(this.mp4Gains, u, c), l = this.mp4States.get(u);
201
- if (l) {
202
- d.gain.value = Math.max(0, c);
203
- const h = (this.ctx.currentTime - l.startCtxTime) * 1e6, m = l.startUs + h;
204
- if (Math.abs(m - r) < 15e4 && l.fps === a)
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)
205
215
  return;
206
- l.loop.stop();
207
- for (const S of l.loop.sources)
216
+ d.loop.stop();
217
+ for (const M of d.loop.sources)
208
218
  try {
209
- S.stop(), S.disconnect();
219
+ M.stop(), M.disconnect();
210
220
  } catch {
211
221
  }
212
- this.mp4Loops.delete(u), this.mp4States.delete(u);
222
+ this.mp4Loops.delete(a), this.mp4States.delete(a);
213
223
  }
214
224
  this.ctx.state === "suspended" && this.ctx.resume().catch(() => {
215
225
  });
216
- const p = this.startMp4Loop(i, r, a, d);
217
- this.mp4Loops.set(u, p), this.mp4States.set(u, {
218
- loop: p,
219
- startUs: r,
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,
220
230
  startCtxTime: this.ctx.currentTime,
221
- fps: a
231
+ fps: n
222
232
  });
223
233
  }
224
234
  destroy() {
@@ -226,22 +236,30 @@ class oe {
226
236
  for (const t of this.clips.values())
227
237
  t.clip.destroy();
228
238
  this.clips.clear();
239
+ for (const t of this.audioElements.values())
240
+ this.destroyAudioElement(t.el);
241
+ this.audioElements.clear();
229
242
  }
230
243
  stopAll() {
244
+ 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
+ }
231
249
  for (const t of this.audioLoops.values()) {
232
250
  t.stop();
233
- for (const i of t.sources)
251
+ for (const o of t.sources)
234
252
  try {
235
- i.stop(0), i.disconnect();
253
+ o.stop(0), o.disconnect();
236
254
  } catch {
237
255
  }
238
256
  t.sources.length = 0;
239
257
  }
240
258
  for (const t of this.mp4Loops.values()) {
241
259
  t.stop();
242
- for (const i of t.sources)
260
+ for (const o of t.sources)
243
261
  try {
244
- i.stop(0), i.disconnect();
262
+ o.stop(0), o.disconnect();
245
263
  } catch {
246
264
  }
247
265
  t.sources.length = 0;
@@ -258,122 +276,183 @@ class oe {
258
276
  }
259
277
  this.audioLoops.clear(), this.audioLoopContexts.clear(), this.audioGains.clear(), this.mp4Loops.clear(), this.mp4States.clear(), this.mp4Gains.clear();
260
278
  }
261
- async ensureAudioLoop(t, i) {
262
- const r = this.audioKey(t.id), a = await this.loadClip(t);
263
- if (!a)
279
+ async ensureAudioLoop(t, o) {
280
+ const i = this.audioKey(t.id), n = await this.loadClip(t);
281
+ if (!n)
264
282
  return;
265
- const u = t.fromTime ?? 0, c = Math.max(0.1, Math.min(100, t.playRate ?? 1)), d = i - t.startTime, l = u + d * c, p = this.getOrCreateGain(this.audioGains, r, t.volume);
266
- this.applyFadeToGain(t, d, p);
267
- const h = this.audioLoops.get(r);
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);
268
286
  if (h && !h.isStopped())
269
287
  return;
270
- h && (this.audioLoops.delete(r), this.audioLoopContexts.delete(r));
271
- const S = (t.endTime - t.startTime) * c, M = u + S, k = this.startAudioLoop(a.clip, Math.max(0, l) * 1e3, p, c, M * 1e3);
272
- this.audioLoops.set(r, k), this.audioLoopContexts.set(r, {
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, {
273
291
  segment: t,
274
292
  startedAt: this.ctx.currentTime,
275
- segmentRelativeMs: d
293
+ segmentRelativeMs: u
276
294
  });
277
295
  }
278
- applyFadeToGain(t, i, r) {
279
- const a = Math.max(0, typeof t.volume == "number" ? t.volume : 1), u = t.endTime - t.startTime, c = t.fadeInDuration ?? 0, d = t.fadeOutDuration ?? 0;
280
- let l = 1;
281
- c > 0 && i < c && (l = Math.max(0, i / c));
282
- const p = u - i;
283
- d > 0 && p < d && (l = Math.min(l, Math.max(0, p / d))), r.gain.value = a * l;
284
- }
285
- startMp4Loop(t, i, r, a) {
286
- let u = !1, c = i, d = 0, l = !0;
287
- const p = Math.round(1e3 / Math.max(r || 30, 1) * 1e3), h = this.getClipSampleRate(t), m = [], S = window.setInterval(async () => {
288
- if (u)
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
+ }
311
+ if (O && Math.abs(n.el.currentTime - m) > 0.06)
312
+ try {
313
+ n.el.currentTime = m, n.lastSeekTimelineMs = o;
314
+ } catch {
315
+ }
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;
323
+ return;
324
+ }
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)
289
340
  return;
290
- const { audio: M, state: k } = await t.tick(Math.round(c));
291
- if (c += p, k === "done")
341
+ const { audio: p, state: v } = await t.tick(Math.round(c));
342
+ if (c += y, v === "done")
292
343
  return;
293
- if (l) {
294
- l = !1;
344
+ if (d) {
345
+ d = !1;
295
346
  return;
296
347
  }
297
- (M?.[0]?.length ?? 0) !== 0 && (d = this.playFrames(M, h, d, a, m));
298
- }, Math.round(1e3 / Math.max(r || 30, 1)));
348
+ (p?.[0]?.length ?? 0) !== 0 && (u = this.playFrames(p, h, u, n, w));
349
+ }, Math.round(1e3 / Math.max(i || 30, 1)));
299
350
  return {
300
- sources: m,
351
+ sources: w,
301
352
  stop: () => {
302
- u = !0, window.clearInterval(S);
353
+ a = !0, window.clearInterval(M);
303
354
  },
304
- isStopped: () => u
355
+ isStopped: () => a
305
356
  };
306
357
  }
307
- startAudioLoop(t, i, r, a = 1, u) {
308
- let c = !1, d = i, l = 0, p = !1;
309
- const h = this.getClipSampleRate(t), m = [], M = Math.round(1e5 * a), k = async () => {
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 () => {
310
361
  if (c)
311
362
  return;
312
- if (p || (i > 0 && await t.tick(i), p = !0), d += M, u !== void 0 && d > u) {
363
+ if (y || (o > 0 && await t.tick(o), y = !0), u += p, a !== void 0 && u > a) {
313
364
  c = !0;
314
365
  return;
315
366
  }
316
- const { audio: w, state: x } = await t.tick(d);
367
+ const { audio: m, state: g } = await t.tick(u);
317
368
  if (c)
318
369
  return;
319
- if (x === "done") {
370
+ if (g === "done") {
320
371
  c = !0;
321
372
  return;
322
373
  }
323
- if ((w?.[0]?.length ?? 0) === 0) {
374
+ if ((m?.[0]?.length ?? 0) === 0) {
324
375
  c = !0;
325
376
  return;
326
377
  }
327
- const E = a !== 1 ? this.resampleForPlayRate(w, a) : w;
328
- l = this.playFrames(E, h, l, r, m), c || setTimeout(() => k(), 0);
378
+ d = this.playFrames(m, h, d, i, w, n), c || setTimeout(() => v(), 0);
329
379
  };
330
- return k(), {
331
- sources: m,
380
+ return v(), {
381
+ sources: w,
332
382
  stop: () => {
333
383
  c = !0;
334
384
  },
335
- isStopped: () => c
385
+ // Treat loop as active while there are still scheduled sources playing.
386
+ isStopped: () => c && w.length === 0
336
387
  };
337
388
  }
338
- resampleForPlayRate(t, i) {
339
- const r = Math.round(t[0].length / i);
340
- return r <= 0 ? t : t.map((a) => {
341
- const u = new Float32Array(r);
342
- for (let c = 0; c < r; c++) {
343
- const d = c * i, l = Math.floor(d), p = Math.min(l + 1, a.length - 1), h = d - l;
344
- u[c] = a[l] * (1 - h) + a[p] * h;
345
- }
346
- return u;
347
- });
348
- }
349
- playFrames(t, i, r, a, u) {
350
- const c = Math.max(t.length, 1), d = t[0]?.length ?? 0;
389
+ playFrames(t, o, i, n, a, c = 1) {
390
+ const u = Math.max(t.length, 1), d = t[0]?.length ?? 0;
351
391
  if (d === 0)
352
- return r;
353
- const l = this.ctx.createBuffer(c, d, i);
354
- for (let m = 0; m < c; m++) {
355
- const S = t[m] ?? new Float32Array(d);
356
- l.copyToChannel(new Float32Array(S), m);
392
+ 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);
357
397
  }
358
- const p = this.ctx.createBufferSource();
359
- p.buffer = l, p.connect(a);
360
- const h = Math.max(this.ctx.currentTime, r);
361
- if (p.start(h), u) {
362
- u.push(p);
363
- const m = l.duration * 1e3;
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;
364
406
  setTimeout(() => {
365
- const S = u.indexOf(p);
366
- S > -1 && u.splice(S, 1);
367
- }, m + 100);
407
+ const v = a.indexOf(h);
408
+ v > -1 && a.splice(v, 1);
409
+ }, p + 100);
410
+ }
411
+ return M + y.duration / w;
412
+ }
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;
417
+ const a = this.ctx.createGain();
418
+ return a.gain.value = this.normalizeVolume(i), a.connect(this.ctx.destination), t.set(o, a), a;
419
+ }
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
430
+ };
431
+ return this.audioElements.set(t, a), a;
432
+ }
433
+ destroyAudioElement(t) {
434
+ try {
435
+ t.pause();
436
+ } catch {
437
+ }
438
+ t.removeAttribute("src");
439
+ try {
440
+ t.load();
441
+ } catch {
368
442
  }
369
- return h + l.duration;
370
443
  }
371
- getOrCreateGain(t, i, r) {
372
- const a = t.get(i);
373
- if (a)
374
- return typeof r == "number" && (a.gain.value = Math.max(0, r)), a;
375
- const u = this.ctx.createGain();
376
- return u.gain.value = Math.max(0, typeof r == "number" ? r : 1), u.connect(this.ctx.destination), t.set(i, u), u;
444
+ normalizePlayRate(t) {
445
+ return typeof t != "number" || !Number.isFinite(t) ? 1 : Math.max(0.1, Math.min(100, t));
446
+ }
447
+ normalizeVolume(t) {
448
+ return typeof t != "number" || !Number.isFinite(t) ? 1 : Math.max(0, Math.min(1, t));
449
+ }
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;
377
456
  }
378
457
  audioKey(t) {
379
458
  return `audio:${t}`;
@@ -382,639 +461,639 @@ class oe {
382
461
  return `video:${t}`;
383
462
  }
384
463
  async loadClip(t) {
385
- const i = this.clips.get(t.id);
464
+ const o = this.clips.get(t.id);
465
+ if (o)
466
+ return o;
467
+ const i = this.loadingClips.get(t.id);
386
468
  if (i)
387
469
  return i;
388
- const r = this.loadingClips.get(t.id);
389
- if (r)
390
- return r;
391
- const a = (async () => {
470
+ const n = (async () => {
392
471
  try {
393
- const u = await fetch(t.url);
394
- if (!u.body) {
472
+ const a = await fetch(t.url);
473
+ if (!a.body) {
395
474
  this.loadingClips.delete(t.id);
396
475
  return;
397
476
  }
398
- const c = new jt(u.body), d = { clip: c, ready: c.ready };
477
+ const c = new Tt(a.body), u = { clip: c, ready: c.ready };
399
478
  if (await c.ready, !this.findSegmentInProtocol(t.id)) {
400
479
  c.destroy(), this.loadingClips.delete(t.id);
401
480
  return;
402
481
  }
403
- return this.clips.set(t.id, d), this.loadingClips.delete(t.id), d;
404
- } catch (u) {
405
- console.error(`[AudioManager] Failed to load audio ${t.url}`, u), this.loadingClips.delete(t.id);
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);
406
485
  return;
407
486
  }
408
487
  })();
409
- return this.loadingClips.set(t.id, a), a;
488
+ return this.loadingClips.set(t.id, n), n;
410
489
  }
411
490
  findSegmentInProtocol(t) {
412
- for (const i of this.protocol.tracks)
413
- for (const r of i.children)
414
- if (r.id === t) return !0;
491
+ for (const o of this.protocol.tracks)
492
+ for (const i of o.children)
493
+ if (i.id === t) return !0;
415
494
  return !1;
416
495
  }
417
496
  getSegmentVolume(t) {
418
- for (const i of this.protocol.tracks)
419
- for (const r of i.children) {
420
- if (r.id !== t)
497
+ for (const o of this.protocol.tracks)
498
+ for (const i of o.children) {
499
+ if (i.id !== t)
421
500
  continue;
422
- const a = r.volume;
423
- return typeof a == "number" ? a : 1;
501
+ const n = i.volume;
502
+ return this.normalizeVolume(n);
424
503
  }
425
504
  return 1;
426
505
  }
427
506
  getClipSampleRate(t) {
428
- const i = t.meta;
429
- if (!i)
507
+ const o = t.meta;
508
+ if (!o)
430
509
  return 48e3;
431
- const r = i.audioSampleRate;
432
- if (typeof r == "number" && r > 0)
433
- return r;
434
- const a = i.sampleRate;
435
- return typeof a == "number" && a > 0 ? a : 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;
436
515
  }
437
516
  }
438
- const re = 100, $ = /* @__PURE__ */ new Map();
439
- let ie = re;
440
- function ne(o, t) {
441
- $.delete(o), $.set(o, t);
517
+ const le = 100, $ = /* @__PURE__ */ new Map();
518
+ let de = le;
519
+ function fe(e, t) {
520
+ $.delete(e), $.set(e, t);
442
521
  }
443
- function ae() {
444
- for (; $.size > ie; ) {
445
- const [o, t] = $.entries().next().value;
446
- $.delete(o), t.close?.();
522
+ function he() {
523
+ for (; $.size > de; ) {
524
+ const [e, t] = $.entries().next().value;
525
+ $.delete(e), t.close?.();
447
526
  }
448
527
  }
449
- function se(o) {
450
- return o.map((t) => t.content).filter(Boolean).join(`
528
+ function pe(e) {
529
+ return e.map((t) => t.content).filter(Boolean).join(`
451
530
  `);
452
531
  }
453
- function ce(o) {
454
- const t = Array.isArray(o.fontFamily) ? o.fontFamily.join(", ") : o.fontFamily, i = o.fontSize ?? 32, r = o.fontWeight ?? "normal", a = o.fontStyle ?? "normal", u = o.fill ?? "#ffffff", c = o.align ?? "left", d = [
455
- `font-size: ${i}px`,
456
- `font-weight: ${r}`,
457
- `font-style: ${a}`,
458
- `color: ${u}`,
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}`,
537
+ `color: ${a}`,
459
538
  `text-align: ${c}`,
460
539
  "white-space: pre-wrap"
461
540
  ];
462
- if (t && d.push(`font-family: ${t}`), typeof o.letterSpacing == "number" && d.push(`letter-spacing: ${o.letterSpacing}px`), typeof o.leading == "number" && d.push(`line-height: ${o.leading}px`), o.background?.color && d.push(`background: ${o.background.color}`), o.stroke?.color && typeof o.stroke.width == "number" && d.push(`-webkit-text-stroke: ${o.stroke.width}px ${o.stroke.color}`), o.underline && d.push("text-decoration: underline"), o.dropShadow?.color && typeof o.dropShadow.distance == "number") {
463
- const l = (o.dropShadow.angle ?? 45) * (Math.PI / 180), p = Math.cos(l) * o.dropShadow.distance, h = Math.sin(l) * o.dropShadow.distance, m = o.dropShadow.blur ?? 0;
464
- d.push(`text-shadow: ${p}px ${h}px ${m}px ${o.dropShadow.color}`);
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}`);
465
544
  }
466
- return d.join("; ");
545
+ return u.join("; ");
467
546
  }
468
- async function de(o, t) {
469
- const i = `${t}::${o}`, r = $.get(i);
470
- if (r)
471
- return ne(i, r), r;
472
- const a = await _t(o, t);
473
- return $.set(i, a), ae(), a;
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;
474
553
  }
475
- const ue = "/video-editor-res";
476
- async function le(o) {
477
- const t = Gt(), i = Kt(o.protocol) ? o.protocol : ut(o.protocol), r = ut(
478
- t.verify(pt(lt(i)))
479
- ), a = o.app ?? await Xt(o.appOptions), u = new Yt();
480
- a.stage.addChild(u);
481
- const c = Nt({ dir: o.resourceDir }), d = /* @__PURE__ */ new Set(), l = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), h = /* @__PURE__ */ new Set(), m = /* @__PURE__ */ new Set(), S = o.videoSourceMode ?? "auto", M = /* @__PURE__ */ new Map(), k = /* @__PURE__ */ new Map(), w = ft(0), x = ft(!1), R = qt(() => J(r.value)), E = new oe(r.value);
482
- let A, L = 0, C = 0;
483
- async function St(e) {
484
- const s = C, { protocol: n, at: f, layer: y } = e, v = Ot(n, f), g = Mt(n, v), T = e.app.renderer.width, b = e.app.renderer.height;
485
- E.sync(f, x.value);
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);
486
565
  const I = [];
487
- for (const { segment: U } of g) {
488
- if (s !== C)
566
+ for (const { segment: N } of T) {
567
+ if (l !== b)
489
568
  return;
490
- const P = await e.getDisplay(U);
491
- if (s !== C)
569
+ const L = await r.getDisplay(N);
570
+ if (l !== b)
492
571
  return;
493
- if (P && !P.destroyed) {
494
- if (Zt(P, U, T, b), Pt(U) && await j(U, v), s !== C)
572
+ if (L && !L.destroyed) {
573
+ if (ae(L, N, k, C), Gt(N) && await H(N, x), l !== b)
495
574
  return;
496
- I.push(P);
575
+ I.push(L);
497
576
  }
498
577
  }
499
- if (s !== C)
578
+ if (l !== b)
500
579
  return;
501
- y.removeChildren();
502
- const F = I.filter(Boolean);
503
- F.length && y.addChild(...F), s === C && e.app.render();
504
- }
505
- const z = fe(() => St({
506
- app: a,
507
- layer: u,
508
- protocol: r.value,
509
- at: w.value,
510
- getDisplay: Rt
511
- })), Q = Bt();
512
- Q.run(() => {
513
- W(
514
- () => lt(i),
515
- (e) => {
580
+ S.removeChildren();
581
+ const U = I.filter(Boolean);
582
+ U.length && S.addChild(...U), l === b && r.app.render();
583
+ }
584
+ const D = Me(() => q({
585
+ app: n,
586
+ layer: a,
587
+ protocol: i.value,
588
+ at: m.value,
589
+ getDisplay: Lt
590
+ })), z = Qt();
591
+ z.run(() => {
592
+ Z(
593
+ () => Mt(o),
594
+ (r) => {
516
595
  try {
517
- r.value = t.verify(pt(e));
518
- } catch (s) {
519
- console.error("[renderer] invalid protocol update", s);
596
+ i.value = t.verify(St(r));
597
+ } catch (l) {
598
+ console.error("[renderer] invalid protocol update", l);
520
599
  return;
521
600
  }
522
- E.setProtocol(r.value), C += 1, Z(), o.warmUpResources !== !1 && Tt(r.value), bt(r.value), K(), o.manualRender || z();
601
+ P.setProtocol(i.value), b += 1, _(), e.warmUpResources !== !1 && F(i.value), Y(i.value), O(), e.manualRender || D();
523
602
  },
524
603
  { deep: !0, immediate: !0 }
525
- ), o.manualRender || W(w, () => {
526
- K(), z();
527
- }), W(R, () => K());
604
+ ), e.manualRender || Z(m, () => {
605
+ O(), D();
606
+ }), Z(R, () => O());
528
607
  });
529
- function K() {
530
- const e = R.value;
531
- e <= 0 ? w.value = 0 : w.value > e ? w.value = e : w.value < 0 && (w.value = 0);
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);
532
611
  }
533
- function Tt(e) {
534
- for (const s of Qt(e))
535
- d.has(s) || (d.add(s), st(s) !== "video" && it(s) && c.add(s).catch(() => {
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(() => {
536
615
  }));
537
616
  }
538
- function bt(e) {
539
- const s = /* @__PURE__ */ new Set();
540
- for (const n of e.tracks)
541
- for (const f of n.children)
542
- s.add(f.id);
543
- for (const [n, f] of l)
544
- s.has(n) || (f.destroy(), l.delete(n));
545
- for (const [n, f] of M)
546
- s.has(n) || (nt(f), M.delete(n));
547
- }
548
- function Z() {
549
- u.removeChildren();
550
- for (const e of l.values())
551
- e.destroy();
552
- l.clear(), p.clear();
553
- for (const e of M.values())
554
- nt(e);
555
- M.clear();
556
- }
557
- function tt() {
558
- x.value || (x.value = !0, L = performance.now(), A = requestAnimationFrame(et));
559
- }
560
- function q() {
561
- x.value = !1, A !== void 0 && cancelAnimationFrame(A), A = void 0, E.sync(w.value, !1), o.freezeOnPause !== !1 && $t();
562
- }
563
- function et() {
564
- ot(), x.value && (A = requestAnimationFrame(et));
565
- }
566
- function ot(e) {
567
- if (!x.value && e === void 0)
617
+ function Y(r) {
618
+ const l = /* @__PURE__ */ new Set();
619
+ 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 _() {
628
+ a.removeChildren();
629
+ for (const r of d.values())
630
+ r.destroy();
631
+ d.clear(), y.clear();
632
+ for (const r of p.values())
633
+ ht(r);
634
+ p.clear();
635
+ }
636
+ function ct() {
637
+ g.value || (g.value = !0, E = performance.now(), A = requestAnimationFrame(ut));
638
+ }
639
+ function X() {
640
+ g.value = !1, A !== void 0 && cancelAnimationFrame(A), A = void 0, P.sync(m.value, !1), e.freezeOnPause !== !1 && qt();
641
+ }
642
+ function ut() {
643
+ lt(), g.value && (A = requestAnimationFrame(ut));
644
+ }
645
+ function lt(r) {
646
+ if (!g.value && r === void 0)
568
647
  return;
569
- const s = performance.now(), n = e ?? (L ? s - L : 0);
570
- L = s, n !== 0 && (w.value = X(
571
- w.value + n,
648
+ const l = performance.now(), s = r ?? (E ? l - E : 0);
649
+ E = l, s !== 0 && (m.value = et(
650
+ m.value + s,
572
651
  0,
573
652
  R.value || Number.POSITIVE_INFINITY
574
- ), R.value > 0 && w.value >= R.value && q());
653
+ ), R.value > 0 && m.value >= R.value && X());
575
654
  }
576
- function kt(e) {
577
- w.value = X(e, 0, R.value || Number.POSITIVE_INFINITY);
655
+ function Ut(r) {
656
+ m.value = et(r, 0, R.value || Number.POSITIVE_INFINITY);
578
657
  }
579
- async function Ct(e) {
580
- w.value = X(e, 0, R.value || Number.POSITIVE_INFINITY), await z();
658
+ async function Ot(r) {
659
+ m.value = et(r, 0, R.value || Number.POSITIVE_INFINITY), await D();
581
660
  }
582
- async function Rt(e) {
583
- const s = l.get(e.id);
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);
584
666
  if (s)
585
667
  return s;
586
- const n = p.get(e.id);
587
- if (n)
588
- return n;
589
- const f = At(e);
590
- p.set(e.id, f);
591
- const y = await f;
592
- return y && l.set(e.id, y), p.delete(e.id), y;
593
- }
594
- async function At(e) {
595
- if (e.segmentType === "frames" || e.segmentType === "sticker") {
596
- if (!e.url)
597
- return Y(e.segmentType);
598
- if ("type" in e && e.type === "video" && ct(e.url)) {
599
- const n = await Et(e);
600
- return n || Y(e.segmentType, e.url);
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;
672
+ }
673
+ async function Vt(r) {
674
+ if (r.segmentType === "frames" || r.segmentType === "sticker") {
675
+ 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);
601
680
  }
602
- const s = await Lt(e.url);
603
- return s ? new O(s) : Y(e.segmentType, e.url);
681
+ const l = await Dt(r.url);
682
+ return l ? new V(l) : tt(r.segmentType, r.url);
604
683
  }
605
- if (e.segmentType === "text")
606
- return await It(e);
607
- e.segmentType === "effect" || e.segmentType;
684
+ if (r.segmentType === "text")
685
+ return await $t(r);
686
+ r.segmentType === "effect" || r.segmentType;
608
687
  }
609
- async function It(e) {
610
- const s = se(e.texts);
611
- if (!s)
688
+ async function $t(r) {
689
+ const l = pe(r.texts);
690
+ if (!l)
612
691
  return;
613
- const [n] = e.texts;
614
- if (!n)
692
+ const [s] = r.texts;
693
+ if (!s)
615
694
  return;
616
- const f = await de(s, ce(n)), y = V.from(f);
617
- return new O(y);
695
+ const f = await ye(l, me(s)), S = G.from(f);
696
+ return new V(S);
618
697
  }
619
- async function Lt(e) {
620
- const s = e.startsWith("data:"), n = /^https?:\/\//.test(e);
621
- if (!s && !n)
698
+ async function Dt(r) {
699
+ const l = r.startsWith("data:"), s = /^https?:\/\//.test(r);
700
+ if (!l && !s)
622
701
  try {
623
- await c.add(e);
624
- const f = await c.get(e);
702
+ await c.add(r);
703
+ const f = await c.get(r);
625
704
  if (f instanceof HTMLImageElement)
626
- return V.from(f);
705
+ return G.from(f);
627
706
  } catch {
628
707
  }
629
- return await Vt(e);
630
- }
631
- async function Et(e) {
632
- const s = M.get(e.id);
633
- if (s)
634
- return s.sprite;
635
- const n = N(e.url), f = S !== "element", y = S !== "mp4clip";
636
- if (n && h.has(n)) {
637
- if (!y)
638
- throw new Error(`[renderer] MP4Clip unsupported for ${e.url}`);
639
- const v = await D(e.url).catch((g) => {
640
- console.warn("[renderer] failed to load video via <video>", e.url, g);
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)
717
+ 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);
641
720
  });
642
- return v ? (M.set(e.id, v), v.sprite) : void 0;
721
+ return x ? (p.set(r.id, x), x.sprite) : void 0;
643
722
  }
644
723
  if (f) {
645
- const v = await at(e.url).catch((g) => {
646
- if (n && B(g) && h.add(n), (!n || !m.has(n)) && (n && m.add(n), console.warn("[renderer] failed to load video via MP4Clip", e.url, g)), !y)
647
- throw g;
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;
648
727
  });
649
- if (v)
650
- return console.info("[renderer] video source: mp4clip", e.url), M.set(e.id, v), v.sprite;
728
+ if (x)
729
+ return console.info("[renderer] video source: mp4clip", r.url), p.set(r.id, x), x.sprite;
651
730
  }
652
- if (y) {
653
- const v = await D(e.url).catch((g) => {
654
- console.warn("[renderer] failed to load video via <video>", e.url, g);
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);
655
734
  });
656
- if (v)
657
- return console.info("[renderer] video source: element", e.url), M.set(e.id, v), v.sprite;
735
+ if (x)
736
+ return console.info("[renderer] video source: element", r.url), p.set(r.id, x), x.sprite;
658
737
  }
659
738
  }
660
- function B(e) {
661
- if (!(e instanceof Error))
739
+ function J(r) {
740
+ if (!(r instanceof Error))
662
741
  return !1;
663
- const s = e.message || "";
664
- return s.includes("stream is done") || s.includes("not emit ready") || s.includes("tick video timeout");
742
+ const l = r.message || "";
743
+ return l.includes("stream is done") || l.includes("not emit ready") || l.includes("tick video timeout");
665
744
  }
666
- async function j(e, s) {
667
- const n = M.get(e.id);
668
- if (n)
745
+ async function H(r, l) {
746
+ const s = p.get(r.id);
747
+ if (s)
669
748
  try {
670
- const f = e.fromTime ?? 0, y = Math.max(0, s - e.startTime + f), v = Math.floor(y * 1e3);
671
- if (n.kind === "frozen") {
672
- const T = N(e.url);
673
- if (!T)
749
+ const f = r.fromTime ?? 0, S = Math.max(0, l - r.startTime + f), x = Math.floor(S * 1e3);
750
+ if (s.kind === "frozen") {
751
+ const k = W(r.url);
752
+ if (!k)
674
753
  return;
675
- const b = await Ft(e.url, T, { sprite: n.sprite, oldTexture: n.texture });
676
- return b ? (M.set(e.id, b), await j(e, s)) : void 0;
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;
677
756
  }
678
- if (n.kind === "mp4clip")
757
+ if (s.kind === "mp4clip")
679
758
  try {
680
- const T = await n.clip.tick(v);
681
- if (T.video) {
682
- const b = n.canvas.getContext("2d");
683
- b && (b.drawImage(T.video, 0, 0, n.canvas.width, n.canvas.height), dt(n.texture)), T.video.close();
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();
684
763
  }
685
- if (x.value && T.audio && T.audio.length > 0) {
686
- const b = n.clip.meta?.audioSampleRate ?? 48e3;
687
- E.playMp4AudioFrames(e.id, T.audio, b);
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);
688
767
  }
689
768
  return;
690
- } catch (T) {
691
- const b = N(e.url);
692
- if (b && B(T) && (h.add(b), n.clip.destroy(), S !== "mp4clip")) {
693
- const I = await D(e.url, { sprite: n.sprite, oldTexture: n.texture }).catch((F) => {
694
- console.warn("[renderer] failed to fallback to <video> after MP4Clip error", e.url, F);
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);
695
774
  });
696
775
  if (I)
697
- return M.set(e.id, I), await j(e, s);
776
+ return p.set(r.id, I), await H(r, l);
698
777
  }
699
- b && !m.has(b) && (m.add(b), console.warn("[renderer] MP4Clip tick failed", e.url, T));
778
+ C && !w.has(C) && (w.add(C), console.warn("[renderer] MP4Clip tick failed", r.url, k));
700
779
  return;
701
780
  }
702
- const g = y / 1e3;
703
- if (!Number.isFinite(g) || n.kind !== "element")
781
+ const T = S / 1e3;
782
+ if (!Number.isFinite(T) || s.kind !== "element")
704
783
  return;
705
- await Ut(n, {
706
- targetSec: g,
707
- playbackRate: e.playRate ?? 1,
708
- volume: e.volume ?? 1
784
+ await Bt(s, {
785
+ targetSec: T,
786
+ playbackRate: r.playRate ?? 1,
787
+ volume: r.volume ?? 1
709
788
  });
710
789
  } catch (f) {
711
790
  console.warn("[renderer] update video frame failed", f);
712
791
  }
713
792
  }
714
- async function Ft(e, s, n) {
715
- const f = S !== "element", y = S !== "mp4clip";
716
- if (h.has(s)) {
717
- if (!y)
718
- throw new Error(`[renderer] MP4Clip unsupported for ${e}`);
719
- return await D(e, n).catch(() => {
793
+ async function Nt(r, l, s) {
794
+ const f = M !== "element", S = M !== "mp4clip";
795
+ if (h.has(l)) {
796
+ if (!S)
797
+ throw new Error(`[renderer] MP4Clip unsupported for ${r}`);
798
+ return await B(r, s).catch(() => {
720
799
  });
721
800
  }
722
801
  if (f) {
723
- const v = await at(e, n).catch((g) => {
724
- if (B(g) && h.add(s), !y)
725
- throw g;
802
+ const x = await pt(r, s).catch((T) => {
803
+ if (J(T) && h.add(l), !S)
804
+ throw T;
726
805
  });
727
- if (v)
728
- return v;
806
+ if (x)
807
+ return x;
729
808
  }
730
- if (y)
731
- return await D(e, n).catch(() => {
809
+ if (S)
810
+ return await B(r, s).catch(() => {
732
811
  });
733
812
  }
734
- function Pt(e) {
735
- return e.segmentType === "frames" && e.type === "video" && typeof e.url == "string" && ct(e.url);
813
+ function Gt(r) {
814
+ return r.segmentType === "frames" && r.type === "video" && typeof r.url == "string" && yt(r.url);
736
815
  }
737
- function Ot(e, s) {
738
- const n = J(e);
739
- if (n <= 0)
816
+ function Kt(r, l) {
817
+ const s = it(r);
818
+ if (s <= 0)
740
819
  return 0;
741
- if (s < n)
742
- return s;
743
- const f = Math.max(1e3 / Math.max(e.fps || 30, 1), 1);
744
- return Math.max(n - f, 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);
745
824
  }
746
- async function rt(e) {
747
- const s = o.resourceDir ?? ue;
825
+ async function dt(r) {
826
+ const l = e.resourceDir ?? we;
748
827
  try {
749
- const n = N(e);
750
- if (!n)
828
+ const s = W(r);
829
+ if (!s)
751
830
  return;
752
- const f = Wt(`${s}/${n}`, "r");
831
+ const f = te(`${l}/${s}`, "r");
753
832
  if (await f.exists())
754
833
  return f;
755
834
  } catch {
756
835
  return;
757
836
  }
758
837
  }
759
- function it(e) {
760
- return !(!e || e.startsWith("data:") || e.startsWith("blob:"));
838
+ function ft(r) {
839
+ return !(!r || r.startsWith("data:") || r.startsWith("blob:"));
761
840
  }
762
- function $t() {
763
- for (const [e, s] of M) {
764
- if (s.kind === "mp4clip") {
765
- s.clip.destroy(), M.set(e, {
841
+ function qt() {
842
+ for (const [r, l] of p) {
843
+ if (l.kind === "mp4clip") {
844
+ l.clip.destroy(), p.set(r, {
766
845
  kind: "frozen",
767
- canvas: s.canvas,
768
- texture: s.texture,
769
- sprite: s.sprite,
770
- meta: s.meta
846
+ canvas: l.canvas,
847
+ texture: l.texture,
848
+ sprite: l.sprite,
849
+ meta: l.meta
771
850
  });
772
851
  continue;
773
852
  }
774
- s.kind === "element" && s.video.pause();
853
+ l.kind === "element" && l.video.pause();
775
854
  }
776
855
  }
777
- function nt(e) {
778
- if (e.kind === "mp4clip") {
779
- e.clip.destroy();
856
+ function ht(r) {
857
+ if (r.kind === "mp4clip") {
858
+ r.clip.destroy();
780
859
  return;
781
860
  }
782
- if (e.kind === "frozen")
861
+ if (r.kind === "frozen")
783
862
  return;
784
- e.video.pause();
785
- const s = k.get(e.video);
786
- s && (URL.revokeObjectURL(s), k.delete(e.video)), e.video.removeAttribute("src"), e.video.load();
787
- }
788
- function _(e, s, n = 1e3) {
789
- return new Promise((f, y) => {
790
- const v = window.setTimeout(() => {
791
- b(), y(new Error(`Timed out waiting for media event: ${s}`));
792
- }, n), g = () => {
793
- b(), f();
794
- }, T = () => {
795
- b();
796
- const I = e.error ? `${e.error.code}` : "unknown";
797
- y(new Error(`Media error (${I}) while waiting for ${s}`));
798
- }, b = () => {
799
- window.clearTimeout(v), e.removeEventListener(s, g), e.removeEventListener("error", T);
863
+ 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();
873
+ }, 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);
800
879
  };
801
- e.addEventListener(s, g, { once: !0 }), e.addEventListener("error", T, { once: !0 });
880
+ r.addEventListener(l, T, { once: !0 }), r.addEventListener("error", k, { once: !0 });
802
881
  });
803
882
  }
804
- async function at(e, s) {
805
- let n;
806
- it(e) && (n = await rt(e), n || (await c.add(e).catch(() => {
807
- }), n = await rt(e)));
883
+ async function pt(r, l) {
884
+ let s;
885
+ ft(r) && (s = await dt(r), s || (await c.add(r).catch(() => {
886
+ }), s = await dt(r)));
808
887
  let f;
809
888
  try {
810
- if (n)
811
- f = new G(n);
889
+ if (s)
890
+ f = new K(s);
812
891
  else {
813
- const I = await fetch(e);
892
+ const I = await fetch(r);
814
893
  if (I.body)
815
- f = new G(I.body);
894
+ f = new K(I.body);
816
895
  else {
817
- const F = await I.arrayBuffer(), U = new ReadableStream({
818
- start(P) {
819
- P.enqueue(new Uint8Array(F)), P.close();
896
+ const U = await I.arrayBuffer(), N = new ReadableStream({
897
+ start(L) {
898
+ L.enqueue(new Uint8Array(U)), L.close();
820
899
  }
821
900
  });
822
- f = new G(U);
901
+ f = new K(N);
823
902
  }
824
903
  }
825
904
  await f.ready;
826
- const { width: y, height: v } = f.meta, g = document.createElement("canvas");
827
- g.width = y || 1, g.height = v || 1;
828
- const T = V.from(g), b = s?.sprite ?? new O(T);
829
- return s?.sprite && (s.sprite.texture = T, s.oldTexture?.destroy(!0)), { kind: "mp4clip", clip: f, canvas: g, texture: T, sprite: b, meta: { width: y, height: v } };
830
- } catch (y) {
831
- throw f?.destroy(), y;
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;
832
911
  }
833
912
  }
834
- function st(e) {
835
- const n = e.split("#")[0].split("?")[0].split("/").pop()?.split(".").pop()?.toLowerCase() ?? "";
836
- return ["mp4", "m4v", "mov", "webm"].includes(n) ? "video" : ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg", "avif"].includes(n) ? "image" : ["mp3", "wav", "aac", "m4a", "ogg", "flac"].includes(n) ? "audio" : "unknown";
913
+ function mt(r) {
914
+ const s = r.split("#")[0].split("?")[0].split("/").pop()?.split(".").pop()?.toLowerCase() ?? "";
915
+ 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";
837
916
  }
838
- function ct(e) {
839
- const s = st(e);
840
- return !(s === "image" || s === "audio");
917
+ function yt(r) {
918
+ const l = mt(r);
919
+ return !(l === "image" || l === "audio");
841
920
  }
842
- async function D(e, s) {
843
- const n = document.createElement("video");
844
- n.crossOrigin = "anonymous", n.muted = !1, n.playsInline = !0, n.preload = "metadata", n.src = e, n.load();
921
+ async function B(r, l) {
922
+ const s = document.createElement("video");
923
+ s.crossOrigin = "anonymous", s.muted = !1, s.playsInline = !0, s.preload = "metadata", s.src = r, s.load();
845
924
  try {
846
- await _(n, "loadedmetadata", 15e3);
847
- } catch (b) {
848
- n.pause();
849
- const I = k.get(n);
850
- throw I && (URL.revokeObjectURL(I), k.delete(n)), n.removeAttribute("src"), n.load(), b;
925
+ await Q(s, "loadedmetadata", 15e3);
926
+ } catch (C) {
927
+ s.pause();
928
+ const I = v.get(s);
929
+ throw I && (URL.revokeObjectURL(I), v.delete(s)), s.removeAttribute("src"), s.load(), C;
851
930
  }
852
- const f = n.videoWidth || 1, y = n.videoHeight || 1, v = document.createElement("canvas");
853
- v.width = f, v.height = y;
854
- const g = V.from(v), T = s?.sprite ?? new O(g);
855
- return s?.sprite && (s.sprite.texture = g, s.oldTexture?.destroy(!0)), { kind: "element", video: n, canvas: v, texture: g, sprite: T, meta: { width: f, height: y } };
856
- }
857
- async function Ut(e, s) {
858
- const { video: n, canvas: f, texture: y } = e;
859
- n.playbackRate = Number.isFinite(s.playbackRate) && s.playbackRate > 0 ? s.playbackRate : 1, n.volume = Math.max(0, Math.min(1, s.volume ?? 1)), x.value ? n.play().catch(() => {
860
- }) : n.pause();
861
- const v = Number.isFinite(n.duration) && n.duration > 0 ? n.duration : null, g = v ? Math.min(s.targetSec, Math.max(v - 0.03, 0)) : s.targetSec, T = n.currentTime, b = Math.abs(T - g), I = x.value ? 0.25 : 0.03;
862
- if (Number.isFinite(T) && b > I) {
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(() => {
939
+ }) : 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) {
863
942
  try {
864
- n.currentTime = g;
943
+ s.currentTime = T;
865
944
  } catch {
866
945
  }
867
- await _(n, "seeked", 250).catch(() => {
946
+ await Q(s, "seeked", 250).catch(() => {
868
947
  });
869
948
  }
870
- if (n.readyState < 2 && (await _(n, "canplay", 250).catch(() => {
871
- }), n.readyState < 2))
949
+ if (s.readyState < 2 && (await Q(s, "canplay", 250).catch(() => {
950
+ }), s.readyState < 2))
872
951
  return;
873
- const F = f.getContext("2d");
874
- F && (F.drawImage(n, 0, 0, f.width, f.height), dt(y));
875
- }
876
- function Vt(e) {
877
- return new Promise((s) => {
878
- const n = new Image();
879
- n.crossOrigin = "anonymous", n.onload = () => s(V.from(n)), n.onerror = () => {
880
- console.warn("[renderer] failed to load image", e), s(void 0);
881
- }, n.src = e;
952
+ const U = f.getContext("2d");
953
+ U && (U.drawImage(s, 0, 0, f.width, f.height), wt(S));
954
+ }
955
+ function jt(r) {
956
+ return new Promise((l) => {
957
+ 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);
960
+ }, s.src = r;
882
961
  });
883
962
  }
884
- function dt(e) {
885
- const s = e.source;
886
- if ("update" in s && typeof s.update == "function") {
887
- s.update();
963
+ function wt(r) {
964
+ const l = r.source;
965
+ if ("update" in l && typeof l.update == "function") {
966
+ l.update();
888
967
  return;
889
968
  }
890
- typeof e.update == "function" && e.update();
969
+ typeof r.update == "function" && r.update();
891
970
  }
892
- function Dt() {
893
- q(), C += 1, Q.stop(), Z(), u.destroy({ children: !0 }), l.clear(), p.clear(), d.clear(), o.app || a.destroy(), E.destroy();
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();
894
973
  }
895
- return o.autoPlay && tt(), {
896
- app: a,
897
- layer: u,
898
- currentTime: w,
974
+ return e.autoPlay && ct(), {
975
+ app: n,
976
+ layer: a,
977
+ currentTime: m,
899
978
  duration: R,
900
- isPlaying: x,
901
- play: tt,
902
- pause: q,
903
- tick: ot,
904
- seek: kt,
905
- renderAt: Ct,
906
- destroy: Dt
979
+ isPlaying: g,
980
+ play: ct,
981
+ pause: X,
982
+ tick: lt,
983
+ seek: Ut,
984
+ renderAt: Ot,
985
+ destroy: _t
907
986
  };
908
987
  }
909
- function fe(o) {
910
- let t = !1, i = !1, r = null, a = null;
988
+ function Me(e) {
989
+ let t = !1, o = !1, i = null, n = null;
911
990
  return async () => {
912
- r || (r = new Promise((d) => {
913
- a = d;
991
+ i || (i = new Promise((u) => {
992
+ n = u;
914
993
  }));
915
- const c = r;
916
- if (i)
994
+ const c = i;
995
+ if (o)
917
996
  return t = !0, c;
918
- i = !0;
997
+ o = !0;
919
998
  do
920
- t = !1, await o();
999
+ t = !1, await e();
921
1000
  while (t);
922
- return i = !1, a?.(), r = null, a = null, c;
1001
+ return o = !1, n?.(), i = null, n = null, c;
923
1002
  };
924
1003
  }
925
- function pe(o) {
926
- return typeof o == "object" && o !== null && "createReader" in o && "getSize" in o;
1004
+ function ge(e) {
1005
+ return typeof e == "object" && e !== null && "createReader" in e && "getSize" in e;
927
1006
  }
928
- function he(o) {
929
- return typeof ReadableStream < "u" && o instanceof ReadableStream;
1007
+ function Se(e) {
1008
+ return typeof ReadableStream < "u" && e instanceof ReadableStream;
930
1009
  }
931
- function me(o) {
932
- return typeof o == "string" || o instanceof Blob || pe(o) || he(o) ? { source: o } : o;
1010
+ function xe(e) {
1011
+ return typeof e == "string" || e instanceof Blob || ge(e) || Se(e) ? { source: e } : e;
933
1012
  }
934
- async function ht(o) {
935
- if (typeof o == "string") {
936
- const t = await fetch(o);
1013
+ async function xt(e) {
1014
+ if (typeof e == "string") {
1015
+ const t = await fetch(e);
937
1016
  if (!t.body)
938
1017
  throw new Error("concatVideos: unable to read video stream from url");
939
1018
  return t.body;
940
1019
  }
941
- return o instanceof Blob ? o.stream() : o;
1020
+ return e instanceof Blob ? e.stream() : e;
942
1021
  }
943
- function we(o, t) {
944
- let i = !1;
945
- const r = () => {
946
- i || (i = !0, t());
947
- }, a = o.getReader();
1022
+ function Te(e, t) {
1023
+ let o = !1;
1024
+ const i = () => {
1025
+ o || (o = !0, t());
1026
+ }, n = e.getReader();
948
1027
  return new ReadableStream({
949
- async pull(u) {
950
- const { done: c, value: d } = await a.read();
1028
+ async pull(a) {
1029
+ const { done: c, value: u } = await n.read();
951
1030
  if (c) {
952
- r(), u.close();
1031
+ i(), a.close();
953
1032
  return;
954
1033
  }
955
- u.enqueue(d);
1034
+ a.enqueue(u);
956
1035
  },
957
- async cancel(u) {
1036
+ async cancel(a) {
958
1037
  try {
959
- await a.cancel(u);
1038
+ await n.cancel(a);
960
1039
  } finally {
961
- r();
1040
+ i();
962
1041
  }
963
1042
  }
964
1043
  });
965
1044
  }
966
- async function Te(o, t = {}) {
967
- if (o.length === 0)
1045
+ async function Ne(e, t = {}) {
1046
+ if (e.length === 0)
968
1047
  throw new Error("concatVideos: expected at least one source");
969
1048
  const {
970
- onProgress: i,
971
- width: r,
972
- height: a,
973
- ...u
974
- } = t, c = o.map(me), [d, ...l] = c, p = await ht(d.source), h = new G(p);
1049
+ onProgress: o,
1050
+ width: i,
1051
+ height: n,
1052
+ ...a
1053
+ } = t, c = e.map(xe), [u, ...d] = c, y = await xt(u.source), h = new K(y);
975
1054
  await h.ready;
976
- const m = r ?? Math.round(h.meta.width || 0), S = a ?? Math.round(h.meta.height || 0);
977
- if (!m || !S)
1055
+ const w = i ?? Math.round(h.meta.width || 0), M = n ?? Math.round(h.meta.height || 0);
1056
+ if (!w || !M)
978
1057
  throw h.destroy(), new Error("concatVideos: output width/height is required");
979
- const M = new mt({
980
- ...u,
981
- width: m,
982
- height: S
1058
+ const p = new bt({
1059
+ ...a,
1060
+ width: w,
1061
+ height: M
983
1062
  });
984
- i && M.on("OutputProgress", i);
985
- let k = 0;
986
- const w = async (A) => {
987
- const L = A.meta.duration;
988
- if (!Number.isFinite(L) || L <= 0)
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)
989
1068
  throw A.destroy(), new Error("concatVideos: invalid clip duration");
990
- const C = new wt(A);
1069
+ const b = new nt(A);
991
1070
  try {
992
- await C.ready, C.rect.x = 0, C.rect.y = 0, C.rect.w = m, C.rect.h = S, C.time.offset = k, C.time.duration = L, await M.addSprite(C), k += L;
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;
993
1072
  } finally {
994
- C.destroy();
1073
+ b.destroy();
995
1074
  }
996
1075
  };
997
1076
  try {
998
- await w(h);
999
- for (const A of l) {
1000
- const L = await ht(A.source), C = new G(L);
1001
- await C.ready, await w(C);
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);
1002
1081
  }
1003
1082
  } catch (A) {
1004
- throw M.destroy(), A;
1083
+ throw p.destroy(), A;
1005
1084
  }
1006
- const x = k, R = M.output({ maxTime: x }), E = () => {
1007
- M.destroy();
1085
+ const g = v, R = p.output({ maxTime: g }), P = () => {
1086
+ p.destroy();
1008
1087
  };
1009
1088
  return {
1010
- stream: we(R, E),
1011
- width: m,
1012
- height: S,
1013
- durationMs: Math.round(x / 1e3),
1014
- destroy: E
1089
+ stream: Te(R, P),
1090
+ width: w,
1091
+ height: M,
1092
+ durationMs: Math.round(g / 1e3),
1093
+ destroy: P
1015
1094
  };
1016
1095
  }
1017
- class H {
1096
+ class at {
1018
1097
  ready;
1019
1098
  meta;
1020
1099
  protocol;
@@ -1022,149 +1101,314 @@ class H {
1022
1101
  renderer;
1023
1102
  app;
1024
1103
  destroyed = !1;
1025
- constructor(t, i = {}) {
1026
- this.protocol = t, this.options = i;
1027
- const r = i.width ?? t.width, a = i.height ?? t.height, u = J(t);
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);
1028
1107
  this.meta = {
1029
- width: r,
1030
- height: a,
1031
- duration: Math.max(0, Math.round(u * 1e3))
1108
+ width: i,
1109
+ height: n,
1110
+ duration: Math.max(0, Math.round(a * 1e3))
1032
1111
  }, this.ready = this.init();
1033
1112
  }
1034
1113
  async init() {
1035
- const t = this.options.width ?? this.protocol.width, i = this.options.height ?? this.protocol.height;
1036
- if (!t || !i)
1114
+ const t = this.options.width ?? this.protocol.width, o = this.options.height ?? this.protocol.height;
1115
+ if (!t || !o)
1037
1116
  throw new Error("ProtocolVideoClip: output width/height is required");
1038
- const r = new yt();
1039
- await r.init({
1117
+ const i = new kt();
1118
+ await i.init({
1040
1119
  width: t,
1041
- height: i,
1120
+ height: o,
1042
1121
  backgroundAlpha: 0,
1043
1122
  ...this.options.appOptions
1044
- }), r.ticker.stop(), this.app = r;
1045
- const a = this.options.rendererOptions ?? {}, u = await le({
1123
+ }), i.ticker.stop(), this.app = i;
1124
+ const n = this.options.rendererOptions ?? {}, a = await ve({
1046
1125
  protocol: this.protocol,
1047
- app: r,
1048
- ...a,
1126
+ app: i,
1127
+ ...n,
1049
1128
  autoPlay: !1,
1050
1129
  freezeOnPause: !1,
1051
1130
  manualRender: !0,
1052
- videoSourceMode: a.videoSourceMode ?? "mp4clip"
1131
+ videoSourceMode: n.videoSourceMode ?? "mp4clip"
1053
1132
  });
1054
- this.renderer = u;
1055
- const c = u.duration.value;
1133
+ this.renderer = a;
1134
+ const c = a.duration.value;
1056
1135
  return this.meta = {
1057
- width: r.renderer.width,
1058
- height: r.renderer.height,
1136
+ width: i.renderer.width,
1137
+ height: i.renderer.height,
1059
1138
  duration: Math.max(0, Math.round(c * 1e3))
1060
1139
  }, this.meta;
1061
1140
  }
1062
1141
  async tick(t) {
1063
- const i = [];
1142
+ const o = [];
1064
1143
  if (this.destroyed)
1065
- return { audio: i, state: "done" };
1144
+ return { audio: o, state: "done" };
1066
1145
  if (await this.ready, !this.renderer)
1067
- return { audio: i, state: "done" };
1068
- const r = this.meta.duration;
1069
- if (t >= r)
1070
- return { audio: i, state: "done" };
1071
- const a = Math.max(0, Math.min(t, r));
1072
- return await this.renderer.renderAt(a / 1e3), {
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), {
1073
1152
  video: new VideoFrame(this.renderer.app.canvas, {
1074
1153
  timestamp: t
1075
1154
  }),
1076
- audio: i,
1155
+ audio: o,
1077
1156
  state: "success"
1078
1157
  };
1079
1158
  }
1080
1159
  async clone() {
1081
- const t = new H(this.protocol, this.options);
1160
+ const t = new at(this.protocol, this.options);
1082
1161
  return await t.ready, t;
1083
1162
  }
1084
1163
  destroy() {
1085
1164
  this.destroyed || (this.destroyed = !0, this.renderer?.destroy(), this.app?.destroy(!0));
1086
1165
  }
1087
1166
  }
1088
- function ye(o, t) {
1089
- let i = !1;
1090
- const r = () => {
1091
- i || (i = !0, t());
1092
- }, a = o.getReader();
1167
+ const It = 12e3;
1168
+ function be(e, t, o) {
1169
+ return new Promise((i, n) => {
1170
+ const a = globalThis.setTimeout(() => {
1171
+ n(new Error(`composeProtocol: ${o} timed out (${t}ms)`));
1172
+ }, t);
1173
+ e.then((c) => {
1174
+ globalThis.clearTimeout(a), i(c);
1175
+ }).catch((c) => {
1176
+ globalThis.clearTimeout(a), n(c);
1177
+ });
1178
+ });
1179
+ }
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);
1184
+ return this.clipMeta = {
1185
+ width: i.width,
1186
+ height: i.height,
1187
+ duration: Math.max(0, Math.min(n, a))
1188
+ }, this.meta;
1189
+ });
1190
+ }
1191
+ ready;
1192
+ clipMeta = {
1193
+ width: 0,
1194
+ height: 0,
1195
+ duration: 0
1196
+ };
1197
+ get meta() {
1198
+ return { ...this.clipMeta };
1199
+ }
1200
+ 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)
1203
+ return {
1204
+ audio: [],
1205
+ state: "done"
1206
+ };
1207
+ const n = this.config.fromUs + o, a = await this.sourceClip.tick(n);
1208
+ ke(a.video);
1209
+ const c = this.resolveGain(i);
1210
+ return {
1211
+ audio: Ce(a.audio ?? [], c),
1212
+ state: a.state
1213
+ };
1214
+ }
1215
+ async clone() {
1216
+ const t = await this.sourceClip.clone(), o = new st(t, this.config);
1217
+ return await o.ready, o;
1218
+ }
1219
+ destroy() {
1220
+ this.sourceClip.destroy();
1221
+ }
1222
+ 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;
1227
+ }
1228
+ }
1229
+ function ke(e) {
1230
+ if (!e || typeof e != "object")
1231
+ return;
1232
+ const t = e.close;
1233
+ typeof t == "function" && t.call(e);
1234
+ }
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;
1241
+ });
1242
+ }
1243
+ function j(e) {
1244
+ return Number.isFinite(e) ? Math.max(0, Math.round(e * 1e3)) : 0;
1245
+ }
1246
+ function rt(e) {
1247
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(0, Math.min(1, e));
1248
+ }
1249
+ function Re(e) {
1250
+ return typeof e != "number" || !Number.isFinite(e) ? 1 : Math.max(0.1, Math.min(100, e));
1251
+ }
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));
1254
+ 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)
1261
+ };
1262
+ }
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);
1271
+ try {
1272
+ const n = await fetch(e, { signal: o.signal });
1273
+ if (!n.body)
1274
+ 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;
1278
+ } finally {
1279
+ globalThis.clearTimeout(i);
1280
+ }
1281
+ }
1282
+ async function Ft(e, t) {
1283
+ const o = Ae(t), i = new st(e, o), n = new nt(i);
1284
+ try {
1285
+ await be(n.ready, It, "prepare audio sprite");
1286
+ } catch (a) {
1287
+ throw n.destroy(), a;
1288
+ }
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);
1294
+ }
1295
+ async function Fe(e) {
1296
+ const t = await Pt(e.url), o = new K(t, { audio: !0 });
1297
+ return await Ft(o, e);
1298
+ }
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)
1317
+ 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);
1322
+ continue;
1323
+ }
1324
+ console.warn("[compose] skip audio sprite due to load failure", n.reason);
1325
+ }
1326
+ return i;
1327
+ }
1328
+ function ot(e) {
1329
+ for (const t of e)
1330
+ t.destroy();
1331
+ }
1332
+ function Oe(e, t) {
1333
+ let o = !1;
1334
+ const i = () => {
1335
+ o || (o = !0, t());
1336
+ }, n = e.getReader();
1093
1337
  return new ReadableStream({
1094
- async pull(u) {
1095
- const { done: c, value: d } = await a.read();
1338
+ async pull(a) {
1339
+ const { done: c, value: u } = await n.read();
1096
1340
  if (c) {
1097
- r(), u.close();
1341
+ i(), a.close();
1098
1342
  return;
1099
1343
  }
1100
- u.enqueue(d);
1344
+ a.enqueue(u);
1101
1345
  },
1102
- async cancel(u) {
1346
+ async cancel(a) {
1103
1347
  try {
1104
- await a.cancel(u);
1348
+ await n.cancel(a);
1105
1349
  } finally {
1106
- r();
1350
+ i();
1107
1351
  }
1108
1352
  }
1109
1353
  });
1110
1354
  }
1111
- async function be(o, t = {}) {
1355
+ async function Ge(e, t = {}) {
1112
1356
  const {
1113
- width: i,
1114
- height: r,
1115
- fps: a,
1116
- onProgress: u,
1357
+ width: o,
1358
+ height: i,
1359
+ fps: n,
1360
+ onProgress: a,
1117
1361
  clipOptions: c,
1118
- audioSprites: d,
1119
- ...l
1120
- } = t, p = i ?? o.width, h = r ?? o.height;
1121
- if (!p || !h)
1362
+ audioSprites: u,
1363
+ ...d
1364
+ } = t, y = o ?? e.width, h = i ?? e.height;
1365
+ if (!y || !h)
1122
1366
  throw new Error("composeProtocol: output width/height is required");
1123
- const m = a ?? o.fps, S = typeof d == "function", M = l.audio ?? (S ? void 0 : !1), k = new mt({
1124
- ...l,
1125
- audio: M,
1126
- width: p,
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,
1127
1371
  height: h,
1128
- fps: m
1372
+ fps: w
1129
1373
  });
1130
- u && k.on("OutputProgress", u);
1131
- let w, x;
1374
+ a && v.on("OutputProgress", a);
1375
+ let m, g;
1132
1376
  try {
1133
- if (w = new H(o, {
1134
- width: p,
1377
+ m = new at(e, {
1378
+ width: y,
1135
1379
  height: h,
1136
- fps: m,
1380
+ fps: w,
1137
1381
  ...c,
1138
1382
  rendererOptions: {
1139
1383
  warmUpResources: !1,
1140
1384
  ...c?.rendererOptions
1141
1385
  }
1142
- }), await w.ready, x = new wt(w), await x.ready, x.time.offset = 0, x.time.duration = w.meta.duration, x.rect.x = 0, x.rect.y = 0, x.rect.w = w.meta.width, x.rect.h = w.meta.height, await k.addSprite(x, { main: !0 }), d) {
1143
- const L = await d(o);
1144
- for (const C of L)
1145
- await k.addSprite(C);
1146
- }
1147
- } catch (L) {
1148
- throw k.destroy(), L;
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;
1149
1391
  }
1150
- const R = w?.meta.duration ?? 0;
1392
+ const R = m?.meta.duration ?? 0;
1151
1393
  if (!R)
1152
- throw new Error("composeProtocol: protocol has no duration");
1153
- const E = k.output({ maxTime: R }), A = () => {
1154
- x?.destroy(), w?.destroy(), k.destroy();
1394
+ throw ot(M), g?.destroy(), m?.destroy(), v.destroy(), new Error("composeProtocol: protocol has no duration");
1395
+ const P = v.output({ maxTime: R });
1396
+ let A = !1;
1397
+ const E = () => {
1398
+ A || (A = !0, ot(M), g?.destroy(), m?.destroy(), v.destroy());
1155
1399
  };
1156
1400
  return {
1157
- stream: ye(E, A),
1158
- width: p,
1401
+ stream: Oe(P, E),
1402
+ width: y,
1159
1403
  height: h,
1160
1404
  durationMs: Math.round(R / 1e3),
1161
- destroy: A
1405
+ destroy: E
1162
1406
  };
1163
1407
  }
1164
1408
  export {
1165
- H as ProtocolVideoClip,
1166
- be as composeProtocol,
1167
- Te as concatVideos,
1168
- le as createRenderer
1409
+ at as ProtocolVideoClip,
1410
+ Ge as composeProtocol,
1411
+ Ne as concatVideos,
1412
+ ve as createRenderer
1169
1413
  };
1170
1414
  //# sourceMappingURL=index.js.map