@editframe/elements 0.6.0-beta.19 → 0.6.0-beta.22
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 +235 -0
- package/dist/packages/elements/src/elements/EFWaveform.d.ts +28 -0
- package/dist/packages/elements/src/elements/EFWaveform.js +219 -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/gui/EFFilmstrip.ts +3 -3
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { TaskStatus } from "@lit/task";
|
|
2
|
+
import { awaitMicrotask } from "../../../lib/util/awaitMicrotask.js";
|
|
3
|
+
import { deepGetElementsWithFrameTasks } from "./elements/EFTemporal.js";
|
|
4
|
+
import { shallowGetTimegroups } from "./elements/EFTimegroup.js";
|
|
5
|
+
class TriggerCanvas {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.canvas = document.createElement("canvas");
|
|
8
|
+
this.canvas.width = 1;
|
|
9
|
+
this.canvas.height = 1;
|
|
10
|
+
Object.assign(this.canvas.style, {
|
|
11
|
+
position: "fixed",
|
|
12
|
+
top: "0px",
|
|
13
|
+
left: "0px",
|
|
14
|
+
width: "1px",
|
|
15
|
+
height: "1px",
|
|
16
|
+
zIndex: "100000"
|
|
17
|
+
});
|
|
18
|
+
document.body.prepend(this.canvas);
|
|
19
|
+
const ctx = this.canvas.getContext("2d", { willReadFrequently: true });
|
|
20
|
+
if (!ctx) throw new Error("Canvas 2d context not ready");
|
|
21
|
+
this.ctx = ctx;
|
|
22
|
+
this.ctx.fillStyle = "black";
|
|
23
|
+
}
|
|
24
|
+
trigger() {
|
|
25
|
+
console.log("TRIGGERING CANVAS");
|
|
26
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
class EfFramegen {
|
|
30
|
+
constructor() {
|
|
31
|
+
this.time = 0;
|
|
32
|
+
this.frameDurationMs = 0;
|
|
33
|
+
this.initialBusyTasks = Promise.resolve([]);
|
|
34
|
+
this.frameBox = document.createElement("div");
|
|
35
|
+
this.BRIDGE = window.FRAMEGEN_BRIDGE;
|
|
36
|
+
this.triggerCanvas = new TriggerCanvas();
|
|
37
|
+
if (this.BRIDGE) {
|
|
38
|
+
this.connectToBridge();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
log(...args) {
|
|
42
|
+
console.log("[EF_FRAMEGEN]", ...args);
|
|
43
|
+
}
|
|
44
|
+
trace(...args) {
|
|
45
|
+
console.trace("[EF_FRAMEGEN]", ...args);
|
|
46
|
+
}
|
|
47
|
+
connectToBridge() {
|
|
48
|
+
const BRIDGE = this.BRIDGE;
|
|
49
|
+
if (!BRIDGE) {
|
|
50
|
+
throw new Error("No BRIDGE when attempting to connect to bridge");
|
|
51
|
+
}
|
|
52
|
+
BRIDGE.onInitialize(async (renderId, renderOptions) => {
|
|
53
|
+
this.log("BRIDGE.onInitialize", renderId, renderOptions);
|
|
54
|
+
await this.initialize(renderId, renderOptions);
|
|
55
|
+
BRIDGE.initialized(renderId);
|
|
56
|
+
});
|
|
57
|
+
BRIDGE.onBeginFrame((renderId, frameNumber, isLast) => {
|
|
58
|
+
this.log("BRIDGE.onBeginFrame", renderId, frameNumber, isLast);
|
|
59
|
+
this.beginFrame(renderId, frameNumber, isLast);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async initialize(renderId, renderOptions) {
|
|
63
|
+
addEventListener("unhandledrejection", (event) => {
|
|
64
|
+
this.trace("Unhandled rejection:", event.reason);
|
|
65
|
+
if (this.BRIDGE) {
|
|
66
|
+
this.BRIDGE.error(renderId, event.reason);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
addEventListener("error", (event) => {
|
|
70
|
+
this.trace("Uncaught error", event.error);
|
|
71
|
+
if (this.BRIDGE) {
|
|
72
|
+
this.BRIDGE.error(renderId, event.error);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
this.renderOptions = renderOptions;
|
|
76
|
+
const workbench = document.querySelector("ef-workbench");
|
|
77
|
+
if (!workbench) {
|
|
78
|
+
throw new Error("No workbench found");
|
|
79
|
+
}
|
|
80
|
+
workbench.rendering = true;
|
|
81
|
+
const timegroups = shallowGetTimegroups(workbench);
|
|
82
|
+
const temporals = deepGetElementsWithFrameTasks(workbench);
|
|
83
|
+
const firstGroup = timegroups[0];
|
|
84
|
+
if (!firstGroup) {
|
|
85
|
+
throw new Error("No temporal elements found");
|
|
86
|
+
}
|
|
87
|
+
firstGroup.currentTimeMs = renderOptions.encoderOptions.fromMs;
|
|
88
|
+
this.frameDurationMs = 1e3 / renderOptions.encoderOptions.video.framerate;
|
|
89
|
+
this.initialBusyTasks = Promise.all(
|
|
90
|
+
temporals.filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE).map((temporal) => temporal.frameTask).map((task) => task.taskComplete)
|
|
91
|
+
);
|
|
92
|
+
this.time = 0;
|
|
93
|
+
if (renderOptions.showFrameBox) {
|
|
94
|
+
Object.assign(this.frameBox.style, {
|
|
95
|
+
width: "200px",
|
|
96
|
+
height: "100px",
|
|
97
|
+
font: "30px Arial",
|
|
98
|
+
backgroundColor: "white",
|
|
99
|
+
position: "absolute",
|
|
100
|
+
top: "0px",
|
|
101
|
+
left: "0px",
|
|
102
|
+
zIndex: "100000"
|
|
103
|
+
});
|
|
104
|
+
document.body.prepend(this.frameBox);
|
|
105
|
+
}
|
|
106
|
+
this.audioBufferPromise = firstGroup.renderAudio(
|
|
107
|
+
renderOptions.encoderOptions.alignedFromUs / 1e3,
|
|
108
|
+
renderOptions.encoderOptions.alignedToUs / 1e3
|
|
109
|
+
// renderOptions.encoderOptions.fromMs,
|
|
110
|
+
// renderOptions.encoderOptions.toMs,
|
|
111
|
+
);
|
|
112
|
+
this.log("Initialized");
|
|
113
|
+
}
|
|
114
|
+
async beginFrame(renderId, frameNumber, isLast) {
|
|
115
|
+
if (this.renderOptions === void 0) {
|
|
116
|
+
throw new Error("No renderOptions");
|
|
117
|
+
}
|
|
118
|
+
if (this.renderOptions.showFrameBox) {
|
|
119
|
+
this.frameBox.innerHTML = `
|
|
120
|
+
<div>Frame #${frameNumber}</div>
|
|
121
|
+
<div>${this.time.toFixed(4)}</div>
|
|
122
|
+
`;
|
|
123
|
+
}
|
|
124
|
+
const workbench = document.querySelector("ef-workbench");
|
|
125
|
+
if (!workbench) {
|
|
126
|
+
throw new Error("No workbench found");
|
|
127
|
+
}
|
|
128
|
+
workbench.rendering = true;
|
|
129
|
+
const timegroups = shallowGetTimegroups(workbench);
|
|
130
|
+
const temporals = deepGetElementsWithFrameTasks(workbench);
|
|
131
|
+
const firstGroup = timegroups[0];
|
|
132
|
+
if (!firstGroup) {
|
|
133
|
+
throw new Error("No temporal elements found");
|
|
134
|
+
}
|
|
135
|
+
this.time = this.renderOptions.encoderOptions.fromMs + frameNumber * this.frameDurationMs;
|
|
136
|
+
firstGroup.currentTimeMs = this.time;
|
|
137
|
+
console.log("Awaiting initialBusyTasks");
|
|
138
|
+
await this.initialBusyTasks;
|
|
139
|
+
console.log("Awaiting microtask");
|
|
140
|
+
await awaitMicrotask();
|
|
141
|
+
console.log("Awaiting frame tasks");
|
|
142
|
+
const now = performance.now();
|
|
143
|
+
await Promise.all(
|
|
144
|
+
temporals.filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE).map((temporal) => {
|
|
145
|
+
return temporal.frameTask;
|
|
146
|
+
}).map((task) => task.taskComplete)
|
|
147
|
+
);
|
|
148
|
+
console.log(
|
|
149
|
+
`frame:${frameNumber} All tasks complete ${performance.now() - now}ms`
|
|
150
|
+
);
|
|
151
|
+
if (isLast && this.audioBufferPromise) {
|
|
152
|
+
const renderedAudio = await this.audioBufferPromise;
|
|
153
|
+
const channelCount = renderedAudio.numberOfChannels;
|
|
154
|
+
const interleavedSamples = new Float32Array(
|
|
155
|
+
channelCount * renderedAudio.length
|
|
156
|
+
);
|
|
157
|
+
for (let i = 0; i < renderedAudio.length; i++) {
|
|
158
|
+
for (let j = 0; j < channelCount; j++) {
|
|
159
|
+
interleavedSamples.set(
|
|
160
|
+
renderedAudio.getChannelData(j).slice(i, i + 1),
|
|
161
|
+
i * channelCount + j
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
if (this.BRIDGE) {
|
|
166
|
+
this.triggerCanvas.trigger();
|
|
167
|
+
this.BRIDGE.frameReady(
|
|
168
|
+
renderId,
|
|
169
|
+
frameNumber,
|
|
170
|
+
interleavedSamples.buffer
|
|
171
|
+
);
|
|
172
|
+
} else {
|
|
173
|
+
const fileReader = new FileReader();
|
|
174
|
+
fileReader.readAsDataURL(new Blob([interleavedSamples.buffer]));
|
|
175
|
+
await new Promise((resolve, reject) => {
|
|
176
|
+
fileReader.onload = resolve;
|
|
177
|
+
fileReader.onerror = reject;
|
|
178
|
+
});
|
|
179
|
+
return fileReader.result;
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
if (this.BRIDGE) {
|
|
183
|
+
this.triggerCanvas.trigger();
|
|
184
|
+
this.BRIDGE.frameReady(renderId, frameNumber, new ArrayBuffer(0));
|
|
185
|
+
} else {
|
|
186
|
+
const fileReader = new FileReader();
|
|
187
|
+
fileReader.readAsDataURL(new Blob([]));
|
|
188
|
+
await new Promise((resolve, reject) => {
|
|
189
|
+
fileReader.onload = resolve;
|
|
190
|
+
fileReader.onerror = reject;
|
|
191
|
+
});
|
|
192
|
+
return fileReader.result;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
window.EF_FRAMEGEN = new EfFramegen();
|
|
198
|
+
export {
|
|
199
|
+
EfFramegen
|
|
200
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const EF_INTERACTIVE: boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
class CrossUpdateController {
|
|
4
|
+
constructor(host, target) {
|
|
5
|
+
this.host = host;
|
|
6
|
+
this.target = target;
|
|
7
|
+
this.host.addController(this);
|
|
8
|
+
}
|
|
9
|
+
hostUpdate() {
|
|
10
|
+
this.target.requestUpdate();
|
|
11
|
+
}
|
|
12
|
+
remove() {
|
|
13
|
+
this.host.removeController(this);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.CrossUpdateController = CrossUpdateController;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { LitElement, ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
|
|
3
|
+
export declare class CrossUpdateController implements ReactiveController {
|
|
4
|
+
private host;
|
|
5
|
+
private target;
|
|
6
|
+
constructor(host: ReactiveControllerHost, target: LitElement);
|
|
7
|
+
hostUpdate(): void;
|
|
8
|
+
remove(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class CrossUpdateController {
|
|
2
|
+
constructor(host, target) {
|
|
3
|
+
this.host = host;
|
|
4
|
+
this.target = target;
|
|
5
|
+
this.host.addController(this);
|
|
6
|
+
}
|
|
7
|
+
hostUpdate() {
|
|
8
|
+
this.target.requestUpdate();
|
|
9
|
+
}
|
|
10
|
+
remove() {
|
|
11
|
+
this.host.removeController(this);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
CrossUpdateController
|
|
16
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const lit = require("lit");
|
|
4
|
+
const ref_js = require("lit/directives/ref.js");
|
|
5
|
+
const decorators_js = require("lit/decorators.js");
|
|
6
|
+
const EFMedia = require("./EFMedia.cjs");
|
|
7
|
+
const task = require("@lit/task");
|
|
8
|
+
var __defProp = Object.defineProperty;
|
|
9
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
10
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
11
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
12
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
13
|
+
if (decorator = decorators[i])
|
|
14
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
15
|
+
if (kind && result) __defProp(target, key, result);
|
|
16
|
+
return result;
|
|
17
|
+
};
|
|
18
|
+
exports.EFAudio = class EFAudio extends EFMedia.EFMedia {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments);
|
|
21
|
+
this.audioElementRef = ref_js.createRef();
|
|
22
|
+
this.src = "";
|
|
23
|
+
this.frameTask = new task.Task(this, {
|
|
24
|
+
args: () => [
|
|
25
|
+
this.trackFragmentIndexLoader.status,
|
|
26
|
+
this.initSegmentsLoader.status,
|
|
27
|
+
this.seekTask.status,
|
|
28
|
+
this.fetchSeekTask.status,
|
|
29
|
+
this.videoAssetTask.status
|
|
30
|
+
],
|
|
31
|
+
task: async () => {
|
|
32
|
+
await this.trackFragmentIndexLoader.taskComplete;
|
|
33
|
+
await this.initSegmentsLoader.taskComplete;
|
|
34
|
+
await this.seekTask.taskComplete;
|
|
35
|
+
await this.fetchSeekTask.taskComplete;
|
|
36
|
+
await this.videoAssetTask.taskComplete;
|
|
37
|
+
this.rootTimegroup?.requestUpdate();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
render() {
|
|
42
|
+
return lit.html`<audio ${ref_js.ref(this.audioElementRef)}></audio>`;
|
|
43
|
+
}
|
|
44
|
+
get audioElement() {
|
|
45
|
+
return this.audioElementRef.value;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
__decorateClass([
|
|
49
|
+
decorators_js.property({ type: String })
|
|
50
|
+
], exports.EFAudio.prototype, "src", 2);
|
|
51
|
+
exports.EFAudio = __decorateClass([
|
|
52
|
+
decorators_js.customElement("ef-audio")
|
|
53
|
+
], exports.EFAudio);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { EFMedia } from './EFMedia';
|
|
2
|
+
import { Task } from '@lit/task';
|
|
3
|
+
|
|
4
|
+
export declare class EFAudio extends EFMedia {
|
|
5
|
+
audioElementRef: import('lit-html/directives/ref').Ref<HTMLAudioElement>;
|
|
6
|
+
src: string;
|
|
7
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
8
|
+
get audioElement(): HTMLAudioElement | undefined;
|
|
9
|
+
frameTask: Task<readonly [import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus], void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { html } from "lit";
|
|
2
|
+
import { createRef, ref } from "lit/directives/ref.js";
|
|
3
|
+
import { property, customElement } from "lit/decorators.js";
|
|
4
|
+
import { EFMedia } from "./EFMedia.js";
|
|
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) __defProp(target, key, result);
|
|
14
|
+
return result;
|
|
15
|
+
};
|
|
16
|
+
let EFAudio = class extends EFMedia {
|
|
17
|
+
constructor() {
|
|
18
|
+
super(...arguments);
|
|
19
|
+
this.audioElementRef = createRef();
|
|
20
|
+
this.src = "";
|
|
21
|
+
this.frameTask = new Task(this, {
|
|
22
|
+
args: () => [
|
|
23
|
+
this.trackFragmentIndexLoader.status,
|
|
24
|
+
this.initSegmentsLoader.status,
|
|
25
|
+
this.seekTask.status,
|
|
26
|
+
this.fetchSeekTask.status,
|
|
27
|
+
this.videoAssetTask.status
|
|
28
|
+
],
|
|
29
|
+
task: async () => {
|
|
30
|
+
await this.trackFragmentIndexLoader.taskComplete;
|
|
31
|
+
await this.initSegmentsLoader.taskComplete;
|
|
32
|
+
await this.seekTask.taskComplete;
|
|
33
|
+
await this.fetchSeekTask.taskComplete;
|
|
34
|
+
await this.videoAssetTask.taskComplete;
|
|
35
|
+
this.rootTimegroup?.requestUpdate();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
render() {
|
|
40
|
+
return html`<audio ${ref(this.audioElementRef)}></audio>`;
|
|
41
|
+
}
|
|
42
|
+
get audioElement() {
|
|
43
|
+
return this.audioElementRef.value;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
__decorateClass([
|
|
47
|
+
property({ type: String })
|
|
48
|
+
], EFAudio.prototype, "src", 2);
|
|
49
|
+
EFAudio = __decorateClass([
|
|
50
|
+
customElement("ef-audio")
|
|
51
|
+
], EFAudio);
|
|
52
|
+
export {
|
|
53
|
+
EFAudio
|
|
54
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const EFAudio = require("./EFAudio.cjs");
|
|
4
|
+
const lit = require("lit");
|
|
5
|
+
const task = require("@lit/task");
|
|
6
|
+
const decorators_js = require("lit/decorators.js");
|
|
7
|
+
const EFVideo = require("./EFVideo.cjs");
|
|
8
|
+
const EFTemporal = require("./EFTemporal.cjs");
|
|
9
|
+
const CrossUpdateController = require("./CrossUpdateController.cjs");
|
|
10
|
+
const FetchMixin = require("./FetchMixin.cjs");
|
|
11
|
+
const EFSourceMixin = require("./EFSourceMixin.cjs");
|
|
12
|
+
const EF_INTERACTIVE = require("../EF_INTERACTIVE.cjs");
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
15
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
16
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
17
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
18
|
+
if (decorator = decorators[i])
|
|
19
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
20
|
+
if (kind && result) __defProp(target, key, result);
|
|
21
|
+
return result;
|
|
22
|
+
};
|
|
23
|
+
exports.EFCaptionsActiveWord = class EFCaptionsActiveWord extends EFTemporal.EFTemporal(lit.LitElement) {
|
|
24
|
+
constructor() {
|
|
25
|
+
super(...arguments);
|
|
26
|
+
this.wordStartMs = 0;
|
|
27
|
+
this.wordEndMs = 0;
|
|
28
|
+
this.wordText = "";
|
|
29
|
+
}
|
|
30
|
+
render() {
|
|
31
|
+
return lit.html`${this.wordText}`;
|
|
32
|
+
}
|
|
33
|
+
get startTimeMs() {
|
|
34
|
+
return this.wordStartMs || 0;
|
|
35
|
+
}
|
|
36
|
+
get durationMs() {
|
|
37
|
+
return this.wordEndMs - this.wordStartMs;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.EFCaptionsActiveWord.styles = [
|
|
41
|
+
lit.css`
|
|
42
|
+
:host {
|
|
43
|
+
display: inline-block;
|
|
44
|
+
}
|
|
45
|
+
`
|
|
46
|
+
];
|
|
47
|
+
__decorateClass([
|
|
48
|
+
decorators_js.property({ type: Number, attribute: false })
|
|
49
|
+
], exports.EFCaptionsActiveWord.prototype, "wordStartMs", 2);
|
|
50
|
+
__decorateClass([
|
|
51
|
+
decorators_js.property({ type: Number, attribute: false })
|
|
52
|
+
], exports.EFCaptionsActiveWord.prototype, "wordEndMs", 2);
|
|
53
|
+
__decorateClass([
|
|
54
|
+
decorators_js.property({ type: String, attribute: false })
|
|
55
|
+
], exports.EFCaptionsActiveWord.prototype, "wordText", 2);
|
|
56
|
+
exports.EFCaptionsActiveWord = __decorateClass([
|
|
57
|
+
decorators_js.customElement("ef-captions-active-word")
|
|
58
|
+
], exports.EFCaptionsActiveWord);
|
|
59
|
+
exports.EFCaptions = class EFCaptions extends EFSourceMixin.EFSourceMixin(
|
|
60
|
+
EFTemporal.EFTemporal(FetchMixin.FetchMixin(lit.LitElement)),
|
|
61
|
+
{ assetType: "caption_files" }
|
|
62
|
+
) {
|
|
63
|
+
constructor() {
|
|
64
|
+
super(...arguments);
|
|
65
|
+
this.target = null;
|
|
66
|
+
this.wordStyle = "";
|
|
67
|
+
this.activeWordContainers = this.getElementsByTagName("ef-captions-active-word");
|
|
68
|
+
this.md5SumLoader = new task.Task(this, {
|
|
69
|
+
autoRun: false,
|
|
70
|
+
args: () => [this.target],
|
|
71
|
+
task: async ([], { signal }) => {
|
|
72
|
+
const md5Path = `/@ef-asset/${this.targetElement.src ?? ""}`;
|
|
73
|
+
const response = await fetch(md5Path, { method: "HEAD", signal });
|
|
74
|
+
return response.headers.get("etag") ?? void 0;
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
this.captionsDataTask = new task.Task(this, {
|
|
78
|
+
autoRun: EF_INTERACTIVE.EF_INTERACTIVE,
|
|
79
|
+
args: () => [this.captionsPath(), this.fetch],
|
|
80
|
+
task: async ([captionsPath, fetch2], { signal }) => {
|
|
81
|
+
const response = await fetch2(captionsPath, { signal });
|
|
82
|
+
return response.json();
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
this.frameTask = new task.Task(this, {
|
|
86
|
+
autoRun: EF_INTERACTIVE.EF_INTERACTIVE,
|
|
87
|
+
args: () => [this.captionsDataTask.status],
|
|
88
|
+
task: async () => {
|
|
89
|
+
await this.captionsDataTask.taskComplete;
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
captionsPath() {
|
|
94
|
+
const targetSrc = this.targetElement.src;
|
|
95
|
+
if (targetSrc.startsWith("editframe://") || targetSrc.startsWith("http")) {
|
|
96
|
+
return targetSrc.replace("isobmff", "caption");
|
|
97
|
+
}
|
|
98
|
+
return `/@ef-captions/${targetSrc}`;
|
|
99
|
+
}
|
|
100
|
+
connectedCallback() {
|
|
101
|
+
super.connectedCallback();
|
|
102
|
+
if (this.targetElement) {
|
|
103
|
+
new CrossUpdateController.CrossUpdateController(this.targetElement, this);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
render() {
|
|
107
|
+
return this.captionsDataTask.render({
|
|
108
|
+
pending: () => lit.html`<div>Generating captions data...</div>`,
|
|
109
|
+
error: () => lit.html`<div>🚫 Error generating captions data</div>`,
|
|
110
|
+
complete: () => lit.html`<slot></slot>`
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
updated(_changedProperties) {
|
|
114
|
+
this.updateActiveWord();
|
|
115
|
+
}
|
|
116
|
+
updateActiveWord() {
|
|
117
|
+
const caption = this.captionsDataTask.value;
|
|
118
|
+
if (!caption) {
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
const words = [];
|
|
122
|
+
let startMs = 0;
|
|
123
|
+
let endMs = 0;
|
|
124
|
+
for (const segment of caption.segments) {
|
|
125
|
+
if (this.targetElement.ownCurrentTimeMs >= segment.start * 1e3 && this.targetElement.ownCurrentTimeMs <= segment.end * 1e3) {
|
|
126
|
+
for (const word of segment.words) {
|
|
127
|
+
if (this.targetElement.ownCurrentTimeMs >= word.start * 1e3 && this.targetElement.ownCurrentTimeMs <= word.end * 1e3) {
|
|
128
|
+
words.push(word.text);
|
|
129
|
+
startMs = word.start * 1e3;
|
|
130
|
+
endMs = word.end * 1e3;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const container of Array.from(this.activeWordContainers)) {
|
|
136
|
+
container.wordText = words.join(" ");
|
|
137
|
+
container.wordStartMs = startMs;
|
|
138
|
+
container.wordEndMs = endMs;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
get targetElement() {
|
|
142
|
+
const target = document.querySelector(this.getAttribute("target") ?? "");
|
|
143
|
+
if (target instanceof EFAudio.EFAudio || target instanceof EFVideo.EFVideo) {
|
|
144
|
+
return target;
|
|
145
|
+
}
|
|
146
|
+
throw new Error("Invalid target, must be an EFAudio or EFVideo element");
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
exports.EFCaptions.styles = [
|
|
150
|
+
lit.css`
|
|
151
|
+
:host {
|
|
152
|
+
display: block;
|
|
153
|
+
}
|
|
154
|
+
`
|
|
155
|
+
];
|
|
156
|
+
__decorateClass([
|
|
157
|
+
decorators_js.property({ type: String, attribute: "target" })
|
|
158
|
+
], exports.EFCaptions.prototype, "target", 2);
|
|
159
|
+
__decorateClass([
|
|
160
|
+
decorators_js.property({ attribute: "word-style" })
|
|
161
|
+
], exports.EFCaptions.prototype, "wordStyle", 2);
|
|
162
|
+
exports.EFCaptions = __decorateClass([
|
|
163
|
+
decorators_js.customElement("ef-captions")
|
|
164
|
+
], exports.EFCaptions);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { EFAudio } from './EFAudio';
|
|
2
|
+
import { LitElement, PropertyValueMap } from 'lit';
|
|
3
|
+
import { Task } from '@lit/task';
|
|
4
|
+
import { EFVideo } from './EFVideo';
|
|
5
|
+
|
|
6
|
+
declare const EFCaptionsActiveWord_base: (new (...args: any[]) => import('./EFTemporal').TemporalMixinInterface) & typeof LitElement;
|
|
7
|
+
export declare class EFCaptionsActiveWord extends EFCaptionsActiveWord_base {
|
|
8
|
+
static styles: import('lit').CSSResult[];
|
|
9
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
10
|
+
wordStartMs: number;
|
|
11
|
+
wordEndMs: number;
|
|
12
|
+
wordText: string;
|
|
13
|
+
get startTimeMs(): number;
|
|
14
|
+
get durationMs(): number;
|
|
15
|
+
}
|
|
16
|
+
declare const EFCaptions_base: (new (...args: any[]) => import('./EFSourceMixin').EFSourceMixinInterface) & (new (...args: any[]) => import('./EFTemporal').TemporalMixinInterface) & (new (...args: any[]) => import('./FetchMixin').FetchMixinInterface) & typeof LitElement;
|
|
17
|
+
export declare class EFCaptions extends EFCaptions_base {
|
|
18
|
+
static styles: import('lit').CSSResult[];
|
|
19
|
+
target: null;
|
|
20
|
+
wordStyle: string;
|
|
21
|
+
activeWordContainers: HTMLCollectionOf<EFCaptionsActiveWord>;
|
|
22
|
+
captionsPath(): string;
|
|
23
|
+
protected md5SumLoader: Task<readonly [null], string | undefined>;
|
|
24
|
+
private captionsDataTask;
|
|
25
|
+
frameTask: Task<import('@lit/task').TaskStatus[], void>;
|
|
26
|
+
connectedCallback(): void;
|
|
27
|
+
render(): import('lit-html').TemplateResult<1> | undefined;
|
|
28
|
+
protected updated(_changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
29
|
+
updateActiveWord(): void;
|
|
30
|
+
get targetElement(): EFAudio | EFVideo;
|
|
31
|
+
}
|
|
32
|
+
declare global {
|
|
33
|
+
interface HTMLElementTagNameMap {
|
|
34
|
+
"ef-captions": EFCaptions;
|
|
35
|
+
"ef-captions-active-word": EFCaptionsActiveWord;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export {};
|