@editframe/elements 0.20.4-beta.0 → 0.21.0-beta.0
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/DelayedLoadingState.js +0 -27
- package/dist/EF_FRAMEGEN.d.ts +5 -3
- package/dist/EF_FRAMEGEN.js +50 -11
- package/dist/_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js +7 -0
- package/dist/elements/ContextProxiesController.js +2 -22
- package/dist/elements/EFAudio.js +4 -8
- package/dist/elements/EFCaptions.js +59 -84
- package/dist/elements/EFImage.js +5 -6
- package/dist/elements/EFMedia/AssetIdMediaEngine.js +2 -4
- package/dist/elements/EFMedia/AssetMediaEngine.js +35 -30
- package/dist/elements/EFMedia/BaseMediaEngine.js +57 -73
- package/dist/elements/EFMedia/BufferedSeekingInput.js +134 -76
- package/dist/elements/EFMedia/JitMediaEngine.js +9 -19
- package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +3 -6
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +6 -5
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +1 -3
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +1 -1
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +1 -1
- package/dist/elements/EFMedia/shared/AudioSpanUtils.js +4 -16
- package/dist/elements/EFMedia/shared/BufferUtils.js +2 -15
- package/dist/elements/EFMedia/shared/GlobalInputCache.js +0 -24
- package/dist/elements/EFMedia/shared/PrecisionUtils.js +0 -21
- package/dist/elements/EFMedia/shared/ThumbnailExtractor.js +0 -17
- package/dist/elements/EFMedia/tasks/makeMediaEngineTask.js +1 -10
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.d.ts +29 -0
- package/dist/elements/EFMedia/videoTasks/MainVideoInputCache.js +32 -0
- package/dist/elements/EFMedia/videoTasks/ScrubInputCache.js +1 -15
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +1 -7
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoInputTask.js +8 -5
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.js +12 -13
- package/dist/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.js +1 -1
- package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +134 -70
- package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +7 -11
- package/dist/elements/EFMedia.js +26 -24
- package/dist/elements/EFSourceMixin.js +5 -7
- package/dist/elements/EFSurface.js +6 -9
- package/dist/elements/EFTemporal.js +19 -37
- package/dist/elements/EFThumbnailStrip.js +16 -59
- package/dist/elements/EFTimegroup.js +95 -90
- package/dist/elements/EFVideo.d.ts +6 -2
- package/dist/elements/EFVideo.js +142 -107
- package/dist/elements/EFWaveform.js +18 -27
- package/dist/elements/SampleBuffer.js +2 -5
- package/dist/elements/TargetController.js +3 -3
- package/dist/elements/durationConverter.js +4 -4
- package/dist/elements/updateAnimations.js +14 -35
- package/dist/gui/ContextMixin.js +23 -52
- package/dist/gui/EFConfiguration.js +7 -7
- package/dist/gui/EFControls.js +5 -5
- package/dist/gui/EFFilmstrip.js +77 -98
- package/dist/gui/EFFitScale.js +5 -6
- package/dist/gui/EFFocusOverlay.js +4 -4
- package/dist/gui/EFPreview.js +4 -4
- package/dist/gui/EFScrubber.js +9 -9
- package/dist/gui/EFTimeDisplay.js +5 -5
- package/dist/gui/EFToggleLoop.js +4 -4
- package/dist/gui/EFTogglePlay.js +5 -5
- package/dist/gui/EFWorkbench.js +5 -5
- package/dist/gui/TWMixin2.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/otel/BridgeSpanExporter.d.ts +13 -0
- package/dist/otel/BridgeSpanExporter.js +87 -0
- package/dist/otel/setupBrowserTracing.d.ts +12 -0
- package/dist/otel/setupBrowserTracing.js +30 -0
- package/dist/otel/tracingHelpers.d.ts +34 -0
- package/dist/otel/tracingHelpers.js +113 -0
- package/dist/transcoding/cache/RequestDeduplicator.js +0 -21
- package/dist/transcoding/cache/URLTokenDeduplicator.js +1 -21
- package/dist/transcoding/utils/UrlGenerator.js +2 -19
- package/dist/utils/LRUCache.js +6 -53
- package/package.json +10 -2
- package/src/elements/EFCaptions.browsertest.ts +2 -0
- package/src/elements/EFMedia/AssetMediaEngine.ts +65 -37
- package/src/elements/EFMedia/BaseMediaEngine.ts +110 -52
- package/src/elements/EFMedia/BufferedSeekingInput.ts +218 -101
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +7 -3
- package/src/elements/EFMedia/videoTasks/MainVideoInputCache.ts +76 -0
- package/src/elements/EFMedia/videoTasks/makeScrubVideoInputTask.ts +16 -10
- package/src/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.ts +7 -1
- package/src/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.ts +222 -116
- package/src/elements/EFMedia.ts +16 -1
- package/src/elements/EFTimegroup.browsertest.ts +10 -8
- package/src/elements/EFTimegroup.ts +164 -76
- package/src/elements/EFVideo.browsertest.ts +19 -27
- package/src/elements/EFVideo.ts +203 -101
- package/src/otel/BridgeSpanExporter.ts +150 -0
- package/src/otel/setupBrowserTracing.ts +68 -0
- package/src/otel/tracingHelpers.ts +251 -0
- package/types.json +1 -1
package/dist/elements/EFVideo.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js";
|
|
2
|
+
import { withSpan, withSpanSync } from "../otel/tracingHelpers.js";
|
|
1
3
|
import { EFMedia } from "./EFMedia.js";
|
|
2
4
|
import { TWMixin } from "../gui/TWMixin2.js";
|
|
3
5
|
import { DelayedLoadingState } from "../DelayedLoadingState.js";
|
|
@@ -13,10 +15,10 @@ import { Task } from "@lit/task";
|
|
|
13
15
|
import debug from "debug";
|
|
14
16
|
import { css, html } from "lit";
|
|
15
17
|
import { customElement, property, state } from "lit/decorators.js";
|
|
16
|
-
import
|
|
18
|
+
import { context, trace } from "@opentelemetry/api";
|
|
17
19
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
var log = debug("ef:elements:EFVideo");
|
|
21
|
+
var EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
20
22
|
static {
|
|
21
23
|
this.styles = [css`
|
|
22
24
|
:host {
|
|
@@ -104,43 +106,31 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
104
106
|
console.error("frameTask error", error);
|
|
105
107
|
},
|
|
106
108
|
onComplete: () => {},
|
|
107
|
-
task: async ([_desiredSeekTimeMs]) => {
|
|
108
|
-
|
|
109
|
-
await
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
},
|
|
120
|
-
onComplete: () => {},
|
|
121
|
-
task: async ([_seekToMs], { signal }) => {
|
|
122
|
-
const isProductionRendering = this.isInProductionRenderingMode();
|
|
123
|
-
try {
|
|
109
|
+
task: async ([_desiredSeekTimeMs], { signal }) => {
|
|
110
|
+
const t0 = performance.now();
|
|
111
|
+
await withSpan("video.frameTask", {
|
|
112
|
+
elementId: this.id || "unknown",
|
|
113
|
+
desiredSeekTimeMs: _desiredSeekTimeMs,
|
|
114
|
+
src: this.src || "none"
|
|
115
|
+
}, void 0, async (span) => {
|
|
116
|
+
const t1 = performance.now();
|
|
117
|
+
span.setAttribute("preworkMs", t1 - t0);
|
|
118
|
+
this.unifiedVideoSeekTask.run();
|
|
119
|
+
const t2 = performance.now();
|
|
120
|
+
span.setAttribute("seekRunMs", t2 - t1);
|
|
124
121
|
await this.unifiedVideoSeekTask.taskComplete;
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
} finally {
|
|
131
|
-
videoFrame.close();
|
|
132
|
-
}
|
|
122
|
+
const t3 = performance.now();
|
|
123
|
+
span.setAttribute("seekAwaitMs", t3 - t2);
|
|
124
|
+
if (signal.aborted) {
|
|
125
|
+
span.setAttribute("aborted", true);
|
|
126
|
+
return;
|
|
133
127
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
if (!this.rootTimegroup) return;
|
|
141
|
-
if (!this.isFrameRenderingActive()) return;
|
|
142
|
-
}
|
|
143
|
-
if (signal.aborted) return;
|
|
128
|
+
const t4 = performance.now();
|
|
129
|
+
this.paint(_desiredSeekTimeMs, span);
|
|
130
|
+
const t5 = performance.now();
|
|
131
|
+
span.setAttribute("paintMs", t5 - t4);
|
|
132
|
+
span.setAttribute("totalFrameMs", t5 - t0);
|
|
133
|
+
});
|
|
144
134
|
}
|
|
145
135
|
});
|
|
146
136
|
this.delayedLoadingState = new DelayedLoadingState(250, (isLoading, message) => {
|
|
@@ -171,23 +161,13 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
171
161
|
if (referencedCanvas) return referencedCanvas;
|
|
172
162
|
const shadowCanvas = this.shadowRoot?.querySelector("canvas");
|
|
173
163
|
if (shadowCanvas) return shadowCanvas;
|
|
174
|
-
return void 0;
|
|
175
164
|
}
|
|
176
|
-
/**
|
|
177
|
-
* Start a delayed loading operation for testing
|
|
178
|
-
*/
|
|
179
165
|
startDelayedLoading(operationId, message, options = {}) {
|
|
180
166
|
this.delayedLoadingState.startLoading(operationId, message, options);
|
|
181
167
|
}
|
|
182
|
-
/**
|
|
183
|
-
* Clear a delayed loading operation for testing
|
|
184
|
-
*/
|
|
185
168
|
clearDelayedLoading(operationId) {
|
|
186
169
|
this.delayedLoadingState.clearLoading(operationId);
|
|
187
170
|
}
|
|
188
|
-
/**
|
|
189
|
-
* Set loading state for user feedback
|
|
190
|
-
*/
|
|
191
171
|
setLoadingState(isLoading, operation = null, message = "") {
|
|
192
172
|
this.loadingState = {
|
|
193
173
|
isLoading,
|
|
@@ -195,96 +175,151 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
195
175
|
message
|
|
196
176
|
};
|
|
197
177
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
178
|
+
paint(seekToMs, parentSpan) {
|
|
179
|
+
const parentContext = parentSpan ? trace.setSpan(context.active(), parentSpan) : void 0;
|
|
180
|
+
withSpanSync("video.paint", {
|
|
181
|
+
elementId: this.id || "unknown",
|
|
182
|
+
seekToMs,
|
|
183
|
+
src: this.src || "none"
|
|
184
|
+
}, parentContext, (span) => {
|
|
185
|
+
const t0 = performance.now();
|
|
186
|
+
const isProductionRendering = this.isInProductionRenderingMode();
|
|
187
|
+
const t1 = performance.now();
|
|
188
|
+
span.setAttribute("isProductionRendering", isProductionRendering);
|
|
189
|
+
span.setAttribute("modeCheckMs", t1 - t0);
|
|
190
|
+
try {
|
|
191
|
+
const t2 = performance.now();
|
|
192
|
+
const videoSample = this.unifiedVideoSeekTask.value;
|
|
193
|
+
span.setAttribute("hasVideoSample", !!videoSample);
|
|
194
|
+
span.setAttribute("valueAccessMs", t2 - t1);
|
|
195
|
+
if (videoSample) {
|
|
196
|
+
const t3 = performance.now();
|
|
197
|
+
const videoFrame = videoSample.toVideoFrame();
|
|
198
|
+
const t4 = performance.now();
|
|
199
|
+
span.setAttribute("toVideoFrameMs", t4 - t3);
|
|
200
|
+
try {
|
|
201
|
+
const t5 = performance.now();
|
|
202
|
+
this.displayFrame(videoFrame, seekToMs, span);
|
|
203
|
+
const t6 = performance.now();
|
|
204
|
+
span.setAttribute("displayFrameMs", t6 - t5);
|
|
205
|
+
} finally {
|
|
206
|
+
videoFrame.close();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.warn("Unified video pipeline error:", error);
|
|
211
|
+
}
|
|
212
|
+
if (!isProductionRendering) {
|
|
213
|
+
if (!this.rootTimegroup || this.rootTimegroup.currentTimeMs === 0 && this.desiredSeekTimeMs === 0) {
|
|
214
|
+
span.setAttribute("skipped", "preview-initialization");
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
if (!this.rootTimegroup) {
|
|
219
|
+
span.setAttribute("skipped", "no-root-timegroup");
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (!this.isFrameRenderingActive()) {
|
|
223
|
+
span.setAttribute("skipped", "frame-rendering-not-active");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
const tEnd = performance.now();
|
|
228
|
+
span.setAttribute("totalPaintMs", tEnd - t0);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
201
231
|
clearCanvas() {
|
|
202
232
|
if (!this.canvasElement) return;
|
|
203
233
|
const ctx = this.canvasElement.getContext("2d");
|
|
204
234
|
if (ctx) ctx.clearRect(0, 0, this.canvasElement.width, this.canvasElement.height);
|
|
205
235
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
log("trace: displayFrame start", {
|
|
236
|
+
displayFrame(frame, seekToMs, parentSpan) {
|
|
237
|
+
const parentContext = parentSpan ? trace.setSpan(context.active(), parentSpan) : void 0;
|
|
238
|
+
withSpanSync("video.displayFrame", {
|
|
239
|
+
elementId: this.id || "unknown",
|
|
211
240
|
seekToMs,
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
if (this.canvasElement.width !== frame.codedWidth || this.canvasElement.height !== frame.codedHeight) {
|
|
225
|
-
log("trace: updating canvas dimensions", {
|
|
226
|
-
width: frame.codedWidth,
|
|
227
|
-
height: frame.codedHeight
|
|
228
|
-
});
|
|
229
|
-
this.canvasElement.width = frame.codedWidth;
|
|
230
|
-
this.canvasElement.height = frame.codedHeight;
|
|
241
|
+
format: frame.format || "unknown",
|
|
242
|
+
width: frame.codedWidth,
|
|
243
|
+
height: frame.codedHeight
|
|
244
|
+
}, parentContext, (span) => {
|
|
245
|
+
const t0 = performance.now();
|
|
246
|
+
log("trace: displayFrame start", {
|
|
247
|
+
seekToMs,
|
|
248
|
+
frameFormat: frame.format
|
|
249
|
+
});
|
|
250
|
+
if (!this.canvasElement) {
|
|
251
|
+
log("trace: displayFrame aborted - no canvas element");
|
|
252
|
+
throw new Error(`Frame display failed: Canvas element is not available at time ${seekToMs}ms. The video component may not be properly initialized.`);
|
|
231
253
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
254
|
+
const t1 = performance.now();
|
|
255
|
+
span.setAttribute("getCanvasMs", Math.round((t1 - t0) * 100) / 100);
|
|
256
|
+
const ctx = this.canvasElement.getContext("2d");
|
|
257
|
+
const t2 = performance.now();
|
|
258
|
+
span.setAttribute("getCtxMs", Math.round((t2 - t1) * 100) / 100);
|
|
259
|
+
if (!ctx) {
|
|
260
|
+
log("trace: displayFrame aborted - no canvas context");
|
|
261
|
+
throw new Error(`Frame display failed: Unable to get 2D canvas context at time ${seekToMs}ms. This may indicate a browser compatibility issue or canvas corruption.`);
|
|
262
|
+
}
|
|
263
|
+
let resized = false;
|
|
264
|
+
if (frame?.codedWidth && frame?.codedHeight) {
|
|
265
|
+
if (this.canvasElement.width !== frame.codedWidth || this.canvasElement.height !== frame.codedHeight) {
|
|
266
|
+
log("trace: updating canvas dimensions", {
|
|
267
|
+
width: frame.codedWidth,
|
|
268
|
+
height: frame.codedHeight
|
|
269
|
+
});
|
|
270
|
+
this.canvasElement.width = frame.codedWidth;
|
|
271
|
+
this.canvasElement.height = frame.codedHeight;
|
|
272
|
+
resized = true;
|
|
273
|
+
const t3 = performance.now();
|
|
274
|
+
span.setAttribute("resizeMs", Math.round((t3 - t2) * 100) / 100);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
span.setAttribute("canvasResized", resized);
|
|
278
|
+
if (frame.format === null) {
|
|
279
|
+
log("trace: displayFrame aborted - null frame format");
|
|
280
|
+
throw new Error(`Frame display failed: Video frame has null format at time ${seekToMs}ms. This indicates corrupted or incompatible video data.`);
|
|
281
|
+
}
|
|
282
|
+
const tDrawStart = performance.now();
|
|
283
|
+
ctx.drawImage(frame, 0, 0, this.canvasElement.width, this.canvasElement.height);
|
|
284
|
+
const tDrawEnd = performance.now();
|
|
285
|
+
span.setAttribute("drawImageMs", Math.round((tDrawEnd - tDrawStart) * 100) / 100);
|
|
286
|
+
span.setAttribute("totalDisplayMs", Math.round((tDrawEnd - t0) * 100) / 100);
|
|
287
|
+
span.setAttribute("canvasWidth", this.canvasElement.width);
|
|
288
|
+
span.setAttribute("canvasHeight", this.canvasElement.height);
|
|
289
|
+
log("trace: frame drawn to canvas", { seekToMs });
|
|
290
|
+
});
|
|
240
291
|
}
|
|
241
|
-
/**
|
|
242
|
-
* Check if we're in production rendering mode (EF_FRAMEGEN active) vs preview mode
|
|
243
|
-
*/
|
|
244
292
|
isInProductionRenderingMode() {
|
|
245
293
|
if (typeof window.EF_RENDERING === "function") return window.EF_RENDERING();
|
|
246
|
-
|
|
247
|
-
if (workbench?.rendering) return true;
|
|
294
|
+
if (document.querySelector("ef-workbench")?.rendering) return true;
|
|
248
295
|
if (window.EF_FRAMEGEN?.renderOptions) return true;
|
|
249
296
|
return false;
|
|
250
297
|
}
|
|
251
|
-
/**
|
|
252
|
-
* Check if EF_FRAMEGEN has explicitly started frame rendering (not just initialization)
|
|
253
|
-
*/
|
|
254
298
|
isFrameRenderingActive() {
|
|
255
299
|
if (!window.EF_FRAMEGEN?.renderOptions) return false;
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
const currentTime = this.rootTimegroup?.currentTimeMs || 0;
|
|
259
|
-
return currentTime >= renderStartTime;
|
|
300
|
+
const renderStartTime = window.EF_FRAMEGEN.renderOptions.encoderOptions.fromMs;
|
|
301
|
+
return (this.rootTimegroup?.currentTimeMs || 0) >= renderStartTime;
|
|
260
302
|
}
|
|
261
|
-
/**
|
|
262
|
-
* Legacy getter for fragment index task
|
|
263
|
-
* Still used by EFCaptions - maps to unified video seek task
|
|
264
|
-
*/
|
|
265
303
|
get fragmentIndexTask() {
|
|
266
304
|
return this.unifiedVideoSeekTask;
|
|
267
305
|
}
|
|
268
|
-
/**
|
|
269
|
-
* Clean up resources when component is disconnected
|
|
270
|
-
*/
|
|
271
306
|
disconnectedCallback() {
|
|
272
307
|
super.disconnectedCallback();
|
|
273
308
|
this.delayedLoadingState.clearAllLoading();
|
|
274
309
|
}
|
|
275
310
|
};
|
|
276
|
-
|
|
311
|
+
__decorate([property({
|
|
277
312
|
type: Number,
|
|
278
313
|
attribute: "video-buffer-duration"
|
|
279
314
|
})], EFVideo.prototype, "videoBufferDurationMs", void 0);
|
|
280
|
-
|
|
315
|
+
__decorate([property({
|
|
281
316
|
type: Number,
|
|
282
317
|
attribute: "max-video-buffer-fetches"
|
|
283
318
|
})], EFVideo.prototype, "maxVideoBufferFetches", void 0);
|
|
284
|
-
|
|
319
|
+
__decorate([property({
|
|
285
320
|
type: Boolean,
|
|
286
321
|
attribute: "enable-video-buffering"
|
|
287
322
|
})], EFVideo.prototype, "enableVideoBuffering", void 0);
|
|
288
|
-
|
|
289
|
-
EFVideo =
|
|
323
|
+
__decorate([state()], EFVideo.prototype, "loadingState", void 0);
|
|
324
|
+
EFVideo = __decorate([customElement("ef-video")], EFVideo);
|
|
290
325
|
export { EFVideo };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EF_RENDERING } from "../EF_RENDERING.js";
|
|
2
|
+
import { __decorate } from "../_virtual/_@oxc-project_runtime@0.93.0/helpers/decorate.js";
|
|
2
3
|
import { EFTemporal } from "./EFTemporal.js";
|
|
3
4
|
import { TargetController } from "./TargetController.js";
|
|
4
5
|
import { TWMixin } from "../gui/TWMixin2.js";
|
|
@@ -6,10 +7,9 @@ import { CrossUpdateController } from "./CrossUpdateController.js";
|
|
|
6
7
|
import { Task } from "@lit/task";
|
|
7
8
|
import { LitElement, css, html } from "lit";
|
|
8
9
|
import { customElement, property, state } from "lit/decorators.js";
|
|
9
|
-
import _decorate from "@oxc-project/runtime/helpers/decorate";
|
|
10
10
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
11
11
|
import { CSSStyleObserver } from "@bramus/style-observer";
|
|
12
|
-
|
|
12
|
+
var EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
13
13
|
constructor(..._args) {
|
|
14
14
|
super(..._args);
|
|
15
15
|
this.canvasRef = createRef();
|
|
@@ -38,8 +38,7 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
38
38
|
if (!frequencyData || !byteTimeData) return;
|
|
39
39
|
ctx.save();
|
|
40
40
|
if (this.color === "currentColor") {
|
|
41
|
-
const
|
|
42
|
-
const currentColor = computedStyle.color;
|
|
41
|
+
const currentColor = getComputedStyle(this).color;
|
|
43
42
|
ctx.strokeStyle = currentColor;
|
|
44
43
|
ctx.fillStyle = currentColor;
|
|
45
44
|
} else {
|
|
@@ -150,13 +149,11 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
150
149
|
const totalBars = frequencyData.length;
|
|
151
150
|
const paddingInner = this.barSpacing;
|
|
152
151
|
const paddingOuter = .01;
|
|
153
|
-
const
|
|
154
|
-
const barWidth = availableWidth / (totalBars + (totalBars - 1) * paddingInner);
|
|
152
|
+
const barWidth = waveWidth / (totalBars + (totalBars - 1) * paddingInner);
|
|
155
153
|
ctx.clearRect(0, 0, waveWidth, waveHeight);
|
|
156
154
|
const path = new Path2D();
|
|
157
155
|
frequencyData.forEach((value, i) => {
|
|
158
|
-
const
|
|
159
|
-
const barHeight = normalizedValue * waveHeight;
|
|
156
|
+
const barHeight = value / 255 * waveHeight;
|
|
160
157
|
const y = (waveHeight - barHeight) / 2;
|
|
161
158
|
const x = waveWidth * paddingOuter + i * (barWidth * (1 + paddingInner));
|
|
162
159
|
path.rect(x, y, barWidth, barHeight);
|
|
@@ -191,13 +188,11 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
191
188
|
const totalBars = frequencyData.length;
|
|
192
189
|
const paddingInner = this.barSpacing;
|
|
193
190
|
const paddingOuter = .01;
|
|
194
|
-
const
|
|
195
|
-
const barWidth = availableWidth / (totalBars + (totalBars - 1) * paddingInner);
|
|
191
|
+
const barWidth = waveWidth / (totalBars + (totalBars - 1) * paddingInner);
|
|
196
192
|
ctx.clearRect(0, 0, waveWidth, waveHeight);
|
|
197
193
|
const path = new Path2D();
|
|
198
194
|
frequencyData.forEach((value, i) => {
|
|
199
|
-
const
|
|
200
|
-
const height = normalizedValue * waveHeight;
|
|
195
|
+
const height = value / 255 * waveHeight;
|
|
201
196
|
const x = waveWidth * paddingOuter + i * (barWidth * (1 + paddingInner));
|
|
202
197
|
const y = (waveHeight - height) / 2;
|
|
203
198
|
path.roundRect(x, y, barWidth, height, barWidth / 2);
|
|
@@ -281,8 +276,7 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
281
276
|
if (i === 0) path.moveTo(x, y);
|
|
282
277
|
else {
|
|
283
278
|
const prevX = startX + (i - 1) / (frequencyData.length - 1) * availableWidth;
|
|
284
|
-
const
|
|
285
|
-
const prevBarHeight = prevValue * waveHeight;
|
|
279
|
+
const prevBarHeight = Math.min((frequencyData[i - 1] ?? 0) / 255 * 2, 1) * waveHeight;
|
|
286
280
|
const prevY = (waveHeight - prevBarHeight) / 2;
|
|
287
281
|
const xc = (prevX + x) / 2;
|
|
288
282
|
const yc = (prevY + y) / 2;
|
|
@@ -297,8 +291,7 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
297
291
|
if (i === frequencyData.length - 1) path.lineTo(x, y);
|
|
298
292
|
else {
|
|
299
293
|
const nextX = startX + (i + 1) / (frequencyData.length - 1) * availableWidth;
|
|
300
|
-
const
|
|
301
|
-
const nextBarHeight = nextValue * waveHeight;
|
|
294
|
+
const nextBarHeight = Math.min((frequencyData[i + 1] ?? 0) / 255 * 2, 1) * waveHeight;
|
|
302
295
|
const nextY = (waveHeight + nextBarHeight) / 2;
|
|
303
296
|
const xc = (nextX + x) / 2;
|
|
304
297
|
const yc = (nextY + y) / 2;
|
|
@@ -331,8 +324,7 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
331
324
|
if (i === 0) path.moveTo(x, y);
|
|
332
325
|
else {
|
|
333
326
|
const prevX = startX + (i - 1) / (frequencyData.length - 1) * availableWidth;
|
|
334
|
-
const
|
|
335
|
-
const prevBarHeight = prevValue * (waveHeight / 2);
|
|
327
|
+
const prevBarHeight = (frequencyData[i - 1] ?? 0) / 255 * (waveHeight / 2);
|
|
336
328
|
const prevY = (waveHeight - prevBarHeight * 2) / 2;
|
|
337
329
|
const xc = (prevX + x) / 2;
|
|
338
330
|
const yc = (prevY + y) / 2;
|
|
@@ -347,8 +339,7 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
347
339
|
if (i === frequencyData.length - 1) path.lineTo(x, y);
|
|
348
340
|
else {
|
|
349
341
|
const nextX = startX + (i + 1) / (frequencyData.length - 1) * availableWidth;
|
|
350
|
-
const
|
|
351
|
-
const nextBarHeight = nextValue * (waveHeight / 2);
|
|
342
|
+
const nextBarHeight = (frequencyData[i + 1] ?? 0) / 255 * (waveHeight / 2);
|
|
352
343
|
const nextY = (waveHeight + nextBarHeight * 2) / 2;
|
|
353
344
|
const xc = (nextX + x) / 2;
|
|
354
345
|
const yc = (nextY + y) / 2;
|
|
@@ -370,23 +361,23 @@ let EFWaveform = class EFWaveform$1 extends EFTemporal(TWMixin(LitElement)) {
|
|
|
370
361
|
if (changedProperties.size > 0) this.frameTask.run();
|
|
371
362
|
}
|
|
372
363
|
};
|
|
373
|
-
|
|
364
|
+
__decorate([property({
|
|
374
365
|
type: String,
|
|
375
366
|
attribute: "mode"
|
|
376
367
|
})], EFWaveform.prototype, "mode", void 0);
|
|
377
|
-
|
|
378
|
-
|
|
368
|
+
__decorate([property({ type: String })], EFWaveform.prototype, "color", void 0);
|
|
369
|
+
__decorate([property({
|
|
379
370
|
type: String,
|
|
380
371
|
reflect: true
|
|
381
372
|
})], EFWaveform.prototype, "target", void 0);
|
|
382
|
-
|
|
373
|
+
__decorate([property({
|
|
383
374
|
type: Number,
|
|
384
375
|
attribute: "bar-spacing"
|
|
385
376
|
})], EFWaveform.prototype, "barSpacing", void 0);
|
|
386
|
-
|
|
387
|
-
|
|
377
|
+
__decorate([state()], EFWaveform.prototype, "targetElement", void 0);
|
|
378
|
+
__decorate([property({
|
|
388
379
|
type: Number,
|
|
389
380
|
attribute: "line-width"
|
|
390
381
|
})], EFWaveform.prototype, "lineWidth", void 0);
|
|
391
|
-
EFWaveform =
|
|
382
|
+
EFWaveform = __decorate([customElement("ef-waveform")], EFWaveform);
|
|
392
383
|
export { EFWaveform };
|
|
@@ -23,8 +23,7 @@ var SampleBuffer = class {
|
|
|
23
23
|
} catch (_error) {}
|
|
24
24
|
}
|
|
25
25
|
peek() {
|
|
26
|
-
|
|
27
|
-
return currentBuffer[0];
|
|
26
|
+
return this.buffer[0];
|
|
28
27
|
}
|
|
29
28
|
find(desiredSeekTimeMs) {
|
|
30
29
|
const currentBuffer = [...this.buffer];
|
|
@@ -36,14 +35,12 @@ var SampleBuffer = class {
|
|
|
36
35
|
const sampleEndMs = roundToMilliseconds(sampleStartMs + sampleDurationMs);
|
|
37
36
|
if (targetTimeMs >= sampleStartMs && targetTimeMs < sampleEndMs) return sample;
|
|
38
37
|
}
|
|
39
|
-
return void 0;
|
|
40
38
|
}
|
|
41
39
|
get length() {
|
|
42
40
|
return this.buffer.length;
|
|
43
41
|
}
|
|
44
42
|
get firstTimestamp() {
|
|
45
|
-
|
|
46
|
-
return currentBuffer[0]?.timestamp || 0;
|
|
43
|
+
return this.buffer[0]?.timestamp || 0;
|
|
47
44
|
}
|
|
48
45
|
getContents() {
|
|
49
46
|
return [...this.buffer];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LitElement } from "lit";
|
|
2
|
-
|
|
2
|
+
var EF_TARGETABLE = Symbol("EF_TARGETABLE");
|
|
3
3
|
var TargetRegistry = class {
|
|
4
4
|
constructor() {
|
|
5
5
|
this.idMap = /* @__PURE__ */ new Map();
|
|
@@ -28,8 +28,8 @@ var TargetRegistry = class {
|
|
|
28
28
|
this.callbacks.delete(id);
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
var documentRegistries = /* @__PURE__ */ new WeakMap();
|
|
32
|
+
var getRegistry = (root) => {
|
|
33
33
|
let registry = documentRegistries.get(root);
|
|
34
34
|
if (!registry) {
|
|
35
35
|
registry = new TargetRegistry();
|
|
@@ -3,7 +3,7 @@ const durationConverter = {
|
|
|
3
3
|
fromAttribute: (value) => value === null ? null : parseTimeToMs(value),
|
|
4
4
|
toAttribute: (value) => value === null ? null : `${value}s`
|
|
5
5
|
};
|
|
6
|
-
|
|
6
|
+
var positiveDurationConverter = (error) => {
|
|
7
7
|
return {
|
|
8
8
|
fromAttribute: (value) => {
|
|
9
9
|
if (value === null) return null;
|
|
@@ -13,7 +13,7 @@ const positiveDurationConverter = (error) => {
|
|
|
13
13
|
toAttribute: (value) => value === null ? null : `${value}s`
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
positiveDurationConverter("Trimstart & trimend must be a positive value in milliseconds or seconds (1s, 1000ms)");
|
|
17
|
+
positiveDurationConverter("Image duration must be a positive value in milliseconds or seconds (1s, 1000ms)");
|
|
18
|
+
positiveDurationConverter("Sourcein & sourceout must be a positive value in milliseconds or seconds (1s, 1000ms)");
|
|
19
19
|
export { durationConverter };
|
|
@@ -1,19 +1,15 @@
|
|
|
1
1
|
import { deepGetTemporalElements } from "./EFTemporal.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Evaluates what the element's state should be based on the timeline
|
|
11
|
-
*/
|
|
2
|
+
var ANIMATION_PRECISION_OFFSET = .1;
|
|
3
|
+
var DEFAULT_ANIMATION_ITERATIONS = 1;
|
|
4
|
+
var PROGRESS_PROPERTY = "--ef-progress";
|
|
5
|
+
var DURATION_PROPERTY = "--ef-duration";
|
|
6
|
+
var TRANSITION_DURATION_PROPERTY = "--ef-transition-duration";
|
|
7
|
+
var TRANSITION_OUT_START_PROPERTY = "--ef-transition-out-start";
|
|
8
|
+
var TIMEGROUP_TAGNAME = "ef-timegroup";
|
|
12
9
|
const evaluateTemporalState = (element) => {
|
|
13
10
|
const timelineTimeMs = (element.rootTimegroup ?? element).currentTimeMs;
|
|
14
11
|
const progress = element.durationMs <= 0 ? 1 : Math.max(0, Math.min(1, element.currentTimeMs / element.durationMs));
|
|
15
|
-
const
|
|
16
|
-
const useInclusiveEnd = isRootTimegroup;
|
|
12
|
+
const useInclusiveEnd = element.tagName.toLowerCase() === TIMEGROUP_TAGNAME && !element.parentTimegroup;
|
|
17
13
|
const isVisible = element.startTimeMs <= timelineTimeMs && (useInclusiveEnd ? element.endTimeMs >= timelineTimeMs : element.endTimeMs > timelineTimeMs);
|
|
18
14
|
return {
|
|
19
15
|
progress,
|
|
@@ -21,10 +17,6 @@ const evaluateTemporalState = (element) => {
|
|
|
21
17
|
timelineTimeMs
|
|
22
18
|
};
|
|
23
19
|
};
|
|
24
|
-
/**
|
|
25
|
-
* Evaluates element visibility specifically for animation coordination
|
|
26
|
-
* Uses inclusive end boundaries to prevent animation jumps at exact boundaries
|
|
27
|
-
*/
|
|
28
20
|
const evaluateTemporalStateForAnimation = (element) => {
|
|
29
21
|
const timelineTimeMs = (element.rootTimegroup ?? element).currentTimeMs;
|
|
30
22
|
const progress = element.durationMs <= 0 ? 1 : Math.max(0, Math.min(1, element.currentTimeMs / element.durationMs));
|
|
@@ -35,10 +27,7 @@ const evaluateTemporalStateForAnimation = (element) => {
|
|
|
35
27
|
timelineTimeMs
|
|
36
28
|
};
|
|
37
29
|
};
|
|
38
|
-
|
|
39
|
-
* Updates the visual state (CSS + display) to match temporal state
|
|
40
|
-
*/
|
|
41
|
-
const updateVisualState = (element, state) => {
|
|
30
|
+
var updateVisualState = (element, state) => {
|
|
42
31
|
element.style.setProperty(PROGRESS_PROPERTY, `${state.progress * 100}%`);
|
|
43
32
|
if (!state.isVisible) {
|
|
44
33
|
if (element.style.display !== "none") element.style.display = "none";
|
|
@@ -49,17 +38,13 @@ const updateVisualState = (element, state) => {
|
|
|
49
38
|
element.style.setProperty(TRANSITION_DURATION_PROPERTY, `${element.parentTimegroup?.overlapMs ?? 0}ms`);
|
|
50
39
|
element.style.setProperty(TRANSITION_OUT_START_PROPERTY, `${element.durationMs - (element.parentTimegroup?.overlapMs ?? 0)}ms`);
|
|
51
40
|
};
|
|
52
|
-
|
|
53
|
-
* Coordinates animations for a single element and its subtree, using the element as the time source
|
|
54
|
-
*/
|
|
55
|
-
const coordinateAnimationsForSingleElement = (element) => {
|
|
41
|
+
var coordinateAnimationsForSingleElement = (element) => {
|
|
56
42
|
const animations = element.getAnimations({ subtree: true });
|
|
57
43
|
for (const animation of animations) {
|
|
58
44
|
if (animation.playState === "running") animation.pause();
|
|
59
45
|
const effect = animation.effect;
|
|
60
46
|
if (!(effect && effect instanceof KeyframeEffect)) continue;
|
|
61
|
-
|
|
62
|
-
if (!target) continue;
|
|
47
|
+
if (!effect.target) continue;
|
|
63
48
|
const timing = effect.getTiming();
|
|
64
49
|
const duration = Number(timing.duration) || 0;
|
|
65
50
|
const delay = Number(timing.delay) || 0;
|
|
@@ -76,8 +61,7 @@ const coordinateAnimationsForSingleElement = (element) => {
|
|
|
76
61
|
const adjustedTime = currentTime - delay;
|
|
77
62
|
const currentIteration = Math.floor(adjustedTime / duration);
|
|
78
63
|
const currentIterationTime = adjustedTime % duration;
|
|
79
|
-
const
|
|
80
|
-
const maxSafeCurrentTime = totalAnimationLength - ANIMATION_PRECISION_OFFSET;
|
|
64
|
+
const maxSafeCurrentTime = delay + duration * iterations - ANIMATION_PRECISION_OFFSET;
|
|
81
65
|
if (currentIteration >= iterations) animation.currentTime = maxSafeCurrentTime;
|
|
82
66
|
else {
|
|
83
67
|
const proposedCurrentTime = Math.min(currentIterationTime, duration - ANIMATION_PRECISION_OFFSET) + delay;
|
|
@@ -85,9 +69,6 @@ const coordinateAnimationsForSingleElement = (element) => {
|
|
|
85
69
|
}
|
|
86
70
|
}
|
|
87
71
|
};
|
|
88
|
-
/**
|
|
89
|
-
* Main function: synchronizes DOM element with timeline
|
|
90
|
-
*/
|
|
91
72
|
const updateAnimations = (element) => {
|
|
92
73
|
const temporalState = evaluateTemporalState(element);
|
|
93
74
|
deepGetTemporalElements(element).forEach((temporalElement) => {
|
|
@@ -95,11 +76,9 @@ const updateAnimations = (element) => {
|
|
|
95
76
|
updateVisualState(temporalElement, temporalState$1);
|
|
96
77
|
});
|
|
97
78
|
updateVisualState(element, temporalState);
|
|
98
|
-
|
|
99
|
-
if (animationState.isVisible) coordinateAnimationsForSingleElement(element);
|
|
79
|
+
if (evaluateTemporalStateForAnimation(element).isVisible) coordinateAnimationsForSingleElement(element);
|
|
100
80
|
deepGetTemporalElements(element).forEach((temporalElement) => {
|
|
101
|
-
|
|
102
|
-
if (childAnimationState.isVisible) coordinateAnimationsForSingleElement(temporalElement);
|
|
81
|
+
if (evaluateTemporalStateForAnimation(temporalElement).isVisible) coordinateAnimationsForSingleElement(temporalElement);
|
|
103
82
|
});
|
|
104
83
|
};
|
|
105
84
|
export { evaluateTemporalStateForAnimation, updateAnimations };
|