@editframe/elements 0.18.26-beta.0 → 0.19.2-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.
Files changed (75) hide show
  1. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +10 -0
  2. package/dist/elements/EFMedia/AssetMediaEngine.js +13 -1
  3. package/dist/elements/EFMedia/BaseMediaEngine.js +1 -5
  4. package/dist/elements/EFMedia/JitMediaEngine.d.ts +10 -0
  5. package/dist/elements/EFMedia/JitMediaEngine.js +12 -0
  6. package/dist/elements/EFMedia/audioTasks/makeAudioBufferTask.js +16 -12
  7. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.d.ts +1 -1
  8. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +0 -4
  9. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.d.ts +1 -1
  10. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +0 -4
  11. package/dist/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.js +1 -1
  12. package/dist/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.js +3 -2
  13. package/dist/elements/EFMedia/videoTasks/makeVideoBufferTask.js +16 -12
  14. package/dist/elements/EFMedia.d.ts +2 -3
  15. package/dist/elements/EFMedia.js +0 -4
  16. package/dist/elements/EFTemporal.d.ts +9 -6
  17. package/dist/elements/EFTemporal.js +15 -12
  18. package/dist/elements/EFTimegroup.browsertest.d.ts +26 -0
  19. package/dist/elements/EFTimegroup.d.ts +12 -9
  20. package/dist/elements/EFTimegroup.js +114 -65
  21. package/dist/elements/EFVideo.d.ts +5 -1
  22. package/dist/elements/EFVideo.js +16 -8
  23. package/dist/elements/EFWaveform.js +2 -3
  24. package/dist/elements/FetchContext.browsertest.d.ts +0 -0
  25. package/dist/elements/FetchMixin.js +14 -9
  26. package/dist/elements/TimegroupController.js +2 -1
  27. package/dist/elements/updateAnimations.browsertest.d.ts +0 -0
  28. package/dist/elements/updateAnimations.d.ts +19 -9
  29. package/dist/elements/updateAnimations.js +64 -25
  30. package/dist/gui/ContextMixin.js +34 -27
  31. package/dist/gui/EFConfiguration.d.ts +1 -1
  32. package/dist/gui/EFConfiguration.js +1 -0
  33. package/dist/gui/EFFilmstrip.d.ts +1 -0
  34. package/dist/gui/EFFilmstrip.js +12 -14
  35. package/dist/gui/TWMixin.js +1 -1
  36. package/dist/style.css +1 -1
  37. package/dist/transcoding/cache/URLTokenDeduplicator.d.ts +38 -0
  38. package/dist/transcoding/cache/URLTokenDeduplicator.js +66 -0
  39. package/dist/transcoding/cache/URLTokenDeduplicator.test.d.ts +1 -0
  40. package/dist/transcoding/types/index.d.ts +10 -0
  41. package/package.json +2 -2
  42. package/src/elements/EFMedia/AssetMediaEngine.ts +16 -2
  43. package/src/elements/EFMedia/BaseMediaEngine.ts +0 -6
  44. package/src/elements/EFMedia/JitMediaEngine.ts +14 -0
  45. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +0 -1
  46. package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +11 -4
  47. package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +0 -4
  48. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +4 -1
  49. package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +0 -5
  50. package/src/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.ts +2 -2
  51. package/src/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.ts +7 -3
  52. package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +11 -4
  53. package/src/elements/EFMedia.browsertest.ts +13 -4
  54. package/src/elements/EFMedia.ts +6 -10
  55. package/src/elements/EFTemporal.ts +21 -26
  56. package/src/elements/EFTimegroup.browsertest.ts +186 -2
  57. package/src/elements/EFTimegroup.ts +190 -94
  58. package/src/elements/EFVideo.browsertest.ts +53 -132
  59. package/src/elements/EFVideo.ts +26 -13
  60. package/src/elements/EFWaveform.ts +2 -3
  61. package/src/elements/FetchContext.browsertest.ts +396 -0
  62. package/src/elements/FetchMixin.ts +25 -8
  63. package/src/elements/TimegroupController.ts +2 -1
  64. package/src/elements/updateAnimations.browsertest.ts +559 -0
  65. package/src/elements/updateAnimations.ts +113 -50
  66. package/src/gui/ContextMixin.browsertest.ts +4 -9
  67. package/src/gui/ContextMixin.ts +52 -33
  68. package/src/gui/EFConfiguration.ts +1 -1
  69. package/src/gui/EFFilmstrip.ts +15 -18
  70. package/src/transcoding/cache/URLTokenDeduplicator.test.ts +182 -0
  71. package/src/transcoding/cache/URLTokenDeduplicator.ts +101 -0
  72. package/src/transcoding/types/index.ts +11 -0
  73. package/test/EFVideo.framegen.browsertest.ts +1 -1
  74. package/test/setup.ts +2 -0
  75. package/types.json +1 -1
