@editframe/elements 0.6.0-beta.9 → 0.7.0-beta.1
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/lib/av/EncodedAsset.cjs +570 -0
- package/dist/lib/av/EncodedAsset.js +553 -0
- package/dist/lib/av/MP4File.cjs +182 -0
- package/dist/lib/av/MP4File.js +165 -0
- package/dist/lib/av/msToTimeCode.cjs +15 -0
- package/dist/lib/av/msToTimeCode.js +15 -0
- package/dist/lib/util/awaitMicrotask.cjs +4 -0
- package/dist/lib/util/awaitMicrotask.js +4 -0
- package/dist/lib/util/memoize.cjs +14 -0
- package/dist/lib/util/memoize.js +14 -0
- package/dist/packages/elements/src/EF_FRAMEGEN.cjs +200 -0
- package/dist/packages/elements/src/EF_FRAMEGEN.d.ts +45 -0
- package/dist/packages/elements/src/EF_FRAMEGEN.js +200 -0
- package/dist/packages/elements/src/EF_INTERACTIVE.cjs +4 -0
- package/dist/packages/elements/src/EF_INTERACTIVE.d.ts +1 -0
- package/dist/packages/elements/src/EF_INTERACTIVE.js +4 -0
- package/dist/packages/elements/src/elements/CrossUpdateController.cjs +16 -0
- package/dist/packages/elements/src/elements/CrossUpdateController.d.ts +9 -0
- package/dist/packages/elements/src/elements/CrossUpdateController.js +16 -0
- package/dist/packages/elements/src/elements/EFAudio.cjs +53 -0
- package/dist/packages/elements/src/elements/EFAudio.d.ts +10 -0
- package/dist/packages/elements/src/elements/EFAudio.js +54 -0
- package/dist/packages/elements/src/elements/EFCaptions.cjs +164 -0
- package/dist/packages/elements/src/elements/EFCaptions.d.ts +38 -0
- package/dist/packages/elements/src/elements/EFCaptions.js +166 -0
- package/dist/packages/elements/src/elements/EFImage.cjs +79 -0
- package/dist/packages/elements/src/elements/EFImage.d.ts +14 -0
- package/dist/packages/elements/src/elements/EFImage.js +80 -0
- package/dist/packages/elements/src/elements/EFMedia.cjs +334 -0
- package/dist/packages/elements/src/elements/EFMedia.d.ts +61 -0
- package/dist/packages/elements/src/elements/EFMedia.js +334 -0
- package/dist/packages/elements/src/elements/EFSourceMixin.cjs +55 -0
- package/dist/packages/elements/src/elements/EFSourceMixin.d.ts +12 -0
- package/dist/packages/elements/src/elements/EFSourceMixin.js +55 -0
- package/dist/packages/elements/src/elements/EFTemporal.cjs +198 -0
- package/dist/packages/elements/src/elements/EFTemporal.d.ts +36 -0
- package/dist/packages/elements/src/elements/EFTemporal.js +198 -0
- package/dist/packages/elements/src/elements/EFTimegroup.browsertest.d.ts +12 -0
- package/dist/packages/elements/src/elements/EFTimegroup.cjs +350 -0
- package/dist/packages/elements/src/elements/EFTimegroup.d.ts +39 -0
- package/dist/packages/elements/src/elements/EFTimegroup.js +351 -0
- package/dist/packages/elements/src/elements/EFTimeline.cjs +15 -0
- package/dist/packages/elements/src/elements/EFTimeline.d.ts +3 -0
- package/dist/packages/elements/src/elements/EFTimeline.js +15 -0
- package/dist/packages/elements/src/elements/EFVideo.cjs +109 -0
- package/dist/packages/elements/src/elements/EFVideo.d.ts +14 -0
- package/dist/packages/elements/src/elements/EFVideo.js +110 -0
- package/dist/packages/elements/src/elements/EFWaveform.cjs +242 -0
- package/dist/packages/elements/src/elements/EFWaveform.d.ts +30 -0
- package/dist/packages/elements/src/elements/EFWaveform.js +226 -0
- package/dist/packages/elements/src/elements/FetchMixin.cjs +28 -0
- package/dist/packages/elements/src/elements/FetchMixin.d.ts +8 -0
- package/dist/packages/elements/src/elements/FetchMixin.js +28 -0
- package/dist/packages/elements/src/elements/TimegroupController.cjs +20 -0
- package/dist/packages/elements/src/elements/TimegroupController.d.ts +14 -0
- package/dist/packages/elements/src/elements/TimegroupController.js +20 -0
- package/dist/packages/elements/src/elements/durationConverter.cjs +8 -0
- package/dist/packages/elements/src/elements/durationConverter.d.ts +4 -0
- package/dist/packages/elements/src/elements/durationConverter.js +8 -0
- package/dist/packages/elements/src/elements/parseTimeToMs.cjs +12 -0
- package/dist/packages/elements/src/elements/parseTimeToMs.d.ts +1 -0
- package/dist/packages/elements/src/elements/parseTimeToMs.js +12 -0
- package/dist/packages/elements/src/elements/util.cjs +11 -0
- package/dist/packages/elements/src/elements/util.d.ts +4 -0
- package/dist/packages/elements/src/elements/util.js +11 -0
- package/dist/packages/elements/src/gui/EFFilmstrip.cjs +820 -0
- package/dist/packages/elements/src/gui/EFFilmstrip.d.ts +147 -0
- package/dist/packages/elements/src/gui/EFFilmstrip.js +828 -0
- package/dist/packages/elements/src/gui/EFWorkbench.cjs +213 -0
- package/dist/packages/elements/src/gui/EFWorkbench.d.ts +45 -0
- package/dist/packages/elements/src/gui/EFWorkbench.js +214 -0
- package/dist/packages/elements/src/gui/TWMixin.cjs +28 -0
- package/dist/packages/elements/src/gui/TWMixin.css.cjs +3 -0
- package/dist/packages/elements/src/gui/TWMixin.css.js +4 -0
- package/dist/packages/elements/src/gui/TWMixin.d.ts +3 -0
- package/dist/packages/elements/src/gui/TWMixin.js +28 -0
- package/dist/packages/elements/src/index.cjs +51 -0
- package/dist/packages/elements/src/index.d.ts +10 -0
- package/dist/packages/elements/src/index.js +24 -0
- package/dist/style.css +787 -0
- package/package.json +2 -2
- package/src/elements/CrossUpdateController.ts +22 -0
- package/src/elements/EFAudio.ts +40 -0
- package/src/elements/EFCaptions.ts +188 -0
- package/src/elements/EFImage.ts +68 -0
- package/src/elements/EFMedia.ts +384 -0
- package/src/elements/EFSourceMixin.ts +57 -0
- package/src/elements/EFTemporal.ts +231 -0
- package/src/elements/EFTimegroup.browsertest.ts +333 -0
- package/src/elements/EFTimegroup.ts +389 -0
- package/src/elements/EFTimeline.ts +13 -0
- package/src/elements/EFVideo.ts +103 -0
- package/src/elements/EFWaveform.ts +417 -0
- package/src/elements/FetchMixin.ts +19 -0
- package/src/elements/TimegroupController.ts +25 -0
- package/src/elements/durationConverter.ts +6 -0
- package/src/elements/parseTimeToMs.ts +9 -0
- package/src/elements/util.ts +24 -0
- package/src/gui/EFFilmstrip.ts +880 -0
- package/src/gui/EFWorkbench.ts +231 -0
- package/src/gui/TWMixin.css +3 -0
- package/src/gui/TWMixin.ts +30 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { html, css, LitElement } from "lit";
|
|
2
|
+
import { provide } from "@lit/context";
|
|
3
|
+
import { property, customElement } from "lit/decorators.js";
|
|
4
|
+
import { EFTemporal, shallowGetTemporalElements, isEFTemporal, timegroupContext } from "./EFTemporal.js";
|
|
5
|
+
import { TimegroupController } from "./TimegroupController.js";
|
|
6
|
+
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
7
|
+
import { deepGetMediaElements } from "./EFMedia.js";
|
|
8
|
+
import { Task } from "@lit/task";
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __typeError = (msg) => {
|
|
12
|
+
throw TypeError(msg);
|
|
13
|
+
};
|
|
14
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
15
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
16
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
17
|
+
if (decorator = decorators[i])
|
|
18
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
19
|
+
if (kind && result) __defProp(target, key, result);
|
|
20
|
+
return result;
|
|
21
|
+
};
|
|
22
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
23
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
24
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
25
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
26
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
27
|
+
var _currentTime, _EFTimegroup_instances, addAudioToContext_fn;
|
|
28
|
+
const shallowGetTimegroups = (element, groups = []) => {
|
|
29
|
+
for (const child of Array.from(element.children)) {
|
|
30
|
+
if (child instanceof EFTimegroup) {
|
|
31
|
+
groups.push(child);
|
|
32
|
+
} else {
|
|
33
|
+
shallowGetTimegroups(child, groups);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return groups;
|
|
37
|
+
};
|
|
38
|
+
let EFTimegroup = class extends EFTemporal(LitElement) {
|
|
39
|
+
constructor() {
|
|
40
|
+
super(...arguments);
|
|
41
|
+
__privateAdd(this, _EFTimegroup_instances);
|
|
42
|
+
this._timeGroupContext = this;
|
|
43
|
+
__privateAdd(this, _currentTime, 0);
|
|
44
|
+
this.mode = "sequence";
|
|
45
|
+
this.crossoverMs = 0;
|
|
46
|
+
this.frameTask = new Task(this, {
|
|
47
|
+
autoRun: EF_INTERACTIVE,
|
|
48
|
+
args: () => [this.ownCurrentTimeMs, this.currentTimeMs],
|
|
49
|
+
task: async ([], { signal: _signal }) => {
|
|
50
|
+
let fullyUpdated = await this.updateComplete;
|
|
51
|
+
while (!fullyUpdated) {
|
|
52
|
+
fullyUpdated = await this.updateComplete;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
set currentTime(time) {
|
|
58
|
+
__privateSet(this, _currentTime, Math.max(0, Math.min(time, this.durationMs / 1e3)));
|
|
59
|
+
try {
|
|
60
|
+
if (this.id) {
|
|
61
|
+
if (this.isConnected) {
|
|
62
|
+
localStorage.setItem(this.storageKey, time.toString());
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.warn("Failed to save time to localStorage", error);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
get currentTime() {
|
|
70
|
+
return __privateGet(this, _currentTime);
|
|
71
|
+
}
|
|
72
|
+
get currentTimeMs() {
|
|
73
|
+
return this.currentTime * 1e3;
|
|
74
|
+
}
|
|
75
|
+
set currentTimeMs(ms) {
|
|
76
|
+
this.currentTime = ms / 1e3;
|
|
77
|
+
}
|
|
78
|
+
render() {
|
|
79
|
+
return html`<slot></slot> `;
|
|
80
|
+
}
|
|
81
|
+
maybeLoadTimeFromLocalStorage() {
|
|
82
|
+
if (this.id) {
|
|
83
|
+
try {
|
|
84
|
+
return Number.parseFloat(localStorage.getItem(this.storageKey) || "0");
|
|
85
|
+
} catch (error) {
|
|
86
|
+
console.warn("Failed to load time from localStorage", error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
connectedCallback() {
|
|
92
|
+
super.connectedCallback();
|
|
93
|
+
if (this.id) {
|
|
94
|
+
__privateSet(this, _currentTime, this.maybeLoadTimeFromLocalStorage());
|
|
95
|
+
}
|
|
96
|
+
if (this.parentTimegroup) {
|
|
97
|
+
new TimegroupController(this.parentTimegroup, this);
|
|
98
|
+
}
|
|
99
|
+
if (this.shouldWrapWithWorkbench()) {
|
|
100
|
+
this.wrapWithWorkbench();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
get storageKey() {
|
|
104
|
+
if (!this.id) {
|
|
105
|
+
throw new Error("Timegroup must have an id to use localStorage.");
|
|
106
|
+
}
|
|
107
|
+
return `ef-timegroup-${this.id}`;
|
|
108
|
+
}
|
|
109
|
+
get crossoverStartMs() {
|
|
110
|
+
const parentTimeGroup = this.parentTimegroup;
|
|
111
|
+
if (!parentTimeGroup || !this.previousElementSibling) {
|
|
112
|
+
return 0;
|
|
113
|
+
}
|
|
114
|
+
return parentTimeGroup.crossoverMs;
|
|
115
|
+
}
|
|
116
|
+
get crossoverEndMs() {
|
|
117
|
+
const parentTimeGroup = this.parentTimegroup;
|
|
118
|
+
if (!parentTimeGroup || !this.nextElementSibling) {
|
|
119
|
+
return 0;
|
|
120
|
+
}
|
|
121
|
+
return parentTimeGroup.crossoverMs;
|
|
122
|
+
}
|
|
123
|
+
get durationMs() {
|
|
124
|
+
switch (this.mode) {
|
|
125
|
+
case "fixed":
|
|
126
|
+
return super.durationMs || 0;
|
|
127
|
+
case "sequence": {
|
|
128
|
+
let duration = 0;
|
|
129
|
+
for (const node of this.childTemporals) {
|
|
130
|
+
duration += node.durationMs;
|
|
131
|
+
}
|
|
132
|
+
return duration;
|
|
133
|
+
}
|
|
134
|
+
case "contain": {
|
|
135
|
+
let maxDuration = 0;
|
|
136
|
+
for (const node of this.childTemporals) {
|
|
137
|
+
if (node.hasOwnDuration) {
|
|
138
|
+
maxDuration = Math.max(maxDuration, node.durationMs);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return maxDuration;
|
|
142
|
+
}
|
|
143
|
+
default:
|
|
144
|
+
throw new Error(`Invalid time mode: ${this.mode}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async waitForMediaDurations() {
|
|
148
|
+
return await Promise.all(
|
|
149
|
+
deepGetMediaElements(this).map(
|
|
150
|
+
(media) => media.trackFragmentIndexLoader.taskComplete
|
|
151
|
+
)
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
get childTemporals() {
|
|
155
|
+
return shallowGetTemporalElements(this);
|
|
156
|
+
}
|
|
157
|
+
updated(changedProperties) {
|
|
158
|
+
super.updated(changedProperties);
|
|
159
|
+
if (changedProperties.has("currentTime") || changedProperties.has("ownCurrentTimeMs")) {
|
|
160
|
+
const timelineTimeMs = (this.rootTimegroup ?? this).currentTimeMs;
|
|
161
|
+
if (this.startTimeMs > timelineTimeMs || this.endTimeMs < timelineTimeMs) {
|
|
162
|
+
this.style.display = "none";
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
this.style.display = "";
|
|
166
|
+
const animations = this.getAnimations({ subtree: true });
|
|
167
|
+
this.style.setProperty(
|
|
168
|
+
"--ef-duration",
|
|
169
|
+
`${this.durationMs + this.crossoverEndMs + this.crossoverStartMs}ms`
|
|
170
|
+
);
|
|
171
|
+
for (const animation of animations) {
|
|
172
|
+
if (animation.playState === "running") {
|
|
173
|
+
animation.pause();
|
|
174
|
+
}
|
|
175
|
+
const effect = animation.effect;
|
|
176
|
+
if (!(effect && effect instanceof KeyframeEffect)) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const target = effect.target;
|
|
180
|
+
if (!target) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
if (target.closest("ef-timegroup") !== this) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (isEFTemporal(target)) {
|
|
187
|
+
const timing = effect.getTiming();
|
|
188
|
+
const duration = Number(timing.duration) ?? 0;
|
|
189
|
+
const delay = Number(timing.delay);
|
|
190
|
+
const newTime = Math.floor(
|
|
191
|
+
Math.min(target.ownCurrentTimeMs, duration - 1 + delay)
|
|
192
|
+
);
|
|
193
|
+
if (Number.isNaN(newTime)) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
animation.currentTime = newTime;
|
|
197
|
+
} else if (target) {
|
|
198
|
+
const nearestTimegroup = target.closest("ef-timegroup");
|
|
199
|
+
if (!nearestTimegroup) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const timing = effect.getTiming();
|
|
203
|
+
const duration = Number(timing.duration) ?? 0;
|
|
204
|
+
const delay = Number(timing.delay);
|
|
205
|
+
const newTime = Math.floor(
|
|
206
|
+
Math.min(nearestTimegroup.ownCurrentTimeMs, duration - 1 + delay)
|
|
207
|
+
);
|
|
208
|
+
if (Number.isNaN(newTime)) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
animation.currentTime = newTime;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
shouldWrapWithWorkbench() {
|
|
217
|
+
return EF_INTERACTIVE && this.closest("ef-timegroup") === this && this.closest("ef-workbench") === null;
|
|
218
|
+
}
|
|
219
|
+
wrapWithWorkbench() {
|
|
220
|
+
const workbench = document.createElement("ef-workbench");
|
|
221
|
+
document.body.append(workbench);
|
|
222
|
+
if (!this.hasAttribute("id")) {
|
|
223
|
+
this.setAttribute("id", "root-this");
|
|
224
|
+
}
|
|
225
|
+
this.setAttribute("slot", "canvas");
|
|
226
|
+
workbench.append(this);
|
|
227
|
+
const filmstrip = document.createElement("ef-filmstrip");
|
|
228
|
+
filmstrip.setAttribute("slot", "timeline");
|
|
229
|
+
filmstrip.setAttribute("target", this.id);
|
|
230
|
+
workbench.append(filmstrip);
|
|
231
|
+
}
|
|
232
|
+
get hasOwnDuration() {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
get efElements() {
|
|
236
|
+
return Array.from(
|
|
237
|
+
this.querySelectorAll(
|
|
238
|
+
"ef-audio, ef-video, ef-image, ef-captions, ef-waveform"
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
async renderAudio(fromMs, toMs) {
|
|
243
|
+
const durationMs = toMs - fromMs;
|
|
244
|
+
const audioContext = new OfflineAudioContext(
|
|
245
|
+
2,
|
|
246
|
+
Math.round(48e3 * durationMs / 1e3),
|
|
247
|
+
48e3
|
|
248
|
+
);
|
|
249
|
+
await __privateMethod(this, _EFTimegroup_instances, addAudioToContext_fn).call(this, audioContext, fromMs, toMs);
|
|
250
|
+
return await audioContext.startRendering();
|
|
251
|
+
}
|
|
252
|
+
async loadMd5Sums() {
|
|
253
|
+
const efElements = this.efElements;
|
|
254
|
+
const loaderTasks = [];
|
|
255
|
+
for (const el of efElements) {
|
|
256
|
+
const md5SumLoader = el.md5SumLoader;
|
|
257
|
+
if (md5SumLoader instanceof Task) {
|
|
258
|
+
md5SumLoader.run();
|
|
259
|
+
loaderTasks.push(md5SumLoader.taskComplete);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
await Promise.all(loaderTasks);
|
|
263
|
+
efElements.map((el) => {
|
|
264
|
+
if ("productionSrc" in el && el.productionSrc instanceof Function) {
|
|
265
|
+
el.setAttribute("src", el.productionSrc());
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
_currentTime = /* @__PURE__ */ new WeakMap();
|
|
271
|
+
_EFTimegroup_instances = /* @__PURE__ */ new WeakSet();
|
|
272
|
+
addAudioToContext_fn = async function(audioContext, fromMs, toMs) {
|
|
273
|
+
await this.waitForMediaDurations();
|
|
274
|
+
const durationMs = toMs - fromMs;
|
|
275
|
+
await Promise.all(
|
|
276
|
+
deepGetMediaElements(this).map(async (mediaElement) => {
|
|
277
|
+
await mediaElement.trackFragmentIndexLoader.taskComplete;
|
|
278
|
+
const mediaStartsBeforeEnd = mediaElement.startTimeMs <= toMs;
|
|
279
|
+
const mediaEndsAfterStart = mediaElement.endTimeMs >= fromMs;
|
|
280
|
+
const mediaOverlaps = mediaStartsBeforeEnd && mediaEndsAfterStart;
|
|
281
|
+
if (!mediaOverlaps || mediaElement.defaultAudioTrackId === void 0) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
const audio = await mediaElement.fetchAudioSpanningTime(fromMs, toMs);
|
|
285
|
+
if (!audio) {
|
|
286
|
+
throw new Error("Failed to fetch audio");
|
|
287
|
+
}
|
|
288
|
+
const ctxStartMs = Math.max(0, mediaElement.startTimeMs - fromMs);
|
|
289
|
+
const ctxEndMs = Math.min(durationMs, mediaElement.endTimeMs - fromMs);
|
|
290
|
+
const ctxDurationMs = ctxEndMs - ctxStartMs;
|
|
291
|
+
const offset = Math.max(0, fromMs - mediaElement.startTimeMs) - audio.startMs;
|
|
292
|
+
const bufferSource = audioContext.createBufferSource();
|
|
293
|
+
bufferSource.buffer = await audioContext.decodeAudioData(
|
|
294
|
+
await audio.blob.arrayBuffer()
|
|
295
|
+
);
|
|
296
|
+
bufferSource.connect(audioContext.destination);
|
|
297
|
+
bufferSource.start(
|
|
298
|
+
ctxStartMs / 1e3,
|
|
299
|
+
offset / 1e3,
|
|
300
|
+
ctxDurationMs / 1e3
|
|
301
|
+
);
|
|
302
|
+
})
|
|
303
|
+
);
|
|
304
|
+
};
|
|
305
|
+
EFTimegroup.styles = css`
|
|
306
|
+
:host {
|
|
307
|
+
display: block;
|
|
308
|
+
width: 100%;
|
|
309
|
+
height: 100%;
|
|
310
|
+
position: relative;
|
|
311
|
+
top: 0;
|
|
312
|
+
}
|
|
313
|
+
`;
|
|
314
|
+
__decorateClass([
|
|
315
|
+
provide({ context: timegroupContext })
|
|
316
|
+
], EFTimegroup.prototype, "_timeGroupContext", 2);
|
|
317
|
+
__decorateClass([
|
|
318
|
+
property({
|
|
319
|
+
type: String,
|
|
320
|
+
attribute: "mode"
|
|
321
|
+
})
|
|
322
|
+
], EFTimegroup.prototype, "mode", 2);
|
|
323
|
+
__decorateClass([
|
|
324
|
+
property({ type: Number })
|
|
325
|
+
], EFTimegroup.prototype, "currentTime", 1);
|
|
326
|
+
__decorateClass([
|
|
327
|
+
property({
|
|
328
|
+
attribute: "crossover",
|
|
329
|
+
converter: {
|
|
330
|
+
fromAttribute: (value) => {
|
|
331
|
+
if (value.endsWith("ms")) {
|
|
332
|
+
return Number.parseFloat(value);
|
|
333
|
+
}
|
|
334
|
+
if (value.endsWith("s")) {
|
|
335
|
+
return Number.parseFloat(value) * 1e3;
|
|
336
|
+
}
|
|
337
|
+
throw new Error(
|
|
338
|
+
"`crossover` MUST be in milliseconds or seconds (10s, 10000ms)"
|
|
339
|
+
);
|
|
340
|
+
},
|
|
341
|
+
toAttribute: (value) => `${value}ms`
|
|
342
|
+
}
|
|
343
|
+
})
|
|
344
|
+
], EFTimegroup.prototype, "crossoverMs", 2);
|
|
345
|
+
EFTimegroup = __decorateClass([
|
|
346
|
+
customElement("ef-timegroup")
|
|
347
|
+
], EFTimegroup);
|
|
348
|
+
export {
|
|
349
|
+
EFTimegroup,
|
|
350
|
+
shallowGetTimegroups
|
|
351
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
class EFTimeline extends HTMLElement {
|
|
4
|
+
get durationMs() {
|
|
5
|
+
let duration = 0;
|
|
6
|
+
for (const node of this.childNodes) {
|
|
7
|
+
if ("durationMs" in node && typeof node.durationMs === "number") {
|
|
8
|
+
duration += node.durationMs;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return duration;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
window.customElements.define("ef-timeline", EFTimeline);
|
|
15
|
+
exports.EFTimeline = EFTimeline;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class EFTimeline extends HTMLElement {
|
|
2
|
+
get durationMs() {
|
|
3
|
+
let duration = 0;
|
|
4
|
+
for (const node of this.childNodes) {
|
|
5
|
+
if ("durationMs" in node && typeof node.durationMs === "number") {
|
|
6
|
+
duration += node.durationMs;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
return duration;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
window.customElements.define("ef-timeline", EFTimeline);
|
|
13
|
+
export {
|
|
14
|
+
EFTimeline
|
|
15
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const lit = require("lit");
|
|
4
|
+
const task = require("@lit/task");
|
|
5
|
+
const ref_js = require("lit/directives/ref.js");
|
|
6
|
+
const decorators_js = require("lit/decorators.js");
|
|
7
|
+
const EFMedia = require("./EFMedia.cjs");
|
|
8
|
+
const TWMixin = require("../gui/TWMixin.cjs");
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __typeError = (msg) => {
|
|
12
|
+
throw TypeError(msg);
|
|
13
|
+
};
|
|
14
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
15
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
16
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
17
|
+
if (decorator = decorators[i])
|
|
18
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
19
|
+
if (kind && result) __defProp(target, key, result);
|
|
20
|
+
return result;
|
|
21
|
+
};
|
|
22
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
23
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), member.get(obj));
|
|
24
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
25
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
26
|
+
var _decoderLock;
|
|
27
|
+
exports.EFVideo = class EFVideo extends TWMixin.TWMixin(EFMedia.EFMedia) {
|
|
28
|
+
constructor() {
|
|
29
|
+
super(...arguments);
|
|
30
|
+
this.canvasRef = ref_js.createRef();
|
|
31
|
+
__privateAdd(this, _decoderLock, false);
|
|
32
|
+
this.frameTask = new task.Task(this, {
|
|
33
|
+
args: () => [
|
|
34
|
+
this.trackFragmentIndexLoader.status,
|
|
35
|
+
this.initSegmentsLoader.status,
|
|
36
|
+
this.seekTask.status,
|
|
37
|
+
this.fetchSeekTask.status,
|
|
38
|
+
this.videoAssetTask.status,
|
|
39
|
+
this.paintTask.status
|
|
40
|
+
],
|
|
41
|
+
task: async () => {
|
|
42
|
+
await this.trackFragmentIndexLoader.taskComplete;
|
|
43
|
+
await this.initSegmentsLoader.taskComplete;
|
|
44
|
+
await this.seekTask.taskComplete;
|
|
45
|
+
await this.fetchSeekTask.taskComplete;
|
|
46
|
+
await this.videoAssetTask.taskComplete;
|
|
47
|
+
await this.paintTask.taskComplete;
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.paintTask = new task.Task(this, {
|
|
51
|
+
args: () => [this.videoAssetTask.value, this.desiredSeekTimeMs],
|
|
52
|
+
task: async ([videoAsset, seekToMs], {
|
|
53
|
+
signal: _signal
|
|
54
|
+
}) => {
|
|
55
|
+
if (!videoAsset) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (__privateGet(this, _decoderLock)) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
__privateSet(this, _decoderLock, true);
|
|
63
|
+
const frame = await videoAsset.seekToTime(seekToMs / 1e3);
|
|
64
|
+
if (!this.canvasElement) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const ctx = this.canvasElement.getContext("2d");
|
|
68
|
+
if (!(frame && ctx)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.canvasElement.width = frame?.codedWidth;
|
|
72
|
+
this.canvasElement.height = frame?.codedHeight;
|
|
73
|
+
ctx.drawImage(
|
|
74
|
+
frame,
|
|
75
|
+
0,
|
|
76
|
+
0,
|
|
77
|
+
this.canvasElement.width,
|
|
78
|
+
this.canvasElement.height
|
|
79
|
+
);
|
|
80
|
+
return seekToMs;
|
|
81
|
+
} catch (error) {
|
|
82
|
+
console.trace("Unexpected error while seeking video", error);
|
|
83
|
+
} finally {
|
|
84
|
+
__privateSet(this, _decoderLock, false);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
render() {
|
|
90
|
+
return lit.html` <canvas
|
|
91
|
+
class="h-full w-full object-fill"
|
|
92
|
+
${ref_js.ref(this.canvasRef)}
|
|
93
|
+
></canvas>`;
|
|
94
|
+
}
|
|
95
|
+
get canvasElement() {
|
|
96
|
+
return this.canvasRef.value;
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
_decoderLock = /* @__PURE__ */ new WeakMap();
|
|
100
|
+
exports.EFVideo.styles = [
|
|
101
|
+
lit.css`
|
|
102
|
+
:host {
|
|
103
|
+
display: block;
|
|
104
|
+
}
|
|
105
|
+
`
|
|
106
|
+
];
|
|
107
|
+
exports.EFVideo = __decorateClass([
|
|
108
|
+
decorators_js.customElement("ef-video")
|
|
109
|
+
], exports.EFVideo);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Task } from '@lit/task';
|
|
2
|
+
import { EFMedia } from './EFMedia';
|
|
3
|
+
|
|
4
|
+
declare const EFVideo_base: typeof EFMedia;
|
|
5
|
+
export declare class EFVideo extends EFVideo_base {
|
|
6
|
+
#private;
|
|
7
|
+
static styles: import('lit').CSSResult[];
|
|
8
|
+
canvasRef: import('lit-html/directives/ref').Ref<HTMLCanvasElement>;
|
|
9
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
10
|
+
get canvasElement(): HTMLCanvasElement | undefined;
|
|
11
|
+
frameTask: Task<readonly [import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus], void>;
|
|
12
|
+
paintTask: Task<readonly [import('../../../../lib/av/EncodedAsset').VideoAsset | undefined, number], number | undefined>;
|
|
13
|
+
}
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { css, html } from "lit";
|
|
2
|
+
import { Task } from "@lit/task";
|
|
3
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
4
|
+
import { customElement } from "lit/decorators.js";
|
|
5
|
+
import { EFMedia } from "./EFMedia.js";
|
|
6
|
+
import { TWMixin } from "../gui/TWMixin.js";
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __typeError = (msg) => {
|
|
10
|
+
throw TypeError(msg);
|
|
11
|
+
};
|
|
12
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
13
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
14
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
15
|
+
if (decorator = decorators[i])
|
|
16
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
17
|
+
if (kind && result) __defProp(target, key, result);
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
20
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
21
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), member.get(obj));
|
|
22
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
23
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
24
|
+
var _decoderLock;
|
|
25
|
+
let EFVideo = class extends TWMixin(EFMedia) {
|
|
26
|
+
constructor() {
|
|
27
|
+
super(...arguments);
|
|
28
|
+
this.canvasRef = createRef();
|
|
29
|
+
__privateAdd(this, _decoderLock, false);
|
|
30
|
+
this.frameTask = new Task(this, {
|
|
31
|
+
args: () => [
|
|
32
|
+
this.trackFragmentIndexLoader.status,
|
|
33
|
+
this.initSegmentsLoader.status,
|
|
34
|
+
this.seekTask.status,
|
|
35
|
+
this.fetchSeekTask.status,
|
|
36
|
+
this.videoAssetTask.status,
|
|
37
|
+
this.paintTask.status
|
|
38
|
+
],
|
|
39
|
+
task: async () => {
|
|
40
|
+
await this.trackFragmentIndexLoader.taskComplete;
|
|
41
|
+
await this.initSegmentsLoader.taskComplete;
|
|
42
|
+
await this.seekTask.taskComplete;
|
|
43
|
+
await this.fetchSeekTask.taskComplete;
|
|
44
|
+
await this.videoAssetTask.taskComplete;
|
|
45
|
+
await this.paintTask.taskComplete;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
this.paintTask = new Task(this, {
|
|
49
|
+
args: () => [this.videoAssetTask.value, this.desiredSeekTimeMs],
|
|
50
|
+
task: async ([videoAsset, seekToMs], {
|
|
51
|
+
signal: _signal
|
|
52
|
+
}) => {
|
|
53
|
+
if (!videoAsset) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (__privateGet(this, _decoderLock)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
__privateSet(this, _decoderLock, true);
|
|
61
|
+
const frame = await videoAsset.seekToTime(seekToMs / 1e3);
|
|
62
|
+
if (!this.canvasElement) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const ctx = this.canvasElement.getContext("2d");
|
|
66
|
+
if (!(frame && ctx)) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
this.canvasElement.width = frame?.codedWidth;
|
|
70
|
+
this.canvasElement.height = frame?.codedHeight;
|
|
71
|
+
ctx.drawImage(
|
|
72
|
+
frame,
|
|
73
|
+
0,
|
|
74
|
+
0,
|
|
75
|
+
this.canvasElement.width,
|
|
76
|
+
this.canvasElement.height
|
|
77
|
+
);
|
|
78
|
+
return seekToMs;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.trace("Unexpected error while seeking video", error);
|
|
81
|
+
} finally {
|
|
82
|
+
__privateSet(this, _decoderLock, false);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
render() {
|
|
88
|
+
return html` <canvas
|
|
89
|
+
class="h-full w-full object-fill"
|
|
90
|
+
${ref(this.canvasRef)}
|
|
91
|
+
></canvas>`;
|
|
92
|
+
}
|
|
93
|
+
get canvasElement() {
|
|
94
|
+
return this.canvasRef.value;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
_decoderLock = /* @__PURE__ */ new WeakMap();
|
|
98
|
+
EFVideo.styles = [
|
|
99
|
+
css`
|
|
100
|
+
:host {
|
|
101
|
+
display: block;
|
|
102
|
+
}
|
|
103
|
+
`
|
|
104
|
+
];
|
|
105
|
+
EFVideo = __decorateClass([
|
|
106
|
+
customElement("ef-video")
|
|
107
|
+
], EFVideo);
|
|
108
|
+
export {
|
|
109
|
+
EFVideo
|
|
110
|
+
};
|