@editframe/elements 0.18.21-beta.0 → 0.18.23-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/EFAudio.d.ts +1 -12
- package/dist/elements/EFAudio.js +3 -18
- package/dist/elements/EFMedia/AssetMediaEngine.d.ts +1 -1
- package/dist/elements/EFMedia/AssetMediaEngine.js +3 -3
- package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +15 -9
- package/dist/elements/EFMedia/BufferedSeekingInput.js +76 -78
- package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +12 -10
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +2 -18
- package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +12 -10
- package/dist/elements/EFTimegroup.d.ts +4 -4
- package/dist/elements/EFTimegroup.js +52 -39
- package/dist/elements/EFVideo.d.ts +1 -32
- package/dist/elements/EFVideo.js +13 -51
- package/dist/elements/SampleBuffer.js +1 -1
- package/package.json +2 -2
- package/src/elements/EFAudio.browsertest.ts +0 -3
- package/src/elements/EFAudio.ts +3 -22
- package/src/elements/EFMedia/AssetMediaEngine.browsertest.ts +39 -1
- package/src/elements/EFMedia/AssetMediaEngine.ts +5 -4
- package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +90 -185
- package/src/elements/EFMedia/BufferedSeekingInput.ts +119 -130
- package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +21 -21
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +10 -5
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +33 -34
- package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +22 -20
- package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +0 -3
- package/src/elements/EFMedia.browsertest.ts +72 -60
- package/src/elements/EFTimegroup.browsertest.ts +9 -4
- package/src/elements/EFTimegroup.ts +79 -55
- package/src/elements/EFVideo.browsertest.ts +172 -160
- package/src/elements/EFVideo.ts +17 -73
- package/src/elements/SampleBuffer.ts +1 -2
- package/test/EFVideo.framegen.browsertest.ts +0 -54
- package/types.json +1 -1
|
@@ -78,42 +78,11 @@ export declare class EFVideo extends EFVideo_base {
|
|
|
78
78
|
* Check if EF_FRAMEGEN has explicitly started frame rendering (not just initialization)
|
|
79
79
|
*/
|
|
80
80
|
private isFrameRenderingActive;
|
|
81
|
-
/**
|
|
82
|
-
* Effective mode - always returns "asset" for EFVideo
|
|
83
|
-
*/
|
|
84
|
-
get effectiveMode(): string;
|
|
85
|
-
/**
|
|
86
|
-
* Legacy getter for asset index loader (maps to mediaEngine task)
|
|
87
|
-
*/
|
|
88
|
-
get assetIndexLoader(): Task<readonly [string, string | null], import('../transcoding/types/index.ts').MediaEngine>;
|
|
89
81
|
/**
|
|
90
82
|
* Legacy getter for fragment index task (maps to videoSegmentIdTask)
|
|
83
|
+
* Still used by EFCaptions
|
|
91
84
|
*/
|
|
92
85
|
get fragmentIndexTask(): Task<readonly [import('../transcoding/types/index.ts').MediaEngine | undefined, number], number | undefined>;
|
|
93
|
-
/**
|
|
94
|
-
* Legacy getter for seek task (maps to videoSeekTask)
|
|
95
|
-
*/
|
|
96
|
-
get seekTask(): Task<readonly [number, import('./EFMedia/BufferedSeekingInput.ts').BufferedSeekingInput | undefined], import('mediabunny').VideoSample | undefined>;
|
|
97
|
-
/**
|
|
98
|
-
* Legacy getter for media segments task (maps to videoSegmentFetchTask)
|
|
99
|
-
*/
|
|
100
|
-
get mediaSegmentsTask(): Task<readonly [import('../transcoding/types/index.ts').MediaEngine | undefined, number | undefined], ArrayBuffer>;
|
|
101
|
-
/**
|
|
102
|
-
* Legacy getter for asset segment keys task (maps to videoSegmentIdTask)
|
|
103
|
-
*/
|
|
104
|
-
get assetSegmentKeysTask(): Task<readonly [import('../transcoding/types/index.ts').MediaEngine | undefined, number], number | undefined>;
|
|
105
|
-
/**
|
|
106
|
-
* Legacy getter for asset init segments task (maps to videoInitSegmentFetchTask)
|
|
107
|
-
*/
|
|
108
|
-
get assetInitSegmentsTask(): Task<readonly [import('../transcoding/types/index.ts').MediaEngine | undefined], ArrayBuffer>;
|
|
109
|
-
/**
|
|
110
|
-
* Legacy getter for asset segment loader (maps to videoSegmentFetchTask)
|
|
111
|
-
*/
|
|
112
|
-
get assetSegmentLoader(): Task<readonly [import('../transcoding/types/index.ts').MediaEngine | undefined, number | undefined], ArrayBuffer>;
|
|
113
|
-
/**
|
|
114
|
-
* Legacy getter for video asset task (maps to videoBufferTask)
|
|
115
|
-
*/
|
|
116
|
-
get videoAssetTask(): Task<readonly [number], import('./EFMedia/videoTasks/makeVideoBufferTask.ts').VideoBufferState>;
|
|
117
86
|
/**
|
|
118
87
|
* Clean up resources when component is disconnected
|
|
119
88
|
*/
|
package/dist/elements/EFVideo.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
1
2
|
import { EFMedia } from "./EFMedia.js";
|
|
2
3
|
import { TWMixin } from "../gui/TWMixin2.js";
|
|
3
4
|
import { DelayedLoadingState } from "../DelayedLoadingState.js";
|
|
@@ -94,6 +95,7 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
94
95
|
message: ""
|
|
95
96
|
};
|
|
96
97
|
this.frameTask = new Task(this, {
|
|
98
|
+
autoRun: EF_INTERACTIVE,
|
|
97
99
|
args: () => [this.desiredSeekTimeMs],
|
|
98
100
|
onError: (error) => {
|
|
99
101
|
console.error("frameTask error", error);
|
|
@@ -117,8 +119,11 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
117
119
|
const sample = this.videoSeekTask.value;
|
|
118
120
|
if (sample) {
|
|
119
121
|
const videoFrame = sample.toVideoFrame();
|
|
120
|
-
|
|
121
|
-
|
|
122
|
+
try {
|
|
123
|
+
this.displayFrame(videoFrame, _seekToMs);
|
|
124
|
+
} finally {
|
|
125
|
+
videoFrame.close();
|
|
126
|
+
}
|
|
122
127
|
}
|
|
123
128
|
if (!isProductionRendering) {
|
|
124
129
|
if (!this.rootTimegroup || this.rootTimegroup.currentTimeMs === 0 && this.desiredSeekTimeMs === 0) return;
|
|
@@ -150,7 +155,11 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
150
155
|
`;
|
|
151
156
|
}
|
|
152
157
|
get canvasElement() {
|
|
153
|
-
|
|
158
|
+
const referencedCanvas = this.canvasRef.value;
|
|
159
|
+
if (referencedCanvas) return referencedCanvas;
|
|
160
|
+
const shadowCanvas = this.shadowRoot?.querySelector("canvas");
|
|
161
|
+
if (shadowCanvas) return shadowCanvas;
|
|
162
|
+
return void 0;
|
|
154
163
|
}
|
|
155
164
|
updated(changedProperties) {
|
|
156
165
|
super.updated(changedProperties);
|
|
@@ -234,60 +243,13 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
|
|
|
234
243
|
return currentTime >= renderStartTime;
|
|
235
244
|
}
|
|
236
245
|
/**
|
|
237
|
-
* Effective mode - always returns "asset" for EFVideo
|
|
238
|
-
*/
|
|
239
|
-
get effectiveMode() {
|
|
240
|
-
return "asset";
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Legacy getter for asset index loader (maps to mediaEngine task)
|
|
244
|
-
*/
|
|
245
|
-
get assetIndexLoader() {
|
|
246
|
-
return this.mediaEngineTask;
|
|
247
|
-
}
|
|
248
|
-
/**
|
|
249
246
|
* Legacy getter for fragment index task (maps to videoSegmentIdTask)
|
|
247
|
+
* Still used by EFCaptions
|
|
250
248
|
*/
|
|
251
249
|
get fragmentIndexTask() {
|
|
252
250
|
return this.videoSegmentIdTask;
|
|
253
251
|
}
|
|
254
252
|
/**
|
|
255
|
-
* Legacy getter for seek task (maps to videoSeekTask)
|
|
256
|
-
*/
|
|
257
|
-
get seekTask() {
|
|
258
|
-
return this.videoSeekTask;
|
|
259
|
-
}
|
|
260
|
-
/**
|
|
261
|
-
* Legacy getter for media segments task (maps to videoSegmentFetchTask)
|
|
262
|
-
*/
|
|
263
|
-
get mediaSegmentsTask() {
|
|
264
|
-
return this.videoSegmentFetchTask;
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Legacy getter for asset segment keys task (maps to videoSegmentIdTask)
|
|
268
|
-
*/
|
|
269
|
-
get assetSegmentKeysTask() {
|
|
270
|
-
return this.videoSegmentIdTask;
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Legacy getter for asset init segments task (maps to videoInitSegmentFetchTask)
|
|
274
|
-
*/
|
|
275
|
-
get assetInitSegmentsTask() {
|
|
276
|
-
return this.videoInitSegmentFetchTask;
|
|
277
|
-
}
|
|
278
|
-
/**
|
|
279
|
-
* Legacy getter for asset segment loader (maps to videoSegmentFetchTask)
|
|
280
|
-
*/
|
|
281
|
-
get assetSegmentLoader() {
|
|
282
|
-
return this.videoSegmentFetchTask;
|
|
283
|
-
}
|
|
284
|
-
/**
|
|
285
|
-
* Legacy getter for video asset task (maps to videoBufferTask)
|
|
286
|
-
*/
|
|
287
|
-
get videoAssetTask() {
|
|
288
|
-
return this.videoBufferTask;
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
253
|
* Clean up resources when component is disconnected
|
|
292
254
|
*/
|
|
293
255
|
disconnectedCallback() {
|
|
@@ -34,7 +34,7 @@ var SampleBuffer = class {
|
|
|
34
34
|
const sampleStartMs = roundToMilliseconds((sample.timestamp || 0) * 1e3);
|
|
35
35
|
const sampleDurationMs = roundToMilliseconds((sample.duration || 0) * 1e3);
|
|
36
36
|
const sampleEndMs = roundToMilliseconds(sampleStartMs + sampleDurationMs);
|
|
37
|
-
if (targetTimeMs >= sampleStartMs && targetTimeMs
|
|
37
|
+
if (targetTimeMs >= sampleStartMs && targetTimeMs < sampleEndMs) return sample;
|
|
38
38
|
}
|
|
39
39
|
return void 0;
|
|
40
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/elements",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.23-beta.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"license": "UNLICENSED",
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@bramus/style-observer": "^1.3.0",
|
|
30
|
-
"@editframe/assets": "0.18.
|
|
30
|
+
"@editframe/assets": "0.18.23-beta.0",
|
|
31
31
|
"@lit/context": "^1.1.2",
|
|
32
32
|
"@lit/task": "^1.0.1",
|
|
33
33
|
"d3": "^7.9.0",
|
|
@@ -237,9 +237,6 @@ describe("EFAudio", () => {
|
|
|
237
237
|
|
|
238
238
|
// Should coordinate the expected tasks
|
|
239
239
|
expect(audio.fragmentIndexTask).toBeDefined();
|
|
240
|
-
expect(audio.mediaSegmentsTask).toBeDefined();
|
|
241
|
-
expect(audio.seekTask).toBeDefined();
|
|
242
|
-
expect(audio.videoAssetTask).toBeDefined();
|
|
243
240
|
});
|
|
244
241
|
|
|
245
242
|
test("frameTask handles missing dependencies", ({ expect }) => {
|
package/src/elements/EFAudio.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { Task } from "@lit/task";
|
|
|
2
2
|
import { html } from "lit";
|
|
3
3
|
import { customElement, property } from "lit/decorators.js";
|
|
4
4
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
5
|
+
import { EF_INTERACTIVE } from "../EF_INTERACTIVE.js";
|
|
5
6
|
import { TWMixin } from "../gui/TWMixin.js";
|
|
6
7
|
import { EFMedia } from "./EFMedia.js";
|
|
7
8
|
|
|
@@ -21,6 +22,7 @@ export class EFAudio extends TWMixin(EFMedia) {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
frameTask = new Task(this, {
|
|
25
|
+
autoRun: EF_INTERACTIVE,
|
|
24
26
|
args: () =>
|
|
25
27
|
[
|
|
26
28
|
this.audioBufferTask.status,
|
|
@@ -37,34 +39,13 @@ export class EFAudio extends TWMixin(EFMedia) {
|
|
|
37
39
|
},
|
|
38
40
|
});
|
|
39
41
|
|
|
40
|
-
// Getter properties for backward compatibility with tests
|
|
41
42
|
/**
|
|
42
43
|
* Legacy getter for fragment index task (maps to audioSegmentIdTask)
|
|
44
|
+
* Still used by EFCaptions
|
|
43
45
|
*/
|
|
44
46
|
get fragmentIndexTask() {
|
|
45
47
|
return this.audioSegmentIdTask;
|
|
46
48
|
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Legacy getter for media segments task (maps to audioSegmentFetchTask)
|
|
50
|
-
*/
|
|
51
|
-
get mediaSegmentsTask() {
|
|
52
|
-
return this.audioSegmentFetchTask;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Legacy getter for seek task (maps to audioSeekTask)
|
|
57
|
-
*/
|
|
58
|
-
get seekTask() {
|
|
59
|
-
return this.audioSeekTask;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Legacy getter for audio asset task (maps to audioBufferTask)
|
|
64
|
-
*/
|
|
65
|
-
get videoAssetTask() {
|
|
66
|
-
return this.audioBufferTask;
|
|
67
|
-
}
|
|
68
49
|
}
|
|
69
50
|
|
|
70
51
|
declare global {
|
|
@@ -40,7 +40,7 @@ describe("AssetMediaEngine", () => {
|
|
|
40
40
|
mediaEngine,
|
|
41
41
|
expect,
|
|
42
42
|
}) => {
|
|
43
|
-
expect(mediaEngine.durationMs).toBeCloseTo(
|
|
43
|
+
expect(mediaEngine.durationMs).toBeCloseTo(10031, 0); // Updated: improved mediabunny processing changed duration
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
test("provides source URL from constructor", async ({
|
|
@@ -97,4 +97,42 @@ describe("AssetMediaEngine", () => {
|
|
|
97
97
|
expect(mediaEngine.computeSegmentId(500, audio as any)).toBe(0);
|
|
98
98
|
expect(mediaEngine.computeSegmentId(1500, audio as any)).toBe(0);
|
|
99
99
|
});
|
|
100
|
+
|
|
101
|
+
describe("bars n tone segment id computation", () => {
|
|
102
|
+
test("computes 0ms is 0", ({ expect, mediaEngine }) => {
|
|
103
|
+
expect(
|
|
104
|
+
mediaEngine.computeSegmentId(0, mediaEngine.getVideoRendition()),
|
|
105
|
+
).toBe(0);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("computes 2000 is 1", ({ expect, mediaEngine }) => {
|
|
109
|
+
expect(
|
|
110
|
+
mediaEngine.computeSegmentId(2000, mediaEngine.getVideoRendition()),
|
|
111
|
+
).toBe(1);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
test("computes 4000 is 2", ({ expect, mediaEngine }) => {
|
|
115
|
+
expect(
|
|
116
|
+
mediaEngine.computeSegmentId(4000, mediaEngine.getVideoRendition()),
|
|
117
|
+
).toBe(2);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("computes 6000 is 3", ({ expect, mediaEngine }) => {
|
|
121
|
+
expect(
|
|
122
|
+
mediaEngine.computeSegmentId(6000, mediaEngine.getVideoRendition()),
|
|
123
|
+
).toBe(3);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("computes 8000 is 4", ({ expect, mediaEngine }) => {
|
|
127
|
+
expect(
|
|
128
|
+
mediaEngine.computeSegmentId(8000, mediaEngine.getVideoRendition()),
|
|
129
|
+
).toBe(4);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("computes 7975 is 3", ({ expect, mediaEngine }) => {
|
|
133
|
+
expect(
|
|
134
|
+
mediaEngine.computeSegmentId(7975, mediaEngine.getVideoRendition()),
|
|
135
|
+
).toBe(3);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
100
138
|
});
|
|
@@ -214,7 +214,7 @@ export class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
|
|
|
214
214
|
return segmentRanges;
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
computeSegmentId(
|
|
217
|
+
computeSegmentId(seekTimeMs: number, rendition: MediaRendition) {
|
|
218
218
|
if (!rendition.trackId) {
|
|
219
219
|
throw new Error("Track ID is required for asset metadata");
|
|
220
220
|
}
|
|
@@ -227,11 +227,12 @@ export class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
|
|
|
227
227
|
// Apply startTimeOffsetMs to map user timeline to media timeline for segment selection
|
|
228
228
|
const startTimeOffsetMs =
|
|
229
229
|
("startTimeOffsetMs" in rendition && rendition.startTimeOffsetMs) || 0;
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
|
|
231
|
+
const offsetSeekTimeMs = roundToMilliseconds(
|
|
232
|
+
seekTimeMs + startTimeOffsetMs,
|
|
232
233
|
);
|
|
233
234
|
// Convert to timescale units using consistent precision
|
|
234
|
-
const scaledSeekTime = convertToScaledTime(
|
|
235
|
+
const scaledSeekTime = convertToScaledTime(offsetSeekTimeMs, timescale);
|
|
235
236
|
|
|
236
237
|
// Find the segment that contains the actual seek time
|
|
237
238
|
for (let i = segments.length - 1; i >= 0; i--) {
|