@scarlett-player/native 1.8.1 → 1.10.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/index.cjs +75 -25
- package/dist/index.js +76 -26
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -27,12 +27,18 @@ module.exports = __toCommonJS(index_exports);
|
|
|
27
27
|
var import_core = require("@scarlett-player/core");
|
|
28
28
|
|
|
29
29
|
// src/version.ts
|
|
30
|
-
var PKG_VERSION = true ? "1.
|
|
30
|
+
var PKG_VERSION = true ? "1.10.0" : "0.0.0-dev";
|
|
31
31
|
|
|
32
32
|
// src/index.ts
|
|
33
33
|
var VIDEO_EXTENSIONS = ["mp4", "webm", "mov", "mkv", "ogv", "m4v"];
|
|
34
34
|
var AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "flac", "aac", "m4a", "opus", "weba"];
|
|
35
35
|
var SUPPORTED_EXTENSIONS = [...VIDEO_EXTENSIONS, ...AUDIO_EXTENSIONS];
|
|
36
|
+
var MEDIA_ERR = {
|
|
37
|
+
ABORTED: 1,
|
|
38
|
+
NETWORK: 2,
|
|
39
|
+
DECODE: 3,
|
|
40
|
+
SRC_NOT_SUPPORTED: 4
|
|
41
|
+
};
|
|
36
42
|
var MIME_TYPES = {
|
|
37
43
|
// Video
|
|
38
44
|
mp4: "video/mp4",
|
|
@@ -59,6 +65,10 @@ function createNativePlugin(config) {
|
|
|
59
65
|
let cleanupEvents = null;
|
|
60
66
|
let derived_title = null;
|
|
61
67
|
let is_audio_source = false;
|
|
68
|
+
let isCorePlayRequested = false;
|
|
69
|
+
let loadSession = 0;
|
|
70
|
+
let abortPendingLoad = null;
|
|
71
|
+
let has_parsed_source = false;
|
|
62
72
|
const getExtension = (src) => {
|
|
63
73
|
try {
|
|
64
74
|
const url = new URL(src, window.location.href);
|
|
@@ -106,11 +116,33 @@ function createNativePlugin(config) {
|
|
|
106
116
|
api?.container.appendChild(video);
|
|
107
117
|
return video;
|
|
108
118
|
};
|
|
119
|
+
const classifyMediaError = (error) => {
|
|
120
|
+
switch (error?.code) {
|
|
121
|
+
case MEDIA_ERR.ABORTED:
|
|
122
|
+
return { code: import_core.ErrorCode.PLAYBACK_FAILED, message: "Playback aborted" };
|
|
123
|
+
case MEDIA_ERR.NETWORK:
|
|
124
|
+
return { code: import_core.ErrorCode.MEDIA_NETWORK_ERROR, message: "Network error" };
|
|
125
|
+
case MEDIA_ERR.DECODE:
|
|
126
|
+
return {
|
|
127
|
+
code: import_core.ErrorCode.MEDIA_DECODE_ERROR,
|
|
128
|
+
message: "Decode error - format may not be supported"
|
|
129
|
+
};
|
|
130
|
+
case MEDIA_ERR.SRC_NOT_SUPPORTED:
|
|
131
|
+
return has_parsed_source ? { code: import_core.ErrorCode.MEDIA_NETWORK_ERROR, message: "Network error" } : { code: import_core.ErrorCode.SOURCE_LOAD_FAILED, message: "Format not supported" };
|
|
132
|
+
default:
|
|
133
|
+
return { code: import_core.ErrorCode.PLAYBACK_FAILED, message: "Unknown video error" };
|
|
134
|
+
}
|
|
135
|
+
};
|
|
109
136
|
const setupEventListeners = (videoEl) => {
|
|
110
137
|
const handlers = [];
|
|
138
|
+
const session = loadSession;
|
|
111
139
|
const on = (event, handler) => {
|
|
112
|
-
|
|
113
|
-
|
|
140
|
+
const guarded = (event_object) => {
|
|
141
|
+
if (session !== loadSession) return;
|
|
142
|
+
handler(event_object);
|
|
143
|
+
};
|
|
144
|
+
videoEl.addEventListener(event, guarded);
|
|
145
|
+
handlers.push([event, guarded]);
|
|
114
146
|
};
|
|
115
147
|
const syncEndedFromElement = () => {
|
|
116
148
|
if (videoEl.ended || !api?.getState("ended")) return;
|
|
@@ -125,14 +157,18 @@ function createNativePlugin(config) {
|
|
|
125
157
|
api?.setState("playing", true);
|
|
126
158
|
api?.setState("paused", false);
|
|
127
159
|
api?.setState("playbackState", "playing");
|
|
128
|
-
api?.emit("playback:play", void 0);
|
|
129
160
|
syncEndedFromElement();
|
|
161
|
+
if (isCorePlayRequested) {
|
|
162
|
+
isCorePlayRequested = false;
|
|
163
|
+
} else {
|
|
164
|
+
api?.emit("playback:play", void 0);
|
|
165
|
+
}
|
|
130
166
|
});
|
|
131
167
|
on("pause", () => {
|
|
168
|
+
isCorePlayRequested = false;
|
|
132
169
|
api?.setState("playing", false);
|
|
133
170
|
api?.setState("paused", true);
|
|
134
171
|
api?.setState("playbackState", "paused");
|
|
135
|
-
api?.emit("playback:pause", void 0);
|
|
136
172
|
});
|
|
137
173
|
on("ended", () => {
|
|
138
174
|
api?.setState("playing", false);
|
|
@@ -201,26 +237,10 @@ function createNativePlugin(config) {
|
|
|
201
237
|
});
|
|
202
238
|
on("error", () => {
|
|
203
239
|
const error = videoEl.error;
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
switch (error.code) {
|
|
207
|
-
case MediaError.MEDIA_ERR_ABORTED:
|
|
208
|
-
message = "Playback aborted";
|
|
209
|
-
break;
|
|
210
|
-
case MediaError.MEDIA_ERR_NETWORK:
|
|
211
|
-
message = "Network error";
|
|
212
|
-
break;
|
|
213
|
-
case MediaError.MEDIA_ERR_DECODE:
|
|
214
|
-
message = "Decode error - format may not be supported";
|
|
215
|
-
break;
|
|
216
|
-
case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
|
|
217
|
-
message = "Format not supported";
|
|
218
|
-
break;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
api?.logger.error("Video error", { code: error?.code, message });
|
|
240
|
+
const { code, message } = classifyMediaError(error);
|
|
241
|
+
api?.logger.error("Video error", { mediaErrorCode: error?.code, code, message });
|
|
222
242
|
api?.emit("error", {
|
|
223
|
-
code
|
|
243
|
+
code,
|
|
224
244
|
message,
|
|
225
245
|
fatal: true,
|
|
226
246
|
timestamp: Date.now()
|
|
@@ -283,18 +303,26 @@ function createNativePlugin(config) {
|
|
|
283
303
|
api = pluginApi;
|
|
284
304
|
api.logger.info("Native video plugin initialized");
|
|
285
305
|
const unsubPlay = api.on("playback:play", async () => {
|
|
306
|
+
if (api?.getState("chromecastActive")) return;
|
|
286
307
|
if (!video) return;
|
|
308
|
+
if (!video.paused) return;
|
|
287
309
|
try {
|
|
310
|
+
isCorePlayRequested = true;
|
|
288
311
|
await video.play();
|
|
289
312
|
} catch (e) {
|
|
313
|
+
isCorePlayRequested = false;
|
|
290
314
|
api?.logger.error("Play failed", e);
|
|
291
315
|
}
|
|
292
316
|
});
|
|
293
317
|
const unsubPause = api.on("playback:pause", () => {
|
|
318
|
+
if (api?.getState("chromecastActive")) return;
|
|
319
|
+
isCorePlayRequested = false;
|
|
294
320
|
video?.pause();
|
|
295
321
|
});
|
|
296
322
|
const unsubSeek = api.on("playback:seeking", ({ time }) => {
|
|
323
|
+
if (api?.getState("chromecastActive")) return;
|
|
297
324
|
if (!video) return;
|
|
325
|
+
if (!Number.isFinite(time)) return;
|
|
298
326
|
const clampedTime = Math.max(0, Math.min(time, video.duration || 0));
|
|
299
327
|
video.currentTime = clampedTime;
|
|
300
328
|
});
|
|
@@ -325,6 +353,10 @@ function createNativePlugin(config) {
|
|
|
325
353
|
},
|
|
326
354
|
async destroy() {
|
|
327
355
|
api?.logger.info("Native video plugin destroying");
|
|
356
|
+
loadSession++;
|
|
357
|
+
const pending = abortPendingLoad;
|
|
358
|
+
abortPendingLoad = null;
|
|
359
|
+
pending?.(new Error("Player destroyed during load"));
|
|
328
360
|
cleanup();
|
|
329
361
|
if (video?.parentNode) {
|
|
330
362
|
video.parentNode.removeChild(video);
|
|
@@ -333,6 +365,7 @@ function createNativePlugin(config) {
|
|
|
333
365
|
api = null;
|
|
334
366
|
derived_title = null;
|
|
335
367
|
is_audio_source = false;
|
|
368
|
+
has_parsed_source = false;
|
|
336
369
|
},
|
|
337
370
|
async loadSource(src) {
|
|
338
371
|
if (!api) throw new Error("Plugin not initialized");
|
|
@@ -340,7 +373,12 @@ function createNativePlugin(config) {
|
|
|
340
373
|
const mimeType = getMimeType(ext);
|
|
341
374
|
const isAudio = isAudioExtension(ext);
|
|
342
375
|
is_audio_source = isAudio;
|
|
343
|
-
api.logger.info("Loading native media source", { src, mimeType, isAudio });
|
|
376
|
+
api.logger.info("Loading native media source", { src: (0, import_core.sanitizeUrl)(src), mimeType, isAudio });
|
|
377
|
+
const session = ++loadSession;
|
|
378
|
+
const superseded = abortPendingLoad;
|
|
379
|
+
abortPendingLoad = null;
|
|
380
|
+
superseded?.(new Error("Load superseded by a newer source"));
|
|
381
|
+
has_parsed_source = false;
|
|
344
382
|
cleanup();
|
|
345
383
|
api.setState("playbackState", "loading");
|
|
346
384
|
api.setState("buffering", true);
|
|
@@ -375,9 +413,19 @@ function createNativePlugin(config) {
|
|
|
375
413
|
clearTimeout(watchdog);
|
|
376
414
|
watchdog = null;
|
|
377
415
|
}
|
|
416
|
+
if (abortPendingLoad === abort) {
|
|
417
|
+
abortPendingLoad = null;
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
const abort = (reason) => {
|
|
421
|
+
settle();
|
|
422
|
+
reject(reason);
|
|
378
423
|
};
|
|
424
|
+
abortPendingLoad = abort;
|
|
379
425
|
const onLoaded = () => {
|
|
426
|
+
if (session !== loadSession) return;
|
|
380
427
|
settle();
|
|
428
|
+
has_parsed_source = true;
|
|
381
429
|
const muted = api?.getState("muted");
|
|
382
430
|
const volume = api?.getState("volume");
|
|
383
431
|
if (muted !== void 0) videoEl.muted = muted;
|
|
@@ -389,12 +437,14 @@ function createNativePlugin(config) {
|
|
|
389
437
|
resolve();
|
|
390
438
|
};
|
|
391
439
|
const onError = () => {
|
|
440
|
+
if (session !== loadSession) return;
|
|
392
441
|
settle();
|
|
393
442
|
const error = videoEl.error;
|
|
394
443
|
reject(new Error(error?.message || "Failed to load video source"));
|
|
395
444
|
};
|
|
396
445
|
if (load_timeout_ms > 0) {
|
|
397
446
|
watchdog = setTimeout(() => {
|
|
447
|
+
if (session !== loadSession) return;
|
|
398
448
|
settle();
|
|
399
449
|
reject(new Error("Video took too long to load (network timeout)"));
|
|
400
450
|
}, load_timeout_ms);
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { ErrorCode } from "@scarlett-player/core";
|
|
2
|
+
import { ErrorCode, sanitizeUrl } from "@scarlett-player/core";
|
|
3
3
|
|
|
4
4
|
// src/version.ts
|
|
5
|
-
var PKG_VERSION = true ? "1.
|
|
5
|
+
var PKG_VERSION = true ? "1.10.0" : "0.0.0-dev";
|
|
6
6
|
|
|
7
7
|
// src/index.ts
|
|
8
8
|
var VIDEO_EXTENSIONS = ["mp4", "webm", "mov", "mkv", "ogv", "m4v"];
|
|
9
9
|
var AUDIO_EXTENSIONS = ["mp3", "wav", "ogg", "flac", "aac", "m4a", "opus", "weba"];
|
|
10
10
|
var SUPPORTED_EXTENSIONS = [...VIDEO_EXTENSIONS, ...AUDIO_EXTENSIONS];
|
|
11
|
+
var MEDIA_ERR = {
|
|
12
|
+
ABORTED: 1,
|
|
13
|
+
NETWORK: 2,
|
|
14
|
+
DECODE: 3,
|
|
15
|
+
SRC_NOT_SUPPORTED: 4
|
|
16
|
+
};
|
|
11
17
|
var MIME_TYPES = {
|
|
12
18
|
// Video
|
|
13
19
|
mp4: "video/mp4",
|
|
@@ -34,6 +40,10 @@ function createNativePlugin(config) {
|
|
|
34
40
|
let cleanupEvents = null;
|
|
35
41
|
let derived_title = null;
|
|
36
42
|
let is_audio_source = false;
|
|
43
|
+
let isCorePlayRequested = false;
|
|
44
|
+
let loadSession = 0;
|
|
45
|
+
let abortPendingLoad = null;
|
|
46
|
+
let has_parsed_source = false;
|
|
37
47
|
const getExtension = (src) => {
|
|
38
48
|
try {
|
|
39
49
|
const url = new URL(src, window.location.href);
|
|
@@ -81,11 +91,33 @@ function createNativePlugin(config) {
|
|
|
81
91
|
api?.container.appendChild(video);
|
|
82
92
|
return video;
|
|
83
93
|
};
|
|
94
|
+
const classifyMediaError = (error) => {
|
|
95
|
+
switch (error?.code) {
|
|
96
|
+
case MEDIA_ERR.ABORTED:
|
|
97
|
+
return { code: ErrorCode.PLAYBACK_FAILED, message: "Playback aborted" };
|
|
98
|
+
case MEDIA_ERR.NETWORK:
|
|
99
|
+
return { code: ErrorCode.MEDIA_NETWORK_ERROR, message: "Network error" };
|
|
100
|
+
case MEDIA_ERR.DECODE:
|
|
101
|
+
return {
|
|
102
|
+
code: ErrorCode.MEDIA_DECODE_ERROR,
|
|
103
|
+
message: "Decode error - format may not be supported"
|
|
104
|
+
};
|
|
105
|
+
case MEDIA_ERR.SRC_NOT_SUPPORTED:
|
|
106
|
+
return has_parsed_source ? { code: ErrorCode.MEDIA_NETWORK_ERROR, message: "Network error" } : { code: ErrorCode.SOURCE_LOAD_FAILED, message: "Format not supported" };
|
|
107
|
+
default:
|
|
108
|
+
return { code: ErrorCode.PLAYBACK_FAILED, message: "Unknown video error" };
|
|
109
|
+
}
|
|
110
|
+
};
|
|
84
111
|
const setupEventListeners = (videoEl) => {
|
|
85
112
|
const handlers = [];
|
|
113
|
+
const session = loadSession;
|
|
86
114
|
const on = (event, handler) => {
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
const guarded = (event_object) => {
|
|
116
|
+
if (session !== loadSession) return;
|
|
117
|
+
handler(event_object);
|
|
118
|
+
};
|
|
119
|
+
videoEl.addEventListener(event, guarded);
|
|
120
|
+
handlers.push([event, guarded]);
|
|
89
121
|
};
|
|
90
122
|
const syncEndedFromElement = () => {
|
|
91
123
|
if (videoEl.ended || !api?.getState("ended")) return;
|
|
@@ -100,14 +132,18 @@ function createNativePlugin(config) {
|
|
|
100
132
|
api?.setState("playing", true);
|
|
101
133
|
api?.setState("paused", false);
|
|
102
134
|
api?.setState("playbackState", "playing");
|
|
103
|
-
api?.emit("playback:play", void 0);
|
|
104
135
|
syncEndedFromElement();
|
|
136
|
+
if (isCorePlayRequested) {
|
|
137
|
+
isCorePlayRequested = false;
|
|
138
|
+
} else {
|
|
139
|
+
api?.emit("playback:play", void 0);
|
|
140
|
+
}
|
|
105
141
|
});
|
|
106
142
|
on("pause", () => {
|
|
143
|
+
isCorePlayRequested = false;
|
|
107
144
|
api?.setState("playing", false);
|
|
108
145
|
api?.setState("paused", true);
|
|
109
146
|
api?.setState("playbackState", "paused");
|
|
110
|
-
api?.emit("playback:pause", void 0);
|
|
111
147
|
});
|
|
112
148
|
on("ended", () => {
|
|
113
149
|
api?.setState("playing", false);
|
|
@@ -176,26 +212,10 @@ function createNativePlugin(config) {
|
|
|
176
212
|
});
|
|
177
213
|
on("error", () => {
|
|
178
214
|
const error = videoEl.error;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
switch (error.code) {
|
|
182
|
-
case MediaError.MEDIA_ERR_ABORTED:
|
|
183
|
-
message = "Playback aborted";
|
|
184
|
-
break;
|
|
185
|
-
case MediaError.MEDIA_ERR_NETWORK:
|
|
186
|
-
message = "Network error";
|
|
187
|
-
break;
|
|
188
|
-
case MediaError.MEDIA_ERR_DECODE:
|
|
189
|
-
message = "Decode error - format may not be supported";
|
|
190
|
-
break;
|
|
191
|
-
case MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED:
|
|
192
|
-
message = "Format not supported";
|
|
193
|
-
break;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
api?.logger.error("Video error", { code: error?.code, message });
|
|
215
|
+
const { code, message } = classifyMediaError(error);
|
|
216
|
+
api?.logger.error("Video error", { mediaErrorCode: error?.code, code, message });
|
|
197
217
|
api?.emit("error", {
|
|
198
|
-
code
|
|
218
|
+
code,
|
|
199
219
|
message,
|
|
200
220
|
fatal: true,
|
|
201
221
|
timestamp: Date.now()
|
|
@@ -258,18 +278,26 @@ function createNativePlugin(config) {
|
|
|
258
278
|
api = pluginApi;
|
|
259
279
|
api.logger.info("Native video plugin initialized");
|
|
260
280
|
const unsubPlay = api.on("playback:play", async () => {
|
|
281
|
+
if (api?.getState("chromecastActive")) return;
|
|
261
282
|
if (!video) return;
|
|
283
|
+
if (!video.paused) return;
|
|
262
284
|
try {
|
|
285
|
+
isCorePlayRequested = true;
|
|
263
286
|
await video.play();
|
|
264
287
|
} catch (e) {
|
|
288
|
+
isCorePlayRequested = false;
|
|
265
289
|
api?.logger.error("Play failed", e);
|
|
266
290
|
}
|
|
267
291
|
});
|
|
268
292
|
const unsubPause = api.on("playback:pause", () => {
|
|
293
|
+
if (api?.getState("chromecastActive")) return;
|
|
294
|
+
isCorePlayRequested = false;
|
|
269
295
|
video?.pause();
|
|
270
296
|
});
|
|
271
297
|
const unsubSeek = api.on("playback:seeking", ({ time }) => {
|
|
298
|
+
if (api?.getState("chromecastActive")) return;
|
|
272
299
|
if (!video) return;
|
|
300
|
+
if (!Number.isFinite(time)) return;
|
|
273
301
|
const clampedTime = Math.max(0, Math.min(time, video.duration || 0));
|
|
274
302
|
video.currentTime = clampedTime;
|
|
275
303
|
});
|
|
@@ -300,6 +328,10 @@ function createNativePlugin(config) {
|
|
|
300
328
|
},
|
|
301
329
|
async destroy() {
|
|
302
330
|
api?.logger.info("Native video plugin destroying");
|
|
331
|
+
loadSession++;
|
|
332
|
+
const pending = abortPendingLoad;
|
|
333
|
+
abortPendingLoad = null;
|
|
334
|
+
pending?.(new Error("Player destroyed during load"));
|
|
303
335
|
cleanup();
|
|
304
336
|
if (video?.parentNode) {
|
|
305
337
|
video.parentNode.removeChild(video);
|
|
@@ -308,6 +340,7 @@ function createNativePlugin(config) {
|
|
|
308
340
|
api = null;
|
|
309
341
|
derived_title = null;
|
|
310
342
|
is_audio_source = false;
|
|
343
|
+
has_parsed_source = false;
|
|
311
344
|
},
|
|
312
345
|
async loadSource(src) {
|
|
313
346
|
if (!api) throw new Error("Plugin not initialized");
|
|
@@ -315,7 +348,12 @@ function createNativePlugin(config) {
|
|
|
315
348
|
const mimeType = getMimeType(ext);
|
|
316
349
|
const isAudio = isAudioExtension(ext);
|
|
317
350
|
is_audio_source = isAudio;
|
|
318
|
-
api.logger.info("Loading native media source", { src, mimeType, isAudio });
|
|
351
|
+
api.logger.info("Loading native media source", { src: sanitizeUrl(src), mimeType, isAudio });
|
|
352
|
+
const session = ++loadSession;
|
|
353
|
+
const superseded = abortPendingLoad;
|
|
354
|
+
abortPendingLoad = null;
|
|
355
|
+
superseded?.(new Error("Load superseded by a newer source"));
|
|
356
|
+
has_parsed_source = false;
|
|
319
357
|
cleanup();
|
|
320
358
|
api.setState("playbackState", "loading");
|
|
321
359
|
api.setState("buffering", true);
|
|
@@ -350,9 +388,19 @@ function createNativePlugin(config) {
|
|
|
350
388
|
clearTimeout(watchdog);
|
|
351
389
|
watchdog = null;
|
|
352
390
|
}
|
|
391
|
+
if (abortPendingLoad === abort) {
|
|
392
|
+
abortPendingLoad = null;
|
|
393
|
+
}
|
|
394
|
+
};
|
|
395
|
+
const abort = (reason) => {
|
|
396
|
+
settle();
|
|
397
|
+
reject(reason);
|
|
353
398
|
};
|
|
399
|
+
abortPendingLoad = abort;
|
|
354
400
|
const onLoaded = () => {
|
|
401
|
+
if (session !== loadSession) return;
|
|
355
402
|
settle();
|
|
403
|
+
has_parsed_source = true;
|
|
356
404
|
const muted = api?.getState("muted");
|
|
357
405
|
const volume = api?.getState("volume");
|
|
358
406
|
if (muted !== void 0) videoEl.muted = muted;
|
|
@@ -364,12 +412,14 @@ function createNativePlugin(config) {
|
|
|
364
412
|
resolve();
|
|
365
413
|
};
|
|
366
414
|
const onError = () => {
|
|
415
|
+
if (session !== loadSession) return;
|
|
367
416
|
settle();
|
|
368
417
|
const error = videoEl.error;
|
|
369
418
|
reject(new Error(error?.message || "Failed to load video source"));
|
|
370
419
|
};
|
|
371
420
|
if (load_timeout_ms > 0) {
|
|
372
421
|
watchdog = setTimeout(() => {
|
|
422
|
+
if (session !== loadSession) return;
|
|
373
423
|
settle();
|
|
374
424
|
reject(new Error("Video took too long to load (network timeout)"));
|
|
375
425
|
}, load_timeout_ms);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scarlett-player/native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Native Video Provider Plugin for Scarlett Player (MP4, WebM, MOV, MKV)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -17,13 +17,14 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@scarlett-player/core": "^1.
|
|
20
|
+
"@scarlett-player/core": "^1.9.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"typescript": "^5.3.0",
|
|
24
24
|
"tsup": "^8.0.0",
|
|
25
25
|
"vitest": "^1.6.0",
|
|
26
|
-
"
|
|
26
|
+
"jsdom": "^24.0.0",
|
|
27
|
+
"@scarlett-player/core": "1.10.0"
|
|
27
28
|
},
|
|
28
29
|
"keywords": [
|
|
29
30
|
"video",
|