@editframe/elements 0.16.8-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.
Files changed (101) hide show
  1. package/README.md +30 -0
  2. package/dist/DecoderResetFrequency.test.d.ts +1 -0
  3. package/dist/DecoderResetRecovery.test.d.ts +1 -0
  4. package/dist/DelayedLoadingState.d.ts +48 -0
  5. package/dist/DelayedLoadingState.integration.test.d.ts +1 -0
  6. package/dist/DelayedLoadingState.js +113 -0
  7. package/dist/DelayedLoadingState.test.d.ts +1 -0
  8. package/dist/EF_FRAMEGEN.d.ts +10 -1
  9. package/dist/EF_FRAMEGEN.js +199 -179
  10. package/dist/EF_INTERACTIVE.js +2 -6
  11. package/dist/EF_RENDERING.js +1 -3
  12. package/dist/JitTranscodingClient.browsertest.d.ts +1 -0
  13. package/dist/JitTranscodingClient.d.ts +167 -0
  14. package/dist/JitTranscodingClient.js +373 -0
  15. package/dist/JitTranscodingClient.test.d.ts +1 -0
  16. package/dist/LoadingDebounce.test.d.ts +1 -0
  17. package/dist/LoadingIndicator.browsertest.d.ts +0 -0
  18. package/dist/ManualScrubTest.test.d.ts +1 -0
  19. package/dist/ScrubResolvedFlashing.test.d.ts +1 -0
  20. package/dist/ScrubTrackIntegration.test.d.ts +1 -0
  21. package/dist/ScrubTrackManager.d.ts +96 -0
  22. package/dist/ScrubTrackManager.js +216 -0
  23. package/dist/ScrubTrackManager.test.d.ts +1 -0
  24. package/dist/SegmentSwitchLoading.test.d.ts +1 -0
  25. package/dist/VideoSeekFlashing.browsertest.d.ts +0 -0
  26. package/dist/VideoStuckDiagnostic.test.d.ts +1 -0
  27. package/dist/elements/CrossUpdateController.js +13 -15
  28. package/dist/elements/EFAudio.browsertest.d.ts +0 -0
  29. package/dist/elements/EFAudio.d.ts +1 -1
  30. package/dist/elements/EFAudio.js +30 -43
  31. package/dist/elements/EFCaptions.js +337 -373
  32. package/dist/elements/EFImage.js +64 -90
  33. package/dist/elements/EFMedia.d.ts +98 -33
  34. package/dist/elements/EFMedia.js +1169 -678
  35. package/dist/elements/EFSourceMixin.js +31 -48
  36. package/dist/elements/EFTemporal.d.ts +1 -0
  37. package/dist/elements/EFTemporal.js +266 -360
  38. package/dist/elements/EFTimegroup.d.ts +3 -1
  39. package/dist/elements/EFTimegroup.js +262 -323
  40. package/dist/elements/EFVideo.browsertest.d.ts +0 -0
  41. package/dist/elements/EFVideo.d.ts +90 -2
  42. package/dist/elements/EFVideo.js +408 -111
  43. package/dist/elements/EFWaveform.js +375 -411
  44. package/dist/elements/FetchMixin.js +14 -24
  45. package/dist/elements/MediaController.d.ts +30 -0
  46. package/dist/elements/TargetController.js +130 -156
  47. package/dist/elements/TimegroupController.js +17 -19
  48. package/dist/elements/durationConverter.js +15 -4
  49. package/dist/elements/parseTimeToMs.js +4 -10
  50. package/dist/elements/printTaskStatus.d.ts +2 -0
  51. package/dist/elements/printTaskStatus.js +11 -0
  52. package/dist/elements/updateAnimations.js +39 -59
  53. package/dist/getRenderInfo.js +58 -67
  54. package/dist/gui/ContextMixin.js +203 -288
  55. package/dist/gui/EFConfiguration.js +27 -43
  56. package/dist/gui/EFFilmstrip.js +440 -620
  57. package/dist/gui/EFFitScale.js +112 -135
  58. package/dist/gui/EFFocusOverlay.js +45 -61
  59. package/dist/gui/EFPreview.js +30 -49
  60. package/dist/gui/EFScrubber.js +78 -99
  61. package/dist/gui/EFTimeDisplay.js +49 -70
  62. package/dist/gui/EFToggleLoop.js +17 -34
  63. package/dist/gui/EFTogglePlay.js +37 -58
  64. package/dist/gui/EFWorkbench.js +66 -88
  65. package/dist/gui/TWMixin.js +2 -48
  66. package/dist/gui/TWMixin2.js +31 -0
  67. package/dist/gui/efContext.js +2 -6
  68. package/dist/gui/fetchContext.js +1 -3
  69. package/dist/gui/focusContext.js +1 -3
  70. package/dist/gui/focusedElementContext.js +2 -6
  71. package/dist/gui/playingContext.js +1 -4
  72. package/dist/index.js +5 -30
  73. package/dist/msToTimeCode.js +11 -13
  74. package/dist/style.css +2 -1
  75. package/package.json +3 -3
  76. package/src/elements/EFAudio.browsertest.ts +569 -0
  77. package/src/elements/EFAudio.ts +4 -6
  78. package/src/elements/EFCaptions.browsertest.ts +0 -1
  79. package/src/elements/EFImage.browsertest.ts +0 -1
  80. package/src/elements/EFMedia.browsertest.ts +147 -115
  81. package/src/elements/EFMedia.ts +1339 -307
  82. package/src/elements/EFTemporal.browsertest.ts +0 -1
  83. package/src/elements/EFTemporal.ts +11 -0
  84. package/src/elements/EFTimegroup.ts +73 -10
  85. package/src/elements/EFVideo.browsertest.ts +680 -0
  86. package/src/elements/EFVideo.ts +729 -50
  87. package/src/elements/EFWaveform.ts +4 -4
  88. package/src/elements/MediaController.ts +108 -0
  89. package/src/elements/__screenshots__/EFMedia.browsertest.ts/EFMedia-JIT-audio-playback-audioBufferTask-should-work-in-JIT-mode-without-URL-errors-1.png +0 -0
  90. package/src/elements/printTaskStatus.ts +16 -0
  91. package/src/elements/updateAnimations.ts +6 -0
  92. package/src/gui/TWMixin.ts +10 -3
  93. package/test/EFVideo.frame-tasks.browsertest.ts +524 -0
  94. package/test/EFVideo.framegen.browsertest.ts +118 -0
  95. package/test/createJitTestClips.ts +293 -0
  96. package/test/useAssetMSW.ts +49 -0
  97. package/test/useMSW.ts +31 -0
  98. package/types.json +1 -1
  99. package/dist/gui/TWMixin.css.js +0 -4
  100. /package/dist/elements/{TargetController.test.d.ts → TargetController.browsertest.d.ts} +0 -0
  101. /package/src/elements/{TargetController.test.ts → TargetController.browsertest.ts} +0 -0
