@editframe/elements 0.5.0-beta.8 → 0.6.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 +561 -0
- package/dist/{editor/util/EncodedAsset/EncodedAsset.mjs → lib/av/EncodedAsset.js} +40 -33
- package/dist/lib/av/MP4File.cjs +182 -0
- package/dist/{editor/util/MP4File.mjs → lib/av/MP4File.js} +55 -51
- package/dist/lib/av/msToTimeCode.cjs +15 -0
- package/dist/lib/util/awaitMicrotask.cjs +8 -0
- package/dist/lib/util/memoize.cjs +14 -0
- package/dist/{util/memoize.mjs → lib/util/memoize.js} +1 -2
- package/dist/packages/elements/src/EF_FRAMEGEN.cjs +197 -0
- package/dist/packages/elements/src/EF_FRAMEGEN.d.ts +45 -0
- package/dist/packages/elements/src/EF_FRAMEGEN.js +197 -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/elements/CrossUpdateController.cjs +16 -0
- package/dist/packages/elements/src/elements/CrossUpdateController.d.ts +9 -0
- package/dist/packages/elements/src/elements/EFAudio.cjs +53 -0
- package/dist/packages/elements/src/elements/EFAudio.d.ts +10 -0
- package/dist/{elements/src/elements/EFAudio.mjs → packages/elements/src/elements/EFAudio.js} +2 -5
- package/dist/packages/elements/src/elements/EFCaptions.cjs +171 -0
- package/dist/packages/elements/src/elements/EFCaptions.d.ts +39 -0
- package/dist/{elements/src/elements/EFCaptions.mjs → packages/elements/src/elements/EFCaptions.js} +18 -20
- package/dist/packages/elements/src/elements/EFImage.cjs +79 -0
- package/dist/packages/elements/src/elements/EFImage.d.ts +14 -0
- package/dist/{elements/src/elements/EFImage.mjs → packages/elements/src/elements/EFImage.js} +8 -7
- package/dist/packages/elements/src/elements/EFMedia.cjs +334 -0
- package/dist/packages/elements/src/elements/EFMedia.d.ts +61 -0
- package/dist/{elements/src/elements/EFMedia.mjs → packages/elements/src/elements/EFMedia.js} +40 -38
- package/dist/packages/elements/src/elements/EFSourceMixin.cjs +55 -0
- package/dist/packages/elements/src/elements/EFSourceMixin.d.ts +12 -0
- package/dist/{elements/src/elements/EFSourceMixin.mjs → packages/elements/src/elements/EFSourceMixin.js} +6 -8
- package/dist/packages/elements/src/elements/EFTemporal.cjs +198 -0
- package/dist/packages/elements/src/elements/EFTemporal.d.ts +36 -0
- package/dist/{elements/src/elements/EFTemporal.mjs → packages/elements/src/elements/EFTemporal.js} +6 -22
- package/dist/packages/elements/src/elements/EFTimegroup.browsertest.d.ts +12 -0
- package/{src/elements/EFTimegroup.ts → dist/packages/elements/src/elements/EFTimegroup.cjs} +162 -213
- package/dist/packages/elements/src/elements/EFTimegroup.d.ts +39 -0
- package/dist/{elements/src/elements/EFTimegroup.mjs → packages/elements/src/elements/EFTimegroup.js} +55 -65
- package/{src/elements/EFTimeline.ts → dist/packages/elements/src/elements/EFTimeline.cjs} +5 -3
- package/dist/packages/elements/src/elements/EFTimeline.d.ts +3 -0
- package/dist/{elements/src/elements/EFTimeline.mjs → packages/elements/src/elements/EFTimeline.js} +5 -2
- package/dist/packages/elements/src/elements/EFVideo.cjs +110 -0
- package/dist/packages/elements/src/elements/EFVideo.d.ts +14 -0
- package/dist/{elements/src/elements/EFVideo.mjs → packages/elements/src/elements/EFVideo.js} +10 -32
- package/dist/packages/elements/src/elements/EFWaveform.cjs +235 -0
- package/dist/packages/elements/src/elements/EFWaveform.d.ts +28 -0
- package/dist/{elements/src/elements/EFWaveform.mjs → packages/elements/src/elements/EFWaveform.js} +15 -16
- package/dist/packages/elements/src/elements/FetchMixin.cjs +28 -0
- package/dist/packages/elements/src/elements/FetchMixin.d.ts +8 -0
- package/dist/{elements/src/elements/FetchMixin.mjs → packages/elements/src/elements/FetchMixin.js} +5 -7
- 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/durationConverter.cjs +8 -0
- package/dist/packages/elements/src/elements/durationConverter.d.ts +4 -0
- package/dist/{elements/src/elements/durationConverter.mjs → packages/elements/src/elements/durationConverter.js} +1 -1
- 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/{elements/src/elements/util.mjs → packages/elements/src/elements/util.js} +1 -1
- package/dist/packages/elements/src/gui/EFFilmstrip.cjs +675 -0
- package/dist/packages/elements/src/gui/EFFilmstrip.d.ts +138 -0
- package/dist/{elements/src/gui/EFFilmstrip.mjs → packages/elements/src/gui/EFFilmstrip.js} +57 -55
- package/dist/packages/elements/src/gui/EFWorkbench.cjs +199 -0
- package/dist/packages/elements/src/gui/EFWorkbench.d.ts +44 -0
- package/dist/{elements/src/gui/EFWorkbench.mjs → packages/elements/src/gui/EFWorkbench.js} +27 -49
- package/{src/gui/TWMixin.ts → dist/packages/elements/src/gui/TWMixin.cjs} +11 -10
- 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/{elements/src/gui/TWMixin.mjs → packages/elements/src/gui/TWMixin.js} +4 -3
- package/dist/packages/elements/src/index.cjs +47 -0
- package/dist/packages/elements/src/index.d.ts +10 -0
- package/dist/packages/elements/src/index.js +23 -0
- package/dist/style.css +13 -4
- package/package.json +23 -4
- package/dist/elements/src/EF_FRAMEGEN.mjs +0 -130
- package/dist/elements/src/elements/parseTimeToMs.mjs +0 -13
- package/dist/elements/src/elements.mjs +0 -12
- package/dist/elements/src/gui/TWMixin.css.mjs +0 -4
- package/dist/util/awaitAnimationFrame.mjs +0 -11
- package/docker-compose.yaml +0 -17
- package/src/EF_FRAMEGEN.ts +0 -208
- package/src/EF_INTERACTIVE.ts +0 -2
- package/src/elements/CrossUpdateController.ts +0 -18
- package/src/elements/EFAudio.ts +0 -42
- package/src/elements/EFCaptions.ts +0 -202
- package/src/elements/EFImage.ts +0 -70
- package/src/elements/EFMedia.ts +0 -395
- package/src/elements/EFSourceMixin.ts +0 -57
- package/src/elements/EFTemporal.ts +0 -246
- package/src/elements/EFTimegroup.browsertest.ts +0 -360
- package/src/elements/EFVideo.ts +0 -114
- package/src/elements/EFWaveform.ts +0 -407
- package/src/elements/FetchMixin.ts +0 -18
- package/src/elements/TimegroupController.ts +0 -25
- package/src/elements/buildLitFixture.ts +0 -13
- package/src/elements/durationConverter.ts +0 -6
- package/src/elements/parseTimeToMs.ts +0 -10
- package/src/elements/util.ts +0 -24
- package/src/gui/EFFilmstrip.ts +0 -702
- package/src/gui/EFWorkbench.ts +0 -242
- package/src/gui/TWMixin.css +0 -3
- package/src/util.d.ts +0 -1
- /package/dist/{editor/msToTimeCode.mjs → lib/av/msToTimeCode.js} +0 -0
- /package/dist/{util/awaitMicrotask.mjs → lib/util/awaitMicrotask.js} +0 -0
- /package/dist/{elements/src/EF_INTERACTIVE.mjs → packages/elements/src/EF_INTERACTIVE.js} +0 -0
- /package/dist/{elements/src/elements/CrossUpdateController.mjs → packages/elements/src/elements/CrossUpdateController.js} +0 -0
- /package/dist/{elements/src/elements/TimegroupController.mjs → packages/elements/src/elements/TimegroupController.js} +0 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const task = require("@lit/task");
|
|
4
|
+
const awaitMicrotask = require("../../../lib/util/awaitMicrotask.cjs");
|
|
5
|
+
const EFTemporal = require("./elements/EFTemporal.cjs");
|
|
6
|
+
const EFTimegroup = require("./elements/EFTimegroup.cjs");
|
|
7
|
+
class TriggerCanvas {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.canvas = document.createElement("canvas");
|
|
10
|
+
this.canvas.width = 1;
|
|
11
|
+
this.canvas.height = 1;
|
|
12
|
+
Object.assign(this.canvas.style, {
|
|
13
|
+
position: "fixed",
|
|
14
|
+
top: "0px",
|
|
15
|
+
left: "0px",
|
|
16
|
+
width: "1px",
|
|
17
|
+
height: "1px",
|
|
18
|
+
zIndex: "100000"
|
|
19
|
+
});
|
|
20
|
+
document.body.prepend(this.canvas);
|
|
21
|
+
const ctx = this.canvas.getContext("2d", { willReadFrequently: true });
|
|
22
|
+
if (!ctx) throw new Error("Canvas 2d context not ready");
|
|
23
|
+
this.ctx = ctx;
|
|
24
|
+
this.ctx.fillStyle = "black";
|
|
25
|
+
}
|
|
26
|
+
trigger() {
|
|
27
|
+
console.log("TRIGGERING CANVAS");
|
|
28
|
+
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class EfFramegen {
|
|
32
|
+
constructor() {
|
|
33
|
+
this.time = 0;
|
|
34
|
+
this.frameDurationMs = 0;
|
|
35
|
+
this.initialBusyTasks = Promise.resolve([]);
|
|
36
|
+
this.frameBox = document.createElement("div");
|
|
37
|
+
this.BRIDGE = window.FRAMEGEN_BRIDGE;
|
|
38
|
+
this.triggerCanvas = new TriggerCanvas();
|
|
39
|
+
if (this.BRIDGE) {
|
|
40
|
+
this.connectToBridge();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
log(...args) {
|
|
44
|
+
console.log("[EF_FRAMEGEN]", ...args);
|
|
45
|
+
}
|
|
46
|
+
trace(...args) {
|
|
47
|
+
console.trace("[EF_FRAMEGEN]", ...args);
|
|
48
|
+
}
|
|
49
|
+
connectToBridge() {
|
|
50
|
+
const BRIDGE = this.BRIDGE;
|
|
51
|
+
if (!BRIDGE) {
|
|
52
|
+
throw new Error("No BRIDGE when attempting to connect to bridge");
|
|
53
|
+
}
|
|
54
|
+
BRIDGE.onInitialize(async (renderId, renderOptions) => {
|
|
55
|
+
this.log("BRIDGE.onInitialize", renderId, renderOptions);
|
|
56
|
+
await this.initialize(renderId, renderOptions);
|
|
57
|
+
BRIDGE.initialized(renderId);
|
|
58
|
+
});
|
|
59
|
+
BRIDGE.onBeginFrame((renderId, frameNumber, isLast) => {
|
|
60
|
+
this.log("BRIDGE.onBeginFrame", renderId, frameNumber, isLast);
|
|
61
|
+
this.beginFrame(renderId, frameNumber, isLast);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async initialize(renderId, renderOptions) {
|
|
65
|
+
addEventListener("unhandledrejection", (event) => {
|
|
66
|
+
this.trace("Unhandled rejection:", event.reason);
|
|
67
|
+
if (this.BRIDGE) {
|
|
68
|
+
this.BRIDGE.error(renderId, event.reason);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
addEventListener("error", (event) => {
|
|
72
|
+
this.trace("Uncaught error", event.error);
|
|
73
|
+
if (this.BRIDGE) {
|
|
74
|
+
this.BRIDGE.error(renderId, event.error);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
this.renderOptions = renderOptions;
|
|
78
|
+
const workbench = document.querySelector("ef-workbench");
|
|
79
|
+
if (!workbench) {
|
|
80
|
+
throw new Error("No workbench found");
|
|
81
|
+
}
|
|
82
|
+
workbench.rendering = true;
|
|
83
|
+
const timegroups = EFTimegroup.shallowGetTimegroups(workbench);
|
|
84
|
+
const temporals = EFTemporal.deepGetElementsWithFrameTasks(workbench);
|
|
85
|
+
const firstGroup = timegroups[0];
|
|
86
|
+
if (!firstGroup) {
|
|
87
|
+
throw new Error("No temporal elements found");
|
|
88
|
+
}
|
|
89
|
+
firstGroup.currentTimeMs = renderOptions.encoderOptions.fromMs;
|
|
90
|
+
this.frameDurationMs = 1e3 / renderOptions.encoderOptions.video.framerate;
|
|
91
|
+
this.initialBusyTasks = Promise.all(
|
|
92
|
+
temporals.filter((temporal) => temporal.frameTask.status < task.TaskStatus.COMPLETE).map((temporal) => temporal.frameTask).map((task2) => task2.taskComplete)
|
|
93
|
+
);
|
|
94
|
+
this.time = 0;
|
|
95
|
+
if (renderOptions.showFrameBox) {
|
|
96
|
+
Object.assign(this.frameBox.style, {
|
|
97
|
+
width: "200px",
|
|
98
|
+
height: "100px",
|
|
99
|
+
font: "30px Arial",
|
|
100
|
+
backgroundColor: "white",
|
|
101
|
+
position: "absolute",
|
|
102
|
+
top: "0px",
|
|
103
|
+
left: "0px",
|
|
104
|
+
zIndex: "100000"
|
|
105
|
+
});
|
|
106
|
+
document.body.prepend(this.frameBox);
|
|
107
|
+
}
|
|
108
|
+
this.audioBufferPromise = firstGroup.renderAudio(
|
|
109
|
+
renderOptions.encoderOptions.alignedFromUs / 1e3,
|
|
110
|
+
renderOptions.encoderOptions.alignedToUs / 1e3
|
|
111
|
+
// renderOptions.encoderOptions.fromMs,
|
|
112
|
+
// renderOptions.encoderOptions.toMs,
|
|
113
|
+
);
|
|
114
|
+
this.log("Initialized");
|
|
115
|
+
}
|
|
116
|
+
async beginFrame(renderId, frameNumber, isLast) {
|
|
117
|
+
if (this.renderOptions === void 0) {
|
|
118
|
+
throw new Error("No renderOptions");
|
|
119
|
+
}
|
|
120
|
+
if (this.renderOptions.showFrameBox) {
|
|
121
|
+
this.frameBox.innerHTML = `
|
|
122
|
+
<div>Frame #${frameNumber}</div>
|
|
123
|
+
<div>${this.time.toFixed(4)}</div>
|
|
124
|
+
`;
|
|
125
|
+
}
|
|
126
|
+
const workbench = document.querySelector("ef-workbench");
|
|
127
|
+
if (!workbench) {
|
|
128
|
+
throw new Error("No workbench found");
|
|
129
|
+
}
|
|
130
|
+
workbench.rendering = true;
|
|
131
|
+
const timegroups = EFTimegroup.shallowGetTimegroups(workbench);
|
|
132
|
+
const temporals = EFTemporal.deepGetElementsWithFrameTasks(workbench);
|
|
133
|
+
const firstGroup = timegroups[0];
|
|
134
|
+
if (!firstGroup) {
|
|
135
|
+
throw new Error("No temporal elements found");
|
|
136
|
+
}
|
|
137
|
+
this.time = this.renderOptions.encoderOptions.fromMs + frameNumber * this.frameDurationMs;
|
|
138
|
+
firstGroup.currentTimeMs = this.time;
|
|
139
|
+
await this.initialBusyTasks;
|
|
140
|
+
await awaitMicrotask.awaitMicrotask();
|
|
141
|
+
const now = performance.now();
|
|
142
|
+
await Promise.all(
|
|
143
|
+
temporals.filter((temporal) => temporal.frameTask.status < task.TaskStatus.COMPLETE).map((temporal) => {
|
|
144
|
+
return temporal.frameTask;
|
|
145
|
+
}).map((task2) => task2.taskComplete)
|
|
146
|
+
);
|
|
147
|
+
console.log(
|
|
148
|
+
`frame:${frameNumber} All tasks complete ${performance.now() - now}ms`
|
|
149
|
+
);
|
|
150
|
+
if (isLast && this.audioBufferPromise) {
|
|
151
|
+
const renderedAudio = await this.audioBufferPromise;
|
|
152
|
+
const channelCount = renderedAudio.numberOfChannels;
|
|
153
|
+
const interleavedSamples = new Float32Array(
|
|
154
|
+
channelCount * renderedAudio.length
|
|
155
|
+
);
|
|
156
|
+
for (let i = 0; i < renderedAudio.length; i++) {
|
|
157
|
+
for (let j = 0; j < channelCount; j++) {
|
|
158
|
+
interleavedSamples.set(
|
|
159
|
+
renderedAudio.getChannelData(j).slice(i, i + 1),
|
|
160
|
+
i * channelCount + j
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
if (this.BRIDGE) {
|
|
165
|
+
this.triggerCanvas.trigger();
|
|
166
|
+
this.BRIDGE.frameReady(
|
|
167
|
+
renderId,
|
|
168
|
+
frameNumber,
|
|
169
|
+
interleavedSamples.buffer
|
|
170
|
+
);
|
|
171
|
+
} else {
|
|
172
|
+
const fileReader = new FileReader();
|
|
173
|
+
fileReader.readAsDataURL(new Blob([interleavedSamples.buffer]));
|
|
174
|
+
await new Promise((resolve, reject) => {
|
|
175
|
+
fileReader.onload = resolve;
|
|
176
|
+
fileReader.onerror = reject;
|
|
177
|
+
});
|
|
178
|
+
return fileReader.result;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
if (this.BRIDGE) {
|
|
182
|
+
this.triggerCanvas.trigger();
|
|
183
|
+
this.BRIDGE.frameReady(renderId, frameNumber, new ArrayBuffer(0));
|
|
184
|
+
} else {
|
|
185
|
+
const fileReader = new FileReader();
|
|
186
|
+
fileReader.readAsDataURL(new Blob([]));
|
|
187
|
+
await new Promise((resolve, reject) => {
|
|
188
|
+
fileReader.onload = resolve;
|
|
189
|
+
fileReader.onerror = reject;
|
|
190
|
+
});
|
|
191
|
+
return fileReader.result;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
window.EF_FRAMEGEN = new EfFramegen();
|
|
197
|
+
exports.EfFramegen = EfFramegen;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { VideoRenderOptions } from '../../assets';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
EF_FRAMEGEN?: EfFramegen;
|
|
6
|
+
FRAMEGEN_BRIDGE?: {
|
|
7
|
+
onInitialize: (callback: (renderId: string, renderOptions: VideoRenderOptions) => void) => void;
|
|
8
|
+
initialized(renderId: string): void;
|
|
9
|
+
onBeginFrame(callback: (renderId: string, frameNumber: number, isLast: boolean) => void): void;
|
|
10
|
+
onTriggerCanvas(callback: () => void): void;
|
|
11
|
+
frameReady(renderId: string, frameNumber: number, audioSamples: ArrayBuffer): void;
|
|
12
|
+
error(renderId: string, error: Error): void;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
declare class TriggerCanvas {
|
|
17
|
+
private canvas;
|
|
18
|
+
private ctx;
|
|
19
|
+
constructor();
|
|
20
|
+
trigger(): void;
|
|
21
|
+
}
|
|
22
|
+
export declare class EfFramegen {
|
|
23
|
+
time: number;
|
|
24
|
+
frameDurationMs: number;
|
|
25
|
+
initialBusyTasks: Promise<unknown[]>;
|
|
26
|
+
audioBufferPromise?: Promise<AudioBuffer>;
|
|
27
|
+
renderOptions?: VideoRenderOptions;
|
|
28
|
+
frameBox: HTMLDivElement;
|
|
29
|
+
BRIDGE: {
|
|
30
|
+
onInitialize: (callback: (renderId: string, renderOptions: VideoRenderOptions) => void) => void;
|
|
31
|
+
initialized(renderId: string): void;
|
|
32
|
+
onBeginFrame(callback: (renderId: string, frameNumber: number, isLast: boolean) => void): void;
|
|
33
|
+
onTriggerCanvas(callback: () => void): void;
|
|
34
|
+
frameReady(renderId: string, frameNumber: number, audioSamples: ArrayBuffer): void;
|
|
35
|
+
error(renderId: string, error: Error): void;
|
|
36
|
+
} | undefined;
|
|
37
|
+
triggerCanvas: TriggerCanvas;
|
|
38
|
+
log(...args: any[]): void;
|
|
39
|
+
trace(...args: any[]): void;
|
|
40
|
+
constructor();
|
|
41
|
+
connectToBridge(): void;
|
|
42
|
+
initialize(renderId: string, renderOptions: VideoRenderOptions): Promise<void>;
|
|
43
|
+
beginFrame(renderId: string, frameNumber: number, isLast: boolean): Promise<string | ArrayBuffer | null | undefined>;
|
|
44
|
+
}
|
|
45
|
+
export {};
|
|
@@ -0,0 +1,197 @@
|
|
|
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
|
+
await this.initialBusyTasks;
|
|
138
|
+
await awaitMicrotask();
|
|
139
|
+
const now = performance.now();
|
|
140
|
+
await Promise.all(
|
|
141
|
+
temporals.filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE).map((temporal) => {
|
|
142
|
+
return temporal.frameTask;
|
|
143
|
+
}).map((task) => task.taskComplete)
|
|
144
|
+
);
|
|
145
|
+
console.log(
|
|
146
|
+
`frame:${frameNumber} All tasks complete ${performance.now() - now}ms`
|
|
147
|
+
);
|
|
148
|
+
if (isLast && this.audioBufferPromise) {
|
|
149
|
+
const renderedAudio = await this.audioBufferPromise;
|
|
150
|
+
const channelCount = renderedAudio.numberOfChannels;
|
|
151
|
+
const interleavedSamples = new Float32Array(
|
|
152
|
+
channelCount * renderedAudio.length
|
|
153
|
+
);
|
|
154
|
+
for (let i = 0; i < renderedAudio.length; i++) {
|
|
155
|
+
for (let j = 0; j < channelCount; j++) {
|
|
156
|
+
interleavedSamples.set(
|
|
157
|
+
renderedAudio.getChannelData(j).slice(i, i + 1),
|
|
158
|
+
i * channelCount + j
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (this.BRIDGE) {
|
|
163
|
+
this.triggerCanvas.trigger();
|
|
164
|
+
this.BRIDGE.frameReady(
|
|
165
|
+
renderId,
|
|
166
|
+
frameNumber,
|
|
167
|
+
interleavedSamples.buffer
|
|
168
|
+
);
|
|
169
|
+
} else {
|
|
170
|
+
const fileReader = new FileReader();
|
|
171
|
+
fileReader.readAsDataURL(new Blob([interleavedSamples.buffer]));
|
|
172
|
+
await new Promise((resolve, reject) => {
|
|
173
|
+
fileReader.onload = resolve;
|
|
174
|
+
fileReader.onerror = reject;
|
|
175
|
+
});
|
|
176
|
+
return fileReader.result;
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
if (this.BRIDGE) {
|
|
180
|
+
this.triggerCanvas.trigger();
|
|
181
|
+
this.BRIDGE.frameReady(renderId, frameNumber, new ArrayBuffer(0));
|
|
182
|
+
} else {
|
|
183
|
+
const fileReader = new FileReader();
|
|
184
|
+
fileReader.readAsDataURL(new Blob([]));
|
|
185
|
+
await new Promise((resolve, reject) => {
|
|
186
|
+
fileReader.onload = resolve;
|
|
187
|
+
fileReader.onerror = reject;
|
|
188
|
+
});
|
|
189
|
+
return fileReader.result;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
window.EF_FRAMEGEN = new EfFramegen();
|
|
195
|
+
export {
|
|
196
|
+
EfFramegen
|
|
197
|
+
};
|
|
@@ -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,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
|
+
}
|
package/dist/{elements/src/elements/EFAudio.mjs → packages/elements/src/elements/EFAudio.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { html } from "lit";
|
|
2
2
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
3
3
|
import { property, customElement } from "lit/decorators.js";
|
|
4
|
-
import { EFMedia } from "./EFMedia.
|
|
4
|
+
import { EFMedia } from "./EFMedia.js";
|
|
5
5
|
import { Task } from "@lit/task";
|
|
6
6
|
var __defProp = Object.defineProperty;
|
|
7
7
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -10,8 +10,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
10
10
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
11
11
|
if (decorator = decorators[i])
|
|
12
12
|
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
13
|
-
if (kind && result)
|
|
14
|
-
__defProp(target, key, result);
|
|
13
|
+
if (kind && result) __defProp(target, key, result);
|
|
15
14
|
return result;
|
|
16
15
|
};
|
|
17
16
|
let EFAudio = class extends EFMedia {
|
|
@@ -28,13 +27,11 @@ let EFAudio = class extends EFMedia {
|
|
|
28
27
|
this.videoAssetTask.status
|
|
29
28
|
],
|
|
30
29
|
task: async () => {
|
|
31
|
-
console.log("EFAudio frameTask", this.ownCurrentTimeMs);
|
|
32
30
|
await this.trackFragmentIndexLoader.taskComplete;
|
|
33
31
|
await this.initSegmentsLoader.taskComplete;
|
|
34
32
|
await this.seekTask.taskComplete;
|
|
35
33
|
await this.fetchSeekTask.taskComplete;
|
|
36
34
|
await this.videoAssetTask.taskComplete;
|
|
37
|
-
console.log("EFAudio frameTask complete", this.ownCurrentTimeMs);
|
|
38
35
|
this.rootTimegroup?.requestUpdate();
|
|
39
36
|
}
|
|
40
37
|
});
|