@@ -12,6 +12,7 @@ import { EFMedia } from "./EFMedia.js";
12
12
  import "./EFTimegroup.js";
13
13
  import type { EFTimegroup } from "./EFTimegroup.js";
14
14
  import "./EFVideo.js";
15
+ import type { EFPreview } from "../gui/EFPreview.js";
15
16
  import { UrlGenerator } from "../transcoding/utils/UrlGenerator.js";
16
17
  import { AssetMediaEngine } from "./EFMedia/AssetMediaEngine.js";
17
18
  import type { EFVideo } from "./EFVideo.js";
@@ -42,11 +43,16 @@ declare global {
42
43
 
43
44
  const test = baseTest.extend<{
44
45
  timegroup: EFTimegroup;
46
+ preview: EFPreview;
45
47
  jitVideo: EFVideo;
46
48
  configuration: EFConfiguration;
47
49
  urlGenerator: UrlGenerator;
48
50
  host: EFVideo;
49
51
  }>({
52
+ preview: async ({}, use) => {
53
+ const preview = document.createElement("ef-preview");
54
+ await use(preview);
55
+ },
50
56
  timegroup: async ({}, use) => {
51
57
  const timegroup = document.createElement("ef-timegroup");
52
58
  timegroup.setAttribute("mode", "contain");
@@ -59,6 +65,7 @@ const test = baseTest.extend<{
59
65
  const apiHost = `${window.location.protocol}//${window.location.host}`;
60
66
  configuration.setAttribute("api-host", apiHost);
61
67
  configuration.apiHost = apiHost;
68
+ configuration.signingURL = "";
62
69
  document.body.appendChild(configuration);
63
70
  await use(configuration);
64
71
  },
@@ -74,9 +81,10 @@ const test = baseTest.extend<{
74
81
  host.src = "http://web:3000/head-moov-480p.mp4";
75
82
  await use(host);
76
83
  },
77
- jitVideo: async ({ configuration, timegroup, host }, use) => {
84
+ jitVideo: async ({ configuration, timegroup, host, preview }, use) => {
78
85
  timegroup.append(host);
79
- configuration.append(timegroup);
86
+ configuration.append(preview);
87
+ preview.append(timegroup);
80
88
  await host.mediaEngineTask.run();
81
89
  await use(host);
82
90
  },
@@ -98,8 +106,7 @@ describe("JIT Media Engine", () => {
98
106
  jitVideo,
99
107
  expect,
100
108
  }) => {
101
- await timegroup.waitForMediaDurations();
102
- timegroup.currentTimeMs = 2200;
109
+ timegroup.currentTime = 2.2;
103
110
  await timegroup.seekTask.taskComplete;
104
111
  const sample = await jitVideo.unifiedVideoSeekTask.taskComplete;
105
112
  expect(sample?.timestamp).toBeCloseTo(2.2, 1);
@@ -373,6 +380,7 @@ describe("EFMedia", () => {
373
380
  const apiHost = `${window.location.protocol}//${window.location.host}`;
374
381
  configuration.setAttribute("api-host", apiHost);
375
382
  configuration.apiHost = apiHost;
383
+ configuration.signingURL = ""; // Disable URL signing for tests
376
384
  document.body.appendChild(configuration);
377
385
  await use(configuration);
378
386
  // configuration.remove();
@@ -529,6 +537,7 @@ describe("EFMedia", () => {
529
537
  const apiHost = `${window.location.protocol}//${window.location.host}`;
530
538
  configuration.setAttribute("api-host", apiHost);
531
539
  configuration.apiHost = apiHost;
540
+ configuration.signingURL = ""; // Disable URL signing for tests
532
541
  document.body.appendChild(configuration);
533
542
  await use(configuration);
534
543
  },
@@ -17,7 +17,6 @@ import { EFSourceMixin } from "./EFSourceMixin.js";
17
17
  import { EFTemporal } from "./EFTemporal.js";
18
18
  import { FetchMixin } from "./FetchMixin.js";
19
19
  import { EFTargetable } from "./TargetController.ts";
20
- import { updateAnimations } from "./updateAnimations.ts";
21
20
 
22
21
  // EF_FRAMEGEN is a global instance created in EF_FRAMEGEN.ts
23
22
  declare global {
@@ -78,9 +77,6 @@ export class EFMedia extends EFTargetable(
78
77
  `,
79
78
  ];
80
79
 
81
- @property({ type: Number })
82
- currentTimeMs = 0;
83
-
84
80
  /**
85
81
  * Duration in milliseconds for audio buffering ahead of current time
86
82
  * @domAttribute "audio-buffer-duration"
@@ -216,12 +212,12 @@ export class EFMedia extends EFTargetable(
216
212
  if (changedProperties.has("ownCurrentTimeMs")) {
217
213
  this.executeSeek(this.currentSourceTimeMs);
218
214
  }
219
- if (
220
- changedProperties.has("currentTime") ||
221
- changedProperties.has("ownCurrentTimeMs")
222
- ) {
223
- updateAnimations(this);
224
- }
215
+ // if (
216
+ // changedProperties.has("currentTime") ||
217
+ // changedProperties.has("ownCurrentTimeMs")
218
+ // ) {
219
+ // updateAnimations(this);
220
+ // }
225
221
  }
226
222
 
227
223
  get hasOwnDuration() {
@@ -1,6 +1,6 @@
1
1
  import { consume, createContext } from "@lit/context";
2
2
  import { Task } from "@lit/task";
3
- import type { LitElement, PropertyValueMap, ReactiveController } from "lit";
3
+ import type { LitElement, ReactiveController } from "lit";
4
4
  import { property, state } from "lit/decorators.js";
5
5
  import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
6
6
  import { durationConverter } from "./durationConverter.js";
@@ -149,6 +149,13 @@ export declare class TemporalMixinInterface {
149
149
  * played.
150
150
  */
151
151
  get ownCurrentTimeMs(): number;
152
+
153
+ /**
154
+ * Element's current time for progress calculation.
155
+ * For timegroups: their timeline currentTimeMs
156
+ * For other temporal elements: their ownCurrentTimeMs
157
+ */
158
+ get currentTimeMs(): number;
152
159
  /**
153
160
  * The current time of the element in milliseconds, adjusted for trimming.
154
161
  *
@@ -211,11 +218,11 @@ const EF_TEMPORAL = Symbol("EF_TEMPORAL");
211
218
 
212
219
  export const deepGetTemporalElements = (
213
220
  element: Element,
214
- temporals: TemporalMixinInterface[] = [],
221
+ temporals: Array<TemporalMixinInterface & HTMLElement> = [],
215
222
  ) => {
216
223
  for (const child of element.children) {
217
224
  if (isEFTemporal(child)) {
218
- temporals.push(child);
225
+ temporals.push(child as TemporalMixinInterface & HTMLElement);
219
226
  }
220
227
  deepGetTemporalElements(child, temporals);
221
228
  }
@@ -224,11 +231,11 @@ export const deepGetTemporalElements = (
224
231
 
225
232
  export const deepGetElementsWithFrameTasks = (
226
233
  element: Element,
227
- elements: Array<HTMLElement & { frameTask: Task }> = [],
234
+ elements: Array<TemporalMixinInterface & HTMLElement> = [],
228
235
  ) => {
229
236
  for (const child of element.children) {
230
237
  if ("frameTask" in child && child.frameTask instanceof Task) {
231
- elements.push(child as HTMLElement & { frameTask: Task });
238
+ elements.push(child as TemporalMixinInterface & HTMLElement);
232
239
  }
233
240
  deepGetElementsWithFrameTasks(child, elements);
234
241
  }
@@ -236,7 +243,7 @@ export const deepGetElementsWithFrameTasks = (
236
243
  };
237
244
 
238
245
  let temporalCache: Map<Element, TemporalMixinInterface[]>;
239
- const resetTemporalCache = () => {
246
+ export const resetTemporalCache = () => {
240
247
  temporalCache = new Map();
241
248
  if (typeof requestAnimationFrame !== "undefined") {
242
249
  requestAnimationFrame(resetTemporalCache);
@@ -597,6 +604,14 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
597
604
  return 0;
598
605
  }
599
606
 
607
+ /**
608
+ * Element's current time for progress calculation.
609
+ * Non-timegroup temporal elements use their local time (ownCurrentTimeMs)
610
+ */
611
+ get currentTimeMs() {
612
+ return this.ownCurrentTimeMs;
613
+ }
614
+
600
615
  /**
601
616
  * Used to calculate the internal currentTimeMs of the element. This is useful
602
617
  * for mapping to internal media time codes for audio/video elements.
@@ -616,26 +631,6 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
616
631
  }
617
632
  },
618
633
  });
619
-
620
- protected updated(
621
- changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
622
- ): void {
623
- super.updated(changedProperties);
624
- if (
625
- changedProperties.has("currentTime") ||
626
- changedProperties.has("ownCurrentTimeMs")
627
- ) {
628
- const timelineTimeMs = (this.rootTimegroup ?? this).ownCurrentTimeMs;
629
- if (
630
- this.startTimeMs > timelineTimeMs ||
631
- this.endTimeMs < timelineTimeMs
632
- ) {
633
- this.style.display = "none";
634
- return;
635
- }
636
- this.style.display = "";
637
- }
638
- }
639
634
  }
640
635
 
641
636
  Object.defineProperty(TemporalMixinClass.prototype, EF_TEMPORAL, {
@@ -12,6 +12,12 @@ import { ContextMixin } from "../gui/ContextMixin.js";
12
12
  import { EFTemporal } from "./EFTemporal.js";
13
13
  // Need workbench to make workbench wrapping occurs
14
14
  import "../gui/EFWorkbench.js";
15
+ // Additional imports for sequence boundary test
16
+ import "./EFVideo.js";
17
+ import "../gui/EFConfiguration.js";
18
+ import { Task } from "@lit/task";
19
+ import type { MediaEngine } from "../transcoding/types/index.js";
20
+ import { EFMedia } from "./EFMedia.js";
15
21
 
16
22
  beforeEach(() => {
17
23
  for (let i = 0; i < localStorage.length; i++) {
@@ -27,6 +33,61 @@ beforeEach(() => {
27
33
  @customElement("test-context")
28
34
  class TestContext extends ContextMixin(LitElement) {}
29
35
 
36
+ @customElement("timegroup-test-media")
37
+ class TimegroupTestMedia extends EFMedia {
38
+ mediaEngineTaskCount = 0;
39
+ mediaEngineTask = new Task(this, {
40
+ autoRun: false,
41
+ args: () => ["source", null] as const,
42
+ task: () => {
43
+ this.mediaEngineTaskCount++;
44
+ return Promise.resolve({} as unknown as MediaEngine);
45
+ },
46
+ });
47
+ }
48
+
49
+ @customElement("test-frame-task-a")
50
+ class TestFrameTaskA extends EFTemporal(LitElement) {
51
+ frameTaskCount = 0;
52
+
53
+ frameTask = new Task(this, {
54
+ autoRun: false,
55
+ args: () => [],
56
+ task: () => {
57
+ this.frameTaskCount++;
58
+ return Promise.resolve();
59
+ },
60
+ });
61
+ }
62
+
63
+ @customElement("test-frame-task-b")
64
+ class TestFrameTaskB extends EFTemporal(LitElement) {
65
+ frameTaskCount = 0;
66
+
67
+ frameTask = new Task(this, {
68
+ autoRun: false,
69
+ args: () => [],
70
+ task: () => {
71
+ this.frameTaskCount++;
72
+ return Promise.resolve();
73
+ },
74
+ });
75
+ }
76
+
77
+ @customElement("test-frame-task-c")
78
+ class TestFrameTaskC extends EFTemporal(LitElement) {
79
+ frameTaskCount = 0;
80
+
81
+ frameTask = new Task(this, {
82
+ autoRun: false,
83
+ args: () => [],
84
+ task: () => {
85
+ this.frameTaskCount++;
86
+ return Promise.resolve();
87
+ },
88
+ });
89
+ }
90
+
30
91
  @customElement("test-temporal")
31
92
  class TestTemporal extends EFTemporal(LitElement) {
32
93
  get hasOwnDuration(): boolean {
@@ -38,20 +99,24 @@ declare global {
38
99
  interface HTMLElementTagNameMap {
39
100
  "test-temporal": TestTemporal;
40
101
  "test-context": TestContext;
102
+ "timegroup-test-media": TimegroupTestMedia;
103
+ "test-frame-task-a": TestFrameTaskA;
104
+ "test-frame-task-b": TestFrameTaskB;
105
+ "test-frame-task-c": TestFrameTaskC;
41
106
  }
42
107
  }
43
108
 
44
109
  const renderTimegroup = (result: TemplateResult) => {
45
110
  const container = document.createElement("div");
46
111
  litRender(result, container);
47
- const firstChild = container.firstElementChild;
112
+ const firstChild = container.querySelector("ef-timegroup");
48
113
  if (!firstChild) {
49
114
  throw new Error("No first child found");
50
115
  }
51
116
  if (!(firstChild instanceof EFTimegroup)) {
52
117
  throw new Error("First child is not an EFTimegroup");
53
118
  }
54
- document.body.appendChild(firstChild);
119
+ document.body.appendChild(container);
55
120
  return firstChild;
56
121
  };
57
122
 
@@ -436,3 +501,122 @@ describe("DOM nodes", () => {
436
501
  assert.equal(timegroup.durationMs, 10_000);
437
502
  });
438
503
  });
504
+
505
+ describe("Dynamic content updates", () => {
506
+ test("updates duration when new child temporal elements are added dynamically", async () => {
507
+ // Create a sequence timegroup with initial children
508
+ const timegroup = renderTimegroup(
509
+ html`<ef-timegroup mode="sequence">
510
+ <ef-timegroup mode="fixed" duration="3s"></ef-timegroup>
511
+ <ef-timegroup mode="fixed" duration="2s"></ef-timegroup>
512
+ </ef-timegroup>`,
513
+ );
514
+
515
+ // Initial duration should be 5 seconds (3s + 2s)
516
+ assert.equal(timegroup.durationMs, 5_000);
517
+ assert.equal(timegroup.childTemporals.length, 2);
518
+
519
+ // Dynamically add a new child element
520
+ const newChild = document.createElement("ef-timegroup");
521
+ newChild.setAttribute("mode", "fixed");
522
+ newChild.setAttribute("duration", "4s");
523
+ timegroup.appendChild(newChild);
524
+
525
+ // Wait for slot change event to process
526
+ await timegroup.updateComplete;
527
+
528
+ // Duration should now include the new child (3s + 2s + 4s = 9s)
529
+ assert.equal(timegroup.durationMs, 9_000);
530
+ assert.equal(timegroup.childTemporals.length, 3);
531
+ });
532
+
533
+ test("updates duration when child temporal elements are removed dynamically", async () => {
534
+ // Create a contain timegroup with initial children
535
+ const timegroup = renderTimegroup(
536
+ html`<ef-timegroup mode="contain">
537
+ <ef-timegroup id="child1" mode="fixed" duration="5s"></ef-timegroup>
538
+ <ef-timegroup id="child2" mode="fixed" duration="8s"></ef-timegroup>
539
+ <ef-timegroup id="child3" mode="fixed" duration="3s"></ef-timegroup>
540
+ </ef-timegroup>`,
541
+ );
542
+
543
+ // Initial duration should be max of children (8s)
544
+ assert.equal(timegroup.durationMs, 8_000);
545
+ assert.equal(timegroup.childTemporals.length, 3);
546
+
547
+ // Remove the longest duration child
548
+ const child2 = timegroup.querySelector("#child2");
549
+ child2?.remove();
550
+
551
+ // Wait for slot change event to process
552
+ await timegroup.updateComplete;
553
+
554
+ // Duration should now be max of remaining children (5s)
555
+ assert.equal(timegroup.durationMs, 5_000);
556
+ assert.equal(timegroup.childTemporals.length, 2);
557
+ });
558
+
559
+ describe("frameTask", () => {
560
+ test("executes all nested frame tasks", async () => {
561
+ const timegroup = renderTimegroup(
562
+ html`<ef-timegroup mode="sequence">
563
+ <test-frame-task-a duration="1s"></test-frame-task-a>
564
+ <div>
565
+ <test-frame-task-b duration="1s">
566
+ <test-frame-task-c duration="1s"></test-frame-task-c>
567
+ </test-frame-task-b>
568
+ </div>
569
+ </ef-timegroup>`,
570
+ );
571
+ const frameTaskA = timegroup.querySelector("test-frame-task-a")!;
572
+ const frameTaskB = timegroup.querySelector("test-frame-task-b")!;
573
+ const frameTaskC = timegroup.querySelector("test-frame-task-c")!;
574
+
575
+ assert.equal(frameTaskA.frameTaskCount, 0);
576
+ assert.equal(frameTaskB.frameTaskCount, 0);
577
+ assert.equal(frameTaskC.frameTaskCount, 0);
578
+
579
+ await timegroup.frameTask.run();
580
+
581
+ // At timeline time 0ms:
582
+ // - frameTaskA (0-1000ms) should run
583
+ // - frameTaskB (1000-2000ms) should NOT run
584
+ // - frameTaskC (0-1000ms) should run (inherits root positioning)
585
+ assert.equal(frameTaskA.frameTaskCount, 1);
586
+ assert.equal(frameTaskB.frameTaskCount, 0); // Not visible at time 0
587
+ assert.equal(frameTaskC.frameTaskCount, 1); // Nested in B but inherits root positioning
588
+ });
589
+ });
590
+
591
+ describe("seekTask", () => {
592
+ test("does not execute if not the root timegroup", async () => {
593
+ const timegroup = renderTimegroup(
594
+ html`<ef-timegroup mode="sequence">
595
+ <ef-timegroup mode="fixed" duration="3s">
596
+ <test-frame-task-a></test-frame-task-a>
597
+ </ef-timegroup>
598
+ </ef-timegroup>`,
599
+ );
600
+ const nonRootTimegroup = timegroup.querySelector("ef-timegroup")!;
601
+ const frameTaskA = timegroup.querySelector("test-frame-task-a")!;
602
+ assert.equal(frameTaskA.frameTaskCount, 0);
603
+ await nonRootTimegroup.seekTask.run();
604
+ assert.equal(frameTaskA.frameTaskCount, 0);
605
+ });
606
+
607
+ test("waits for media durations", async () => {
608
+ const timegroup = renderTimegroup(
609
+ html`
610
+ <ef-preview>
611
+ <ef-timegroup mode="sequence">
612
+ <timegroup-test-media></timegroup-test-media>
613
+ </ef-timegroup>
614
+ </ef-preview>`,
615
+ );
616
+ const media = timegroup.querySelector("timegroup-test-media")!;
617
+ assert.equal(media.mediaEngineTaskCount, 0);
618
+ await timegroup.seekTask.run();
619
+ assert.equal(media.mediaEngineTaskCount, 1);
620
+ });
621
+ });
622
+ });