@aelionsdk/media 0.1.0-beta.1 → 1.1.0-rc.1
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/README.md +27 -4
- package/dist/mediabunny-adapter.d.ts.map +1 -1
- package/dist/mediabunny-adapter.js +35 -4
- package/dist/range-reader.d.ts +4 -0
- package/dist/range-reader.d.ts.map +1 -1
- package/dist/range-reader.js +69 -31
- package/dist/types.d.ts +9 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,7 +1,30 @@
|
|
|
1
|
-
#
|
|
1
|
+
# `@aelionsdk/media`
|
|
2
2
|
|
|
3
|
-
Range I/O, media indexing, decoding and
|
|
3
|
+
Range I/O, media indexing, exact seek, decoding, cache and proxy primitives for
|
|
4
|
+
AelionSDK.
|
|
4
5
|
|
|
5
|
-
Install
|
|
6
|
+
## Install
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
```bash
|
|
9
|
+
npm install @aelionsdk/media@next
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
`next` currently resolves to `1.1.0-rc.1`. Applications should prefer
|
|
13
|
+
`ProductionMediaProvider` from `@aelionsdk/sdk`; direct use is intended for
|
|
14
|
+
custom media providers, cache implementations and decode hosts.
|
|
15
|
+
|
|
16
|
+
## Public surface
|
|
17
|
+
|
|
18
|
+
- HTTP/file range readers and proxy contracts;
|
|
19
|
+
- MP4/MOV/MKV/TS/WebM indexing and exact seek;
|
|
20
|
+
- video, audio and image adapters;
|
|
21
|
+
- content-addressed cache and OPFS storage;
|
|
22
|
+
- shared decoder, cache and request resource governance.
|
|
23
|
+
|
|
24
|
+
Callers own returned browser media resources unless an API explicitly transfers
|
|
25
|
+
ownership. Close frames, cancel obsolete reads and release cache/provider
|
|
26
|
+
resources when a session ends.
|
|
27
|
+
|
|
28
|
+
See the [media lifecycle guide](https://foyonaczy.github.io/AelionSDK/concepts/media-lifecycle/)
|
|
29
|
+
and [API reference](https://foyonaczy.github.io/AelionSDK/api/aelionsdk/media/overview/).
|
|
30
|
+
Licensed under MIT.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mediabunny-adapter.d.ts","sourceRoot":"","sources":["../src/mediabunny-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"mediabunny-adapter.d.ts","sourceRoot":"","sources":["../src/mediabunny-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { throwIfAborted } from '@aelionsdk/core';
|
|
2
|
-
import { ALL_FORMATS, AudioSampleSink, BufferSource, CustomSource, EncodedPacketSink, Input, MP4, VideoSampleSink, WEBM, } from 'mediabunny';
|
|
2
|
+
import { ALL_FORMATS, AudioSampleSink, BufferSource, CustomSource, EncodedPacketSink, Input, MATROSKA, MP4, MPEG_TS, QTFF, VideoSampleSink, WEBM, } from 'mediabunny';
|
|
3
3
|
import { resolveVideoSeek } from './seek.js';
|
|
4
4
|
const MICROSECONDS_PER_SECOND = 1_000_000;
|
|
5
5
|
let activeVideoDecoders = 0;
|
|
@@ -61,12 +61,15 @@ function copyVideoDecoderConfig(config) {
|
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
async function videoTrackInfo(track) {
|
|
64
|
-
const [codec, codecString, width, height, rotation, timeResolution, config] = await Promise.all([
|
|
64
|
+
const [codec, codecString, width, height, rotation, colorSpace, highDynamicRange, canBeTransparent, timeResolution, config,] = await Promise.all([
|
|
65
65
|
track.getCodec(),
|
|
66
66
|
track.getCodecParameterString(),
|
|
67
67
|
track.getCodedWidth(),
|
|
68
68
|
track.getCodedHeight(),
|
|
69
69
|
track.getRotation(),
|
|
70
|
+
track.getColorSpace(),
|
|
71
|
+
track.hasHighDynamicRange(),
|
|
72
|
+
track.canBeTransparent(),
|
|
70
73
|
track.getTimeResolution(),
|
|
71
74
|
track.getDecoderConfig(),
|
|
72
75
|
]);
|
|
@@ -79,6 +82,14 @@ async function videoTrackInfo(track) {
|
|
|
79
82
|
codedWidth: width,
|
|
80
83
|
codedHeight: height,
|
|
81
84
|
rotation,
|
|
85
|
+
color: {
|
|
86
|
+
primaries: colorSpace.primaries ?? null,
|
|
87
|
+
transfer: colorSpace.transfer ?? null,
|
|
88
|
+
matrix: colorSpace.matrix ?? null,
|
|
89
|
+
fullRange: colorSpace.fullRange ?? null,
|
|
90
|
+
highDynamicRange,
|
|
91
|
+
canBeTransparent,
|
|
92
|
+
},
|
|
82
93
|
timeBase: { numerator: 1, denominator: timeResolution },
|
|
83
94
|
...(configDescription === undefined ? {} : { description: configDescription }),
|
|
84
95
|
};
|
|
@@ -178,7 +189,17 @@ export async function createSampleIndex(bytes, options = {}) {
|
|
|
178
189
|
}
|
|
179
190
|
return {
|
|
180
191
|
schemaVersion: '1.0.0',
|
|
181
|
-
container: format === MP4
|
|
192
|
+
container: format === MP4
|
|
193
|
+
? 'mp4'
|
|
194
|
+
: format === QTFF
|
|
195
|
+
? 'mov'
|
|
196
|
+
: format === MATROSKA
|
|
197
|
+
? 'mkv'
|
|
198
|
+
: format === MPEG_TS
|
|
199
|
+
? 'ts'
|
|
200
|
+
: format === WEBM
|
|
201
|
+
? 'webm'
|
|
202
|
+
: 'unknown',
|
|
182
203
|
durationUs: secondsToUs(durationSeconds, 'media duration'),
|
|
183
204
|
tracks: trackInfos,
|
|
184
205
|
capabilities: {
|
|
@@ -216,7 +237,17 @@ export async function createSampleIndexFromReader(reader, options = {}) {
|
|
|
216
237
|
}
|
|
217
238
|
return {
|
|
218
239
|
schemaVersion: '1.0.0',
|
|
219
|
-
container: format === MP4
|
|
240
|
+
container: format === MP4
|
|
241
|
+
? 'mp4'
|
|
242
|
+
: format === QTFF
|
|
243
|
+
? 'mov'
|
|
244
|
+
: format === MATROSKA
|
|
245
|
+
? 'mkv'
|
|
246
|
+
: format === MPEG_TS
|
|
247
|
+
? 'ts'
|
|
248
|
+
: format === WEBM
|
|
249
|
+
? 'webm'
|
|
250
|
+
: 'unknown',
|
|
220
251
|
durationUs: secondsToUs(durationSeconds, 'media duration'),
|
|
221
252
|
tracks: trackInfos,
|
|
222
253
|
capabilities: {
|
package/dist/range-reader.d.ts
CHANGED
|
@@ -18,6 +18,10 @@ export declare class BlobRangeReader implements RangeReader {
|
|
|
18
18
|
export interface FetchRangeReaderOptions {
|
|
19
19
|
readonly headers?: Readonly<Record<string, string>>;
|
|
20
20
|
readonly fetch?: typeof globalThis.fetch;
|
|
21
|
+
/** Transient network/408/429/5xx retries after the first attempt. Defaults to 2. */
|
|
22
|
+
readonly maxRetries?: number;
|
|
23
|
+
/** Base delay for bounded exponential backoff. Defaults to 100 ms. */
|
|
24
|
+
readonly retryDelayMs?: number;
|
|
21
25
|
}
|
|
22
26
|
export declare class FetchRangeReader implements RangeReader {
|
|
23
27
|
#private;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"range-reader.d.ts","sourceRoot":"","sources":["../src/range-reader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgCpE,qBAAa,iBAAkB,YAAW,WAAW;;aAKjC,EAAE,EAAE,MAAM;IAJ5B,SAAgB,IAAI,EAAG,QAAQ,CAAU;gBAIvB,EAAE,EAAE,MAAM,EAC1B,KAAK,EAAE,UAAU;IAKZ,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAS3C,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;CAiBxE;AAED,qBAAa,eAAgB,YAAW,WAAW;;aAK/B,EAAE,EAAE,MAAM;IAJ5B,SAAgB,IAAI,EAAG,MAAM,CAAU;gBAIrB,EAAE,EAAE,MAAM,EAC1B,IAAI,EAAE,IAAI;IAKL,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IASrC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;CAe9E;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"range-reader.d.ts","sourceRoot":"","sources":["../src/range-reader.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAgCpE,qBAAa,iBAAkB,YAAW,WAAW;;aAKjC,EAAE,EAAE,MAAM;IAJ5B,SAAgB,IAAI,EAAG,QAAQ,CAAU;gBAIvB,EAAE,EAAE,MAAM,EAC1B,KAAK,EAAE,UAAU;IAKZ,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAS3C,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;CAiBxE;AAED,qBAAa,eAAgB,YAAW,WAAW;;aAK/B,EAAE,EAAE,MAAM;IAJ5B,SAAgB,IAAI,EAAG,MAAM,CAAU;gBAIrB,EAAE,EAAE,MAAM,EAC1B,IAAI,EAAE,IAAI;IAKL,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IASrC,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;CAe9E;AAED,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACpD,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAC;IACzC,oFAAoF;IACpF,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAED,qBAAa,gBAAiB,YAAW,WAAW;;aAShC,EAAE,EAAE,MAAM;aACV,GAAG,EAAE,MAAM;IAT7B,SAAgB,IAAI,EAAG,SAAS,CAAU;gBAQxB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EAC3B,OAAO,GAAE,uBAA4B;IAkB1B,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IA0B3C,IAAI,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC;CAqH9E"}
|
package/dist/range-reader.js
CHANGED
|
@@ -99,28 +99,34 @@ export class FetchRangeReader {
|
|
|
99
99
|
kind = 'network';
|
|
100
100
|
#fetch;
|
|
101
101
|
#headers;
|
|
102
|
+
#maxRetries;
|
|
103
|
+
#retryDelayMs;
|
|
102
104
|
#size;
|
|
103
105
|
constructor(id, url, options = {}) {
|
|
104
106
|
this.id = id;
|
|
105
107
|
this.url = url;
|
|
106
108
|
this.#fetch = options.fetch ?? globalThis.fetch;
|
|
107
109
|
this.#headers = options.headers ?? {};
|
|
110
|
+
this.#maxRetries = options.maxRetries ?? 2;
|
|
111
|
+
this.#retryDelayMs = options.retryDelayMs ?? 100;
|
|
112
|
+
if (!Number.isSafeInteger(this.#maxRetries) || this.#maxRetries < 0 || this.#maxRetries > 8) {
|
|
113
|
+
throw new RangeError('maxRetries must be a safe integer from 0 through 8');
|
|
114
|
+
}
|
|
115
|
+
if (!Number.isSafeInteger(this.#retryDelayMs) ||
|
|
116
|
+
this.#retryDelayMs < 0 ||
|
|
117
|
+
this.#retryDelayMs > 10_000) {
|
|
118
|
+
throw new RangeError('retryDelayMs must be a safe integer from 0 through 10000');
|
|
119
|
+
}
|
|
108
120
|
}
|
|
109
121
|
async size(signal) {
|
|
110
122
|
throwIfAborted(signal, 'network source size');
|
|
111
123
|
if (this.#size !== undefined)
|
|
112
124
|
return this.#size;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
...(signal === undefined ? {} : { signal }),
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
catch (cause) {
|
|
122
|
-
throw mediaNetworkError('MEDIA_NETWORK_OR_CORS_FAILED', 'Media HEAD request failed because of network or CORS policy', cause);
|
|
123
|
-
}
|
|
125
|
+
const response = await this.#request({
|
|
126
|
+
method: 'HEAD',
|
|
127
|
+
headers: this.#headers,
|
|
128
|
+
...(signal === undefined ? {} : { signal }),
|
|
129
|
+
}, 'Media HEAD request', signal);
|
|
124
130
|
if (!response.ok) {
|
|
125
131
|
throw new Error(`HEAD request failed with HTTP ${response.status}`);
|
|
126
132
|
}
|
|
@@ -138,16 +144,10 @@ export class FetchRangeReader {
|
|
|
138
144
|
throwIfAborted(signal, 'network range read');
|
|
139
145
|
assertRange(range);
|
|
140
146
|
const end = range.offset + range.length - 1;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
...(signal === undefined ? {} : { signal }),
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
catch (cause) {
|
|
149
|
-
throw mediaNetworkError('MEDIA_NETWORK_OR_CORS_FAILED', 'Media Range request failed because of network or CORS policy', cause);
|
|
150
|
-
}
|
|
147
|
+
const response = await this.#request({
|
|
148
|
+
headers: { ...this.#headers, Range: `bytes=${range.offset}-${end}` },
|
|
149
|
+
...(signal === undefined ? {} : { signal }),
|
|
150
|
+
}, 'Media Range request', signal);
|
|
151
151
|
if (response.status !== 206) {
|
|
152
152
|
throw mediaNetworkError(response.status === 200 ? 'MEDIA_RANGE_UNSUPPORTED' : 'MEDIA_RANGE_REQUEST_FAILED', response.status === 200
|
|
153
153
|
? 'Server ignored Range and returned the full resource'
|
|
@@ -175,16 +175,10 @@ export class FetchRangeReader {
|
|
|
175
175
|
return { bytes, range, totalSize, source: 'network' };
|
|
176
176
|
}
|
|
177
177
|
async #probeSize(signal) {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
...(signal === undefined ? {} : { signal }),
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
catch (cause) {
|
|
186
|
-
throw mediaNetworkError('MEDIA_NETWORK_OR_CORS_FAILED', 'Media Range size probe failed because of network or CORS policy', cause);
|
|
187
|
-
}
|
|
178
|
+
const response = await this.#request({
|
|
179
|
+
headers: { ...this.#headers, Range: 'bytes=0-0' },
|
|
180
|
+
...(signal === undefined ? {} : { signal }),
|
|
181
|
+
}, 'Media Range size probe', signal);
|
|
188
182
|
if (response.status !== 206) {
|
|
189
183
|
throw mediaNetworkError('MEDIA_RANGE_UNSUPPORTED', 'Source size is unavailable and the server does not support byte ranges');
|
|
190
184
|
}
|
|
@@ -197,4 +191,48 @@ export class FetchRangeReader {
|
|
|
197
191
|
this.#size = size;
|
|
198
192
|
return size;
|
|
199
193
|
}
|
|
194
|
+
async #request(init, operation, signal) {
|
|
195
|
+
for (let attempt = 0; attempt <= this.#maxRetries; attempt += 1) {
|
|
196
|
+
throwIfAborted(signal, operation);
|
|
197
|
+
try {
|
|
198
|
+
const response = await this.#fetch(this.url, init);
|
|
199
|
+
const retryable = response.status === 408 || response.status === 429 || response.status >= 500;
|
|
200
|
+
if (!retryable || attempt === this.#maxRetries)
|
|
201
|
+
return response;
|
|
202
|
+
await response.body?.cancel();
|
|
203
|
+
}
|
|
204
|
+
catch (cause) {
|
|
205
|
+
throwIfAborted(signal, operation);
|
|
206
|
+
if (attempt === this.#maxRetries) {
|
|
207
|
+
throw mediaNetworkError('MEDIA_NETWORK_OR_CORS_FAILED', `${operation} failed after ${(attempt + 1).toString()} attempt(s)`, cause);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
await this.#waitBeforeRetry(attempt, operation, signal);
|
|
211
|
+
}
|
|
212
|
+
throw new Error(`${operation} retry loop exhausted unexpectedly`);
|
|
213
|
+
}
|
|
214
|
+
async #waitBeforeRetry(attempt, operation, signal) {
|
|
215
|
+
const delayMs = this.#retryDelayMs * 2 ** attempt;
|
|
216
|
+
if (delayMs === 0)
|
|
217
|
+
return;
|
|
218
|
+
await new Promise((resolve, reject) => {
|
|
219
|
+
const onAbort = () => {
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
signal?.removeEventListener('abort', onAbort);
|
|
222
|
+
try {
|
|
223
|
+
throwIfAborted(signal, operation);
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
reject(error instanceof Error
|
|
227
|
+
? error
|
|
228
|
+
: new Error(`${operation} was aborted`, { cause: error }));
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
const timer = setTimeout(() => {
|
|
232
|
+
signal?.removeEventListener('abort', onAbort);
|
|
233
|
+
resolve();
|
|
234
|
+
}, delayMs);
|
|
235
|
+
signal?.addEventListener('abort', onAbort, { once: true });
|
|
236
|
+
});
|
|
237
|
+
}
|
|
200
238
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -40,6 +40,14 @@ export interface VideoTrackInfo {
|
|
|
40
40
|
readonly codedWidth: number;
|
|
41
41
|
readonly codedHeight: number;
|
|
42
42
|
readonly rotation: number;
|
|
43
|
+
readonly color: {
|
|
44
|
+
readonly primaries: 'bt709' | 'bt470bg' | 'smpte170m' | 'bt2020' | null;
|
|
45
|
+
readonly transfer: 'bt709' | 'smpte170m' | 'iec61966-2-1' | 'linear' | 'pq' | 'hlg' | null;
|
|
46
|
+
readonly matrix: 'rgb' | 'bt709' | 'bt470bg' | 'smpte170m' | 'bt2020-ncl' | null;
|
|
47
|
+
readonly fullRange: boolean | null;
|
|
48
|
+
readonly highDynamicRange: boolean;
|
|
49
|
+
readonly canBeTransparent: boolean;
|
|
50
|
+
};
|
|
43
51
|
readonly timeBase?: Rational;
|
|
44
52
|
readonly description?: Uint8Array;
|
|
45
53
|
}
|
|
@@ -56,7 +64,7 @@ export interface AudioTrackInfo {
|
|
|
56
64
|
export type TrackInfo = VideoTrackInfo | AudioTrackInfo;
|
|
57
65
|
export interface SampleIndex {
|
|
58
66
|
readonly schemaVersion: '1.0.0';
|
|
59
|
-
readonly container: 'mp4' | 'webm' | 'unknown';
|
|
67
|
+
readonly container: 'mp4' | 'mov' | 'mkv' | 'ts' | 'webm' | 'unknown';
|
|
60
68
|
readonly durationUs: number;
|
|
61
69
|
readonly tracks: readonly TrackInfo[];
|
|
62
70
|
readonly capabilities: {
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aelionsdk/media",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.1.0-rc.1",
|
|
4
4
|
"description": "Range I/O, media indexing, decoding and exact seek for AelionSDK",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -27,14 +27,14 @@
|
|
|
27
27
|
"!dist/.tsbuildinfo"
|
|
28
28
|
],
|
|
29
29
|
"engines": {
|
|
30
|
-
"node": ">=
|
|
30
|
+
"node": ">=24 <25"
|
|
31
31
|
},
|
|
32
32
|
"publishConfig": {
|
|
33
33
|
"access": "public",
|
|
34
34
|
"provenance": true
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@aelionsdk/core": "
|
|
37
|
+
"@aelionsdk/core": "1.1.0-rc.1",
|
|
38
38
|
"mediabunny": "1.50.8"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|