@@ -1,49 +1,31 @@
1
- import { Task } from "@lit/task";
2
- import { LitElement, html, css } from "lit";
3
- import { property, customElement } from "lit/decorators.js";
4
1
  import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
5
- import { CrossUpdateController } from "./CrossUpdateController.js";
6
- import { EFAudio } from "./EFAudio.js";
7
2
  import { EFSourceMixin } from "./EFSourceMixin.js";
8
3
  import { EFTemporal } from "./EFTemporal.js";
9
- import { EFVideo } from "./EFVideo.js";
10
4
  import { FetchMixin } from "./FetchMixin.js";
11
- var __defProp = Object.defineProperty;
12
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
- var __decorateClass = (decorators, target, key, kind) => {
14
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
15
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
16
- if (decorator = decorators[i])
17
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
18
- if (kind && result) __defProp(target, key, result);
19
- return result;
20
- };
21
- const stopWords = /* @__PURE__ */ new Set(["", ".", "!", "?", ","]);
22
- let EFCaptionsActiveWord = class extends EFTemporal(LitElement) {
23
- constructor() {
24
- super(...arguments);
25
- this.wordStartMs = 0;
26
- this.wordEndMs = 0;
27
- this.wordText = "";
28
- this.hidden = false;
29
- }
30
- render() {
31
- if (stopWords.has(this.wordText)) {
32
- this.hidden = true;
33
- return void 0;
34
- }
35
- this.hidden = false;
36
- return html` ${this.wordText.trim()} `;
37
- }
38
- get startTimeMs() {
39
- return this.wordStartMs || 0;
40
- }
41
- get durationMs() {
42
- return this.wordEndMs - this.wordStartMs;
43
- }
44
- };
45
- EFCaptionsActiveWord.styles = [
46
- css`
5
+ import { EFAudio } from "./EFAudio.js";
6
+ import { EFVideo } from "./EFVideo.js";
7
+ import { CrossUpdateController } from "./CrossUpdateController.js";
8
+ import { Task } from "@lit/task";
9
+ import { LitElement, css, html } from "lit";
10
+ import { customElement, property } from "lit/decorators.js";
11
+ import _decorate from "@oxc-project/runtime/helpers/decorate";
12
+ const stopWords = new Set([
13
+ "",
14
+ ".",
15
+ "!",
16
+ "?",
17
+ ","
18
+ ]);
19
+ let EFCaptionsActiveWord = class EFCaptionsActiveWord$1 extends EFTemporal(LitElement) {
20
+ constructor(..._args) {
21
+ super(..._args);
22
+ this.wordStartMs = 0;
23
+ this.wordEndMs = 0;
24
+ this.wordText = "";
25
+ this.hidden = false;
26
+ }
27
+ static {
28
+ this.styles = [css`
47
29
  :host {
48
30
  display: inline-block;
49
31
  white-space: pre;
@@ -51,96 +33,100 @@ EFCaptionsActiveWord.styles = [
51
33
  :host([hidden]) {
52
34
  display: none;
53
35
  }
54
- `
55
- ];
56
- __decorateClass([
57
- property({ type: Number, attribute: false })
58
- ], EFCaptionsActiveWord.prototype, "wordStartMs", 2);
59
- __decorateClass([
60
- property({ type: Number, attribute: false })
61
- ], EFCaptionsActiveWord.prototype, "wordEndMs", 2);
62
- __decorateClass([
63
- property({ type: String, attribute: false })
64
- ], EFCaptionsActiveWord.prototype, "wordText", 2);
65
- __decorateClass([
66
- property({ type: Boolean, reflect: true })
67
- ], EFCaptionsActiveWord.prototype, "hidden", 2);
68
- EFCaptionsActiveWord = __decorateClass([
69
- customElement("ef-captions-active-word")
70
- ], EFCaptionsActiveWord);
71
- let EFCaptionsSegment = class extends EFTemporal(LitElement) {
72
- constructor() {
73
- super(...arguments);
74
- this.segmentStartMs = 0;
75
- this.segmentEndMs = 0;
76
- this.segmentText = "";
77
- this.hidden = false;
78
- }
79
- render() {
80
- if (stopWords.has(this.segmentText)) {
81
- this.hidden = true;
82
- return void 0;
83
- }
84
- this.hidden = false;
85
- return html`${this.segmentText}`;
86
- }
87
- get startTimeMs() {
88
- return this.segmentStartMs || 0;
89
- }
90
- get durationMs() {
91
- return this.segmentEndMs - this.segmentStartMs;
92
- }
36
+ `];
37
+ }
38
+ render() {
39
+ if (stopWords.has(this.wordText)) {
40
+ this.hidden = true;
41
+ return void 0;
42
+ }
43
+ this.hidden = false;
44
+ return html` ${this.wordText.trim()} `;
45
+ }
46
+ get startTimeMs() {
47
+ return this.wordStartMs || 0;
48
+ }
49
+ get durationMs() {
50
+ return this.wordEndMs - this.wordStartMs;
51
+ }
93
52
  };
