@editframe/elements 0.18.7-beta.0 → 0.18.8-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 -2
- package/dist/elements/EFAudio.js +6 -9
- package/dist/elements/EFMedia/AssetMediaEngine.js +12 -2
- package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +7 -2
- package/package.json +2 -2
- package/src/elements/EFAudio.ts +7 -20
- package/src/elements/EFMedia/AssetMediaEngine.ts +20 -0
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +10 -1
- package/types.json +1 -1
|
@@ -2,8 +2,7 @@ import { Task } from '@lit/task';
|
|
|
2
2
|
import { EFMedia } from './EFMedia.js';
|
|
3
3
|
declare const EFAudio_base: typeof EFMedia;
|
|
4
4
|
export declare class EFAudio extends EFAudio_base {
|
|
5
|
-
|
|
6
|
-
attributeChangedCallback(name: string, old: string | null, value: string | null): void;
|
|
5
|
+
private _propertyHack;
|
|
7
6
|
audioElementRef: import('lit-html/directives/ref.js').Ref<HTMLAudioElement>;
|
|
8
7
|
render(): import('lit-html').TemplateResult<1>;
|
|
9
8
|
frameTask: Task<readonly [import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus], void>;
|
package/dist/elements/EFAudio.js
CHANGED
|
@@ -2,12 +2,13 @@ import { EFMedia } from "./EFMedia.js";
|
|
|
2
2
|
import { TWMixin } from "../gui/TWMixin2.js";
|
|
3
3
|
import { Task } from "@lit/task";
|
|
4
4
|
import { html } from "lit";
|
|
5
|
-
import { customElement } from "lit/decorators.js";
|
|
5
|
+
import { customElement, property } from "lit/decorators.js";
|
|
6
6
|
import _decorate from "@oxc-project/runtime/helpers/decorate";
|
|
7
7
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
8
8
|
let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
|
|
9
9
|
constructor(..._args) {
|
|
10
10
|
super(..._args);
|
|
11
|
+
this._propertyHack = false;
|
|
11
12
|
this.audioElementRef = createRef();
|
|
12
13
|
this.frameTask = new Task(this, {
|
|
13
14
|
args: () => [
|
|
@@ -25,14 +26,6 @@ let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
|
|
|
25
26
|
}
|
|
26
27
|
});
|
|
27
28
|
}
|
|
28
|
-
static get observedAttributes() {
|
|
29
|
-
const parentAttributes = super.observedAttributes || [];
|
|
30
|
-
return [...parentAttributes];
|
|
31
|
-
}
|
|
32
|
-
attributeChangedCallback(name, old, value) {
|
|
33
|
-
super.attributeChangedCallback(name, old, value);
|
|
34
|
-
if (name === "asset-id") this.assetId = value;
|
|
35
|
-
}
|
|
36
29
|
render() {
|
|
37
30
|
return html`<audio ${ref(this.audioElementRef)}></audio>`;
|
|
38
31
|
}
|
|
@@ -61,5 +54,9 @@ let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
|
|
|
61
54
|
return this.audioBufferTask;
|
|
62
55
|
}
|
|
63
56
|
};
|
|
57
|
+
_decorate([property({
|
|
58
|
+
type: Boolean,
|
|
59
|
+
attribute: "dummy-property"
|
|
60
|
+
})], EFAudio.prototype, "_propertyHack", void 0);
|
|
64
61
|
EFAudio = _decorate([customElement("ef-audio")], EFAudio);
|
|
65
62
|
export { EFAudio };
|
|
@@ -82,9 +82,15 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
|
|
|
82
82
|
* Calculate audio segments for variable-duration segments using track fragment index
|
|
83
83
|
*/
|
|
84
84
|
calculateAudioSegmentRange(fromMs, toMs, rendition, _durationMs) {
|
|
85
|
-
if (fromMs >= toMs || !rendition.trackId)
|
|
85
|
+
if (fromMs >= toMs || !rendition.trackId) {
|
|
86
|
+
console.warn(`calculateAudioSegmentRange: invalid fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(rendition)}`);
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
86
89
|
const track = this.data[rendition.trackId];
|
|
87
|
-
if (!track)
|
|
90
|
+
if (!track) {
|
|
91
|
+
console.warn(`calculateAudioSegmentRange: track not found for rendition ${JSON.stringify(rendition)}`);
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
88
94
|
const { timescale, segments } = track;
|
|
89
95
|
const segmentRanges = [];
|
|
90
96
|
for (let i = 0; i < segments.length; i++) {
|
|
@@ -99,6 +105,10 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
|
|
|
99
105
|
endMs: segmentEndMs
|
|
100
106
|
});
|
|
101
107
|
}
|
|
108
|
+
if (segmentRanges.length === 0) console.warn(`calculateAudioSegmentRange: no segments found for fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify({
|
|
109
|
+
rendition,
|
|
110
|
+
track
|
|
111
|
+
})}`);
|
|
102
112
|
return segmentRanges;
|
|
103
113
|
}
|
|
104
114
|
computeSegmentId(desiredSeekTimeMs, rendition) {
|
|
@@ -4,8 +4,13 @@ const makeAudioSeekTask = (host) => {
|
|
|
4
4
|
return new Task(host, {
|
|
5
5
|
args: () => [host.desiredSeekTimeMs, host.audioInputTask.value],
|
|
6
6
|
onError: (error) => {
|
|
7
|
-
if (error instanceof IgnorableError)
|
|
8
|
-
|
|
7
|
+
if (error instanceof IgnorableError) {
|
|
8
|
+
console.info("audioSeekTask aborted");
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
if (error instanceof DOMException) console.error(`audioSeekTask error: ${error.message} ${error.name} ${error.code}`);
|
|
12
|
+
else if (error instanceof Error) console.error(`audioSeekTask error ${error.name}: ${error.message}`);
|
|
13
|
+
else console.error("audioSeekTask unknown error", error);
|
|
9
14
|
},
|
|
10
15
|
onComplete: (_value) => {},
|
|
11
16
|
task: async ([targetSeekTimeMs], { signal }) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/elements",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.8-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.8-beta.0",
|
|
31
31
|
"@lit/context": "^1.1.2",
|
|
32
32
|
"@lit/task": "^1.0.1",
|
|
33
33
|
"d3": "^7.9.0",
|
package/src/elements/EFAudio.ts
CHANGED
|
@@ -1,31 +1,18 @@
|
|
|
1
1
|
import { Task } from "@lit/task";
|
|
2
2
|
import { html } from "lit";
|
|
3
|
-
import { customElement } from "lit/decorators.js";
|
|
3
|
+
import { customElement, property } from "lit/decorators.js";
|
|
4
4
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
5
5
|
import { TWMixin } from "../gui/TWMixin.js";
|
|
6
6
|
import { EFMedia } from "./EFMedia.js";
|
|
7
7
|
|
|
8
8
|
@customElement("ef-audio")
|
|
9
9
|
export class EFAudio extends TWMixin(EFMedia) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
attributeChangedCallback(
|
|
17
|
-
name: string,
|
|
18
|
-
old: string | null,
|
|
19
|
-
value: string | null,
|
|
20
|
-
) {
|
|
21
|
-
super.attributeChangedCallback(name, old, value);
|
|
22
|
-
|
|
23
|
-
// Explicitly handle asset-id attribute to property conversion
|
|
24
|
-
// EFVideo works without this fix, but EFAudio requires it due to some fundamental difference
|
|
25
|
-
if (name === "asset-id") {
|
|
26
|
-
this.assetId = value;
|
|
27
|
-
}
|
|
28
|
-
}
|
|
10
|
+
// HACK: This dummy property is needed to activate Lit's property processing system
|
|
11
|
+
// Without it, inherited properties from EFMedia don't work correctly
|
|
12
|
+
// TODO: Remove this as soon as we have an audio-specific property that needs @property
|
|
13
|
+
@property({ type: Boolean, attribute: "dummy-property" })
|
|
14
|
+
// @ts-expect-error - This is a hack to activate Lit's property processing system
|
|
15
|
+
private _propertyHack = false;
|
|
29
16
|
|
|
30
17
|
audioElementRef = createRef<HTMLAudioElement>();
|
|
31
18
|
|
|
@@ -156,11 +156,21 @@ export class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
|
|
|
156
156
|
_durationMs: number,
|
|
157
157
|
): SegmentTimeRange[] {
|
|
158
158
|
if (fromMs >= toMs || !rendition.trackId) {
|
|
159
|
+
console.warn(
|
|
160
|
+
`calculateAudioSegmentRange: invalid fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(
|
|
161
|
+
rendition,
|
|
162
|
+
)}`,
|
|
163
|
+
);
|
|
159
164
|
return [];
|
|
160
165
|
}
|
|
161
166
|
|
|
162
167
|
const track = this.data[rendition.trackId];
|
|
163
168
|
if (!track) {
|
|
169
|
+
console.warn(
|
|
170
|
+
`calculateAudioSegmentRange: track not found for rendition ${JSON.stringify(
|
|
171
|
+
rendition,
|
|
172
|
+
)}`,
|
|
173
|
+
);
|
|
164
174
|
return [];
|
|
165
175
|
}
|
|
166
176
|
|
|
@@ -186,6 +196,16 @@ export class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
|
|
|
186
196
|
});
|
|
187
197
|
}
|
|
188
198
|
}
|
|
199
|
+
if (segmentRanges.length === 0) {
|
|
200
|
+
console.warn(
|
|
201
|
+
`calculateAudioSegmentRange: no segments found for fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(
|
|
202
|
+
{
|
|
203
|
+
rendition,
|
|
204
|
+
track,
|
|
205
|
+
},
|
|
206
|
+
)}`,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
189
209
|
|
|
190
210
|
return segmentRanges;
|
|
191
211
|
}
|
|
@@ -13,8 +13,17 @@ export const makeAudioSeekTask = (host: EFMedia): AudioSeekTask => {
|
|
|
13
13
|
onError: (error) => {
|
|
14
14
|
if (error instanceof IgnorableError) {
|
|
15
15
|
console.info("audioSeekTask aborted");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (error instanceof DOMException) {
|
|
19
|
+
console.error(
|
|
20
|
+
`audioSeekTask error: ${error.message} ${error.name} ${error.code}`,
|
|
21
|
+
);
|
|
22
|
+
} else if (error instanceof Error) {
|
|
23
|
+
console.error(`audioSeekTask error ${error.name}: ${error.message}`);
|
|
24
|
+
} else {
|
|
25
|
+
console.error("audioSeekTask unknown error", error);
|
|
16
26
|
}
|
|
17
|
-
console.error("audioSeekTask error", error);
|
|
18
27
|
},
|
|
19
28
|
onComplete: (_value) => {},
|
|
20
29
|
task: async (
|