@editframe/elements 0.15.0-beta.18 → 0.15.0-beta.20

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 (37) hide show
  1. package/dist/EF_FRAMEGEN.js +1 -0
  2. package/dist/elements/EFMedia.d.ts +7 -3
  3. package/dist/elements/EFMedia.js +42 -90
  4. package/dist/elements/EFTemporal.browsertest.d.ts +4 -3
  5. package/dist/elements/EFTemporal.d.ts +14 -11
  6. package/dist/elements/EFTemporal.js +63 -87
  7. package/dist/elements/EFTimegroup.d.ts +1 -1
  8. package/dist/elements/EFTimegroup.js +12 -107
  9. package/dist/elements/EFVideo.js +3 -1
  10. package/dist/elements/durationConverter.d.ts +8 -8
  11. package/dist/elements/durationConverter.js +2 -2
  12. package/dist/elements/updateAnimations.d.ts +9 -0
  13. package/dist/elements/updateAnimations.js +62 -0
  14. package/dist/getRenderInfo.d.ts +2 -2
  15. package/dist/gui/EFFilmstrip.js +7 -16
  16. package/dist/gui/EFFitScale.d.ts +27 -0
  17. package/dist/gui/EFFitScale.js +137 -0
  18. package/dist/gui/EFWorkbench.d.ts +1 -5
  19. package/dist/gui/EFWorkbench.js +7 -54
  20. package/dist/gui/TWMixin.css.js +1 -1
  21. package/dist/index.d.ts +1 -0
  22. package/dist/index.js +2 -0
  23. package/dist/style.css +0 -6
  24. package/package.json +2 -2
  25. package/src/elements/EFMedia.browsertest.ts +10 -10
  26. package/src/elements/EFMedia.ts +48 -118
  27. package/src/elements/EFTemporal.browsertest.ts +64 -31
  28. package/src/elements/EFTemporal.ts +99 -119
  29. package/src/elements/EFTimegroup.ts +12 -131
  30. package/src/elements/EFVideo.ts +3 -1
  31. package/src/elements/durationConverter.ts +9 -4
  32. package/src/elements/updateAnimations.ts +88 -0
  33. package/src/gui/ContextMixin.ts +0 -3
  34. package/src/gui/EFFilmstrip.ts +7 -16
  35. package/src/gui/EFFitScale.ts +151 -0
  36. package/src/gui/EFWorkbench.ts +13 -63
  37. package/types.json +1 -1
