@video-editor/renderer 0.0.1-beta.15 → 0.0.1-beta.17

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.d.ts CHANGED
@@ -34,6 +34,7 @@ export declare interface RendererOptions {
34
34
  appOptions?: Partial<ApplicationOptions>;
35
35
  resourceDir?: string;
36
36
  autoPlay?: boolean;
37
+ freezeOnPause?: boolean;
37
38
  }
38
39
 
39
40
  export { }
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
- import { createValidator as Me, createResourceManager as Se, getResourceKey as O } from "@video-editor/protocol";
2
- import { toRaw as Ie, isRef as be, shallowRef as X, unref as Z, ref as ee, computed as Ce, effectScope as Re, watch as $ } from "@vue/reactivity";
3
- import { MP4Clip as L } from "@webav/av-cliper";
4
- import { file as Fe } from "opfs-tools";
5
- import { Application as Ve, Sprite as V, Texture as C, Graphics as ie, Container as De } from "pixi.js";
6
- async function Pe(n) {
7
- const o = new Ve();
8
- return await o.init({ resizeTo: window, ...n }), o;
1
+ import { createValidator as Se, createResourceManager as Ie, getResourceKey as N } from "@video-editor/protocol";
2
+ import { toRaw as be, isRef as Ce, shallowRef as ee, unref as te, ref as re, computed as Re, effectScope as Fe, watch as U } from "@vue/reactivity";
3
+ import { MP4Clip as $ } from "@webav/av-cliper";
4
+ import { file as Ve } from "opfs-tools";
5
+ import { Application as Pe, Sprite as V, Texture as C, Graphics as ae, Container as Ae } from "pixi.js";
6
+ async function De(n) {
7
+ const o = new Pe();
8
+ return await o.init({ resizeTo: window, backgroundAlpha: 0, ...n }), o;
9
9
  }
10
- function Ae(n) {
10
+ function Oe(n) {
11
11
  const o = /* @__PURE__ */ new Set();
12
12
  for (const a of n.tracks)
13
13
  for (const c of a.children)
@@ -22,107 +22,107 @@ function Ne(n, o) {
22
22
  });
23
23
  }), a.sort((c, v) => c.trackIndex === v.trackIndex ? c.childIndex - v.childIndex : c.trackIndex - v.trackIndex);
24
24
  }
25
- function Oe(n, o, a, c) {
25
+ function Ue(n, o, a, c) {
26
26
  const v = Le(o);
27
27
  n instanceof V ? (n.anchor.set(0.5), n.width = a, n.height = c, n.x = a / 2, n.y = c / 2, n.texture.source?.addEventListener?.("error", () => {
28
28
  n.texture = C.from($e(a, c));
29
- }, { once: !0 })) : n instanceof ie && (n.clear(), n.rect(0, 0, a, c).fill({ color: oe("url" in o && typeof o.url == "string" ? o.url : o.segmentType), alpha: ae(o) ? v : 0.35 }), n.pivot.set(a / 2, c / 2), n.position.set(a / 2, c / 2)), n.alpha = v;
29
+ }, { once: !0 })) : n instanceof ae && (n.clear(), n.rect(0, 0, a, c).fill({ color: ce("url" in o && typeof o.url == "string" ? o.url : o.segmentType), alpha: se(o) ? v : 0.35 }), n.pivot.set(a / 2, c / 2), n.position.set(a / 2, c / 2)), n.alpha = v;
30
30
  const p = We(o);
31
31
  if (p) {
32
- const [w, S] = p.position ?? [0, 0], [y, g] = p.scale ?? [1, 1], k = p.rotation?.[2] ?? 0;
33
- n.position.set(a / 2 + w * a / 2, c / 2 - S * c / 2), n.scale.set(y, g), n.rotation = k / 180 * Math.PI;
32
+ const [w, S] = p.position ?? [0, 0], [y, k] = p.scale ?? [1, 1], E = p.rotation?.[2] ?? 0;
33
+ n.position.set(a / 2 + w * a / 2, c / 2 - S * c / 2), n.scale.set(y, k), n.rotation = E / 180 * Math.PI;
34
34
  }
35
35
  }
