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