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