94
- EFCaptionsSegment.styles = [
95
- css`
53
+ _decorate([property({
54
+ type: Number,
55
+ attribute: false
56
+ })], EFCaptionsActiveWord.prototype, "wordStartMs", void 0);
57
+ _decorate([property({
58
+ type: Number,
59
+ attribute: false
60
+ })], EFCaptionsActiveWord.prototype, "wordEndMs", void 0);
61
+ _decorate([property({
62
+ type: String,
63
+ attribute: false
64
+ })], EFCaptionsActiveWord.prototype, "wordText", void 0);
65
+ _decorate([property({
66
+ type: Boolean,
67
+ reflect: true
68
+ })], EFCaptionsActiveWord.prototype, "hidden", void 0);
69
+ EFCaptionsActiveWord = _decorate([customElement("ef-captions-active-word")], EFCaptionsActiveWord);
70
+ let EFCaptionsSegment = class EFCaptionsSegment$1 extends EFTemporal(LitElement) {
71
+ constructor(..._args2) {
72
+ super(..._args2);
73
+ this.segmentStartMs = 0;
74
+ this.segmentEndMs = 0;
75
+ this.segmentText = "";
76
+ this.hidden = false;
77
+ }
78
+ static {
79
+ this.styles = [css`
96
80
  :host {
97
81
  display: block;
98
82
  }
99
83
  :host([hidden]) {
100
84
  display: none;
101
85
  }
102
- `
103
- ];
104
- __decorateClass([
105
- property({ type: Number, attribute: false })
106
- ], EFCaptionsSegment.prototype, "segmentStartMs", 2);
107
- __decorateClass([
108
- property({ type: Number, attribute: false })
109
- ], EFCaptionsSegment.prototype, "segmentEndMs", 2);
110
- __decorateClass([
111
- property({ type: String, attribute: false })
112
- ], EFCaptionsSegment.prototype, "segmentText", 2);
113
- __decorateClass([
114
- property({ type: Boolean, reflect: true })
115
- ], EFCaptionsSegment.prototype, "hidden", 2);
116
- EFCaptionsSegment = __decorateClass([
117
- customElement("ef-captions-segment")
118
- ], EFCaptionsSegment);
119
- let EFCaptionsBeforeActiveWord = class extends EFCaptionsSegment {
120
- constructor() {
121
- super(...arguments);
122
- this.hidden = false;
123
- this.segmentText = "";
124
- this.segmentStartMs = 0;
125
- this.segmentEndMs = 0;
126
- }
127
- render() {
128
- if (stopWords.has(this.segmentText)) {
129
- this.hidden = true;
130
- return void 0;
131
- }
132
- this.hidden = false;
133
- return html` ${this.segmentText}`;
134
- }
135
- get startTimeMs() {
136
- return this.segmentStartMs || 0;
137
- }
138
- get durationMs() {
139
- return this.segmentEndMs - this.segmentStartMs;
140
- }
86
+ `];
87
+ }
88
+ render() {
89
+ if (stopWords.has(this.segmentText)) {
90
+ this.hidden = true;
91
+ return void 0;
92
+ }
93
+ this.hidden = false;
94
+ return html`${this.segmentText}`;
95
+ }
96
+ get startTimeMs() {
97
+ return this.segmentStartMs || 0;
98
+ }
99
+ get durationMs() {
100
+ return this.segmentEndMs - this.segmentStartMs;
101
+ }
141
102
  };
