@editframe/elements 0.16.7-beta.0 → 0.17.6-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/README.md +30 -0
- package/dist/DecoderResetFrequency.test.d.ts +1 -0
- package/dist/DecoderResetRecovery.test.d.ts +1 -0
- package/dist/DelayedLoadingState.d.ts +48 -0
- package/dist/DelayedLoadingState.integration.test.d.ts +1 -0
- package/dist/DelayedLoadingState.js +113 -0
- package/dist/DelayedLoadingState.test.d.ts +1 -0
- package/dist/EF_FRAMEGEN.d.ts +10 -1
- package/dist/EF_FRAMEGEN.js +199 -179
- package/dist/EF_INTERACTIVE.js +2 -6
- package/dist/EF_RENDERING.js +1 -3
- package/dist/JitTranscodingClient.browsertest.d.ts +1 -0
- package/dist/JitTranscodingClient.d.ts +167 -0
- package/dist/JitTranscodingClient.js +373 -0
- package/dist/JitTranscodingClient.test.d.ts +1 -0
- package/dist/LoadingDebounce.test.d.ts +1 -0
- package/dist/LoadingIndicator.browsertest.d.ts +0 -0
- package/dist/ManualScrubTest.test.d.ts +1 -0
- package/dist/ScrubResolvedFlashing.test.d.ts +1 -0
- package/dist/ScrubTrackIntegration.test.d.ts +1 -0
- package/dist/ScrubTrackManager.d.ts +96 -0
- package/dist/ScrubTrackManager.js +216 -0
- package/dist/ScrubTrackManager.test.d.ts +1 -0
- package/dist/SegmentSwitchLoading.test.d.ts +1 -0
- package/dist/VideoSeekFlashing.browsertest.d.ts +0 -0
- package/dist/VideoStuckDiagnostic.test.d.ts +1 -0
- package/dist/elements/CrossUpdateController.js +13 -15
- package/dist/elements/EFAudio.browsertest.d.ts +0 -0
- package/dist/elements/EFAudio.d.ts +1 -1
- package/dist/elements/EFAudio.js +30 -43
- package/dist/elements/EFCaptions.js +337 -373
- package/dist/elements/EFImage.js +64 -90
- package/dist/elements/EFMedia.d.ts +98 -33
- package/dist/elements/EFMedia.js +1169 -678
- package/dist/elements/EFSourceMixin.js +31 -48
- package/dist/elements/EFTemporal.d.ts +1 -0
- package/dist/elements/EFTemporal.js +266 -360
- package/dist/elements/EFTimegroup.d.ts +3 -1
- package/dist/elements/EFTimegroup.js +262 -323
- package/dist/elements/EFVideo.browsertest.d.ts +0 -0
- package/dist/elements/EFVideo.d.ts +90 -2
- package/dist/elements/EFVideo.js +408 -111
- package/dist/elements/EFWaveform.js +375 -411
- package/dist/elements/FetchMixin.js +14 -24
- package/dist/elements/MediaController.d.ts +30 -0
- package/dist/elements/TargetController.js +130 -156
- package/dist/elements/TimegroupController.js +17 -19
- package/dist/elements/durationConverter.js +15 -4
- package/dist/elements/parseTimeToMs.js +4 -10
- package/dist/elements/printTaskStatus.d.ts +2 -0
- package/dist/elements/printTaskStatus.js +11 -0
- package/dist/elements/updateAnimations.js +39 -59
- package/dist/getRenderInfo.js +58 -67
- package/dist/gui/ContextMixin.js +203 -288
- package/dist/gui/EFConfiguration.js +27 -43
- package/dist/gui/EFFilmstrip.js +440 -620
- package/dist/gui/EFFitScale.js +112 -135
- package/dist/gui/EFFocusOverlay.js +45 -61
- package/dist/gui/EFPreview.js +30 -49
- package/dist/gui/EFScrubber.js +78 -99
- package/dist/gui/EFTimeDisplay.js +49 -70
- package/dist/gui/EFToggleLoop.js +17 -34
- package/dist/gui/EFTogglePlay.js +37 -58
- package/dist/gui/EFWorkbench.js +66 -88
- package/dist/gui/TWMixin.js +2 -48
- package/dist/gui/TWMixin2.js +31 -0
- package/dist/gui/efContext.js +2 -6
- package/dist/gui/fetchContext.js +1 -3
- package/dist/gui/focusContext.js +1 -3
- package/dist/gui/focusedElementContext.js +2 -6
- package/dist/gui/playingContext.js +1 -4
- package/dist/index.js +5 -30
- package/dist/msToTimeCode.js +11 -13
- package/dist/style.css +2 -1
- package/package.json +3 -3
- package/src/elements/EFAudio.browsertest.ts +569 -0
- package/src/elements/EFAudio.ts +4 -6
- package/src/elements/EFCaptions.browsertest.ts +0 -1
- package/src/elements/EFImage.browsertest.ts +0 -1
- package/src/elements/EFMedia.browsertest.ts +147 -115
- package/src/elements/EFMedia.ts +1339 -307
- package/src/elements/EFTemporal.browsertest.ts +0 -1
- package/src/elements/EFTemporal.ts +11 -0
- package/src/elements/EFTimegroup.ts +73 -10
- package/src/elements/EFVideo.browsertest.ts +680 -0
- package/src/elements/EFVideo.ts +729 -50
- package/src/elements/EFWaveform.ts +4 -4
- package/src/elements/MediaController.ts +108 -0
- package/src/elements/__screenshots__/EFMedia.browsertest.ts/EFMedia-JIT-audio-playback-audioBufferTask-should-work-in-JIT-mode-without-URL-errors-1.png +0 -0
- package/src/elements/printTaskStatus.ts +16 -0
- package/src/elements/updateAnimations.ts +6 -0
- package/src/gui/TWMixin.ts +10 -3
- package/test/EFVideo.frame-tasks.browsertest.ts +524 -0
- package/test/EFVideo.framegen.browsertest.ts +118 -0
- package/test/createJitTestClips.ts +293 -0
- package/test/useAssetMSW.ts +49 -0
- package/test/useMSW.ts +31 -0
- package/types.json +1 -1
- package/dist/gui/TWMixin.css.js +0 -4
- /package/dist/elements/{TargetController.test.d.ts → TargetController.browsertest.d.ts} +0 -0
- /package/src/elements/{TargetController.test.ts → TargetController.browsertest.ts} +0 -0
|
@@ -47,7 +47,6 @@ describe("sourcein and sourceout", () => {
|
|
|
47
47
|
const element = document.createElement("ten-seconds");
|
|
48
48
|
element.sourceInMs = 5_000;
|
|
49
49
|
element.sourceOutMs = 1_000;
|
|
50
|
-
console.log(element.sourceInMs, element.sourceOutMs, element.durationMs);
|
|
51
50
|
expect(element.durationMs).toBe(0);
|
|
52
51
|
});
|
|
53
52
|
});
|
|
@@ -292,6 +292,10 @@ const resetStartTimeMsCache = () => {
|
|
|
292
292
|
};
|
|
293
293
|
resetStartTimeMsCache();
|
|
294
294
|
|
|
295
|
+
export const flushStartTimeMsCache = () => {
|
|
296
|
+
startTimeMsCache = new WeakMap();
|
|
297
|
+
};
|
|
298
|
+
|
|
295
299
|
export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
296
300
|
superClass: T,
|
|
297
301
|
) => {
|
|
@@ -536,12 +540,19 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
536
540
|
const ownIndex = siblingTemorals?.indexOf(
|
|
537
541
|
this as InstanceType<Constructor<TemporalMixinInterface> & T>,
|
|
538
542
|
);
|
|
543
|
+
if (ownIndex === -1) {
|
|
544
|
+
return 0;
|
|
545
|
+
}
|
|
539
546
|
if (ownIndex === 0) {
|
|
540
547
|
startTimeMsCache.set(this, parentTimegroup.startTimeMs);
|
|
541
548
|
return parentTimegroup.startTimeMs;
|
|
542
549
|
}
|
|
543
550
|
const previous = siblingTemorals?.[(ownIndex ?? 0) - 1];
|
|
544
551
|
if (!previous) {
|
|
552
|
+
console.log("Previous temporal element not found", {
|
|
553
|
+
ownIndex,
|
|
554
|
+
siblingTemorals,
|
|
555
|
+
});
|
|
545
556
|
throw new Error("Previous temporal element not found");
|
|
546
557
|
}
|
|
547
558
|
startTimeMsCache.set(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { provide } from "@lit/context";
|
|
2
|
-
import { Task } from "@lit/task";
|
|
2
|
+
import { Task, TaskStatus } from "@lit/task";
|
|
3
3
|
import debug from "debug";
|
|
4
4
|
import { LitElement, type PropertyValueMap, css, html } from "lit";
|
|
5
5
|
import { customElement, property } from "lit/decorators.js";
|
|
@@ -9,6 +9,8 @@ import { isContextMixin } from "../gui/ContextMixin.js";
|
|
|
9
9
|
import { deepGetMediaElements } from "./EFMedia.js";
|
|
10
10
|
import {
|
|
11
11
|
EFTemporal,
|
|
12
|
+
deepGetElementsWithFrameTasks,
|
|
13
|
+
flushStartTimeMsCache,
|
|
12
14
|
shallowGetTemporalElements,
|
|
13
15
|
timegroupContext,
|
|
14
16
|
} from "./EFTemporal.js";
|
|
@@ -110,7 +112,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
110
112
|
super.connectedCallback();
|
|
111
113
|
if (this.id) {
|
|
112
114
|
this.waitForMediaDurations().then(() => {
|
|
113
|
-
this
|
|
115
|
+
this.currentTime = this.maybeLoadTimeFromLocalStorage();
|
|
114
116
|
});
|
|
115
117
|
}
|
|
116
118
|
|
|
@@ -197,6 +199,30 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
197
199
|
}
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
async getPendingFrameTasks() {
|
|
203
|
+
await this.updateComplete;
|
|
204
|
+
const temporals = deepGetElementsWithFrameTasks(this);
|
|
205
|
+
return temporals
|
|
206
|
+
.map((temporal) => temporal.frameTask)
|
|
207
|
+
.filter((task) => task.status < TaskStatus.COMPLETE);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async waitForFrameTasks() {
|
|
211
|
+
const limit = 10;
|
|
212
|
+
let step = 0;
|
|
213
|
+
await this.updateComplete;
|
|
214
|
+
while (step < limit) {
|
|
215
|
+
step++;
|
|
216
|
+
let pendingTasks = await this.getPendingFrameTasks();
|
|
217
|
+
await Promise.all(pendingTasks.map((task) => task.taskComplete));
|
|
218
|
+
await this.updateComplete;
|
|
219
|
+
pendingTasks = await this.getPendingFrameTasks();
|
|
220
|
+
if (pendingTasks.length === 0) {
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
200
226
|
/**
|
|
201
227
|
* Wait for all media elements to load their initial segments.
|
|
202
228
|
* Ideally we would only need the extracted index json data, but
|
|
@@ -204,10 +230,32 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
204
230
|
* in calculations and it was not clear why.
|
|
205
231
|
*/
|
|
206
232
|
async waitForMediaDurations() {
|
|
233
|
+
// We must await updateComplete to ensure all media elements inside this are connected
|
|
234
|
+
// and will match deepGetMediaElements
|
|
235
|
+
await this.updateComplete;
|
|
207
236
|
const mediaElements = deepGetMediaElements(this);
|
|
208
|
-
|
|
209
|
-
|
|
237
|
+
// Then, we must await the fragmentIndexTask to ensure all media elements have their
|
|
238
|
+
// fragment index loaded, which is where their duration is parsed from.
|
|
239
|
+
await Promise.all(
|
|
240
|
+
mediaElements.map((m) => m.fragmentIndexTask.taskComplete),
|
|
210
241
|
);
|
|
242
|
+
|
|
243
|
+
// After waiting for durations, we must force some updates to cascade and ensure all temporal elements
|
|
244
|
+
// have correct durations and start times. It is not ideal that we have to do this inside here,
|
|
245
|
+
// but it is the best current way to ensure that all temporal elements have correct durations and start times.
|
|
246
|
+
|
|
247
|
+
// Next, we must flush the startTimeMs cache to ensure all media elements have their
|
|
248
|
+
// startTimeMs parsed fresh, otherwise the startTimeMs is cached per animation frame.
|
|
249
|
+
flushStartTimeMsCache();
|
|
250
|
+
|
|
251
|
+
// Request an update to the currentTime of this group, ensuring that time updates will cascade
|
|
252
|
+
// down to children, forcing sequence groups to arrange correctly.
|
|
253
|
+
// This also makes the filmstrip update correctly.
|
|
254
|
+
this.requestUpdate("currentTime");
|
|
255
|
+
// Finally, we must await updateComplete to ensure all temporal elements have their
|
|
256
|
+
// currentTime updated and all animations have run.
|
|
257
|
+
|
|
258
|
+
await this.updateComplete;
|
|
211
259
|
}
|
|
212
260
|
|
|
213
261
|
get childTemporals() {
|
|
@@ -328,13 +376,28 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
328
376
|
|
|
329
377
|
async renderAudio(fromMs: number, toMs: number) {
|
|
330
378
|
const durationMs = toMs - fromMs;
|
|
331
|
-
const
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
379
|
+
const contextSize = Math.round((48000 * durationMs) / 1000);
|
|
380
|
+
|
|
381
|
+
// Debug logging for audio duration calculations
|
|
382
|
+
if (contextSize <= 0) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`Duration must be greater than 0 when rendering audio. ${contextSize}ms`,
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
let audioContext: OfflineAudioContext;
|
|
389
|
+
try {
|
|
390
|
+
audioContext = new OfflineAudioContext(2, contextSize, 48000);
|
|
391
|
+
} catch (error) {
|
|
392
|
+
throw new Error(
|
|
393
|
+
`[EFTimegroup.renderAudio] Failed to create OfflineAudioContext(2, ${contextSize}, 48000) for renderAudio(${fromMs}, ${toMs}) with contextSize=${contextSize}: ${error instanceof Error ? error.message : String(error)}. This typically happens when audio parameters are invalid (e.g., contextSize <= 0).`,
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
336
397
|
await this.#addAudioToContext(audioContext, fromMs, toMs);
|
|
337
|
-
|
|
398
|
+
const renderedBuffer = await audioContext.startRendering();
|
|
399
|
+
|
|
400
|
+
return renderedBuffer;
|
|
338
401
|
}
|
|
339
402
|
|
|
340
403
|
async loadMd5Sums() {
|