36
- function U(n, o) {
37
- const a = new ie();
38
- return a.rect(0, 0, 10, 10).fill({ color: oe(o ?? n), alpha: 1 }), a;
36
+ function L(n, o) {
37
+ const a = new ae();
38
+ return a.rect(0, 0, 10, 10).fill({ color: ce(o ?? n), alpha: 1 }), a;
39
39
  }
40
40
  function $e(n, o, a) {
41
41
  const c = `<svg xmlns="http://www.w3.org/2000/svg" width="${n}" height="${o}"><rect width="100%" height="100%" fill="#0f172a" fill-opacity="0.8"/></svg>`;
42
42
  return `data:image/svg+xml;base64,${btoa(c)}`;
43
43
  }
44
- function oe(n) {
44
+ function ce(n) {
45
45
  let o = 0;
46
46
  for (let a = 0; a < n.length; a++)
47
47
  o = n.charCodeAt(a) + ((o << 5) - o);
48
48
  return o & 16777215;
49
49
  }
50
- function te(n) {
50
+ function ne(n) {
51
51
  const o = n.tracks.flatMap((a) => a.children.map((c) => c.endTime));
52
52
  return o.length ? Math.max(...o) : 0;
53
53
  }
54
- function re(n, o, a) {
54
+ function ie(n, o, a) {
55
55
  return Math.min(Math.max(n, o), a);
56
56
  }
57
- function ne(n) {
58
- const o = Ie(n);
57
+ function oe(n) {
58
+ const o = be(n);
59
59
  return JSON.parse(JSON.stringify(o));
60
60
  }
61
- function ae(n) {
61
+ function se(n) {
62
62
  return "opacity" in n;
63
63
  }
64
64
  function Le(n) {
65
- return ae(n) && typeof n.opacity == "number" ? n.opacity : 1;
65
+ return se(n) && typeof n.opacity == "number" ? n.opacity : 1;
66
66
  }
67
- function Ue(n) {
67
+ function ze(n) {
68
68
  return "transform" in n;
69
69
  }
70
70
  function We(n) {
71
- if (Ue(n))
71
+ if (ze(n))
72
72
  return n.transform;
73
73
  }
74
- const ze = "/video-editor-res";
75
- async function je(n) {
76
- const o = Me(), a = be(n.protocol) ? n.protocol : X(n.protocol), c = X(
77
- o.verify(ne(Z(a)))
78
- ), v = n.app ?? await Pe(n.appOptions), p = new De();
74
+ const qe = "/video-editor-res";
75
+ async function Be(n) {
76
+ const o = Se(), a = Ce(n.protocol) ? n.protocol : ee(n.protocol), c = ee(
77
+ o.verify(oe(te(a)))
78
+ ), v = n.app ?? await De(n.appOptions), p = new Ae();
79
79
  v.stage.addChild(p);
80
- const w = Se({ dir: n.resourceDir }), S = /* @__PURE__ */ new Set(), y = /* @__PURE__ */ new Map(), g = /* @__PURE__ */ new Map(), k = /* @__PURE__ */ new Set(), W = /* @__PURE__ */ new Set(), m = /* @__PURE__ */ new Map(), h = ee(0), x = ee(!1), E = Ce(() => te(c.value));
80
+ const w = Ie({ dir: n.resourceDir }), S = /* @__PURE__ */ new Set(), y = /* @__PURE__ */ new Map(), k = /* @__PURE__ */ new Map(), E = /* @__PURE__ */ new Set(), z = /* @__PURE__ */ new Set(), m = /* @__PURE__ */ new Map(), h = re(0), x = re(!1), g = Re(() => ne(c.value));
81
81
  let I, R = 0;
82
- async function ce(e) {
83
- const { protocol: r, at: t, layer: i } = e, s = we(r, t), u = Ne(r, s), d = e.app.renderer.width, f = e.app.renderer.height, l = [];
82
+ async function ue(e) {
83
+ const { protocol: r, at: t, layer: i } = e, s = xe(r, t), u = Ne(r, s), d = e.app.renderer.width, f = e.app.renderer.height, l = [];
84
84
  for (const { segment: M } of u) {
85
85
  const b = await e.getDisplay(M);
86
- b && (Oe(b, M, d, f), he(M) && await j(M, s), l.push(b));
86
+ b && (Ue(b, M, d, f), ye(M) && await j(M, s), l.push(b));
87
87
  }
88
88
  i.removeChildren();
89
89
  const T = l.filter(Boolean);
90
90
  T.length && i.addChild(...T), e.app.render();
91
91
  }
92
- const z = qe(() => ce({
92
+ const W = He(() => ue({
93
93
  app: v,
94
94
  layer: p,
95
95
  protocol: c.value,
96
96
  at: h.value,
97
- getDisplay: fe
98
- })), q = Re();
97
+ getDisplay: pe
98
+ })), q = Fe();
99
99
  q.run(() => {
100
- $(
101
- () => Z(a),
100
+ U(
101
+ () => te(a),
102
102
  (e) => {
103
103
  try {
104
- c.value = o.verify(ne(e));
104
+ c.value = o.verify(oe(e));
105
105
  } catch (r) {
106
106
  console.error("[renderer] invalid protocol update", r);
107
107
  return;
108
108
  }
109
- H(), se(c.value), ue(c.value), D(), z();
109
+ H(), de(c.value), fe(c.value), P(), W();
110
110
  },
111
111
  { deep: !0, immediate: !0 }
112
- ), $(h, () => {
113
- D(), z();
114
- }), $(E, () => D());
112
+ ), U(h, () => {
113
+ P(), W();
114
+ }), U(g, () => P());
115
115
  });
116
- function D() {
117
- const e = E.value;
116
+ function P() {
117
+ const e = g.value;
118
118
  e <= 0 ? h.value = 0 : h.value > e ? h.value = e : h.value < 0 && (h.value = 0);
119
119
  }
120
- function se(e) {
121
- for (const r of Ae(e))
122
- S.has(r) || (S.add(r), Te(r) !== "video" && A(r) && w.add(r).catch(() => {
120
+ function de(e) {
121
+ for (const r of Oe(e))
122
+ S.has(r) || (S.add(r), Q(r) !== "video" && D(r) && w.add(r).catch(() => {
123
123
  }));
124
124
  }
125
- function ue(e) {
125
+ function fe(e) {
126
126
  const r = new Set(e.tracks.flatMap((t) => t.children.map((i) => i.id)));
127
127
  for (const [t, i] of y)
128
128
  r.has(t) || (i.destroy(), y.delete(t));
@@ -133,7 +133,7 @@ async function je(n) {
133
133
  p.removeChildren();
134
134
  for (const e of y.values())
135
135
  e.destroy();
136
- y.clear(), g.clear();
136
+ y.clear(), k.clear();
137
137
  for (const e of m.values())
138
138
  B(e);
139
139
  m.clear();
@@ -141,8 +141,8 @@ async function je(n) {
141
141
  function K() {
142
142
  x.value || (x.value = !0, R = performance.now(), I = requestAnimationFrame(_));
143
143
  }
144
- function P() {
145
- x.value = !1, I !== void 0 && cancelAnimationFrame(I), I = void 0, xe();
144
+ function A() {
145
+ x.value = !1, I !== void 0 && cancelAnimationFrame(I), I = void 0, n.freezeOnPause !== !1 && ke();
146
146
  }
147
147
  function _() {
148
148
  J(), x.value && (I = requestAnimationFrame(_));
@@ -151,41 +151,41 @@ async function je(n) {
151
151
  if (!x.value && e === void 0)
152
152
  return;
153
153
  const r = performance.now(), t = e ?? (R ? r - R : 0);
154
- R = r, t !== 0 && (h.value = re(
154
+ R = r, t !== 0 && (h.value = ie(
155
155
  h.value + t,
156
156
  0,
157
- E.value || Number.POSITIVE_INFINITY
158
- ), E.value > 0 && h.value >= E.value && P());
157
+ g.value || Number.POSITIVE_INFINITY
158
+ ), g.value > 0 && h.value >= g.value && A());
159
159
  }
160
- function de(e) {
161
- h.value = re(e, 0, E.value || Number.POSITIVE_INFINITY);
160
+ function le(e) {
161
+ h.value = ie(e, 0, g.value || Number.POSITIVE_INFINITY);
162
162
  }
163
- async function fe(e) {
163
+ async function pe(e) {
164
164
  const r = y.get(e.id);
165
165
  if (r)
166
166
  return r;
167
- const t = g.get(e.id);
167
+ const t = k.get(e.id);
168
168
  if (t)
169
169
  return t;
170
- const i = le(e);
171
- g.set(e.id, i);
170
+ const i = ve(e);
171
+ k.set(e.id, i);
172
172
  const s = await i;
173
- return s && y.set(e.id, s), g.delete(e.id), s;
173
+ return s && y.set(e.id, s), k.delete(e.id), s;
174
174
  }
175
- async function le(e) {
175
+ async function ve(e) {
176
176
  if (e.segmentType === "frames" || e.segmentType === "sticker") {
177
177
  if (!e.url)
178
- return U(e.segmentType);
179
- if ("type" in e && e.type === "video") {
180
- const t = await ve(e);
181
- return t || U(e.segmentType, e.url);
178
+ return L(e.segmentType);
179
+ if ("type" in e && e.type === "video" && X(e.url)) {
180
+ const t = await he(e);
181
+ return t || L(e.segmentType, e.url);
182
182
  }
183
- const r = await pe(e.url);
184
- return r ? new V(r) : U(e.segmentType, e.url);
183
+ const r = await me(e.url);
184
+ return r ? new V(r) : L(e.segmentType, e.url);
185
185
  }
186
186
  e.segmentType !== "text" && (e.segmentType === "effect" || e.segmentType);
187
187
  }
188
- async function pe(e) {
188
+ async function me(e) {
189
189
  const r = e.startsWith("data:"), t = /^https?:\/\//.test(e);
190
190
  if (!r && !t)
191
191
  try {
@@ -197,19 +197,19 @@ async function je(n) {
197
197
  }
198
198
  return await Ee(e);
199
199
  }
200
- async function ve(e) {
200
+ async function he(e) {
201
201
  const r = m.get(e.id);
202
202
  if (r)
203
203
  return r.sprite;
204
- const t = O(e.url);
205
- if (t && k.has(t)) {
204
+ const t = N(e.url);
205
+ if (t && E.has(t)) {
206
206
  const u = await F(e.url).catch((d) => {
207
207
  console.warn("[renderer] failed to load video via <video>", e.url, d);
208
208
  });
209
209
  return u ? (m.set(e.id, u), u.sprite) : void 0;
210
210
  }
211
211
  const i = await G(e.url).catch((u) => {
212
- t && Y(u) && k.add(t), (!t || !W.has(t)) && (t && W.add(t), console.warn("[renderer] failed to load video via MP4Clip", e.url, u));
212
+ t && Y(u) && E.add(t), (!t || !z.has(t)) && (t && z.add(t), console.warn("[renderer] failed to load video via MP4Clip", e.url, u));
213
213
  });
214
214
  if (i)
215
215
  return m.set(e.id, i), i.sprite;
@@ -231,17 +231,17 @@ async function je(n) {
231
231
  try {
232
232
  const i = e.fromTime ?? 0, s = Math.max(0, r - e.startTime + i), u = Math.floor(s * 1e3);
233
233
  if (t.kind === "frozen") {
234
- const f = O(e.url);
234
+ const f = N(e.url);
235
235
  if (!f)
236
236
  return;
237
- const l = await me(e.url, f, { sprite: t.sprite, oldTexture: t.texture });
237
+ const l = await we(e.url, f, { sprite: t.sprite, oldTexture: t.texture });
238
238
  return l ? (m.set(e.id, l), await j(e, r)) : void 0;
239
239
  }
240
240
  if (t.kind === "mp4clip") {
241
241
  const f = await t.clip.tick(u);
242
242
  if (f.video) {
243
243
  const l = t.canvas.getContext("2d");
244
- l && (l.drawImage(f.video, 0, 0, t.canvas.width, t.canvas.height), Q(t.texture)), f.video.close();
244
+ l && (l.drawImage(f.video, 0, 0, t.canvas.width, t.canvas.height), Z(t.texture)), f.video.close();
245
245
  }
246
246
  return;
247
247
  }
@@ -256,21 +256,21 @@ async function je(n) {
256
256
  console.warn("[renderer] update video frame failed", i);
257
257
  }
258
258
  }
259
- async function me(e, r, t) {
260
- if (k.has(r))
259
+ async function we(e, r, t) {
260
+ if (E.has(r))
261
261
  return await F(e, t).catch(() => {
262
262
  });
263
263
  const i = await G(e, t).catch((s) => {
264
- Y(s) && k.add(r);
264
+ Y(s) && E.add(r);
265
265
  });
266
266
  return i || await F(e, t).catch(() => {
267
267
  });
268
268
  }
269
- function he(e) {
270
- return e.segmentType === "frames" && e.type === "video" && typeof e.url == "string";
269
+ function ye(e) {
270
+ return e.segmentType === "frames" && e.type === "video" && typeof e.url == "string" && X(e.url);
271
271
  }
272
- function we(e, r) {
273
- const t = te(e);
272
+ function xe(e, r) {
273
+ const t = ne(e);
274
274
  if (t <= 0)
275
275
  return 0;
276
276
  if (r < t)
@@ -278,23 +278,23 @@ async function je(n) {
278
278
  const i = Math.max(1e3 / Math.max(e.fps || 30, 1), 1);
279
279
  return Math.max(t - i, 0);
280
280
  }
281
- async function ye(e) {
282
- const r = n.resourceDir ?? ze;
281
+ async function Te(e) {
282
+ const r = n.resourceDir ?? qe;
283
283
  try {
284
- const t = O(e);
284
+ const t = N(e);
285
285
  if (!t)
286
286
  return;
287
- const i = Fe(`${r}/${t}`, "r");
287
+ const i = Ve(`${r}/${t}`, "r");
288
288
  if (await i.exists())
289
289
  return i;
290
290
  } catch {
291
291
  return;
292
292
  }
293
293
  }
294
- function A(e) {
294
+ function D(e) {
295
295
  return !(!e || e.startsWith("data:") || e.startsWith("blob:"));
296
296
  }
297
- function xe() {
297
+ function ke() {
298
298
  for (const [e, r] of m) {
299
299
  if (r.kind === "mp4clip") {
300
300
  r.clip.destroy(), m.set(e, {
@@ -316,7 +316,7 @@ async function je(n) {
316
316
  }
317
317
  e.kind !== "frozen" && (e.video.pause(), e.video.removeAttribute("src"), e.video.load());
318
318
  }
319
- function N(e, r, t = 1e3) {
319
+ function O(e, r, t = 1e3) {
320
320
  return new Promise((i, s) => {
321
321
  const u = window.setTimeout(() => {
322
322
  l(), s(new Error(`Timed out waiting for media event: ${r}`));
@@ -334,21 +334,21 @@ async function je(n) {
334
334
  }
335
335
  async function G(e, r) {
336
336
  let t;
337
- A(e) && (t = await ye(e));
337
+ D(e) && (t = await Te(e));
338
338
  let i;
339
339
  try {
340
340
  if (t)
341
- i = new L(t);
341
+ i = new $(t);
342
342
  else {
343
343
  const T = await fetch(e);
344
344
  if (!T.body)
345
345
  return;
346
- if (A(e)) {
346
+ if (D(e)) {
347
347
  const [M, b] = T.body.tee();
348
348
  w.add(e, { body: b }).catch(() => {
349
- }), i = new L(M);
349
+ }), i = new $(M);
350
350
  } else
351
- i = new L(T.body);
351
+ i = new $(T.body);
352
352
  }
353
353
  await i.ready;
354
354
  const { width: s, height: u } = i.meta, d = document.createElement("canvas");
@@ -359,15 +359,19 @@ async function je(n) {
359
359
  throw i?.destroy(), s;
360
360
  }
361
361
  }
362
- function Te(e) {
362
+ function Q(e) {
363
363
  const t = e.split("#")[0].split("?")[0].split("/").pop()?.split(".").pop()?.toLowerCase() ?? "";
364
364
  return ["mp4", "m4v", "mov", "webm"].includes(t) ? "video" : ["png", "jpg", "jpeg", "gif", "webp", "bmp", "svg", "avif"].includes(t) ? "image" : ["mp3", "wav", "aac", "m4a", "ogg", "flac"].includes(t) ? "audio" : "unknown";
365
365
  }
366
+ function X(e) {
367
+ const r = Q(e);
368
+ return !(r === "image" || r === "audio");
369
+ }
366
370
  async function F(e, r) {
367
371
  const t = document.createElement("video");
368
372
  t.crossOrigin = "anonymous", t.muted = !0, t.playsInline = !0, t.preload = "auto", t.src = e;
369
373
  try {
370
- await N(t, "loadedmetadata", 4e3);
374
+ await O(t, "loadedmetadata", 4e3);
371
375
  } catch (l) {
372
376
  throw t.pause(), t.removeAttribute("src"), t.load(), l;
373
377
  }
@@ -386,14 +390,14 @@ async function je(n) {
386
390
  t.currentTime = r.targetSec;
387
391
  } catch {
388
392
  }
389
- x.value || await N(t, "seeked", 250).catch(() => {
393
+ x.value || await O(t, "seeked", 250).catch(() => {
390
394
  });
391
395
  }
392
- if (t.readyState < 2 && (await N(t, "canplay", 250).catch(() => {
396
+ if (t.readyState < 2 && (await O(t, "canplay", 250).catch(() => {
393
397
  }), t.readyState < 2))
394
398
  return;
395
399
  const l = i.getContext("2d");
396
- l && (l.drawImage(t, 0, 0, i.width, i.height), Q(s));
400
+ l && (l.drawImage(t, 0, 0, i.width, i.height), Z(s));
397
401
  }
398
402
  function Ee(e) {
399
403
  return new Promise((r) => {
@@ -403,7 +407,7 @@ async function je(n) {
403
407
  }, t.src = e;
404
408
  });
405
409
  }
406
- function Q(e) {
410
+ function Z(e) {
407
411
  const r = e.source;
408
412
  if ("update" in r && typeof r.update == "function") {
409
413
  r.update();
@@ -411,23 +415,23 @@ async function je(n) {
411
415
  }
412
416
  typeof e.update == "function" && e.update();
413
417
  }
414
- function ke() {
415
- P(), q.stop(), H(), p.destroy({ children: !0 }), y.clear(), g.clear(), S.clear(), n.app || v.destroy();
418
+ function Me() {
419
+ A(), q.stop(), H(), p.destroy({ children: !0 }), y.clear(), k.clear(), S.clear(), n.app || v.destroy();
416
420
  }
417
421
  return n.autoPlay && K(), {
418
422
  app: v,
419
423
  layer: p,
420
424
  currentTime: h,
421
- duration: E,
425
+ duration: g,
422
426
  isPlaying: x,
423
427
  play: K,
424
- pause: P,
428
+ pause: A,
425
429
  tick: J,
426
- seek: de,
427
- destroy: ke
430
+ seek: le,
431
+ destroy: Me
428
432
  };
429
433
  }
430
- function qe(n) {
434
+ function He(n) {
431
435
  let o = !1, a = !1;
432
436
  return async () => {
433
437
  if (a) {
@@ -442,6 +446,6 @@ function qe(n) {
442
446
  };
443
447
  }
444
448
  export {
445
- je as createRenderer
449
+ Be as createRenderer
446
450
  };
447
451
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/2d/index.ts","../src/helpers.ts","../src/index.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport type { ApplicationOptions } from 'pixi.js'\nimport { Application } from 'pixi.js'\n\ndeclare global {\n\n // eslint-disable-next-line vars-on-top\n var __PIXI_APP__: Application\n}\n\nexport async function createApp(opts?: Partial<ApplicationOptions>) {\n const app = new Application()\n\n await app.init({ resizeTo: window, ...opts })\n\n if (import.meta.env.DEV) {\n globalThis.__PIXI_APP__ = app\n }\n\n return app\n}\n","import type { ITransform, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { PixiDisplayObject } from './types'\nimport { toRaw } from '@vue/reactivity'\nimport { Graphics, Sprite, Texture } from 'pixi.js'\n\nexport function collectResourceUrls(protocol: IVideoProtocol) {\n const urls = new Set<string>()\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (segment.url)\n urls.add(segment.url)\n }\n }\n return urls\n}\n\nexport function collectActiveSegments(protocol: IVideoProtocol, at: number) {\n const active: { segment: SegmentUnion, trackIndex: number, childIndex: number }[] = []\n protocol.tracks.forEach((track, trackIndex) => {\n track.children.forEach((segment, childIndex) => {\n if (segment.startTime <= at && at < segment.endTime)\n active.push({ segment, trackIndex, childIndex })\n })\n })\n\n return active.sort((a, b) => {\n if (a.trackIndex === b.trackIndex)\n return a.childIndex - b.childIndex\n return a.trackIndex - b.trackIndex\n })\n}\n\nexport function applyDisplayProps(display: PixiDisplayObject, segment: SegmentUnion, width: number, height: number) {\n const opacity = readOpacity(segment)\n // size\n if (display instanceof Sprite) {\n display.anchor.set(0.5)\n display.width = width\n display.height = height\n display.x = width / 2\n display.y = height / 2\n const src = display.texture.source as { addEventListener?: (type: string, cb: () => void, opts?: AddEventListenerOptions) => void } | undefined\n src?.addEventListener?.('error', () => {\n // fallback to a colored rect if texture failed\n display.texture = Texture.from(placeholderTexture(width, height))\n }, { once: true })\n }\n else if (display instanceof Graphics) {\n display.clear()\n display\n .rect(0, 0, width, height)\n .fill({ color: stringToColor('url' in segment && typeof segment.url === 'string' ? segment.url : segment.segmentType), alpha: hasOpacity(segment) ? opacity : 0.35 })\n display.pivot.set(width / 2, height / 2)\n display.position.set(width / 2, height / 2)\n }\n\n display.alpha = opacity\n\n // simple 2D transform\n const transform = readTransform(segment)\n if (transform) {\n const [px, py] = transform.position ?? [0, 0]\n const [sx, sy] = transform.scale ?? [1, 1]\n const rotation = transform.rotation?.[2] ?? 0\n\n display.position.set(width / 2 + (px * width) / 2, height / 2 - (py * height) / 2)\n display.scale.set(sx, sy)\n display.rotation = (rotation / 180) * Math.PI\n }\n}\n\nexport function placeholder(key: string, url?: string) {\n const g = new Graphics()\n g.rect(0, 0, 10, 10).fill({ color: stringToColor(url ?? key), alpha: 1 })\n return g\n}\n\nexport function placeholderTexture(width: number, height: number, color?: string) {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"><rect width=\"100%\" height=\"100%\" fill=\"${color ?? '#0f172a'}\" fill-opacity=\"0.8\"/></svg>`\n return `data:image/svg+xml;base64,${btoa(svg)}`\n}\n\nexport function stringToColor(key: string) {\n let hash = 0\n for (let i = 0; i < key.length; i++)\n hash = key.charCodeAt(i) + ((hash << 5) - hash)\n return hash & 0x00FFFFFF\n}\n\nexport function computeDuration(protocol: IVideoProtocol) {\n const endTimes = protocol.tracks.flatMap(track => track.children.map(seg => seg.endTime))\n return endTimes.length ? Math.max(...endTimes) : 0\n}\n\nexport function clamp(num: number, min: number, max: number) {\n return Math.min(Math.max(num, min), max)\n}\n\nexport function cloneProtocol(protocol: IVideoProtocol) {\n const raw = toRaw(protocol) as IVideoProtocol\n // use JSON clone to avoid structuredClone errors on proxies (e.g., Vue reactive)\n return JSON.parse(JSON.stringify(raw)) as IVideoProtocol\n}\n\nfunction hasOpacity(segment: SegmentUnion): segment is SegmentUnion & { opacity?: number } {\n return 'opacity' in segment\n}\n\nfunction readOpacity(segment: SegmentUnion) {\n if (hasOpacity(segment) && typeof segment.opacity === 'number')\n return segment.opacity\n return 1\n}\n\nfunction hasTransform(segment: SegmentUnion): segment is SegmentUnion & { transform?: ITransform } {\n return 'transform' in segment\n}\n\nfunction readTransform(segment: SegmentUnion) {\n if (hasTransform(segment))\n return segment.transform\n return undefined\n}\n","import type { IVideoFramesSegment, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { ComputedRef, Ref, ShallowRef } from '@vue/reactivity'\nimport type { Application, ApplicationOptions } from 'pixi.js'\nimport type { MaybeRef, PixiDisplayObject } from './types'\nimport { createResourceManager, createValidator, getResourceKey } from '@video-editor/protocol'\nimport {\n computed,\n effectScope,\n isRef,\n ref,\n shallowRef,\n unref,\n watch,\n} from '@vue/reactivity'\nimport { MP4Clip } from '@webav/av-cliper'\nimport { file as opfsFile } from 'opfs-tools'\nimport { Container, Sprite, Texture } from 'pixi.js'\nimport { createApp as create2dApp } from './2d'\nimport {\n applyDisplayProps,\n clamp,\n cloneProtocol,\n collectActiveSegments,\n collectResourceUrls,\n computeDuration,\n placeholder,\n} from './helpers'\n\nconst DEFAULT_RES_DIR = '/video-editor-res'\n\nexport interface RendererOptions {\n protocol: MaybeRef<IVideoProtocol>\n app?: Application\n appOptions?: Partial<ApplicationOptions>\n resourceDir?: string\n autoPlay?: boolean\n}\n\nexport interface Renderer {\n app: Application\n layer: Container\n currentTime: Ref<number>\n duration: ComputedRef<number>\n isPlaying: Ref<boolean>\n play: () => void\n pause: () => void\n tick: (deltaMs?: number) => void\n seek: (time: number) => void\n destroy: () => void\n}\n\n/**\n * Create a renderer that reacts to protocol updates and drives playback state.\n * - Pass a reactive `protocol` (Ref/readonly/normal object)\n * - Call `play/pause/seek/tick` to drive the timeline\n * - Rendering updates when `protocol` or `currentTime` changes\n */\nexport async function createRenderer(opts: RendererOptions): Promise<Renderer> {\n const validator = createValidator()\n const protocolInput: Ref<IVideoProtocol> | ShallowRef<IVideoProtocol>\n = isRef(opts.protocol) ? opts.protocol : shallowRef(opts.protocol)\n const validatedProtocol: ShallowRef<IVideoProtocol> = shallowRef(\n validator.verify(cloneProtocol(unref(protocolInput))),\n )\n\n const app = opts.app ?? await create2dApp(opts.appOptions)\n const layer = new Container()\n app.stage.addChild(layer)\n\n const resourceManager = createResourceManager({ dir: opts.resourceDir })\n const resourceWarmUp = new Set<string>()\n const displayCache = new Map<string, PixiDisplayObject>()\n const displayLoading = new Map<string, Promise<PixiDisplayObject | undefined>>()\n const mp4ClipUnsupportedKeys = new Set<string>()\n const mp4ClipErrorLoggedKeys = new Set<string>()\n type VideoEntry = (\n | {\n kind: 'mp4clip'\n clip: MP4Clip\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'element'\n video: HTMLVideoElement\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'frozen'\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n )\n const videoEntries = new Map<string, VideoEntry>()\n\n const currentTime = ref(0)\n const isPlaying = ref(false)\n const duration = computed(() => computeDuration(validatedProtocol.value))\n\n let rafId: number | undefined\n let lastTickAt = 0\n\n interface RenderTask {\n app: Application\n layer: Container\n protocol: IVideoProtocol\n at: number\n getDisplay: (segment: SegmentUnion) => Promise<PixiDisplayObject | undefined>\n }\n\n async function renderScene(task: RenderTask) {\n const { protocol, at, layer } = task\n const renderAt = normalizeRenderTime(protocol, at)\n const active = collectActiveSegments(protocol, renderAt)\n const stageWidth = task.app.renderer.width\n const stageHeight = task.app.renderer.height\n\n const renders: (PixiDisplayObject | undefined)[] = []\n for (const { segment } of active) {\n const display = await task.getDisplay(segment)\n if (!display)\n continue\n applyDisplayProps(display, segment, stageWidth, stageHeight)\n if (isVideoSegment(segment))\n await updateVideoFrame(segment, renderAt)\n renders.push(display)\n }\n\n layer.removeChildren()\n const cleaned = renders.filter(Boolean) as PixiDisplayObject[]\n if (cleaned.length)\n layer.addChild(...cleaned)\n task.app.render()\n }\n\n const queueRender = createRenderQueue(() => renderScene({\n app,\n layer,\n protocol: validatedProtocol.value,\n at: currentTime.value,\n getDisplay: getDisplayForSegment,\n }))\n\n const scope = effectScope()\n scope.run(() => {\n // Sync external protocol mutations into a verified snapshot the renderer can rely on.\n watch(\n () => unref(protocolInput),\n (protocol) => {\n try {\n validatedProtocol.value = validator.verify(cloneProtocol(protocol))\n }\n catch (err) {\n console.error('[renderer] invalid protocol update', err)\n return\n }\n clearDisplays()\n warmUpResources(validatedProtocol.value)\n cleanupCache(validatedProtocol.value)\n clampCurrentTime()\n queueRender()\n },\n { deep: true, immediate: true },\n )\n\n // React to time changes.\n watch(currentTime, () => {\n clampCurrentTime()\n queueRender()\n })\n\n // Keep duration/currentTime in sync with protocol updates.\n watch(duration, () => clampCurrentTime())\n })\n\n function clampCurrentTime() {\n const nextDuration = duration.value\n if (nextDuration <= 0)\n currentTime.value = 0\n else if (currentTime.value > nextDuration)\n currentTime.value = nextDuration\n else if (currentTime.value < 0)\n currentTime.value = 0\n }\n\n function warmUpResources(protocol: IVideoProtocol) {\n for (const url of collectResourceUrls(protocol)) {\n if (resourceWarmUp.has(url))\n continue\n\n resourceWarmUp.add(url)\n if (inferUrlMediaType(url) === 'video')\n continue\n if (!shouldUseResourceManager(url))\n continue\n resourceManager.add(url).catch(() => {\n // noop – render will fall back to Texture.from(url)\n })\n }\n }\n\n function cleanupCache(protocol: IVideoProtocol) {\n const ids = new Set(protocol.tracks.flatMap(track => track.children.map(seg => seg.id)))\n for (const [id, display] of displayCache) {\n if (ids.has(id))\n continue\n display.destroy()\n displayCache.delete(id)\n }\n for (const [id, entry] of videoEntries) {\n if (ids.has(id))\n continue\n destroyVideoEntry(entry)\n videoEntries.delete(id)\n }\n }\n\n function clearDisplays() {\n layer.removeChildren()\n for (const display of displayCache.values()) {\n display.destroy()\n }\n displayCache.clear()\n displayLoading.clear()\n for (const entry of videoEntries.values())\n destroyVideoEntry(entry)\n videoEntries.clear()\n }\n\n function play() {\n if (isPlaying.value)\n return\n isPlaying.value = true\n lastTickAt = performance.now()\n rafId = requestAnimationFrame(loop)\n }\n\n function pause() {\n isPlaying.value = false\n if (rafId !== undefined)\n cancelAnimationFrame(rafId)\n rafId = undefined\n freezeVideoEntries()\n }\n\n function loop() {\n tick()\n if (isPlaying.value)\n rafId = requestAnimationFrame(loop)\n }\n\n function tick(deltaMs?: number) {\n if (!isPlaying.value && deltaMs === undefined)\n return\n\n const now = performance.now()\n const delta = deltaMs ?? (lastTickAt ? now - lastTickAt : 0)\n lastTickAt = now\n\n if (delta === 0)\n return\n\n currentTime.value = clamp(\n currentTime.value + delta,\n 0,\n duration.value || Number.POSITIVE_INFINITY,\n )\n\n if (duration.value > 0 && currentTime.value >= duration.value)\n pause()\n\n // render happens via watch on currentTime\n }\n\n function seek(time: number) {\n currentTime.value = clamp(time, 0, duration.value || Number.POSITIVE_INFINITY)\n }\n\n async function getDisplayForSegment(segment: SegmentUnion) {\n const cached = displayCache.get(segment.id)\n if (cached)\n return cached\n\n const loading = displayLoading.get(segment.id)\n if (loading)\n return loading\n\n const promise = loadDisplay(segment)\n displayLoading.set(segment.id, promise)\n\n const display = await promise\n if (display)\n displayCache.set(segment.id, display)\n\n displayLoading.delete(segment.id)\n return display\n }\n\n async function loadDisplay(segment: SegmentUnion): Promise<PixiDisplayObject | undefined> {\n // prioritize static resources via protocol resource manager\n if (segment.segmentType === 'frames' || segment.segmentType === 'sticker') {\n if (!segment.url)\n return placeholder(segment.segmentType)\n\n if ('type' in segment && segment.type === 'video') {\n const sprite = await loadVideoSprite(segment)\n if (sprite)\n return sprite\n return placeholder(segment.segmentType, segment.url)\n }\n\n const texture = await loadTexture(segment.url)\n if (texture)\n return new Sprite(texture)\n return placeholder(segment.segmentType, segment.url)\n }\n\n if (segment.segmentType === 'text')\n return undefined\n\n if (segment.segmentType === 'effect' || segment.segmentType === 'filter')\n return undefined\n\n // audio segments do not render visuals\n return undefined\n }\n\n async function loadTexture(url: string) {\n const isDataUrl = url.startsWith('data:')\n const isHttp = /^https?:\\/\\//.test(url)\n\n if (!isDataUrl && !isHttp) {\n try {\n await resourceManager.add(url)\n const res = await resourceManager.get(url)\n if (res instanceof HTMLImageElement)\n return Texture.from(res)\n }\n catch {\n // fall through to direct image load\n }\n }\n\n // load image directly to avoid invalid path issues with http/data URLs\n return await loadImageTexture(url)\n }\n\n async function loadVideoSprite(segment: SegmentUnion & { type: 'video', url: string }): Promise<Sprite | undefined> {\n const existing = videoEntries.get(segment.id)\n if (existing)\n return existing.sprite\n\n const urlKey = getResourceKey(segment.url)\n if (urlKey && mp4ClipUnsupportedKeys.has(urlKey)) {\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n return undefined\n }\n\n const spriteFromClip = await loadVideoSpriteViaMP4Clip(segment.url).catch((err) => {\n if (urlKey && isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n if (!urlKey || !mp4ClipErrorLoggedKeys.has(urlKey)) {\n if (urlKey)\n mp4ClipErrorLoggedKeys.add(urlKey)\n console.warn('[renderer] failed to load video via MP4Clip', segment.url, err)\n }\n return undefined\n })\n if (spriteFromClip) {\n videoEntries.set(segment.id, spriteFromClip)\n return spriteFromClip.sprite\n }\n\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n\n return undefined\n }\n\n function isMp4ClipUnsupported(err: unknown) {\n if (!(err instanceof Error))\n return false\n const msg = err.message || ''\n return msg.includes('stream is done') || msg.includes('not emit ready')\n }\n\n async function updateVideoFrame(segment: IVideoFramesSegment, at: number) {\n const entry = videoEntries.get(segment.id)\n if (!entry)\n return\n\n try {\n const offsetMs = segment.fromTime ?? 0\n const relativeMs = Math.max(0, at - segment.startTime + offsetMs)\n const relativeUs = Math.floor(relativeMs * 1000)\n if (entry.kind === 'frozen') {\n const urlKey = getResourceKey(segment.url)\n if (!urlKey)\n return\n const revived = await loadVideoEntry(segment.url, urlKey, { sprite: entry.sprite, oldTexture: entry.texture })\n if (!revived)\n return\n videoEntries.set(segment.id, revived)\n return await updateVideoFrame(segment, at)\n }\n if (entry.kind === 'mp4clip') {\n const res = await entry.clip.tick(relativeUs)\n if (res.video) {\n const ctx = entry.canvas.getContext('2d')\n if (ctx) {\n ctx.drawImage(res.video, 0, 0, entry.canvas.width, entry.canvas.height)\n refreshCanvasTexture(entry.texture)\n }\n res.video.close()\n }\n return\n }\n\n const relativeSec = relativeMs / 1000\n if (!Number.isFinite(relativeSec))\n return\n if (entry.kind !== 'element')\n return\n await updateVideoElementFrame(entry, {\n targetSec: relativeSec,\n playbackRate: segment.playRate ?? 1,\n })\n }\n catch (err) {\n console.warn('[renderer] update video frame failed', err)\n }\n }\n\n async function loadVideoEntry(url: string, urlKey: string, reuse: { sprite: Sprite, oldTexture?: Texture }) {\n if (mp4ClipUnsupportedKeys.has(urlKey))\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n\n const fromClip = await loadVideoSpriteViaMP4Clip(url, reuse).catch((err) => {\n if (isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n return undefined\n })\n if (fromClip)\n return fromClip\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n }\n\n function isVideoSegment(segment: SegmentUnion): segment is IVideoFramesSegment {\n return segment.segmentType === 'frames'\n && segment.type === 'video'\n && typeof segment.url === 'string'\n }\n\n function normalizeRenderTime(protocol: IVideoProtocol, at: number) {\n const total = computeDuration(protocol)\n if (total <= 0)\n return 0\n if (at < total)\n return at\n // Keep the last visible frame when playback reaches the end.\n const frameWindow = Math.max(1000 / Math.max(protocol.fps || 30, 1), 1)\n return Math.max(total - frameWindow, 0)\n }\n\n async function getOpfsFile(url: string) {\n const dir = opts.resourceDir ?? DEFAULT_RES_DIR\n try {\n const key = getResourceKey(url)\n if (!key)\n return undefined\n const file = opfsFile(`${dir}/${key}`, 'r')\n if (await file.exists())\n return file\n }\n catch {\n return undefined\n }\n return undefined\n }\n\n function shouldUseResourceManager(url: string) {\n if (!url)\n return false\n if (url.startsWith('data:') || url.startsWith('blob:'))\n return false\n return true\n }\n\n function freezeVideoEntries() {\n for (const [id, entry] of videoEntries) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n videoEntries.set(id, {\n kind: 'frozen',\n canvas: entry.canvas,\n texture: entry.texture,\n sprite: entry.sprite,\n meta: entry.meta,\n })\n continue\n }\n\n if (entry.kind === 'element')\n entry.video.pause()\n }\n }\n\n function destroyVideoEntry(entry: VideoEntry) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n return\n }\n\n if (entry.kind === 'frozen')\n return\n\n entry.video.pause()\n entry.video.removeAttribute('src')\n entry.video.load()\n }\n\n function waitForMediaEvent(target: HTMLMediaElement, type: string, timeoutMs = 1000) {\n return new Promise<void>((resolve, reject) => {\n const timer = window.setTimeout(() => {\n cleanup()\n reject(new Error(`Timed out waiting for media event: ${type}`))\n }, timeoutMs)\n\n const onOk = () => {\n cleanup()\n resolve()\n }\n const onErr = () => {\n cleanup()\n const mediaError = target.error ? `${target.error.code}` : 'unknown'\n reject(new Error(`Media error (${mediaError}) while waiting for ${type}`))\n }\n const cleanup = () => {\n window.clearTimeout(timer)\n target.removeEventListener(type, onOk)\n target.removeEventListener('error', onErr)\n }\n\n target.addEventListener(type, onOk, { once: true })\n target.addEventListener('error', onErr, { once: true })\n })\n }\n\n async function loadVideoSpriteViaMP4Clip(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n let file: ReturnType<typeof opfsFile> | undefined\n if (shouldUseResourceManager(url))\n file = await getOpfsFile(url)\n\n let clip: MP4Clip | undefined\n try {\n if (file) {\n clip = new MP4Clip(file)\n }\n else {\n const res = await fetch(url)\n if (!res.body)\n return undefined\n if (shouldUseResourceManager(url)) {\n const [clipStream, cacheStream] = res.body.tee()\n resourceManager.add(url, { body: cacheStream }).catch(() => {})\n clip = new MP4Clip(clipStream)\n }\n else {\n clip = new MP4Clip(res.body)\n }\n }\n\n await clip.ready\n\n const { width, height } = clip.meta\n const canvas = document.createElement('canvas')\n canvas.width = width || 1\n canvas.height = height || 1\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'mp4clip', clip, canvas, texture, sprite, meta: { width, height } }\n }\n catch (err) {\n clip?.destroy()\n throw err\n }\n }\n\n function inferUrlMediaType(url: string): 'video' | 'image' | 'audio' | 'unknown' {\n const raw = url.split('#')[0]!.split('?')[0]!\n const ext = raw.split('/').pop()?.split('.').pop()?.toLowerCase() ?? ''\n if (['mp4', 'm4v', 'mov', 'webm'].includes(ext))\n return 'video'\n if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif'].includes(ext))\n return 'image'\n if (['mp3', 'wav', 'aac', 'm4a', 'ogg', 'flac'].includes(ext))\n return 'audio'\n return 'unknown'\n }\n\n async function loadVideoSpriteViaElement(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n const video = document.createElement('video')\n video.crossOrigin = 'anonymous'\n video.muted = true\n video.playsInline = true\n video.preload = 'auto'\n video.src = url\n\n try {\n await waitForMediaEvent(video, 'loadedmetadata', 4000)\n }\n catch (err) {\n video.pause()\n video.removeAttribute('src')\n video.load()\n throw err\n }\n\n const width = video.videoWidth || 1\n const height = video.videoHeight || 1\n\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'element', video, canvas, texture, sprite, meta: { width, height } }\n }\n\n async function updateVideoElementFrame(entry: Extract<VideoEntry, { kind: 'element' }>, opts: { targetSec: number, playbackRate: number }) {\n const { video, canvas, texture } = entry\n\n video.playbackRate = Number.isFinite(opts.playbackRate) && opts.playbackRate > 0 ? opts.playbackRate : 1\n if (isPlaying.value)\n video.play().catch(() => {})\n else\n video.pause()\n\n const current = video.currentTime\n const drift = Math.abs(current - opts.targetSec)\n const driftThreshold = isPlaying.value ? 0.25 : 0.03\n if (Number.isFinite(current) && drift > driftThreshold) {\n try {\n video.currentTime = opts.targetSec\n }\n catch {\n // ignore seek errors for not-yet-ready media\n }\n if (!isPlaying.value)\n await waitForMediaEvent(video, 'seeked', 250).catch(() => {})\n }\n\n if (video.readyState < 2) {\n // Avoid blocking the render queue for too long.\n await waitForMediaEvent(video, 'canplay', 250).catch(() => {})\n if (video.readyState < 2)\n return\n }\n\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height)\n refreshCanvasTexture(texture)\n }\n\n function loadImageTexture(url: string): Promise<Texture | undefined> {\n return new Promise((resolve) => {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => resolve(Texture.from(img))\n img.onerror = () => {\n console.warn('[renderer] failed to load image', url)\n resolve(undefined)\n }\n img.src = url\n })\n }\n\n function refreshCanvasTexture(texture: Texture) {\n const source = texture.source\n if ('update' in source && typeof source.update === 'function') {\n source.update()\n return\n }\n\n if (typeof texture.update === 'function')\n texture.update()\n }\n\n function destroy() {\n pause()\n scope.stop()\n clearDisplays()\n layer.destroy({ children: true })\n displayCache.clear()\n displayLoading.clear()\n resourceWarmUp.clear()\n if (!opts.app)\n app.destroy()\n }\n\n if (opts.autoPlay)\n play()\n\n return {\n app,\n layer,\n currentTime,\n duration,\n isPlaying,\n play,\n pause,\n tick,\n seek,\n destroy,\n }\n}\n\nfunction createRenderQueue(job: () => Promise<void> | void) {\n let queued = false\n let running = false\n\n const run = async () => {\n if (running) {\n queued = true\n return\n }\n running = true\n do {\n queued = false\n await job()\n } while (queued)\n running = false\n }\n\n return run\n}\n"],"names":["createApp","opts","app","Application","collectResourceUrls","protocol","urls","track","segment","collectActiveSegments","at","active","trackIndex","childIndex","a","b","applyDisplayProps","display","width","height","opacity","readOpacity","Sprite","Texture","placeholderTexture","Graphics","stringToColor","hasOpacity","transform","readTransform","px","py","sx","sy","rotation","placeholder","key","url","g","color","svg","hash","i","computeDuration","endTimes","seg","clamp","num","min","max","cloneProtocol","raw","toRaw","hasTransform","DEFAULT_RES_DIR","createRenderer","validator","createValidator","protocolInput","isRef","shallowRef","validatedProtocol","unref","create2dApp","layer","Container","resourceManager","createResourceManager","resourceWarmUp","displayCache","displayLoading","mp4ClipUnsupportedKeys","mp4ClipErrorLoggedKeys","videoEntries","currentTime","ref","isPlaying","duration","computed","rafId","lastTickAt","renderScene","task","renderAt","normalizeRenderTime","stageWidth","stageHeight","renders","isVideoSegment","updateVideoFrame","cleaned","queueRender","createRenderQueue","getDisplayForSegment","scope","effectScope","watch","err","clearDisplays","warmUpResources","cleanupCache","clampCurrentTime","nextDuration","inferUrlMediaType","shouldUseResourceManager","ids","id","entry","destroyVideoEntry","play","loop","pause","freezeVideoEntries","tick","deltaMs","now","delta","seek","time","cached","loading","promise","loadDisplay","sprite","loadVideoSprite","texture","loadTexture","isDataUrl","isHttp","res","loadImageTexture","existing","urlKey","getResourceKey","spriteFromElement","loadVideoSpriteViaElement","spriteFromClip","loadVideoSpriteViaMP4Clip","isMp4ClipUnsupported","msg","offsetMs","relativeMs","relativeUs","revived","loadVideoEntry","ctx","refreshCanvasTexture","relativeSec","updateVideoElementFrame","reuse","fromClip","total","frameWindow","getOpfsFile","dir","file","opfsFile","waitForMediaEvent","target","type","timeoutMs","resolve","reject","timer","cleanup","onOk","onErr","mediaError","clip","MP4Clip","clipStream","cacheStream","canvas","ext","video","current","drift","driftThreshold","img","source","destroy","job","queued","running"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/2d/index.ts","../src/helpers.ts","../src/index.ts"],"sourcesContent":["/// <reference types=\"vite/client\" />\nimport type { ApplicationOptions } from 'pixi.js'\nimport { Application } from 'pixi.js'\n\ndeclare global {\n\n // eslint-disable-next-line vars-on-top\n var __PIXI_APP__: Application\n}\n\nexport async function createApp(opts?: Partial<ApplicationOptions>) {\n const app = new Application()\n\n await app.init({ resizeTo: window, backgroundAlpha: 0, ...opts })\n\n if (import.meta.env.DEV) {\n globalThis.__PIXI_APP__ = app\n }\n\n return app\n}\n","import type { ITransform, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { PixiDisplayObject } from './types'\nimport { toRaw } from '@vue/reactivity'\nimport { Graphics, Sprite, Texture } from 'pixi.js'\n\nexport function collectResourceUrls(protocol: IVideoProtocol) {\n const urls = new Set<string>()\n for (const track of protocol.tracks) {\n for (const segment of track.children) {\n if (segment.url)\n urls.add(segment.url)\n }\n }\n return urls\n}\n\nexport function collectActiveSegments(protocol: IVideoProtocol, at: number) {\n const active: { segment: SegmentUnion, trackIndex: number, childIndex: number }[] = []\n protocol.tracks.forEach((track, trackIndex) => {\n track.children.forEach((segment, childIndex) => {\n if (segment.startTime <= at && at < segment.endTime)\n active.push({ segment, trackIndex, childIndex })\n })\n })\n\n return active.sort((a, b) => {\n if (a.trackIndex === b.trackIndex)\n return a.childIndex - b.childIndex\n return a.trackIndex - b.trackIndex\n })\n}\n\nexport function applyDisplayProps(display: PixiDisplayObject, segment: SegmentUnion, width: number, height: number) {\n const opacity = readOpacity(segment)\n // size\n if (display instanceof Sprite) {\n display.anchor.set(0.5)\n display.width = width\n display.height = height\n display.x = width / 2\n display.y = height / 2\n const src = display.texture.source as { addEventListener?: (type: string, cb: () => void, opts?: AddEventListenerOptions) => void } | undefined\n src?.addEventListener?.('error', () => {\n // fallback to a colored rect if texture failed\n display.texture = Texture.from(placeholderTexture(width, height))\n }, { once: true })\n }\n else if (display instanceof Graphics) {\n display.clear()\n display\n .rect(0, 0, width, height)\n .fill({ color: stringToColor('url' in segment && typeof segment.url === 'string' ? segment.url : segment.segmentType), alpha: hasOpacity(segment) ? opacity : 0.35 })\n display.pivot.set(width / 2, height / 2)\n display.position.set(width / 2, height / 2)\n }\n\n display.alpha = opacity\n\n // simple 2D transform\n const transform = readTransform(segment)\n if (transform) {\n const [px, py] = transform.position ?? [0, 0]\n const [sx, sy] = transform.scale ?? [1, 1]\n const rotation = transform.rotation?.[2] ?? 0\n\n display.position.set(width / 2 + (px * width) / 2, height / 2 - (py * height) / 2)\n display.scale.set(sx, sy)\n display.rotation = (rotation / 180) * Math.PI\n }\n}\n\nexport function placeholder(key: string, url?: string) {\n const g = new Graphics()\n g.rect(0, 0, 10, 10).fill({ color: stringToColor(url ?? key), alpha: 1 })\n return g\n}\n\nexport function placeholderTexture(width: number, height: number, color?: string) {\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${width}\" height=\"${height}\"><rect width=\"100%\" height=\"100%\" fill=\"${color ?? '#0f172a'}\" fill-opacity=\"0.8\"/></svg>`\n return `data:image/svg+xml;base64,${btoa(svg)}`\n}\n\nexport function stringToColor(key: string) {\n let hash = 0\n for (let i = 0; i < key.length; i++)\n hash = key.charCodeAt(i) + ((hash << 5) - hash)\n return hash & 0x00FFFFFF\n}\n\nexport function computeDuration(protocol: IVideoProtocol) {\n const endTimes = protocol.tracks.flatMap(track => track.children.map(seg => seg.endTime))\n return endTimes.length ? Math.max(...endTimes) : 0\n}\n\nexport function clamp(num: number, min: number, max: number) {\n return Math.min(Math.max(num, min), max)\n}\n\nexport function cloneProtocol(protocol: IVideoProtocol) {\n const raw = toRaw(protocol) as IVideoProtocol\n // use JSON clone to avoid structuredClone errors on proxies (e.g., Vue reactive)\n return JSON.parse(JSON.stringify(raw)) as IVideoProtocol\n}\n\nfunction hasOpacity(segment: SegmentUnion): segment is SegmentUnion & { opacity?: number } {\n return 'opacity' in segment\n}\n\nfunction readOpacity(segment: SegmentUnion) {\n if (hasOpacity(segment) && typeof segment.opacity === 'number')\n return segment.opacity\n return 1\n}\n\nfunction hasTransform(segment: SegmentUnion): segment is SegmentUnion & { transform?: ITransform } {\n return 'transform' in segment\n}\n\nfunction readTransform(segment: SegmentUnion) {\n if (hasTransform(segment))\n return segment.transform\n return undefined\n}\n","import type { IVideoFramesSegment, IVideoProtocol, SegmentUnion } from '@video-editor/shared'\nimport type { ComputedRef, Ref, ShallowRef } from '@vue/reactivity'\nimport type { Application, ApplicationOptions } from 'pixi.js'\nimport type { MaybeRef, PixiDisplayObject } from './types'\nimport { createResourceManager, createValidator, getResourceKey } from '@video-editor/protocol'\nimport {\n computed,\n effectScope,\n isRef,\n ref,\n shallowRef,\n unref,\n watch,\n} from '@vue/reactivity'\nimport { MP4Clip } from '@webav/av-cliper'\nimport { file as opfsFile } from 'opfs-tools'\nimport { Container, Sprite, Texture } from 'pixi.js'\nimport { createApp as create2dApp } from './2d'\nimport {\n applyDisplayProps,\n clamp,\n cloneProtocol,\n collectActiveSegments,\n collectResourceUrls,\n computeDuration,\n placeholder,\n} from './helpers'\n\nconst DEFAULT_RES_DIR = '/video-editor-res'\n\nexport interface RendererOptions {\n protocol: MaybeRef<IVideoProtocol>\n app?: Application\n appOptions?: Partial<ApplicationOptions>\n resourceDir?: string\n autoPlay?: boolean\n freezeOnPause?: boolean\n}\n\nexport interface Renderer {\n app: Application\n layer: Container\n currentTime: Ref<number>\n duration: ComputedRef<number>\n isPlaying: Ref<boolean>\n play: () => void\n pause: () => void\n tick: (deltaMs?: number) => void\n seek: (time: number) => void\n destroy: () => void\n}\n\n/**\n * Create a renderer that reacts to protocol updates and drives playback state.\n * - Pass a reactive `protocol` (Ref/readonly/normal object)\n * - Call `play/pause/seek/tick` to drive the timeline\n * - Rendering updates when `protocol` or `currentTime` changes\n */\nexport async function createRenderer(opts: RendererOptions): Promise<Renderer> {\n const validator = createValidator()\n const protocolInput: Ref<IVideoProtocol> | ShallowRef<IVideoProtocol>\n = isRef(opts.protocol) ? opts.protocol : shallowRef(opts.protocol)\n const validatedProtocol: ShallowRef<IVideoProtocol> = shallowRef(\n validator.verify(cloneProtocol(unref(protocolInput))),\n )\n\n const app = opts.app ?? await create2dApp(opts.appOptions)\n const layer = new Container()\n app.stage.addChild(layer)\n\n const resourceManager = createResourceManager({ dir: opts.resourceDir })\n const resourceWarmUp = new Set<string>()\n const displayCache = new Map<string, PixiDisplayObject>()\n const displayLoading = new Map<string, Promise<PixiDisplayObject | undefined>>()\n const mp4ClipUnsupportedKeys = new Set<string>()\n const mp4ClipErrorLoggedKeys = new Set<string>()\n type VideoEntry = (\n | {\n kind: 'mp4clip'\n clip: MP4Clip\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'element'\n video: HTMLVideoElement\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n | {\n kind: 'frozen'\n canvas: HTMLCanvasElement\n texture: Texture\n sprite: Sprite\n meta?: { width: number, height: number }\n }\n )\n const videoEntries = new Map<string, VideoEntry>()\n\n const currentTime = ref(0)\n const isPlaying = ref(false)\n const duration = computed(() => computeDuration(validatedProtocol.value))\n\n let rafId: number | undefined\n let lastTickAt = 0\n\n interface RenderTask {\n app: Application\n layer: Container\n protocol: IVideoProtocol\n at: number\n getDisplay: (segment: SegmentUnion) => Promise<PixiDisplayObject | undefined>\n }\n\n async function renderScene(task: RenderTask) {\n const { protocol, at, layer } = task\n const renderAt = normalizeRenderTime(protocol, at)\n const active = collectActiveSegments(protocol, renderAt)\n const stageWidth = task.app.renderer.width\n const stageHeight = task.app.renderer.height\n\n const renders: (PixiDisplayObject | undefined)[] = []\n for (const { segment } of active) {\n const display = await task.getDisplay(segment)\n if (!display)\n continue\n applyDisplayProps(display, segment, stageWidth, stageHeight)\n if (isVideoSegment(segment))\n await updateVideoFrame(segment, renderAt)\n renders.push(display)\n }\n\n layer.removeChildren()\n const cleaned = renders.filter(Boolean) as PixiDisplayObject[]\n if (cleaned.length)\n layer.addChild(...cleaned)\n task.app.render()\n }\n\n const queueRender = createRenderQueue(() => renderScene({\n app,\n layer,\n protocol: validatedProtocol.value,\n at: currentTime.value,\n getDisplay: getDisplayForSegment,\n }))\n\n const scope = effectScope()\n scope.run(() => {\n // Sync external protocol mutations into a verified snapshot the renderer can rely on.\n watch(\n () => unref(protocolInput),\n (protocol) => {\n try {\n validatedProtocol.value = validator.verify(cloneProtocol(protocol))\n }\n catch (err) {\n console.error('[renderer] invalid protocol update', err)\n return\n }\n clearDisplays()\n warmUpResources(validatedProtocol.value)\n cleanupCache(validatedProtocol.value)\n clampCurrentTime()\n queueRender()\n },\n { deep: true, immediate: true },\n )\n\n // React to time changes.\n watch(currentTime, () => {\n clampCurrentTime()\n queueRender()\n })\n\n // Keep duration/currentTime in sync with protocol updates.\n watch(duration, () => clampCurrentTime())\n })\n\n function clampCurrentTime() {\n const nextDuration = duration.value\n if (nextDuration <= 0)\n currentTime.value = 0\n else if (currentTime.value > nextDuration)\n currentTime.value = nextDuration\n else if (currentTime.value < 0)\n currentTime.value = 0\n }\n\n function warmUpResources(protocol: IVideoProtocol) {\n for (const url of collectResourceUrls(protocol)) {\n if (resourceWarmUp.has(url))\n continue\n\n resourceWarmUp.add(url)\n if (inferUrlMediaType(url) === 'video')\n continue\n if (!shouldUseResourceManager(url))\n continue\n resourceManager.add(url).catch(() => {\n // noop – render will fall back to Texture.from(url)\n })\n }\n }\n\n function cleanupCache(protocol: IVideoProtocol) {\n const ids = new Set(protocol.tracks.flatMap(track => track.children.map(seg => seg.id)))\n for (const [id, display] of displayCache) {\n if (ids.has(id))\n continue\n display.destroy()\n displayCache.delete(id)\n }\n for (const [id, entry] of videoEntries) {\n if (ids.has(id))\n continue\n destroyVideoEntry(entry)\n videoEntries.delete(id)\n }\n }\n\n function clearDisplays() {\n layer.removeChildren()\n for (const display of displayCache.values()) {\n display.destroy()\n }\n displayCache.clear()\n displayLoading.clear()\n for (const entry of videoEntries.values())\n destroyVideoEntry(entry)\n videoEntries.clear()\n }\n\n function play() {\n if (isPlaying.value)\n return\n isPlaying.value = true\n lastTickAt = performance.now()\n rafId = requestAnimationFrame(loop)\n }\n\n function pause() {\n isPlaying.value = false\n if (rafId !== undefined)\n cancelAnimationFrame(rafId)\n rafId = undefined\n if (opts.freezeOnPause !== false)\n freezeVideoEntries()\n }\n\n function loop() {\n tick()\n if (isPlaying.value)\n rafId = requestAnimationFrame(loop)\n }\n\n function tick(deltaMs?: number) {\n if (!isPlaying.value && deltaMs === undefined)\n return\n\n const now = performance.now()\n const delta = deltaMs ?? (lastTickAt ? now - lastTickAt : 0)\n lastTickAt = now\n\n if (delta === 0)\n return\n\n currentTime.value = clamp(\n currentTime.value + delta,\n 0,\n duration.value || Number.POSITIVE_INFINITY,\n )\n\n if (duration.value > 0 && currentTime.value >= duration.value)\n pause()\n\n // render happens via watch on currentTime\n }\n\n function seek(time: number) {\n currentTime.value = clamp(time, 0, duration.value || Number.POSITIVE_INFINITY)\n }\n\n async function getDisplayForSegment(segment: SegmentUnion) {\n const cached = displayCache.get(segment.id)\n if (cached)\n return cached\n\n const loading = displayLoading.get(segment.id)\n if (loading)\n return loading\n\n const promise = loadDisplay(segment)\n displayLoading.set(segment.id, promise)\n\n const display = await promise\n if (display)\n displayCache.set(segment.id, display)\n\n displayLoading.delete(segment.id)\n return display\n }\n\n async function loadDisplay(segment: SegmentUnion): Promise<PixiDisplayObject | undefined> {\n // prioritize static resources via protocol resource manager\n if (segment.segmentType === 'frames' || segment.segmentType === 'sticker') {\n if (!segment.url)\n return placeholder(segment.segmentType)\n\n if ('type' in segment && segment.type === 'video') {\n if (isRenderableVideoUrl(segment.url)) {\n const sprite = await loadVideoSprite(segment)\n if (sprite)\n return sprite\n return placeholder(segment.segmentType, segment.url)\n }\n }\n\n const texture = await loadTexture(segment.url)\n if (texture)\n return new Sprite(texture)\n return placeholder(segment.segmentType, segment.url)\n }\n\n if (segment.segmentType === 'text')\n return undefined\n\n if (segment.segmentType === 'effect' || segment.segmentType === 'filter')\n return undefined\n\n // audio segments do not render visuals\n return undefined\n }\n\n async function loadTexture(url: string) {\n const isDataUrl = url.startsWith('data:')\n const isHttp = /^https?:\\/\\//.test(url)\n\n if (!isDataUrl && !isHttp) {\n try {\n await resourceManager.add(url)\n const res = await resourceManager.get(url)\n if (res instanceof HTMLImageElement)\n return Texture.from(res)\n }\n catch {\n // fall through to direct image load\n }\n }\n\n // load image directly to avoid invalid path issues with http/data URLs\n return await loadImageTexture(url)\n }\n\n async function loadVideoSprite(segment: SegmentUnion & { type: 'video', url: string }): Promise<Sprite | undefined> {\n const existing = videoEntries.get(segment.id)\n if (existing)\n return existing.sprite\n\n const urlKey = getResourceKey(segment.url)\n if (urlKey && mp4ClipUnsupportedKeys.has(urlKey)) {\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n return undefined\n }\n\n const spriteFromClip = await loadVideoSpriteViaMP4Clip(segment.url).catch((err) => {\n if (urlKey && isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n if (!urlKey || !mp4ClipErrorLoggedKeys.has(urlKey)) {\n if (urlKey)\n mp4ClipErrorLoggedKeys.add(urlKey)\n console.warn('[renderer] failed to load video via MP4Clip', segment.url, err)\n }\n return undefined\n })\n if (spriteFromClip) {\n videoEntries.set(segment.id, spriteFromClip)\n return spriteFromClip.sprite\n }\n\n const spriteFromElement = await loadVideoSpriteViaElement(segment.url).catch((err) => {\n console.warn('[renderer] failed to load video via <video>', segment.url, err)\n return undefined\n })\n if (spriteFromElement) {\n videoEntries.set(segment.id, spriteFromElement)\n return spriteFromElement.sprite\n }\n\n return undefined\n }\n\n function isMp4ClipUnsupported(err: unknown) {\n if (!(err instanceof Error))\n return false\n const msg = err.message || ''\n return msg.includes('stream is done') || msg.includes('not emit ready')\n }\n\n async function updateVideoFrame(segment: IVideoFramesSegment, at: number) {\n const entry = videoEntries.get(segment.id)\n if (!entry)\n return\n\n try {\n const offsetMs = segment.fromTime ?? 0\n const relativeMs = Math.max(0, at - segment.startTime + offsetMs)\n const relativeUs = Math.floor(relativeMs * 1000)\n if (entry.kind === 'frozen') {\n const urlKey = getResourceKey(segment.url)\n if (!urlKey)\n return\n const revived = await loadVideoEntry(segment.url, urlKey, { sprite: entry.sprite, oldTexture: entry.texture })\n if (!revived)\n return\n videoEntries.set(segment.id, revived)\n return await updateVideoFrame(segment, at)\n }\n if (entry.kind === 'mp4clip') {\n const res = await entry.clip.tick(relativeUs)\n if (res.video) {\n const ctx = entry.canvas.getContext('2d')\n if (ctx) {\n ctx.drawImage(res.video, 0, 0, entry.canvas.width, entry.canvas.height)\n refreshCanvasTexture(entry.texture)\n }\n res.video.close()\n }\n return\n }\n\n const relativeSec = relativeMs / 1000\n if (!Number.isFinite(relativeSec))\n return\n if (entry.kind !== 'element')\n return\n await updateVideoElementFrame(entry, {\n targetSec: relativeSec,\n playbackRate: segment.playRate ?? 1,\n })\n }\n catch (err) {\n console.warn('[renderer] update video frame failed', err)\n }\n }\n\n async function loadVideoEntry(url: string, urlKey: string, reuse: { sprite: Sprite, oldTexture?: Texture }) {\n if (mp4ClipUnsupportedKeys.has(urlKey))\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n\n const fromClip = await loadVideoSpriteViaMP4Clip(url, reuse).catch((err) => {\n if (isMp4ClipUnsupported(err))\n mp4ClipUnsupportedKeys.add(urlKey)\n return undefined\n })\n if (fromClip)\n return fromClip\n return await loadVideoSpriteViaElement(url, reuse).catch(() => undefined)\n }\n\n function isVideoSegment(segment: SegmentUnion): segment is IVideoFramesSegment {\n return segment.segmentType === 'frames'\n && segment.type === 'video'\n && typeof segment.url === 'string'\n && isRenderableVideoUrl(segment.url)\n }\n\n function normalizeRenderTime(protocol: IVideoProtocol, at: number) {\n const total = computeDuration(protocol)\n if (total <= 0)\n return 0\n if (at < total)\n return at\n // Keep the last visible frame when playback reaches the end.\n const frameWindow = Math.max(1000 / Math.max(protocol.fps || 30, 1), 1)\n return Math.max(total - frameWindow, 0)\n }\n\n async function getOpfsFile(url: string) {\n const dir = opts.resourceDir ?? DEFAULT_RES_DIR\n try {\n const key = getResourceKey(url)\n if (!key)\n return undefined\n const file = opfsFile(`${dir}/${key}`, 'r')\n if (await file.exists())\n return file\n }\n catch {\n return undefined\n }\n return undefined\n }\n\n function shouldUseResourceManager(url: string) {\n if (!url)\n return false\n if (url.startsWith('data:') || url.startsWith('blob:'))\n return false\n return true\n }\n\n function freezeVideoEntries() {\n for (const [id, entry] of videoEntries) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n videoEntries.set(id, {\n kind: 'frozen',\n canvas: entry.canvas,\n texture: entry.texture,\n sprite: entry.sprite,\n meta: entry.meta,\n })\n continue\n }\n\n if (entry.kind === 'element')\n entry.video.pause()\n }\n }\n\n function destroyVideoEntry(entry: VideoEntry) {\n if (entry.kind === 'mp4clip') {\n entry.clip.destroy()\n return\n }\n\n if (entry.kind === 'frozen')\n return\n\n entry.video.pause()\n entry.video.removeAttribute('src')\n entry.video.load()\n }\n\n function waitForMediaEvent(target: HTMLMediaElement, type: string, timeoutMs = 1000) {\n return new Promise<void>((resolve, reject) => {\n const timer = window.setTimeout(() => {\n cleanup()\n reject(new Error(`Timed out waiting for media event: ${type}`))\n }, timeoutMs)\n\n const onOk = () => {\n cleanup()\n resolve()\n }\n const onErr = () => {\n cleanup()\n const mediaError = target.error ? `${target.error.code}` : 'unknown'\n reject(new Error(`Media error (${mediaError}) while waiting for ${type}`))\n }\n const cleanup = () => {\n window.clearTimeout(timer)\n target.removeEventListener(type, onOk)\n target.removeEventListener('error', onErr)\n }\n\n target.addEventListener(type, onOk, { once: true })\n target.addEventListener('error', onErr, { once: true })\n })\n }\n\n async function loadVideoSpriteViaMP4Clip(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n let file: ReturnType<typeof opfsFile> | undefined\n if (shouldUseResourceManager(url))\n file = await getOpfsFile(url)\n\n let clip: MP4Clip | undefined\n try {\n if (file) {\n clip = new MP4Clip(file)\n }\n else {\n const res = await fetch(url)\n if (!res.body)\n return undefined\n if (shouldUseResourceManager(url)) {\n const [clipStream, cacheStream] = res.body.tee()\n resourceManager.add(url, { body: cacheStream }).catch(() => {})\n clip = new MP4Clip(clipStream)\n }\n else {\n clip = new MP4Clip(res.body)\n }\n }\n\n await clip.ready\n\n const { width, height } = clip.meta\n const canvas = document.createElement('canvas')\n canvas.width = width || 1\n canvas.height = height || 1\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'mp4clip', clip, canvas, texture, sprite, meta: { width, height } }\n }\n catch (err) {\n clip?.destroy()\n throw err\n }\n }\n\n function inferUrlMediaType(url: string): 'video' | 'image' | 'audio' | 'unknown' {\n const raw = url.split('#')[0]!.split('?')[0]!\n const ext = raw.split('/').pop()?.split('.').pop()?.toLowerCase() ?? ''\n if (['mp4', 'm4v', 'mov', 'webm'].includes(ext))\n return 'video'\n if (['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif'].includes(ext))\n return 'image'\n if (['mp3', 'wav', 'aac', 'm4a', 'ogg', 'flac'].includes(ext))\n return 'audio'\n return 'unknown'\n }\n\n function isRenderableVideoUrl(url: string) {\n const kind = inferUrlMediaType(url)\n if (kind === 'image' || kind === 'audio')\n return false\n // Treat unknown as video to support blob URLs or extension-less endpoints.\n return true\n }\n\n async function loadVideoSpriteViaElement(url: string, reuse?: { sprite: Sprite, oldTexture?: Texture }): Promise<VideoEntry | undefined> {\n const video = document.createElement('video')\n video.crossOrigin = 'anonymous'\n video.muted = true\n video.playsInline = true\n video.preload = 'auto'\n video.src = url\n\n try {\n await waitForMediaEvent(video, 'loadedmetadata', 4000)\n }\n catch (err) {\n video.pause()\n video.removeAttribute('src')\n video.load()\n throw err\n }\n\n const width = video.videoWidth || 1\n const height = video.videoHeight || 1\n\n const canvas = document.createElement('canvas')\n canvas.width = width\n canvas.height = height\n const texture = Texture.from(canvas)\n const sprite = reuse?.sprite ?? new Sprite(texture)\n if (reuse?.sprite) {\n reuse.sprite.texture = texture\n reuse.oldTexture?.destroy(true)\n }\n\n return { kind: 'element', video, canvas, texture, sprite, meta: { width, height } }\n }\n\n async function updateVideoElementFrame(entry: Extract<VideoEntry, { kind: 'element' }>, opts: { targetSec: number, playbackRate: number }) {\n const { video, canvas, texture } = entry\n\n video.playbackRate = Number.isFinite(opts.playbackRate) && opts.playbackRate > 0 ? opts.playbackRate : 1\n if (isPlaying.value)\n video.play().catch(() => {})\n else\n video.pause()\n\n const current = video.currentTime\n const drift = Math.abs(current - opts.targetSec)\n const driftThreshold = isPlaying.value ? 0.25 : 0.03\n if (Number.isFinite(current) && drift > driftThreshold) {\n try {\n video.currentTime = opts.targetSec\n }\n catch {\n // ignore seek errors for not-yet-ready media\n }\n if (!isPlaying.value)\n await waitForMediaEvent(video, 'seeked', 250).catch(() => {})\n }\n\n if (video.readyState < 2) {\n // Avoid blocking the render queue for too long.\n await waitForMediaEvent(video, 'canplay', 250).catch(() => {})\n if (video.readyState < 2)\n return\n }\n\n const ctx = canvas.getContext('2d')\n if (!ctx)\n return\n ctx.drawImage(video, 0, 0, canvas.width, canvas.height)\n refreshCanvasTexture(texture)\n }\n\n function loadImageTexture(url: string): Promise<Texture | undefined> {\n return new Promise((resolve) => {\n const img = new Image()\n img.crossOrigin = 'anonymous'\n img.onload = () => resolve(Texture.from(img))\n img.onerror = () => {\n console.warn('[renderer] failed to load image', url)\n resolve(undefined)\n }\n img.src = url\n })\n }\n\n function refreshCanvasTexture(texture: Texture) {\n const source = texture.source\n if ('update' in source && typeof source.update === 'function') {\n source.update()\n return\n }\n\n if (typeof texture.update === 'function')\n texture.update()\n }\n\n function destroy() {\n pause()\n scope.stop()\n clearDisplays()\n layer.destroy({ children: true })\n displayCache.clear()\n displayLoading.clear()\n resourceWarmUp.clear()\n if (!opts.app)\n app.destroy()\n }\n\n if (opts.autoPlay)\n play()\n\n return {\n app,\n layer,\n currentTime,\n duration,\n isPlaying,\n play,\n pause,\n tick,\n seek,\n destroy,\n }\n}\n\nfunction createRenderQueue(job: () => Promise<void> | void) {\n let queued = false\n let running = false\n\n const run = async () => {\n if (running) {\n queued = true\n return\n }\n running = true\n do {\n queued = false\n await job()\n } while (queued)\n running = false\n }\n\n return run\n}\n"],"names":["createApp","opts","app","Application","collectResourceUrls","protocol","urls","track","segment","collectActiveSegments","at","active","trackIndex","childIndex","a","b","applyDisplayProps","display","width","height","opacity","readOpacity","Sprite","Texture","placeholderTexture","Graphics","stringToColor","hasOpacity","transform","readTransform","px","py","sx","sy","rotation","placeholder","key","url","g","color","svg","hash","i","computeDuration","endTimes","seg","clamp","num","min","max","cloneProtocol","raw","toRaw","hasTransform","DEFAULT_RES_DIR","createRenderer","validator","createValidator","protocolInput","isRef","shallowRef","validatedProtocol","unref","create2dApp","layer","Container","resourceManager","createResourceManager","resourceWarmUp","displayCache","displayLoading","mp4ClipUnsupportedKeys","mp4ClipErrorLoggedKeys","videoEntries","currentTime","ref","isPlaying","duration","computed","rafId","lastTickAt","renderScene","task","renderAt","normalizeRenderTime","stageWidth","stageHeight","renders","isVideoSegment","updateVideoFrame","cleaned","queueRender","createRenderQueue","getDisplayForSegment","scope","effectScope","watch","err","clearDisplays","warmUpResources","cleanupCache","clampCurrentTime","nextDuration","inferUrlMediaType","shouldUseResourceManager","ids","id","entry","destroyVideoEntry","play","loop","pause","freezeVideoEntries","tick","deltaMs","now","delta","seek","time","cached","loading","promise","loadDisplay","isRenderableVideoUrl","sprite","loadVideoSprite","texture","loadTexture","isDataUrl","isHttp","res","loadImageTexture","existing","urlKey","getResourceKey","spriteFromElement","loadVideoSpriteViaElement","spriteFromClip","loadVideoSpriteViaMP4Clip","isMp4ClipUnsupported","msg","offsetMs","relativeMs","relativeUs","revived","loadVideoEntry","ctx","refreshCanvasTexture","relativeSec","updateVideoElementFrame","reuse","fromClip","total","frameWindow","getOpfsFile","dir","file","opfsFile","waitForMediaEvent","target","type","timeoutMs","resolve","reject","timer","cleanup","onOk","onErr","mediaError","clip","MP4Clip","clipStream","cacheStream","canvas","ext","kind","video","current","drift","driftThreshold","img","source","destroy","job","queued","running"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@video-editor/renderer",
3
3
  "type": "module",
4
- "version": "0.0.1-beta.15",
4
+ "version": "0.0.1-beta.17",
5
5
  "exports": {
6
6
  ".": {
7
7
  "import": "./dist/index.js"
@@ -15,14 +15,17 @@
15
15
  "dist"
16
16
  ],
17
17
  "peerDependencies": {
18
- "@vue/reactivity": "^3.4.19"
18
+ "@vue/reactivity": "^3.5.26"
19
+ },
20
+ "devDependencies": {
21
+ "@vue/reactivity": "^3.5.26"
19
22
  },
20
23
  "dependencies": {
21
24
  "@webav/av-cliper": "^1.2.7",
22
25
  "opfs-tools": "^0.7.4",
23
26
  "pixi.js": "^8.14.3",
24
- "@video-editor/protocol": "0.0.1-beta.15",
25
- "@video-editor/shared": "0.0.1-beta.15"
27
+ "@video-editor/protocol": "0.0.1-beta.17",
28
+ "@video-editor/shared": "0.0.1-beta.17"
26
29
  },
27
30
  "scripts": {
28
31
  "build": "vite build",