142
- EFCaptionsBeforeActiveWord.styles = [
143
- css`
103
+ _decorate([property({
104
+ type: Number,
105
+ attribute: false
106
+ })], EFCaptionsSegment.prototype, "segmentStartMs", void 0);
107
+ _decorate([property({
108
+ type: Number,
109
+ attribute: false
110
+ })], EFCaptionsSegment.prototype, "segmentEndMs", void 0);
111
+ _decorate([property({
112
+ type: String,
113
+ attribute: false
114
+ })], EFCaptionsSegment.prototype, "segmentText", void 0);
115
+ _decorate([property({
116
+ type: Boolean,
117
+ reflect: true
118
+ })], EFCaptionsSegment.prototype, "hidden", void 0);
119
+ EFCaptionsSegment = _decorate([customElement("ef-captions-segment")], EFCaptionsSegment);
120
+ let EFCaptionsBeforeActiveWord = class EFCaptionsBeforeActiveWord$1 extends EFCaptionsSegment {
121
+ constructor(..._args3) {
122
+ super(..._args3);
123
+ this.hidden = false;
124
+ this.segmentText = "";
125
+ this.segmentStartMs = 0;
126
+ this.segmentEndMs = 0;
127
+ }
128
+ static {
129
+ this.styles = [css`
144
130
  :host {
145
131
  display: inline-block;
146
132
  white-space: pre;
@@ -148,48 +134,50 @@ EFCaptionsBeforeActiveWord.styles = [
148
134
  :host([hidden]) {
149
135
  display: none;
150
136
  }
151
- `
152
- ];
153
- __decorateClass([
154
- property({ type: Boolean, reflect: true })
155
- ], EFCaptionsBeforeActiveWord.prototype, "hidden", 2);
156
- __decorateClass([
157
- property({ type: String, attribute: false })
158
- ], EFCaptionsBeforeActiveWord.prototype, "segmentText", 2);
159
- __decorateClass([
160
- property({ type: Number, attribute: false })
161
- ], EFCaptionsBeforeActiveWord.prototype, "segmentStartMs", 2);
162
- __decorateClass([
163
- property({ type: Number, attribute: false })
164
- ], EFCaptionsBeforeActiveWord.prototype, "segmentEndMs", 2);
165
- EFCaptionsBeforeActiveWord = __decorateClass([
166
- customElement("ef-captions-before-active-word")
167
- ], EFCaptionsBeforeActiveWord);
168
- let EFCaptionsAfterActiveWord = class extends EFCaptionsSegment {
169
- constructor() {
170
- super(...arguments);
171
- this.hidden = false;
172
- this.segmentText = "";
173
- this.segmentStartMs = 0;
174
- this.segmentEndMs = 0;
175
- }
176
- render() {
177
- if (stopWords.has(this.segmentText)) {
178
- this.hidden = true;
179
- return void 0;
180
- }
181
- this.hidden = false;
182
- return html`${this.segmentText} `;
183
- }
184
- get startTimeMs() {
185
- return this.segmentStartMs || 0;
186
- }
187
- get durationMs() {
188
- return this.segmentEndMs - this.segmentStartMs;
189
- }
137
+ `];
138
+ }
139
+ render() {
140
+ if (stopWords.has(this.segmentText)) {
141
+ this.hidden = true;
142
+ return void 0;
143
+ }
144
+ this.hidden = false;
145
+ return html` ${this.segmentText}`;
146
+ }
147
+ get startTimeMs() {
148
+ return this.segmentStartMs || 0;
149
+ }
150
+ get durationMs() {
151
+ return this.segmentEndMs - this.segmentStartMs;
152
+ }
190
153
  };
