@editframe/elements 0.5.0-beta.4 → 0.5.0-beta.6
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/editor/msToTimeCode.mjs +15 -0
- package/dist/editor/util/EncodedAsset/EncodedAsset.mjs +537 -0
- package/dist/editor/util/MP4File.mjs +161 -0
- package/dist/elements/elements/CrossUpdateController.mjs +16 -0
- package/dist/elements/elements/EFAudio.mjs +37 -0
- package/dist/elements/elements/EFCaptions.mjs +172 -0
- package/dist/elements/elements/EFImage.mjs +67 -0
- package/dist/elements/elements/EFMedia.mjs +255 -0
- package/dist/elements/elements/EFSourceMixin.mjs +57 -0
- package/dist/elements/elements/EFTemporal.mjs +186 -0
- package/dist/elements/elements/EFTimegroup.mjs +230 -0
- package/dist/elements/elements/EFTimeline.mjs +12 -0
- package/dist/elements/elements/EFVideo.mjs +123 -0
- package/dist/elements/elements/EFWaveform.mjs +203 -0
- package/dist/elements/elements/FetchMixin.mjs +30 -0
- package/dist/elements/elements/TimegroupController.mjs +20 -0
- package/dist/elements/elements/durationConverter.mjs +8 -0
- package/dist/elements/elements/parseTimeToMs.mjs +13 -0
- package/dist/elements/elements/util.mjs +11 -0
- package/dist/elements/elements.css.mjs +1 -0
- package/dist/elements/elements.mjs +11 -0
- package/dist/elements/gui/EFFilmstrip.mjs +680 -0
- package/dist/elements/gui/EFWorkbench.mjs +234 -0
- package/dist/elements/gui/TWMixin.css.mjs +4 -0
- package/dist/elements/gui/TWMixin.mjs +27 -0
- package/dist/style.css +754 -0
- package/dist/util/awaitMicrotask.mjs +8 -0
- package/dist/util/memoize.mjs +15 -0
- package/package.json +11 -4
- package/dist/editframe-elements.css +0 -1
- package/dist/editframe-elements.mjs +0 -9089
- package/dist/editframe-elements.umd.js +0 -288
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { createContext, consume } from "@lit/context";
|
|
2
|
+
import { property, state } from "lit/decorators.js";
|
|
3
|
+
import { EFTimegroup } from "./EFTimegroup.mjs";
|
|
4
|
+
import { durationConverter } from "./durationConverter.mjs";
|
|
5
|
+
import { Task } from "@lit/task";
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
9
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
10
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
11
|
+
if (decorator = decorators[i])
|
|
12
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
13
|
+
if (kind && result)
|
|
14
|
+
__defProp(target, key, result);
|
|
15
|
+
return result;
|
|
16
|
+
};
|
|
17
|
+
const timegroupContext = createContext(
|
|
18
|
+
Symbol("timeGroupContext")
|
|
19
|
+
);
|
|
20
|
+
const isEFTemporal = (obj) => obj[EF_TEMPORAL];
|
|
21
|
+
const EF_TEMPORAL = Symbol("EF_TEMPORAL");
|
|
22
|
+
const deepGetTemporalElements = (element, temporals = []) => {
|
|
23
|
+
for (const child of element.children) {
|
|
24
|
+
if (isEFTemporal(child)) {
|
|
25
|
+
temporals.push(child);
|
|
26
|
+
}
|
|
27
|
+
deepGetTemporalElements(child, temporals);
|
|
28
|
+
}
|
|
29
|
+
return temporals;
|
|
30
|
+
};
|
|
31
|
+
const shallowGetTemporalElements = (element, temporals = []) => {
|
|
32
|
+
for (const child of element.children) {
|
|
33
|
+
if (isEFTemporal(child)) {
|
|
34
|
+
temporals.push(child);
|
|
35
|
+
} else {
|
|
36
|
+
shallowGetTemporalElements(child, temporals);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return temporals;
|
|
40
|
+
};
|
|
41
|
+
const shallowGetTimegroups = (element, groups = []) => {
|
|
42
|
+
for (const child of element.children) {
|
|
43
|
+
if (child instanceof EFTimegroup) {
|
|
44
|
+
groups.push(child);
|
|
45
|
+
} else {
|
|
46
|
+
shallowGetTimegroups(child, groups);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return groups;
|
|
50
|
+
};
|
|
51
|
+
class OwnCurrentTimeController {
|
|
52
|
+
constructor(host, temporal) {
|
|
53
|
+
this.host = host;
|
|
54
|
+
this.temporal = temporal;
|
|
55
|
+
host.addController(this);
|
|
56
|
+
}
|
|
57
|
+
hostUpdated() {
|
|
58
|
+
this.temporal.requestUpdate("ownCurrentTimeMs");
|
|
59
|
+
}
|
|
60
|
+
remove() {
|
|
61
|
+
this.host.removeController(this);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const EFTemporal = (superClass) => {
|
|
65
|
+
class TemporalMixinClass extends superClass {
|
|
66
|
+
constructor() {
|
|
67
|
+
super(...arguments);
|
|
68
|
+
this._offsetMs = 0;
|
|
69
|
+
this.rootTimegroup = this.getRootTimegroup();
|
|
70
|
+
this.frameTask = new Task(this, {
|
|
71
|
+
autoRun: false,
|
|
72
|
+
args: () => [this.ownCurrentTimeMs],
|
|
73
|
+
task: async ([], { signal }) => {
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
#parentTimegroup;
|
|
78
|
+
set parentTimegroup(value) {
|
|
79
|
+
this.#parentTimegroup = value;
|
|
80
|
+
this.ownCurrentTimeController?.remove();
|
|
81
|
+
this.rootTimegroup = this.getRootTimegroup();
|
|
82
|
+
if (this.rootTimegroup) {
|
|
83
|
+
this.ownCurrentTimeController = new OwnCurrentTimeController(
|
|
84
|
+
this.rootTimegroup,
|
|
85
|
+
this
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
get parentTimegroup() {
|
|
90
|
+
return this.#parentTimegroup;
|
|
91
|
+
}
|
|
92
|
+
get offsetAppliesToDuration() {
|
|
93
|
+
return !(this.parentTimegroup?.mode === "sequence");
|
|
94
|
+
}
|
|
95
|
+
getRootTimegroup() {
|
|
96
|
+
let parent = this instanceof EFTimegroup ? this : this.parentTimegroup;
|
|
97
|
+
while (parent?.parentTimegroup) {
|
|
98
|
+
parent = parent.parentTimegroup;
|
|
99
|
+
}
|
|
100
|
+
return parent;
|
|
101
|
+
}
|
|
102
|
+
get hasOwnDuration() {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
// Defining this as a getter to a private property allows us to
|
|
106
|
+
// override it classes that include this mixin.
|
|
107
|
+
get durationMs() {
|
|
108
|
+
let durationMs = this._durationMs || this.parentTimegroup?.durationMs || 0;
|
|
109
|
+
return durationMs || 0;
|
|
110
|
+
}
|
|
111
|
+
get offsetMs() {
|
|
112
|
+
return this._offsetMs || 0;
|
|
113
|
+
}
|
|
114
|
+
get startTimeMs() {
|
|
115
|
+
const parentTimegroup = this.parentTimegroup;
|
|
116
|
+
if (!parentTimegroup) {
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
switch (parentTimegroup.mode) {
|
|
120
|
+
case "sequence": {
|
|
121
|
+
const siblingTemorals = shallowGetTemporalElements(parentTimegroup);
|
|
122
|
+
const ownIndex = siblingTemorals.indexOf(this);
|
|
123
|
+
if (ownIndex === 0) {
|
|
124
|
+
return parentTimegroup.startTimeMs;
|
|
125
|
+
}
|
|
126
|
+
const previous = siblingTemorals[ownIndex - 1];
|
|
127
|
+
if (!previous) {
|
|
128
|
+
throw new Error("Previous temporal element not found");
|
|
129
|
+
}
|
|
130
|
+
return previous.startTimeMs + previous.durationMs;
|
|
131
|
+
}
|
|
132
|
+
case "contain":
|
|
133
|
+
case "fixed":
|
|
134
|
+
return parentTimegroup.startTimeMs + this.offsetMs;
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`Invalid time mode: ${parentTimegroup.mode}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
get endTimeMs() {
|
|
140
|
+
return this.startTimeMs + this.durationMs;
|
|
141
|
+
}
|
|
142
|
+
get ownCurrentTimeMs() {
|
|
143
|
+
if (this.rootTimegroup) {
|
|
144
|
+
return Math.min(
|
|
145
|
+
Math.max(0, this.rootTimegroup.currentTimeMs - this.startTimeMs),
|
|
146
|
+
this.durationMs
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
return 0;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
__decorateClass([
|
|
153
|
+
consume({ context: timegroupContext, subscribe: true }),
|
|
154
|
+
property({ attribute: false })
|
|
155
|
+
], TemporalMixinClass.prototype, "parentTimegroup", 1);
|
|
156
|
+
__decorateClass([
|
|
157
|
+
property({
|
|
158
|
+
type: String,
|
|
159
|
+
attribute: "offset",
|
|
160
|
+
converter: durationConverter
|
|
161
|
+
})
|
|
162
|
+
], TemporalMixinClass.prototype, "_offsetMs", 2);
|
|
163
|
+
__decorateClass([
|
|
164
|
+
property({
|
|
165
|
+
type: Number,
|
|
166
|
+
attribute: "duration",
|
|
167
|
+
converter: durationConverter
|
|
168
|
+
})
|
|
169
|
+
], TemporalMixinClass.prototype, "_durationMs", 2);
|
|
170
|
+
__decorateClass([
|
|
171
|
+
state()
|
|
172
|
+
], TemporalMixinClass.prototype, "rootTimegroup", 2);
|
|
173
|
+
Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, {
|
|
174
|
+
value: true
|
|
175
|
+
});
|
|
176
|
+
return TemporalMixinClass;
|
|
177
|
+
};
|
|
178
|
+
export {
|
|
179
|
+
EFTemporal,
|
|
180
|
+
OwnCurrentTimeController,
|
|
181
|
+
deepGetTemporalElements,
|
|
182
|
+
isEFTemporal,
|
|
183
|
+
shallowGetTemporalElements,
|
|
184
|
+
shallowGetTimegroups,
|
|
185
|
+
timegroupContext
|
|
186
|
+
};
|
|
@@ -0,0 +1,230 @@
|
|
|
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.mjs";
|
|
5
|
+
import { TimegroupController } from "./TimegroupController.mjs";
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
8
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
9
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
10
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
11
|
+
if (decorator = decorators[i])
|
|
12
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
13
|
+
if (kind && result)
|
|
14
|
+
__defProp(target, key, result);
|
|
15
|
+
return result;
|
|
16
|
+
};
|
|
17
|
+
var __accessCheck = (obj, member, msg) => {
|
|
18
|
+
if (!member.has(obj))
|
|
19
|
+
throw TypeError("Cannot " + msg);
|
|
20
|
+
};
|
|
21
|
+
var __privateGet = (obj, member, getter) => {
|
|
22
|
+
__accessCheck(obj, member, "read from private field");
|
|
23
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
24
|
+
};
|
|
25
|
+
var __privateAdd = (obj, member, value) => {
|
|
26
|
+
if (member.has(obj))
|
|
27
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
28
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
29
|
+
};
|
|
30
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
31
|
+
__accessCheck(obj, member, "write to private field");
|
|
32
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
33
|
+
return value;
|
|
34
|
+
};
|
|
35
|
+
var _currentTime;
|
|
36
|
+
let EFTimegroup = class extends EFTemporal(LitElement) {
|
|
37
|
+
constructor() {
|
|
38
|
+
super(...arguments);
|
|
39
|
+
this._timeGroupContext = this;
|
|
40
|
+
__privateAdd(this, _currentTime, 0);
|
|
41
|
+
this.mode = "sequence";
|
|
42
|
+
this.crossoverMs = 0;
|
|
43
|
+
}
|
|
44
|
+
set currentTime(time) {
|
|
45
|
+
__privateSet(this, _currentTime, Math.max(0, Math.min(time, this.durationMs / 1e3)));
|
|
46
|
+
try {
|
|
47
|
+
if (this.id) {
|
|
48
|
+
if (this.isConnected) {
|
|
49
|
+
localStorage.setItem(this.storageKey, time.toString());
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.warn("Failed to save time to localStorage", error);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
get currentTime() {
|
|
57
|
+
return __privateGet(this, _currentTime);
|
|
58
|
+
}
|
|
59
|
+
get currentTimeMs() {
|
|
60
|
+
return this.currentTime * 1e3;
|
|
61
|
+
}
|
|
62
|
+
set currentTimeMs(ms) {
|
|
63
|
+
this.currentTime = ms / 1e3;
|
|
64
|
+
}
|
|
65
|
+
render() {
|
|
66
|
+
return html`<slot></slot> `;
|
|
67
|
+
}
|
|
68
|
+
maybeLoadTimeFromLocalStorage() {
|
|
69
|
+
if (this.id) {
|
|
70
|
+
try {
|
|
71
|
+
return parseFloat(localStorage.getItem(this.storageKey) || "0");
|
|
72
|
+
} catch (error) {
|
|
73
|
+
console.warn("Failed to load time from localStorage", error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
connectedCallback() {
|
|
79
|
+
super.connectedCallback();
|
|
80
|
+
if (this.id) {
|
|
81
|
+
__privateSet(this, _currentTime, this.maybeLoadTimeFromLocalStorage());
|
|
82
|
+
}
|
|
83
|
+
if (this.parentTimegroup) {
|
|
84
|
+
new TimegroupController(this.parentTimegroup, this);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
get storageKey() {
|
|
88
|
+
if (!this.id) {
|
|
89
|
+
throw new Error("Timegroup must have an id to use localStorage.");
|
|
90
|
+
}
|
|
91
|
+
return `ef-timegroup-${this.id}`;
|
|
92
|
+
}
|
|
93
|
+
get crossoverStartMs() {
|
|
94
|
+
const parentTimeGroup = this.parentTimegroup;
|
|
95
|
+
if (!parentTimeGroup || !this.previousElementSibling) {
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
return parentTimeGroup.crossoverMs;
|
|
99
|
+
}
|
|
100
|
+
get crossoverEndMs() {
|
|
101
|
+
const parentTimeGroup = this.parentTimegroup;
|
|
102
|
+
if (!parentTimeGroup || !this.nextElementSibling) {
|
|
103
|
+
return 0;
|
|
104
|
+
}
|
|
105
|
+
return parentTimeGroup.crossoverMs;
|
|
106
|
+
}
|
|
107
|
+
get durationMs() {
|
|
108
|
+
switch (this.mode) {
|
|
109
|
+
case "fixed":
|
|
110
|
+
return super.durationMs || 0;
|
|
111
|
+
case "sequence":
|
|
112
|
+
let duration = 0;
|
|
113
|
+
this.childTemporals.forEach((node) => {
|
|
114
|
+
duration += node.durationMs;
|
|
115
|
+
});
|
|
116
|
+
return duration;
|
|
117
|
+
case "contain":
|
|
118
|
+
let maxDuration = 0;
|
|
119
|
+
this.childTemporals.forEach((node) => {
|
|
120
|
+
if (node.hasOwnDuration) {
|
|
121
|
+
maxDuration = Math.max(maxDuration, node.durationMs);
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
return maxDuration;
|
|
125
|
+
default:
|
|
126
|
+
throw new Error(`Invalid time mode: ${this.mode}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
get childTemporals() {
|
|
130
|
+
return shallowGetTemporalElements(this);
|
|
131
|
+
}
|
|
132
|
+
updated(changedProperties) {
|
|
133
|
+
super.updated(changedProperties);
|
|
134
|
+
if (changedProperties.has("currentTime") || changedProperties.has("ownCurrentTimeMs")) {
|
|
135
|
+
const animations = this.getAnimations({ subtree: true });
|
|
136
|
+
this.style.setProperty(
|
|
137
|
+
"--ef-duration",
|
|
138
|
+
`${this.durationMs + this.crossoverEndMs + this.crossoverStartMs}ms`
|
|
139
|
+
);
|
|
140
|
+
animations.forEach((animation) => {
|
|
141
|
+
if (animation.playState === "running") {
|
|
142
|
+
animation.pause();
|
|
143
|
+
}
|
|
144
|
+
const effect = animation.effect;
|
|
145
|
+
if (!(effect && effect instanceof KeyframeEffect)) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const target = effect.target;
|
|
149
|
+
if (isEFTemporal(target)) {
|
|
150
|
+
const timing = effect.getTiming();
|
|
151
|
+
const duration = Number(timing.duration) ?? 0;
|
|
152
|
+
const delay = Number(timing.delay);
|
|
153
|
+
const newTime = Math.floor(
|
|
154
|
+
Math.min(target.ownCurrentTimeMs, duration - 1 + delay)
|
|
155
|
+
);
|
|
156
|
+
if (Number.isNaN(newTime)) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
animation.currentTime = newTime;
|
|
160
|
+
} else if (target) {
|
|
161
|
+
const nearestTimegroup = target.closest("ef-timegroup");
|
|
162
|
+
if (!nearestTimegroup) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const timing = effect.getTiming();
|
|
166
|
+
const duration = Number(timing.duration) ?? 0;
|
|
167
|
+
const delay = Number(timing.delay);
|
|
168
|
+
const newTime = Math.floor(
|
|
169
|
+
Math.min(nearestTimegroup.ownCurrentTimeMs, duration - 1 + delay)
|
|
170
|
+
);
|
|
171
|
+
if (Number.isNaN(newTime)) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
animation.currentTime = newTime;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
get hasOwnDuration() {
|
|
180
|
+
return true;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
_currentTime = /* @__PURE__ */ new WeakMap();
|
|
184
|
+
EFTimegroup.styles = css`
|
|
185
|
+
:host {
|
|
186
|
+
display: block;
|
|
187
|
+
width: 100%;
|
|
188
|
+
height: 100%;
|
|
189
|
+
position: relative;
|
|
190
|
+
top: 0;
|
|
191
|
+
}
|
|
192
|
+
`;
|
|
193
|
+
__decorateClass([
|
|
194
|
+
provide({ context: timegroupContext })
|
|
195
|
+
], EFTimegroup.prototype, "_timeGroupContext", 2);
|
|
196
|
+
__decorateClass([
|
|
197
|
+
property({
|
|
198
|
+
type: String,
|
|
199
|
+
attribute: "mode"
|
|
200
|
+
})
|
|
201
|
+
], EFTimegroup.prototype, "mode", 2);
|
|
202
|
+
__decorateClass([
|
|
203
|
+
property({ type: Number })
|
|
204
|
+
], EFTimegroup.prototype, "currentTime", 1);
|
|
205
|
+
__decorateClass([
|
|
206
|
+
property({
|
|
207
|
+
attribute: "crossover",
|
|
208
|
+
converter: {
|
|
209
|
+
fromAttribute: (value) => {
|
|
210
|
+
if (value.endsWith("ms")) {
|
|
211
|
+
return parseFloat(value);
|
|
212
|
+
}
|
|
213
|
+
if (value.endsWith("s")) {
|
|
214
|
+
return parseFloat(value) * 1e3;
|
|
215
|
+
} else {
|
|
216
|
+
throw new Error(
|
|
217
|
+
"`crossover` MUST be in milliseconds or seconds (10s, 10000ms)"
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
toAttribute: (value) => `${value}ms`
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
], EFTimegroup.prototype, "crossoverMs", 2);
|
|
225
|
+
EFTimegroup = __decorateClass([
|
|
226
|
+
customElement("ef-timegroup")
|
|
227
|
+
], EFTimegroup);
|
|
228
|
+
export {
|
|
229
|
+
EFTimegroup
|
|
230
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
class EFTimeline extends HTMLElement {
|
|
2
|
+
get durationMs() {
|
|
3
|
+
let duration = 0;
|
|
4
|
+
this.childNodes.forEach((node) => {
|
|
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);
|
|
@@ -0,0 +1,123 @@
|
|
|
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.mjs";
|
|
6
|
+
import { TWMixin } from "../gui/TWMixin.mjs";
|
|
7
|
+
var __defProp = Object.defineProperty;
|
|
8
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
10
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
11
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
12
|
+
if (decorator = decorators[i])
|
|
13
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
14
|
+
if (kind && result)
|
|
15
|
+
__defProp(target, key, result);
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
18
|
+
var __accessCheck = (obj, member, msg) => {
|
|
19
|
+
if (!member.has(obj))
|
|
20
|
+
throw TypeError("Cannot " + msg);
|
|
21
|
+
};
|
|
22
|
+
var __privateGet = (obj, member, getter) => {
|
|
23
|
+
__accessCheck(obj, member, "read from private field");
|
|
24
|
+
return getter ? getter.call(obj) : member.get(obj);
|
|
25
|
+
};
|
|
26
|
+
var __privateAdd = (obj, member, value) => {
|
|
27
|
+
if (member.has(obj))
|
|
28
|
+
throw TypeError("Cannot add the same private member more than once");
|
|
29
|
+
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
30
|
+
};
|
|
31
|
+
var __privateSet = (obj, member, value, setter) => {
|
|
32
|
+
__accessCheck(obj, member, "write to private field");
|
|
33
|
+
setter ? setter.call(obj, value) : member.set(obj, value);
|
|
34
|
+
return value;
|
|
35
|
+
};
|
|
36
|
+
var _decoderLock;
|
|
37
|
+
let EFVideo = class extends TWMixin(EFMedia) {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(...arguments);
|
|
40
|
+
this.canvasRef = createRef();
|
|
41
|
+
__privateAdd(this, _decoderLock, false);
|
|
42
|
+
this.frameTask = new Task(this, {
|
|
43
|
+
args: () => [
|
|
44
|
+
this.trackFragmentIndexLoader.status,
|
|
45
|
+
this.initSegmentsLoader.status,
|
|
46
|
+
this.seekTask.status,
|
|
47
|
+
this.fetchSeekTask.status,
|
|
48
|
+
this.videoAssetTask.status,
|
|
49
|
+
this.paintTask.status
|
|
50
|
+
],
|
|
51
|
+
task: async () => {
|
|
52
|
+
await this.trackFragmentIndexLoader.taskComplete;
|
|
53
|
+
await this.initSegmentsLoader.taskComplete;
|
|
54
|
+
await this.seekTask.taskComplete;
|
|
55
|
+
await this.fetchSeekTask.taskComplete;
|
|
56
|
+
await this.videoAssetTask.taskComplete;
|
|
57
|
+
await this.paintTask.taskComplete;
|
|
58
|
+
this.rootTimegroup?.requestUpdate();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
this.paintTask = new Task(this, {
|
|
62
|
+
args: () => [this.videoAssetTask.value, this.desiredSeekTimeMs],
|
|
63
|
+
task: async ([videoAsset, seekToMs], {
|
|
64
|
+
signal: _signal
|
|
65
|
+
}) => {
|
|
66
|
+
if (!videoAsset) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (__privateGet(this, _decoderLock)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
__privateSet(this, _decoderLock, true);
|
|
74
|
+
const frame = await videoAsset.seekToTime(seekToMs / 1e3);
|
|
75
|
+
if (!this.canvasElement) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const ctx = this.canvasElement.getContext("2d");
|
|
79
|
+
if (!(frame && ctx)) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.canvasElement.width = frame?.codedWidth;
|
|
83
|
+
this.canvasElement.height = frame?.codedHeight;
|
|
84
|
+
ctx.drawImage(
|
|
85
|
+
frame,
|
|
86
|
+
0,
|
|
87
|
+
0,
|
|
88
|
+
this.canvasElement.width,
|
|
89
|
+
this.canvasElement.height
|
|
90
|
+
);
|
|
91
|
+
return seekToMs;
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.trace("Unexpected error while seeking video", error);
|
|
94
|
+
} finally {
|
|
95
|
+
__privateSet(this, _decoderLock, false);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
render() {
|
|
101
|
+
return html` <canvas
|
|
102
|
+
class="h-full w-full object-fill"
|
|
103
|
+
${ref(this.canvasRef)}
|
|
104
|
+
></canvas>`;
|
|
105
|
+
}
|
|
106
|
+
get canvasElement() {
|
|
107
|
+
return this.canvasRef.value;
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
_decoderLock = /* @__PURE__ */ new WeakMap();
|
|
111
|
+
EFVideo.styles = [
|
|
112
|
+
css`
|
|
113
|
+
:host {
|
|
114
|
+
display: block;
|
|
115
|
+
}
|
|
116
|
+
`
|
|
117
|
+
];
|
|
118
|
+
EFVideo = __decorateClass([
|
|
119
|
+
customElement("ef-video")
|
|
120
|
+
], EFVideo);
|
|
121
|
+
export {
|
|
122
|
+
EFVideo
|
|
123
|
+
};
|