@@ -136,6 +136,7 @@ class EfFramegen {
136
136
  await new Promise(queueMicrotask);
137
137
  console.log("Awaiting frame tasks");
138
138
  const now = performance.now();
139
+ console.log("HTML", document.body.innerHTML);
139
140
  await Promise.all(
140
141
  temporals.filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE).map((temporal) => {
141
142
  return temporal.frameTask;
@@ -50,7 +50,7 @@ export declare class EFMedia extends EFMedia_base {
50
50
  protected executeSeek(seekToMs: number): Promise<void>;
51
51
  protected updated(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
52
52
  get hasOwnDuration(): boolean;
53
- get durationMs(): number;
53
+ get intrinsicDurationMs(): number;
54
54
  audioBufferTask: Task<readonly [Record<string, File> | undefined, Record<string, {
55
55
  segment: TrackSegment;
56
56
  track: MP4Box.TrackInfo;
@@ -68,10 +68,14 @@ export declare class EFMedia extends EFMedia_base {
68
68
  set fftDecay(value: number);
69
69
  get fftSize(): number;
70
70
  get fftDecay(): number;
71
+ set interpolateFrequencies(value: boolean);
72
+ get interpolateFrequencies(): boolean;
71
73
  get shouldInterpolateFrequencies(): boolean;
72
74
  private static readonly DECAY_WEIGHT;
73
75
  get FREQ_WEIGHTS(): Float32Array;
74
- byteTimeDomainTask: Task<readonly [import('@lit/task').TaskStatus, number, number, number], Uint8Array | null>;
75
- frequencyDataTask: Task<readonly [import('@lit/task').TaskStatus, number, number, number], Uint8Array | null>;
76
+ byteTimeDomainTask: Task<readonly [import('@lit/task').TaskStatus, number, number, number, number, boolean], Uint8Array | null>;
77
+ frequencyDataTask: Task<readonly [import('@lit/task').TaskStatus, number, number, number, number, boolean], Uint8Array | null>;
78
+ set fftGain(value: number);
79
+ get fftGain(): number;
76
80
  }
77
81
  export {};
@@ -8,9 +8,10 @@ import { MP4File } from "@editframe/assets/MP4File.js";
8
8
  import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
9
9
  import { EF_RENDERING } from "../EF_RENDERING.js";
10
10
  import { EFSourceMixin } from "./EFSourceMixin.js";
11
- import { EFTemporal, isEFTemporal } from "./EFTemporal.js";
11
+ import { EFTemporal } from "./EFTemporal.js";
12
12
  import { FetchMixin } from "./FetchMixin.js";
13
13
  import { EFTargetable } from "./TargetController.js";
14
+ import { updateAnimations } from "./updateAnimations.js";
14
15
  var __defProp = Object.defineProperty;
15
16
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
16
17
  var __decorateClass = (decorators, target, key, kind) => {
@@ -79,8 +80,11 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
79
80
  }
80
81
  },
81
82
  onComplete: () => {
83
+ this.requestUpdate("intrinsicDurationMs");
82
84
  this.requestUpdate("ownCurrentTimeMs");
85
+ console.log("Requesting update for durationMs", this, this.rootTimegroup);
83
86
  this.rootTimegroup?.requestUpdate("ownCurrentTimeMs");
87
+ this.rootTimegroup?.requestUpdate("durationMs");
84
88
  }
85
89
  });
86
90
  this.initSegmentsLoader = new Task(this, {
@@ -254,7 +258,9 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
254
258
  this.audioBufferTask.status,
255
259
  this.currentSourceTimeMs,
256
260
  this.fftSize,
257
- this.fftDecay
261
+ this.fftDecay,
262
+ this.fftGain,
263
+ this.shouldInterpolateFrequencies
258
264
  ],
259
265
  task: async () => {
260
266
  await this.audioBufferTask.taskComplete;
@@ -263,7 +269,7 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
263
269
  const currentTimeMs = this.currentSourceTimeMs;
264
270
  const startOffsetMs = this.audioBufferTask.value.startOffsetMs;
265
271
  const audioBuffer = this.audioBufferTask.value.buffer;
266
- const smoothedKey = `${this.fftSize}:${this.fftDecay}:${startOffsetMs}:${currentTimeMs}`;
272
+ const smoothedKey = `${this.shouldInterpolateFrequencies}:${this.fftSize}:${this.fftDecay}:${this.fftGain}:${startOffsetMs}:${currentTimeMs}`;
267
273
  const cachedData = this.#byteTimeDomainCache.get(smoothedKey);
268
274
  if (cachedData) return cachedData;
269
275
  const framesData = await Promise.all(
@@ -273,7 +279,7 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
273
279
  0,
274
280
  (currentTimeMs - frameOffset - startOffsetMs) / 1e3
275
281
  );
276
- const cacheKey = `${this.fftSize}:${startOffsetMs}:${startTime}`;
282
+ const cacheKey = `${this.shouldInterpolateFrequencies}:${this.fftSize}:${this.fftGain}:${startOffsetMs}:${startTime}`;
277
283
  const cachedFrame = this.#byteTimeDomainCache.get(cacheKey);
278
284
  if (cachedFrame) return cachedFrame;
279
285
  const audioContext = new OfflineAudioContext(
@@ -288,7 +294,7 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
288
294
  analyser.minDecibels = -90;
289
295
  analyser.maxDecibels = -20;
290
296
  const gainNode = audioContext.createGain();
291
- gainNode.gain.value = 2;
297
+ gainNode.gain.value = this.fftGain;
292
298
  source.connect(gainNode);
293
299
  gainNode.connect(analyser);
294
300
  analyser.connect(audioContext.destination);
@@ -346,9 +352,9 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
346
352
  this.audioBufferTask.status,
347
353
  this.currentSourceTimeMs,
348
354
  this.fftSize,
349
- // Add fftSize to dependency array
350
- this.fftDecay
351
- // Add fftDecay to dependency array
355
+ this.fftDecay,
356
+ this.fftGain,
357
+ this.shouldInterpolateFrequencies
352
358
  ],
353
359
  task: async () => {
354
360
  await this.audioBufferTask.taskComplete;
@@ -357,7 +363,7 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
357
363
  const currentTimeMs = this.currentSourceTimeMs;
358
364
  const startOffsetMs = this.audioBufferTask.value.startOffsetMs;
359
365
  const audioBuffer = this.audioBufferTask.value.buffer;
360
- const smoothedKey = `${this.fftSize}:${this.fftDecay}:${startOffsetMs}:${currentTimeMs}`;
366
+ const smoothedKey = `${this.shouldInterpolateFrequencies}:${this.fftSize}:${this.fftDecay}:${this.fftGain}:${startOffsetMs}:${currentTimeMs}`;
361
367
  const cachedSmoothedData = this.#frequencyDataCache.get(smoothedKey);
362
368
  if (cachedSmoothedData) {
363
369
  return cachedSmoothedData;
@@ -369,7 +375,7 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
369
375
  0,
370
376
  (currentTimeMs - frameOffset - startOffsetMs) / 1e3
371
377
  );
372
- const cacheKey = `${this.fftSize}:${startOffsetMs}:${startTime}`;
378
+ const cacheKey = `${this.shouldInterpolateFrequencies}:${this.fftSize}:${this.fftGain}:${startOffsetMs}:${startTime}`;
373
379
  const cachedFrame = this.#frequencyDataCache.get(cacheKey);
374
380
  if (cachedFrame) {
375
381
  return cachedFrame;
@@ -384,7 +390,7 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
384
390
  analyser.minDecibels = -90;
385
391
  analyser.maxDecibels = -10;
386
392
  const gainNode = audioContext.createGain();
387
- gainNode.gain.value = 3;
393
+ gainNode.gain.value = this.fftGain;
388
394
  const filter = audioContext.createBiquadFilter();
389
395
  filter.type = "bandpass";
390
396
  filter.frequency.value = 15e3;
@@ -488,71 +494,13 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
488
494
  this.executeSeek(this.currentSourceTimeMs);
489
495
  }
490
496
  if (changedProperties.has("currentTime") || changedProperties.has("ownCurrentTimeMs")) {
491
- const timelineTimeMs = (this.rootTimegroup ?? this).currentTimeMs;
492
- if (this.startTimeMs > timelineTimeMs || this.endTimeMs < timelineTimeMs) {
493
- this.style.display = "none";
494
- return;
495
- }
496
- this.style.display = "";
497
- const animations = this.getAnimations({ subtree: true });
498
- this.style.setProperty("--ef-duration", `${this.durationMs}ms`);
499
- this.style.setProperty(
500
- "--ef-transition-duration",
501
- `${this.parentTimegroup?.overlapMs ?? 0}ms`
502
- );
503
- this.style.setProperty(
504
- "--ef-transition-out-start",
505
- `${this.durationMs - (this.parentTimegroup?.overlapMs ?? 0)}ms`
506
- );
507
- for (const animation of animations) {
508
- if (animation.playState === "running") {
509
- animation.pause();
510
- }
511
- const effect = animation.effect;
512
- if (!(effect && effect instanceof KeyframeEffect)) {
513
- return;
514
- }
515
- const target = effect.target;
516
- if (!target) {
517
- return;
518
- }
519
- if (target.closest("ef-video, ef-audio") !== this) {
520
- return;
521
- }
522
- if (isEFTemporal(target)) {
523
- const timing = effect.getTiming();
524
- const duration = Number(timing.duration) ?? 0;
525
- const delay = Number(timing.delay);
526
- const newTime = Math.floor(
527
- Math.min(target.ownCurrentTimeMs, duration - 1 + delay)
528
- );
529
- if (Number.isNaN(newTime)) {
530
- return;
531
- }
532
- animation.currentTime = newTime;
533
- } else if (target) {
534
- const nearestTimegroup = target.closest("ef-timegroup");
535
- if (!nearestTimegroup) {
536
- return;
537
- }
538
- const timing = effect.getTiming();
539
- const duration = Number(timing.duration) ?? 0;
540
- const delay = Number(timing.delay);
541
- const newTime = Math.floor(
542
- Math.min(nearestTimegroup.ownCurrentTimeMs, duration - 1 + delay)
543
- );
544
- if (Number.isNaN(newTime)) {
545
- return;
546
- }
547
- animation.currentTime = newTime;
548
- }
549
- }
497
+ updateAnimations(this);
550
498
  }
551
499
  }
552
500
  get hasOwnDuration() {
553
501
  return true;
554
502
  }
555
- get durationMs() {
503
+ get intrinsicDurationMs() {
556
504
  if (!this.trackFragmentIndexLoader.value) {
557
505
  return 0;
558
506
  }
@@ -564,30 +512,18 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
564
512
  if (durations.length === 0) {
565
513
  return 0;
566
514
  }
567
- if (this.sourceInMs && this.sourceOutMs && this.sourceOutMs > this.sourceInMs) {
568
- return Math.max(this.sourceOutMs - this.sourceInMs);
569
- }
570
- if (this.sourceInMs) {
571
- return Math.max(...durations) - this.trimStartMs - this.trimEndMs - this.sourceInMs;
572
- }
573
- if (this.sourceOutMs) {
574
- return Math.max(...durations) - this.trimStartMs - this.trimEndMs - this.sourceOutMs;
575
- }
576
- if (this.sourceInMs && this.sourceOutMs) {
577
- return Math.max(...durations) - this.trimStartMs - this.trimEndMs - this.sourceOutMs - this.sourceInMs;
578
- }
579
- return Math.max(...durations) - this.trimStartMs - this.trimEndMs;
515
+ return Math.max(...durations);
580
516
  }
581
517
  #audioContext;
582
518
  async fetchAudioSpanningTime(fromMs, toMs) {
583
519
  if (this.sourceInMs) {
584
- fromMs -= this.startTimeMs - this.trimStartMs - this.sourceInMs;
520
+ fromMs -= this.startTimeMs - (this.trimStartMs ?? 0) - (this.sourceInMs ?? 0);
585
521
  }
586
522
  if (this.sourceOutMs) {
587
- toMs -= this.startTimeMs - this.trimStartMs - this.sourceOutMs;
523
+ toMs -= this.startTimeMs - (this.trimStartMs ?? 0) - (this.sourceOutMs ?? 0);
588
524
  }
589
- fromMs -= this.startTimeMs - this.trimStartMs;
590
- toMs -= this.startTimeMs - this.trimStartMs;
525
+ fromMs -= this.startTimeMs - (this.trimStartMs ?? 0);
526
+ toMs -= this.startTimeMs - (this.trimStartMs ?? 0);
591
527
  await this.trackFragmentIndexLoader.taskComplete;
592
528
  const audioTrackId = this.defaultAudioTrackId;
593
529
  if (!audioTrackId) {
@@ -641,8 +577,8 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
641
577
  });
642
578
  return {
643
579
  blob: audioBlob,
644
- startMs: firstFragment.dts / audioTrackIndex.timescale * 1e3 - this.trimStartMs,
645
- endMs: lastFragment.dts / audioTrackIndex.timescale * 1e3 + lastFragment.duration / audioTrackIndex.timescale * 1e3 - this.trimEndMs
580
+ startMs: firstFragment.dts / audioTrackIndex.timescale * 1e3 - (this.trimStartMs ?? 0),
581
+ endMs: lastFragment.dts / audioTrackIndex.timescale * 1e3 + lastFragment.duration / audioTrackIndex.timescale * 1e3 - (this.trimEndMs ?? 0)
646
582
  };
647
583
  }
648
584
  set fftSize(value) {
@@ -661,6 +597,14 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
661
597
  get fftDecay() {
662
598
  return Number.parseInt(this.getAttribute("fft-decay") ?? "8", 10);
663
599
  }
600
+ set interpolateFrequencies(value) {
601
+ const oldValue = this.interpolateFrequencies;
602
+ this.setAttribute("interpolate-frequencies", String(value));
603
+ this.requestUpdate("interpolate-frequencies", oldValue);
604
+ }
605
+ get interpolateFrequencies() {
606
+ return this.getAttribute("interpolate-frequencies") !== "false";
607
+ }
664
608
  get shouldInterpolateFrequencies() {
665
609
  if (this.hasAttribute("interpolate-frequencies")) {
666
610
  return this.getAttribute("interpolate-frequencies") !== "false";
@@ -690,6 +634,14 @@ const _EFMedia = class _EFMedia2 extends EFTargetable(
690
634
  }
691
635
  #byteTimeDomainCache;
692
636
  #frequencyDataCache;
637
+ set fftGain(value) {
638
+ const oldValue = this.fftGain;
639
+ this.setAttribute("fft-gain", String(value));
640
+ this.requestUpdate("fft-gain", oldValue);
641
+ }
642
+ get fftGain() {
643
+ return Number.parseFloat(this.getAttribute("fft-gain") ?? "3.0");
644
+ }
693
645
  };
694
646
  __decorateClass([
695
647
  property({ type: Number })
@@ -1,10 +1,11 @@
1
1
  import { LitElement } from 'lit';
2
- declare const TestTemporal_base: (new (...args: any[]) => import('./EFTemporal.js').TemporalMixinInterface) & typeof LitElement;
3
- declare class TestTemporal extends TestTemporal_base {
2
+ declare const TenSeconds_base: (new (...args: any[]) => import('./EFTemporal.js').TemporalMixinInterface) & typeof LitElement;
3
+ declare class TenSeconds extends TenSeconds_base {
4
+ get intrinsicDurationMs(): number;
4
5
  }
5
6
  declare global {
6
7
  interface HTMLElementTagNameMap {
7
- "test-temporal": TestTemporal;
8
+ "ten-seconds": TenSeconds;
8
9
  }
9
10
  }
10
11
  export {};
@@ -10,6 +10,7 @@ export declare class TemporalMixinInterface {
10
10
  * Whether the element has a duration set as an attribute.
11
11
  */
12
12
  get hasExplicitDuration(): boolean;
13
+ get sourceStartMs(): number;
13
14
  /**
14
15
  * Used to trim the start of the media.
15
16
  *
@@ -19,7 +20,7 @@ export declare class TemporalMixinInterface {
19
20
  *
20
21
  * @domAttribute "trimstart"
21
22
  */
22
- get trimStartMs(): number;
23
+ get trimStartMs(): number | undefined;
23
24
  /**
24
25
  * Used to trim the end of the media.
25
26
  *
@@ -30,10 +31,10 @@ export declare class TemporalMixinInterface {
30
31
  * @domAttribute "trimend"
31
32
  */
32
33
  get trimEndMs(): number;
33
- set trimStartMs(value: number);
34
- set trimEndMs(value: number);
35
- set trimstart(value: string);
36
- set trimend(value: string);
34
+ set trimStartMs(value: number | undefined);
35
+ set trimEndMs(value: number | undefined);
36
+ set trimstart(value: string | undefined);
37
+ set trimend(value: string | undefined);
37
38
  /**
38
39
  * The source in time of the element.
39
40
  *
@@ -53,7 +54,7 @@ export declare class TemporalMixinInterface {
53
54
  *
54
55
  * @domAttribute "sourcein"
55
56
  */
56
- get sourceInMs(): number;
57
+ get sourceInMs(): number | undefined;
57
58
  /**
58
59
  * The source out time of the element.
59
60
  *
@@ -75,15 +76,17 @@ export declare class TemporalMixinInterface {
75
76
  *
76
77
  * @domAttribute "sourceout"
77
78
  */
78
- get sourceOutMs(): number;
79
- set sourceInMs(value: number);
80
- set sourceOutMs(value: number);
81
- set sourcein(value: string);
82
- set sourceout(value: string);
79
+ get sourceOutMs(): number | undefined;
80
+ set sourceInMs(value: number | undefined);
81
+ set sourceOutMs(value: number | undefined);
82
+ set sourcein(value: string | undefined);
83
+ set sourceout(value: string | undefined);
83
84
  /**
84
85
  * @domAttribute "duration"
85
86
  */
86
87
  get durationMs(): number;
88
+ get explicitDurationMs(): number | undefined;
89
+ get intrinsicDurationMs(): number | undefined;
87
90
  /**
88
91
  * The start time of the element within its root timegroup in milliseconds.
89
92
  *
@@ -76,8 +76,10 @@ const EFTemporal = (superClass) => {
76
76
  constructor() {
77
77
  super(...arguments);
78
78
  this._offsetMs = 0;
79
- this._trimStartMs = 0;
80
- this._trimEndMs = 0;
79
+ this._trimStartMs = void 0;
80
+ this._trimEndMs = void 0;
81
+ this._sourceInMs = void 0;
82
+ this._sourceOutMs = void 0;
81
83
  this._startOffsetMs = 0;
82
84
  this.rootTimegroup = this.getRootTimegroup();
83
85
  this.frameTask = new Task(this, {
@@ -118,75 +120,46 @@ const EFTemporal = (superClass) => {
118
120
  }
119
121
  }
120
122
  get trimStartMs() {
121
- return this._trimStartMs;
122
- }
123
- set trimStartMs(value) {
124
- if (this._trimStartMs === value) {
125
- return;
123
+ if (this._trimStartMs === void 0) {
124
+ return void 0;
126
125
  }
127
- this._trimStartMs = value;
128
- this.setAttribute(
129
- "trimstart",
130
- durationConverter.toAttribute(value / 1e3)
126
+ return Math.min(
127
+ Math.max(this._trimStartMs, 0),
128
+ this.intrinsicDurationMs ?? 0
131
129
  );
132
130
  }
133
- set trimstart(value) {
134
- if (value !== void 0) {
135
- this.setAttribute("trimstart", value);
136
- } else {
137
- this.removeAttribute("trimstart");
138
- }
131
+ set trimStartMs(value) {
132
+ this._trimStartMs = value;
139
133
  }
140
134
  get trimEndMs() {
141
- return this._trimEndMs;
135
+ if (this._trimEndMs === void 0) {
136
+ return void 0;
137
+ }
138
+ return Math.min(this._trimEndMs, this.intrinsicDurationMs ?? 0);
142
139
  }
143
140
  set trimEndMs(value) {
144
- if (this._trimEndMs === value) {
145
- return;
146
- }
147
141
  this._trimEndMs = value;
148
- this.setAttribute("trimend", durationConverter.toAttribute(value / 1e3));
149
- }
150
- set trimend(value) {
151
- if (value !== void 0) {
152
- this.setAttribute("trimend", value);
153
- } else {
154
- this.removeAttribute("trimend");
155
- }
156
142
  }
157
143
  get sourceInMs() {
158
- return this._sourceInMs;
144
+ if (this._sourceInMs === void 0) {
145
+ return void 0;
146
+ }
147
+ return Math.max(this._sourceInMs, 0);
159
148
  }
160
149
  set sourceInMs(value) {
161
150
  this._sourceInMs = value;
162
- value !== void 0 ? this.setAttribute(
163
- "sourcein",
164
- durationConverter.toAttribute(value / 1e3)
165
- ) : this.removeAttribute("sourcein");
166
- }
167
- set sourcein(value) {
168
- if (value !== void 0) {
169
- this.setAttribute("sourcein", value);
170
- } else {
171
- this.removeAttribute("sourcein");
172
- }
173
151
  }
174
152
  get sourceOutMs() {
175
- return this._sourceOutMs;
153
+ if (this._sourceOutMs === void 0) {
154
+ return void 0;
155
+ }
156
+ if (this.intrinsicDurationMs && this._sourceOutMs > this.intrinsicDurationMs) {
157
+ return this.intrinsicDurationMs;
158
+ }
159
+ return Math.max(this._sourceOutMs, 0);
176
160
  }
177
161
  set sourceOutMs(value) {
178
162
  this._sourceOutMs = value;
179
- value !== void 0 ? this.setAttribute(
180
- "sourceout",
181
- durationConverter.toAttribute(value / 1e3)
182
- ) : this.removeAttribute("sourceout");
183
- }
184
- set sourceout(value) {
185
- if (value !== void 0) {
186
- this.setAttribute("sourceout", value);
187
- } else {
188
- this.removeAttribute("sourceout");
189
- }
190
163
  }
191
164
  get startOffsetMs() {
192
165
  return this._startOffsetMs;
@@ -201,19 +174,41 @@ const EFTemporal = (superClass) => {
201
174
  get hasExplicitDuration() {
202
175
  return this._durationMs !== void 0;
203
176
  }
177
+ get explicitDurationMs() {
178
+ if (this.hasExplicitDuration) {
179
+ return this._durationMs;
180
+ }
181
+ return void 0;
182
+ }
204
183
  get hasOwnDuration() {
205
184
  return false;
206
185
  }
207
- // Defining this as a getter to a private property allows us to
208
- // override it classes that include this mixin.
186
+ get intrinsicDurationMs() {
187
+ return void 0;
188
+ }
209
189
  get durationMs() {
210
- if (this.sourceInMs) {
211
- return this._durationMs || this.parentTimegroup?.durationMs || 0 - this.sourceInMs;
190
+ if (this.intrinsicDurationMs === void 0) {
191
+ return this._durationMs || this.parentTimegroup?.durationMs || 0;
212
192
  }
213
- if (this.sourceOutMs) {
214
- return this._durationMs || this.parentTimegroup?.durationMs || 0 - this.sourceOutMs;
193
+ if (this.trimStartMs || this.trimEndMs) {
194
+ const trimmedDurationMs = this.intrinsicDurationMs - (this.trimStartMs ?? 0) - (this.trimEndMs ?? 0);
195
+ if (trimmedDurationMs < 0) {
196
+ return 0;
197
+ }
198
+ return trimmedDurationMs;
199
+ }
200
+ if (this.sourceInMs || this.sourceOutMs) {
201
+ const sourceInMs = this.sourceInMs ?? 0;
202
+ const sourceOutMs = this.sourceOutMs ?? this.intrinsicDurationMs;
203
+ if (sourceInMs >= sourceOutMs) {
204
+ return 0;
205
+ }
206
+ return sourceOutMs - sourceInMs;
215
207
  }
216
- return this._durationMs || this.parentTimegroup?.durationMs || 0;
208
+ return this.intrinsicDurationMs;
209
+ }
210
+ get sourceStartMs() {
211
+ return this.trimStartMs ?? this.sourceInMs ?? 0;
217
212
  }
218
213
  get offsetMs() {
219
214
  return this._offsetMs || 0;
@@ -296,25 +291,8 @@ const EFTemporal = (superClass) => {
296
291
  * for mapping to internal media time codes for audio/video elements.
297
292
  */
298
293
  get currentSourceTimeMs() {
299
- if (this.rootTimegroup) {
300
- if (this.sourceInMs && this.sourceOutMs) {
301
- return Math.min(
302
- Math.max(
303
- 0,
304
- this.rootTimegroup.currentTimeMs - this.startTimeMs + this.trimStartMs + this.sourceInMs
305
- ),
306
- this.durationMs + Math.abs(this.startOffsetMs) + this.trimStartMs + this.sourceInMs
307
- );
308
- }
309
- return Math.min(
310
- Math.max(
311
- 0,
312
- this.rootTimegroup.currentTimeMs - this.startTimeMs + this.trimStartMs
313
- ),
314
- this.durationMs + Math.abs(this.startOffsetMs) + this.trimStartMs
315
- );
316
- }
317
- return 0;
294
+ const leadingTrimMs = this.sourceInMs || this.trimStartMs || 0;
295
+ return this.ownCurrentTimeMs + leadingTrimMs;
318
296
  }
319
297
  updated(changedProperties) {
320
298
  super.updated(changedProperties);
@@ -352,30 +330,28 @@ const EFTemporal = (superClass) => {
352
330
  attribute: "trimstart",
353
331
  converter: durationConverter
354
332
  })
355
- ], TemporalMixinClass.prototype, "trimStartMs", 1);
333
+ ], TemporalMixinClass.prototype, "_trimStartMs", 2);
356
334
  __decorateClass([
357
335
  property({
358
336
  type: Number,
359
337
  attribute: "trimend",
360
338
  converter: durationConverter
361
339
  })
362
- ], TemporalMixinClass.prototype, "trimEndMs", 1);
340
+ ], TemporalMixinClass.prototype, "_trimEndMs", 2);
363
341
  __decorateClass([
364
342
  property({
365
343
  type: Number,
366
344
  attribute: "sourcein",
367
- converter: durationConverter,
368
- reflect: true
345
+ converter: durationConverter
369
346
  })
370
- ], TemporalMixinClass.prototype, "sourceInMs", 1);
347
+ ], TemporalMixinClass.prototype, "_sourceInMs", 2);
371
348
  __decorateClass([
372
349
  property({
373
350
  type: Number,
374
351
  attribute: "sourceout",
375
- converter: durationConverter,
376
- reflect: true
352
+ converter: durationConverter
377
353
  })
378
- ], TemporalMixinClass.prototype, "sourceOutMs", 1);
354
+ ], TemporalMixinClass.prototype, "_sourceOutMs", 2);
379
355
  __decorateClass([
380
356
  property({
381
357
  type: Number,
@@ -18,6 +18,7 @@ export declare class EFTimegroup extends EFTimegroup_base {
18
18
  connectedCallback(): void;
19
19
  disconnectedCallback(): void;
20
20
  get storageKey(): string;
21
+ get intrinsicDurationMs(): number | undefined;
21
22
  get durationMs(): number;
22
23
  /**
23
24
  * Wait for all media elements to load their initial segments.
@@ -41,7 +42,6 @@ export declare class EFTimegroup extends EFTimegroup_base {
41
42
  */
42
43
  shouldWrapWithWorkbench(): boolean;
43
44
  wrapWithWorkbench(): void;
44
- get hasOwnDuration(): boolean;
45
45
  get efElements(): Element[];
46
46
  renderAudio(fromMs: number, toMs: number): Promise<AudioBuffer>;
47
47
  loadMd5Sums(): Promise<void>;