191
- EFCaptionsAfterActiveWord.styles = [
192
- css`
154
+ _decorate([property({
155
+ type: Boolean,
156
+ reflect: true
157
+ })], EFCaptionsBeforeActiveWord.prototype, "hidden", void 0);
158
+ _decorate([property({
159
+ type: String,
160
+ attribute: false
161
+ })], EFCaptionsBeforeActiveWord.prototype, "segmentText", void 0);
162
+ _decorate([property({
163
+ type: Number,
164
+ attribute: false
165
+ })], EFCaptionsBeforeActiveWord.prototype, "segmentStartMs", void 0);
166
+ _decorate([property({
167
+ type: Number,
168
+ attribute: false
169
+ })], EFCaptionsBeforeActiveWord.prototype, "segmentEndMs", void 0);
170
+ EFCaptionsBeforeActiveWord = _decorate([customElement("ef-captions-before-active-word")], EFCaptionsBeforeActiveWord);
171
+ let EFCaptionsAfterActiveWord = class EFCaptionsAfterActiveWord$1 extends EFCaptionsSegment {
172
+ constructor(..._args4) {
173
+ super(..._args4);
174
+ this.hidden = false;
175
+ this.segmentText = "";
176
+ this.segmentStartMs = 0;
177
+ this.segmentEndMs = 0;
178
+ }
179
+ static {
180
+ this.styles = [css`
193
181
  :host {
194
182
  display: inline-block;
195
183
  white-space: pre;
@@ -197,192 +185,105 @@ EFCaptionsAfterActiveWord.styles = [
197
185
  :host([hidden]) {
198
186
  display: none;
199
187
  }
200
- `
201
- ];
202
- __decorateClass([
203
- property({ type: Boolean, reflect: true })
204
- ], EFCaptionsAfterActiveWord.prototype, "hidden", 2);
205
- __decorateClass([
206
- property({ type: String, attribute: false })
207
- ], EFCaptionsAfterActiveWord.prototype, "segmentText", 2);
208
- __decorateClass([
209
- property({ type: Number, attribute: false })
210
- ], EFCaptionsAfterActiveWord.prototype, "segmentStartMs", 2);
211
- __decorateClass([
212
- property({ type: Number, attribute: false })
213
- ], EFCaptionsAfterActiveWord.prototype, "segmentEndMs", 2);
214
- EFCaptionsAfterActiveWord = __decorateClass([
215
- customElement("ef-captions-after-active-word")
216
- ], EFCaptionsAfterActiveWord);
217
- let EFCaptions = class extends EFSourceMixin(
218
- EFTemporal(FetchMixin(LitElement)),
219
- { assetType: "caption_files" }
220
- ) {
221
- constructor() {
222
- super(...arguments);
223
- this.displayMode = "segment";
224
- this.contextWords = 3;
225
- this.targetSelector = "";
226
- this.wordStyle = "";
227
- this.activeWordContainers = this.getElementsByTagName("ef-captions-active-word");
228
- this.segmentContainers = this.getElementsByTagName("ef-captions-segment");
229
- this.beforeActiveWordContainers = this.getElementsByTagName(
230
- "ef-captions-before-active-word"
231
- );
232
- this.afterActiveWordContainers = this.getElementsByTagName(
233
- "ef-captions-after-active-word"
234
- );
235
- this.md5SumLoader = new Task(this, {
236
- autoRun: false,
237
- args: () => [this.target, this.fetch],
238
- task: async ([_target, fetch], { signal }) => {
239
- const md5Path = `/@ef-asset/${this.targetElement.src ?? ""}`;
240
- const response = await fetch(md5Path, { method: "HEAD", signal });
241
- return response.headers.get("etag") ?? void 0;
242
- }
243
- });
244
- this.transcriptionDataTask = new Task(this, {
245
- autoRun: EF_INTERACTIVE,
246
- args: () => [this.transcriptionsPath(), this.fetch],
247
- task: async ([transcriptionsPath, fetch], { signal }) => {
248
- if (!transcriptionsPath) {
249
- return null;
250
- }
251
- const response = await fetch(transcriptionsPath, { signal });
252
- return response.json();
253
- }
254
- });
255
- this.fragmentIndexTask = new Task(this, {
256
- autoRun: EF_INTERACTIVE,
257
- args: () => [this.transcriptionDataTask.value, this.ownCurrentTimeMs],
258
- task: async ([transcription, ownCurrentTimeMs]) => {
259
- if (!transcription) {
260
- return null;
261
- }
262
- const fragmentIndex = Math.floor(
263
- ownCurrentTimeMs / transcription.work_slice_ms
264
- );
265
- return fragmentIndex;
266
- }
267
- });
268
- this.transcriptionFragmentDataTask = new Task(this, {
269
- autoRun: EF_INTERACTIVE,
270
- args: () => [
271
- this.transcriptionDataTask.value,
272
- this.fragmentIndexTask.value,
273
- this.fetch
274
- ],
275
- task: async ([transcription, fragmentIndex, fetch], { signal }) => {
276
- if (transcription === null || transcription === void 0 || fragmentIndex === null || fragmentIndex === void 0) {
277
- return null;
278
- }
279
- const fragmentPath = this.transcriptionFragmentPath(
280
- transcription.id,
281
- fragmentIndex
282
- );
283
- const response = await fetch(fragmentPath, { signal });
284
- return response.json();
285
- }
286
- });
287
- this.frameTask = new Task(this, {
288
- autoRun: EF_INTERACTIVE,
289
- args: () => [this.transcriptionFragmentDataTask.status],
290
- task: async () => {
291
- await this.transcriptionFragmentDataTask.taskComplete;
292
- }
293
- });
294
- }
295
- set target(value) {
296
- this.targetSelector = value;
297
- }
298
- render() {
299
- return html`<slot></slot>`;
300
- }
301
- transcriptionsPath() {
302
- if (this.targetElement.assetId) {
303
- return `${this.apiHost}/api/v1/isobmff_files/${this.targetElement.assetId}/transcription`;
304
- }
305
- return null;
306
- }
307
- captionsPath() {
308
- if (this.targetElement.assetId) {
309
- return `${this.apiHost}/api/v1/caption_files/${this.targetElement.assetId}`;
310
- }
311
- const targetSrc = this.targetElement.src;
312
- return `/@ef-captions/${targetSrc}`;
313
- }
314
- transcriptionFragmentPath(transcriptionId, fragmentIndex) {
315
- return `${this.apiHost}/api/v1/transcriptions/${transcriptionId}/fragments/${fragmentIndex}`;
316
- }
317
- connectedCallback() {
318
- super.connectedCallback();
319
- if (this.targetElement) {
320
- new CrossUpdateController(this.targetElement, this);
321
- }
322
- }
323
- updated(_changedProperties) {
324
- this.updateTextContainers();
325
- }
326
- updateTextContainers() {
327
- const transcriptionFragment = this.transcriptionFragmentDataTask.value;
328
- if (!transcriptionFragment) {
329
- return;
330
- }
331
- const currentTimeMs = this.targetElement.currentSourceTimeMs;
332
- const currentTimeSec = currentTimeMs / 1e3;
333
- const currentWord = transcriptionFragment.word_segments.find(
334
- (word) => currentTimeSec >= word.start && currentTimeSec <= word.end
335
- );
336
- const currentSegment = transcriptionFragment.segments.find(
337
- (segment) => currentTimeSec >= segment.start && currentTimeSec <= segment.end
338
- );
339
- for (const wordContainer of this.activeWordContainers) {
340
- if (currentWord) {
341
- wordContainer.wordText = currentWord.text;
342
- wordContainer.wordStartMs = currentWord.start * 1e3;
343
- wordContainer.wordEndMs = currentWord.end * 1e3;
344
- }
345
- }
346
- for (const segmentContainer of this.segmentContainers) {
347
- if (currentSegment) {
348
- segmentContainer.segmentText = currentSegment.text;
349
- segmentContainer.segmentStartMs = currentSegment.start * 1e3;
350
- segmentContainer.segmentEndMs = currentSegment.end * 1e3;
351
- }
352
- }
353
- if (currentWord && currentSegment) {
354
- const segmentWords = transcriptionFragment.word_segments.filter(
355
- (word) => word.start >= currentSegment.start && word.end <= currentSegment.end
356
- );
357
- const currentWordIndex = segmentWords.findIndex(
358
- (word) => word.start === currentWord.start && word.end === currentWord.end
359
- );
360
- if (currentWordIndex !== -1) {
361
- const beforeWords = segmentWords.slice(0, currentWordIndex).map((w) => w.text.trim()).join(" ");
362
- const afterWords = segmentWords.slice(currentWordIndex + 1).map((w) => w.text.trim()).join(" ");
363
- for (const container of this.beforeActiveWordContainers) {
364
- container.segmentText = beforeWords;
365
- container.segmentStartMs = currentSegment.start * 1e3;
366
- container.segmentEndMs = currentWord.start * 1e3;
367
- }
368
- for (const container of this.afterActiveWordContainers) {
369
- container.segmentText = afterWords;
370
- container.segmentStartMs = currentWord.end * 1e3;
371
- container.segmentEndMs = currentSegment.end * 1e3;
372
- }
373
- }
374
- }
375
- }
376
- get targetElement() {
377
- const target = document.getElementById(this.targetSelector ?? "");
378
- if (target instanceof EFAudio || target instanceof EFVideo) {
379
- return target;
380
- }
381
- throw new Error("Invalid target, must be an EFAudio or EFVideo element");
382
- }
188
+ `];
189
+ }
190
+ render() {
191
+ if (stopWords.has(this.segmentText)) {
192
+ this.hidden = true;
193
+ return void 0;
194
+ }
195
+ this.hidden = false;
196
+ return html`${this.segmentText} `;
197
+ }
198
+ get startTimeMs() {
199
+ return this.segmentStartMs || 0;
200
+ }
201
+ get durationMs() {
202
+ return this.segmentEndMs - this.segmentStartMs;
203
+ }
383
204
  };
384
- EFCaptions.styles = [
385
- css`
205
+ _decorate([property({
206
+ type: Boolean,
207
+ reflect: true
208
+ })], EFCaptionsAfterActiveWord.prototype, "hidden", void 0);
209
+ _decorate([property({
210
+ type: String,
211
+ attribute: false
212
+ })], EFCaptionsAfterActiveWord.prototype, "segmentText", void 0);
213
+ _decorate([property({
214
+ type: Number,
215
+ attribute: false
216
+ })], EFCaptionsAfterActiveWord.prototype, "segmentStartMs", void 0);
217
+ _decorate([property({
218
+ type: Number,
219
+ attribute: false
220
+ })], EFCaptionsAfterActiveWord.prototype, "segmentEndMs", void 0);
221
+ EFCaptionsAfterActiveWord = _decorate([customElement("ef-captions-after-active-word")], EFCaptionsAfterActiveWord);
222
+ let EFCaptions = class EFCaptions$1 extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), { assetType: "caption_files" }) {
223
+ constructor(..._args5) {
224
+ super(..._args5);
225
+ this.displayMode = "segment";
226
+ this.contextWords = 3;
227
+ this.targetSelector = "";
228
+ this.wordStyle = "";
229
+ this.activeWordContainers = this.getElementsByTagName("ef-captions-active-word");
230
+ this.segmentContainers = this.getElementsByTagName("ef-captions-segment");
231
+ this.beforeActiveWordContainers = this.getElementsByTagName("ef-captions-before-active-word");
232
+ this.afterActiveWordContainers = this.getElementsByTagName("ef-captions-after-active-word");
233
+ this.md5SumLoader = new Task(this, {
234
+ autoRun: false,
235
+ args: () => [this.target, this.fetch],
236
+ task: async ([_target, fetch], { signal }) => {
237
+ const md5Path = `/@ef-asset/${this.targetElement.src ?? ""}`;
238
+ const response = await fetch(md5Path, {
239
+ method: "HEAD",
240
+ signal
241
+ });
242
+ return response.headers.get("etag") ?? void 0;
243
+ }
244
+ });
245
+ this.transcriptionDataTask = new Task(this, {
246
+ autoRun: EF_INTERACTIVE,
247
+ args: () => [this.transcriptionsPath(), this.fetch],
248
+ task: async ([transcriptionsPath, fetch], { signal }) => {
249
+ if (!transcriptionsPath) return null;
250
+ const response = await fetch(transcriptionsPath, { signal });
251
+ return response.json();
252
+ }
253
+ });
254
+ this.fragmentIndexTask = new Task(this, {
255
+ autoRun: EF_INTERACTIVE,
256
+ args: () => [this.transcriptionDataTask.value, this.ownCurrentTimeMs],
257
+ task: async ([transcription, ownCurrentTimeMs]) => {
258
+ if (!transcription) return null;
259
+ const fragmentIndex = Math.floor(ownCurrentTimeMs / transcription.work_slice_ms);
260
+ return fragmentIndex;
261
+ }
262
+ });
263
+ this.transcriptionFragmentDataTask = new Task(this, {
264
+ autoRun: EF_INTERACTIVE,
265
+ args: () => [
266
+ this.transcriptionDataTask.value,
267
+ this.fragmentIndexTask.value,
268
+ this.fetch
269
+ ],
270
+ task: async ([transcription, fragmentIndex, fetch], { signal }) => {
271
+ if (transcription === null || transcription === void 0 || fragmentIndex === null || fragmentIndex === void 0) return null;
272
+ const fragmentPath = this.transcriptionFragmentPath(transcription.id, fragmentIndex);
273
+ const response = await fetch(fragmentPath, { signal });
274
+ return response.json();
275
+ }
276
+ });
277
+ this.frameTask = new Task(this, {
278
+ autoRun: EF_INTERACTIVE,
279
+ args: () => [this.transcriptionFragmentDataTask.status],
280
+ task: async () => {
281
+ await this.transcriptionFragmentDataTask.taskComplete;
282
+ }
283
+ });
284
+ }
285
+ static {
286
+ this.styles = [css`
386
287
  :host {
387
288
  display: flex;
388
289
  flex-wrap: wrap;
@@ -393,27 +294,90 @@ EFCaptions.styles = [
393
294
  margin: 0;
394
295
  padding: 0;
395
296
  }
396
- `
397
- ];
398
- __decorateClass([
399
- property({ type: String, attribute: "display-mode", reflect: true })
400
- ], EFCaptions.prototype, "displayMode", 2);
401
- __decorateClass([
402
- property({ type: Number, attribute: "context-words", reflect: true })
403
- ], EFCaptions.prototype, "contextWords", 2);
404
- __decorateClass([
405
- property({ type: String, attribute: "target", reflect: true })
406
- ], EFCaptions.prototype, "targetSelector", 2);
407
- __decorateClass([
408
- property({ attribute: "word-style" })
409
- ], EFCaptions.prototype, "wordStyle", 2);
410
- EFCaptions = __decorateClass([
411
- customElement("ef-captions")
412
- ], EFCaptions);
413
- export {
414
- EFCaptions,
415
- EFCaptionsActiveWord,
416
- EFCaptionsAfterActiveWord,
417
- EFCaptionsBeforeActiveWord,
418
- EFCaptionsSegment
297
+ `];
298
+ }
299
+ set target(value) {
300
+ this.targetSelector = value;
301
+ }
302
+ render() {
303
+ return html`<slot></slot>`;
304
+ }
305
+ transcriptionsPath() {
306
+ if (this.targetElement.assetId) return `${this.apiHost}/api/v1/isobmff_files/${this.targetElement.assetId}/transcription`;
307
+ return null;
308
+ }
309
+ captionsPath() {
310
+ if (this.targetElement.assetId) return `${this.apiHost}/api/v1/caption_files/${this.targetElement.assetId}`;
311
+ const targetSrc = this.targetElement.src;
312
+ return `/@ef-captions/${targetSrc}`;
313
+ }
314
+ transcriptionFragmentPath(transcriptionId, fragmentIndex) {
315
+ return `${this.apiHost}/api/v1/transcriptions/${transcriptionId}/fragments/${fragmentIndex}`;
316
+ }
317
+ connectedCallback() {
318
+ super.connectedCallback();
319
+ if (this.targetElement) new CrossUpdateController(this.targetElement, this);
320
+ }
321
+ updated(_changedProperties) {
322
+ this.updateTextContainers();
323
+ }
324
+ updateTextContainers() {
325
+ const transcriptionFragment = this.transcriptionFragmentDataTask.value;
326
+ if (!transcriptionFragment) return;
327
+ const currentTimeMs = this.targetElement.currentSourceTimeMs;
328
+ const currentTimeSec = currentTimeMs / 1e3;
329
+ const currentWord = transcriptionFragment.word_segments.find((word) => currentTimeSec >= word.start && currentTimeSec <= word.end);
330
+ const currentSegment = transcriptionFragment.segments.find((segment) => currentTimeSec >= segment.start && currentTimeSec <= segment.end);
331
+ for (const wordContainer of this.activeWordContainers) if (currentWord) {
332
+ wordContainer.wordText = currentWord.text;
333
+ wordContainer.wordStartMs = currentWord.start * 1e3;
334
+ wordContainer.wordEndMs = currentWord.end * 1e3;
335
+ }
336
+ for (const segmentContainer of this.segmentContainers) if (currentSegment) {
337
+ segmentContainer.segmentText = currentSegment.text;
338
+ segmentContainer.segmentStartMs = currentSegment.start * 1e3;
339
+ segmentContainer.segmentEndMs = currentSegment.end * 1e3;
340
+ }
341
+ if (currentWord && currentSegment) {
342
+ const segmentWords = transcriptionFragment.word_segments.filter((word) => word.start >= currentSegment.start && word.end <= currentSegment.end);
343
+ const currentWordIndex = segmentWords.findIndex((word) => word.start === currentWord.start && word.end === currentWord.end);
344
+ if (currentWordIndex !== -1) {
345
+ const beforeWords = segmentWords.slice(0, currentWordIndex).map((w) => w.text.trim()).join(" ");
346
+ const afterWords = segmentWords.slice(currentWordIndex + 1).map((w) => w.text.trim()).join(" ");
347
+ for (const container of this.beforeActiveWordContainers) {
348
+ container.segmentText = beforeWords;
349
+ container.segmentStartMs = currentSegment.start * 1e3;
350
+ container.segmentEndMs = currentWord.start * 1e3;
351
+ }
352
+ for (const container of this.afterActiveWordContainers) {
353
+ container.segmentText = afterWords;
354
+ container.segmentStartMs = currentWord.end * 1e3;
355
+ container.segmentEndMs = currentSegment.end * 1e3;
356
+ }
357
+ }
358
+ }
359
+ }
360
+ get targetElement() {
361
+ const target = document.getElementById(this.targetSelector ?? "");
362
+ if (target instanceof EFAudio || target instanceof EFVideo) return target;
363
+ throw new Error("Invalid target, must be an EFAudio or EFVideo element");
364
+ }
419
365
  };
366
+ _decorate([property({
367
+ type: String,
368
+ attribute: "display-mode",
369
+ reflect: true
370
+ })], EFCaptions.prototype, "displayMode", void 0);
371
+ _decorate([property({
372
+ type: Number,
373
+ attribute: "context-words",
374
+ reflect: true
375
+ })], EFCaptions.prototype, "contextWords", void 0);
376
+ _decorate([property({
377
+ type: String,
378
+ attribute: "target",
379
+ reflect: true
380
+ })], EFCaptions.prototype, "targetSelector", void 0);
381
+ _decorate([property({ attribute: "word-style" })], EFCaptions.prototype, "wordStyle", void 0);
382
+ EFCaptions = _decorate([customElement("ef-captions")], EFCaptions);
383
+ export { EFCaptions, EFCaptionsActiveWord, EFCaptionsAfterActiveWord, EFCaptionsBeforeActiveWord, EFCaptionsSegment };