@gcorevideo/player 2.3.1 → 2.4.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/dist/index.js +147 -103
- package/lib/Player.d.ts +1 -1
- package/lib/Player.d.ts.map +1 -1
- package/lib/Player.js +23 -68
- package/lib/internal.types.d.ts +2 -3
- package/lib/internal.types.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.js +52 -34
- package/lib/types.d.ts +2 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/utils/mediaSources.d.ts +13 -0
- package/lib/utils/mediaSources.d.ts.map +1 -0
- package/lib/utils/mediaSources.js +82 -0
- package/package.json +1 -1
- package/src/Player.ts +26 -77
- package/src/internal.types.ts +2 -2
- package/src/plugins/dash-playback/DashPlayback.ts +349 -258
- package/src/types.ts +3 -2
- package/src/typings/@clappr/core/player.d.ts +58 -58
- package/src/utils/mediaSources.ts +104 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// Copyright 2014 Globo.com Player authors. All rights reserved.
|
|
2
2
|
// Use of this source code is governed by a BSD-style
|
|
3
3
|
// license that can be found in the LICENSE file.
|
|
4
|
-
import { Events, HTML5Video, Log, Playback,
|
|
4
|
+
import { Events, HTML5Video, Log, Playback, Utils, } from '@clappr/core';
|
|
5
5
|
import assert from 'assert'; // uses Node.js's assert types
|
|
6
6
|
import DASHJS from 'dashjs';
|
|
7
7
|
import { trace } from '../../trace/index.js';
|
|
8
8
|
const AUTO = -1;
|
|
9
9
|
const { now } = Utils;
|
|
10
|
-
const T =
|
|
10
|
+
const T = 'DashPlayback';
|
|
11
11
|
export default class DashPlayback extends HTML5Video {
|
|
12
12
|
_levels = null;
|
|
13
13
|
_currentLevel = null;
|
|
@@ -59,8 +59,8 @@ export default class DashPlayback extends HTML5Video {
|
|
|
59
59
|
autoSwitchBitrate: {
|
|
60
60
|
video: id === -1,
|
|
61
61
|
},
|
|
62
|
-
ABRStrategy: 'abrL2A'
|
|
63
|
-
}
|
|
62
|
+
ABRStrategy: 'abrL2A',
|
|
63
|
+
},
|
|
64
64
|
},
|
|
65
65
|
};
|
|
66
66
|
assert.ok(this._dash, 'An instance of dashjs MediaPlayer is required to switch levels');
|
|
@@ -81,7 +81,8 @@ export default class DashPlayback extends HTML5Video {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
get _startTime() {
|
|
84
|
-
if (this._playbackType === Playback.LIVE &&
|
|
84
|
+
if (this._playbackType === Playback.LIVE &&
|
|
85
|
+
this._playlistType !== 'EVENT') {
|
|
85
86
|
return this._extrapolatedStartTime;
|
|
86
87
|
}
|
|
87
88
|
return this._playableRegionStartTime;
|
|
@@ -127,7 +128,8 @@ export default class DashPlayback extends HTML5Video {
|
|
|
127
128
|
// Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
|
|
128
129
|
// removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
|
|
129
130
|
// added/removed every 5.
|
|
130
|
-
this._extrapolatedWindowNumSegments =
|
|
131
|
+
this._extrapolatedWindowNumSegments =
|
|
132
|
+
this.options.playback?.extrapolatedWindowNumSegments ?? 2;
|
|
131
133
|
if (this.options.playbackType) {
|
|
132
134
|
this._playbackType = this.options.playbackType;
|
|
133
135
|
}
|
|
@@ -192,7 +194,8 @@ export default class DashPlayback extends HTML5Video {
|
|
|
192
194
|
});
|
|
193
195
|
this._dash.on(DASHJS.MediaPlayer.events.METRIC_ADDED, (e) => {
|
|
194
196
|
// Listen for the first manifest request in order to update player UI
|
|
195
|
-
if (e.metric === 'DVRInfo') {
|
|
197
|
+
if (e.metric === 'DVRInfo') {
|
|
198
|
+
// TODO fix typings
|
|
196
199
|
assert.ok(this._dash, 'An instance of dashjs MediaPlayer is required to get metrics');
|
|
197
200
|
const dvrInfo = this._dash.getDashMetrics().getCurrentDVRInfo('video');
|
|
198
201
|
if (dvrInfo) {
|
|
@@ -297,7 +300,7 @@ export default class DashPlayback extends HTML5Video {
|
|
|
297
300
|
}
|
|
298
301
|
_updateDvr(status) {
|
|
299
302
|
this.trigger(Events.PLAYBACK_DVR, status);
|
|
300
|
-
this.trigger(Events.PLAYBACK_STATS_ADD, {
|
|
303
|
+
this.trigger(Events.PLAYBACK_STATS_ADD, { dvr: status });
|
|
301
304
|
}
|
|
302
305
|
_updateSettings() {
|
|
303
306
|
if (this._playbackType === Playback.VOD) {
|
|
@@ -328,19 +331,19 @@ export default class DashPlayback extends HTML5Video {
|
|
|
328
331
|
Log.error('The media cannot be played because it requires a feature ' +
|
|
329
332
|
'that your browser does not support.');
|
|
330
333
|
}
|
|
331
|
-
else if (event.error === 'manifestError' &&
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
334
|
+
else if (event.error === 'manifestError' &&
|
|
335
|
+
// Manifest type not supported
|
|
336
|
+
(event.event.id === 'createParser' ||
|
|
337
|
+
// Codec(s) not supported
|
|
338
|
+
event.event.id === 'codec' ||
|
|
339
|
+
// No streams available to stream
|
|
340
|
+
event.event.id === 'nostreams' ||
|
|
341
|
+
// Error creating Stream object
|
|
342
|
+
event.event.id === 'nostreamscomposed' ||
|
|
343
|
+
// syntax error parsing the manifest
|
|
344
|
+
event.event.id === 'parse' ||
|
|
345
|
+
// a stream has multiplexed audio+video
|
|
346
|
+
event.event.id === 'multiplexedrep')) {
|
|
344
347
|
// These errors have useful error messages, so we forward it on
|
|
345
348
|
const formattedError = this.createError(event.error);
|
|
346
349
|
this.trigger(Events.PLAYBACK_ERROR, formattedError);
|
|
@@ -359,7 +362,8 @@ export default class DashPlayback extends HTML5Video {
|
|
|
359
362
|
this.trigger(Events.PLAYBACK_ERROR, formattedError);
|
|
360
363
|
Log.error(event.event);
|
|
361
364
|
}
|
|
362
|
-
else if (event.error === 'capability' &&
|
|
365
|
+
else if (event.error === 'capability' &&
|
|
366
|
+
event.event === 'encryptedmedia') {
|
|
363
367
|
// Browser doesn't support EME
|
|
364
368
|
const formattedError = this.createError(event.error);
|
|
365
369
|
this.trigger(Events.PLAYBACK_ERROR, formattedError);
|
|
@@ -387,7 +391,7 @@ export default class DashPlayback extends HTML5Video {
|
|
|
387
391
|
}
|
|
388
392
|
else {
|
|
389
393
|
// ignore the error
|
|
390
|
-
if (typeof event.error ===
|
|
394
|
+
if (typeof event.error === 'object') {
|
|
391
395
|
const formattedError = this.createError(event.error);
|
|
392
396
|
this.trigger(Events.PLAYBACK_ERROR, formattedError);
|
|
393
397
|
Log.error(event.error.message);
|
|
@@ -411,10 +415,11 @@ export default class DashPlayback extends HTML5Video {
|
|
|
411
415
|
const update = {
|
|
412
416
|
current: this.getCurrentTime(),
|
|
413
417
|
total: this.getDuration(),
|
|
414
|
-
firstFragDateTime: this.getProgramDateTime()
|
|
418
|
+
firstFragDateTime: this.getProgramDateTime(),
|
|
415
419
|
};
|
|
416
|
-
const isSame = this._lastTimeUpdate &&
|
|
417
|
-
update.
|
|
420
|
+
const isSame = this._lastTimeUpdate &&
|
|
421
|
+
update.current === this._lastTimeUpdate.current &&
|
|
422
|
+
update.total === this._lastTimeUpdate.total;
|
|
418
423
|
if (isSame) {
|
|
419
424
|
return;
|
|
420
425
|
}
|
|
@@ -431,7 +436,8 @@ export default class DashPlayback extends HTML5Video {
|
|
|
431
436
|
}
|
|
432
437
|
get dvrEnabled() {
|
|
433
438
|
assert.ok(this._dash, 'An instance of dashjs MediaPlayer is required to get the DVR status');
|
|
434
|
-
return this._dash?.getDVRWindowSize() >= this._minDvrSize &&
|
|
439
|
+
return (this._dash?.getDVRWindowSize() >= this._minDvrSize &&
|
|
440
|
+
this.getPlaybackType() === Playback.LIVE);
|
|
435
441
|
}
|
|
436
442
|
_onProgress() {
|
|
437
443
|
if (!this._dash) {
|
|
@@ -444,7 +450,7 @@ export default class DashPlayback extends HTML5Video {
|
|
|
444
450
|
const progress = {
|
|
445
451
|
start: this.getCurrentTime(),
|
|
446
452
|
current: this.getCurrentTime() + buffer,
|
|
447
|
-
total: this.getDuration()
|
|
453
|
+
total: this.getDuration(),
|
|
448
454
|
};
|
|
449
455
|
this.trigger(Events.PLAYBACK_PROGRESS, progress, {});
|
|
450
456
|
}
|
|
@@ -625,22 +631,34 @@ export default class DashPlayback extends HTML5Video {
|
|
|
625
631
|
height: currentLevel.height,
|
|
626
632
|
width: currentLevel.width,
|
|
627
633
|
bitrate: currentLevel.bitrate,
|
|
628
|
-
level: currentLevel.qualityIndex
|
|
634
|
+
level: currentLevel.qualityIndex,
|
|
629
635
|
});
|
|
630
636
|
}
|
|
631
637
|
getPlaybackType() {
|
|
632
638
|
return this._playbackType;
|
|
633
639
|
}
|
|
634
640
|
isSeekEnabled() {
|
|
635
|
-
return
|
|
641
|
+
return this._playbackType === Playback.VOD || this.dvrEnabled;
|
|
636
642
|
}
|
|
637
643
|
}
|
|
638
644
|
DashPlayback.canPlay = function (resource, mimeType) {
|
|
639
645
|
const resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
|
|
640
|
-
const isDash = (
|
|
641
|
-
mimeType === 'application/dash+xml' ||
|
|
642
|
-
|
|
646
|
+
const isDash = (resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'mpd') ||
|
|
647
|
+
mimeType === 'application/dash+xml' ||
|
|
648
|
+
mimeType === 'video/mp4';
|
|
649
|
+
// TODO check
|
|
650
|
+
const ms = window.MediaSource;
|
|
651
|
+
const mms = 'ManagedMediaSource' in window ? window.ManagedMediaSource : undefined;
|
|
652
|
+
const wms = 'WebKitMediaSource' in window ? window.WebKitMediaSource : undefined;
|
|
653
|
+
const ctor = ms || mms || wms;
|
|
643
654
|
const hasSupport = typeof ctor === 'function';
|
|
644
|
-
trace(`${T} canPlay`, {
|
|
655
|
+
trace(`${T} canPlay`, {
|
|
656
|
+
hasSupport,
|
|
657
|
+
isDash,
|
|
658
|
+
resource,
|
|
659
|
+
ms: typeof ms === 'function',
|
|
660
|
+
mms: typeof mms === 'function',
|
|
661
|
+
wms: typeof wms === 'function',
|
|
662
|
+
});
|
|
645
663
|
return !!(hasSupport && isDash);
|
|
646
664
|
};
|
package/lib/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PlayerMediaSource } from "./internal.types";
|
|
1
2
|
export type PlayerDebugTag = 'all' | 'clappr' | 'dash' | 'hls' | 'none';
|
|
2
3
|
export type PlayerDebugSettings = PlayerDebugTag | boolean;
|
|
3
4
|
export type PlaybackType = 'live' | 'vod';
|
|
@@ -18,6 +19,7 @@ export type PlayerConfig = {
|
|
|
18
19
|
pluginSettings?: Record<string, unknown>;
|
|
19
20
|
poster?: string;
|
|
20
21
|
priorityTransport?: TransportPreference;
|
|
22
|
+
sources: PlayerMediaSource[];
|
|
21
23
|
strings: TranslationSettings;
|
|
22
24
|
};
|
|
23
25
|
export type PlayerOptionsThumbnails = {
|
|
@@ -83,7 +85,6 @@ export type QualityLevelInfo = {
|
|
|
83
85
|
height: number;
|
|
84
86
|
bitrate: number;
|
|
85
87
|
};
|
|
86
|
-
export type BitrateInfo = QualityLevelInfo;
|
|
87
88
|
export declare enum PlayerEvent {
|
|
88
89
|
Ready = "ready",
|
|
89
90
|
Play = "play",
|
package/lib/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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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { PlayerMediaSource } from '../internal.types';
|
|
2
|
+
import { StreamMediaSource, TransportPreference } from '../types';
|
|
3
|
+
export type SourceVariants = {
|
|
4
|
+
dash: string | null;
|
|
5
|
+
master: string | null;
|
|
6
|
+
hls: string | null;
|
|
7
|
+
mpegts: string | null;
|
|
8
|
+
};
|
|
9
|
+
export declare function buildSourcesSet(sources: PlayerMediaSource[]): SourceVariants;
|
|
10
|
+
export declare function buildSourcesPriorityList(sources: SourceVariants, priorityTransport?: TransportPreference): PlayerMediaSource[];
|
|
11
|
+
export declare function unwrapSource(s: PlayerMediaSource): string;
|
|
12
|
+
export declare function buildGcoreStreamSourcesList(ms: StreamMediaSource, priorityTransport: TransportPreference): PlayerMediaSource[];
|
|
13
|
+
//# sourceMappingURL=mediaSources.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mediaSources.d.ts","sourceRoot":"","sources":["../../src/utils/mediaSources.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAGrD,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEjE,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB,CAAA;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,cAAc,CAkB5E;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,cAAc,EACvB,iBAAiB,GAAE,mBAA4B,GAC9C,iBAAiB,EAAE,CAmDrB;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAEzD;AAED,wBAAgB,2BAA2B,CACzC,EAAE,EAAE,iBAAiB,EACrB,iBAAiB,EAAE,mBAAmB,GACrC,iBAAiB,EAAE,CAQrB"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import DashPlayback from '../plugins/dash-playback/DashPlayback';
|
|
2
|
+
import HlsPlayback from '../plugins/hls-playback/HlsPlayback';
|
|
3
|
+
export function buildSourcesSet(sources) {
|
|
4
|
+
const sv = {
|
|
5
|
+
dash: null,
|
|
6
|
+
master: null,
|
|
7
|
+
hls: null,
|
|
8
|
+
mpegts: null,
|
|
9
|
+
};
|
|
10
|
+
sources.forEach((ps) => {
|
|
11
|
+
const [s, t] = typeof ps === 'string' ? [ps, ''] : [ps.source, ps.mimeType];
|
|
12
|
+
if (DashPlayback.canPlay(s, t)) {
|
|
13
|
+
sv.dash = s;
|
|
14
|
+
}
|
|
15
|
+
else if (HlsPlayback.canPlay(s, t)) {
|
|
16
|
+
sv.hls = s;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
sv.master = s;
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
return sv;
|
|
23
|
+
}
|
|
24
|
+
export function buildSourcesPriorityList(sources, priorityTransport = 'auto') {
|
|
25
|
+
const msl = [];
|
|
26
|
+
switch (priorityTransport) {
|
|
27
|
+
case 'dash':
|
|
28
|
+
addDash();
|
|
29
|
+
break;
|
|
30
|
+
case 'hls':
|
|
31
|
+
addHls();
|
|
32
|
+
break;
|
|
33
|
+
case 'mpegts':
|
|
34
|
+
addMpegts();
|
|
35
|
+
break;
|
|
36
|
+
case 'auto':
|
|
37
|
+
addDash();
|
|
38
|
+
addHls();
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
Object.values(sources).forEach((s) => {
|
|
42
|
+
if (s) {
|
|
43
|
+
msl.push(s);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return msl;
|
|
47
|
+
function addMpegts() {
|
|
48
|
+
if (sources.mpegts) {
|
|
49
|
+
msl.push(sources.mpegts);
|
|
50
|
+
sources.mpegts = null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function addHls() {
|
|
54
|
+
if (sources.hls && HlsPlayback.canPlay(sources.hls)) {
|
|
55
|
+
msl.push(sources.hls);
|
|
56
|
+
sources.hls = null;
|
|
57
|
+
}
|
|
58
|
+
if (sources.master?.endsWith('.m3u8') &&
|
|
59
|
+
HlsPlayback.canPlay(sources.master)) {
|
|
60
|
+
msl.push(sources.master);
|
|
61
|
+
sources.master = null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function addDash() {
|
|
65
|
+
if (sources.dash && DashPlayback.canPlay(sources.dash)) {
|
|
66
|
+
msl.push(sources.dash);
|
|
67
|
+
sources.dash = null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function unwrapSource(s) {
|
|
72
|
+
return typeof s === 'string' ? s : s.source;
|
|
73
|
+
}
|
|
74
|
+
export function buildGcoreStreamSourcesList(ms, priorityTransport) {
|
|
75
|
+
const sources = {
|
|
76
|
+
dash: ms.sourceDash,
|
|
77
|
+
master: ms.source,
|
|
78
|
+
hls: ms.hlsCmafUrl,
|
|
79
|
+
mpegts: ms.hlsMpegtsUrl,
|
|
80
|
+
};
|
|
81
|
+
return buildSourcesPriorityList(sources, priorityTransport);
|
|
82
|
+
}
|
package/package.json
CHANGED
package/src/Player.ts
CHANGED
|
@@ -13,19 +13,20 @@ import type {
|
|
|
13
13
|
CorePlayerEvents,
|
|
14
14
|
CoreOptions,
|
|
15
15
|
CorePluginOptions,
|
|
16
|
+
PlayerMediaSource,
|
|
16
17
|
} from './internal.types.js'
|
|
17
18
|
import type {
|
|
18
19
|
PlaybackType,
|
|
19
20
|
PlayerPlugin,
|
|
20
21
|
QualityLevelInfo,
|
|
21
22
|
StreamMediaSource,
|
|
23
|
+
TransportPreference,
|
|
22
24
|
} from './types.js'
|
|
23
25
|
import { reportError, trace } from './trace/index.js'
|
|
24
26
|
import { PlayerConfig, PlayerEvent } from './types.js'
|
|
25
27
|
import DashPlayback from './plugins/dash-playback/DashPlayback.js'
|
|
26
28
|
import HlsPlayback from './plugins/hls-playback/HlsPlayback.js'
|
|
27
|
-
|
|
28
|
-
// import '../assets/style/main.scss' // TODO check if needed
|
|
29
|
+
import { buildSourcesPriorityList, buildSourcesSet, unwrapSource } from './utils/mediaSources.js'
|
|
29
30
|
|
|
30
31
|
// TODO implement transport retry/failover and fallback logic
|
|
31
32
|
|
|
@@ -35,15 +36,16 @@ const T = 'GPlayer'
|
|
|
35
36
|
|
|
36
37
|
const DEFAULT_OPTIONS: PlayerConfig = {
|
|
37
38
|
autoPlay: false,
|
|
38
|
-
|
|
39
|
+
debug: 'none',
|
|
39
40
|
loop: false,
|
|
41
|
+
mute: false,
|
|
40
42
|
multisources: [],
|
|
41
43
|
playbackType: 'vod',
|
|
42
|
-
priorityTransport: 'dash',
|
|
43
|
-
debug: 'none',
|
|
44
44
|
pluginSettings: {},
|
|
45
|
-
strings: {},
|
|
46
45
|
poster: '',
|
|
46
|
+
priorityTransport: 'dash',
|
|
47
|
+
sources: [],
|
|
48
|
+
strings: {},
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export type PlaybackModule = 'dash' | 'hls' | 'native'
|
|
@@ -236,7 +238,6 @@ export class Player {
|
|
|
236
238
|
player.core.on(
|
|
237
239
|
ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED,
|
|
238
240
|
() => {
|
|
239
|
-
// this.trigger(Events.ContainerChanged)
|
|
240
241
|
this.bindBitrateChangeHandler()
|
|
241
242
|
},
|
|
242
243
|
null,
|
|
@@ -345,16 +346,20 @@ export class Player {
|
|
|
345
346
|
}
|
|
346
347
|
|
|
347
348
|
private buildCoreOptions(rootNode: HTMLElement): CoreOptions {
|
|
348
|
-
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
349
|
+
// TODO extract
|
|
350
|
+
// const multisources = this.config.multisources
|
|
351
|
+
// const mainSource =
|
|
352
|
+
// this.config.playbackType === 'live'
|
|
353
|
+
// ? multisources.find((ms) => ms.live !== false)
|
|
354
|
+
// : multisources[0]
|
|
355
|
+
// const mediaSources = mainSource
|
|
356
|
+
// ? this.buildMediaSourcesList(mainSource)
|
|
357
|
+
// : []
|
|
356
358
|
// const mainSourceUrl = mediaSources[0];
|
|
357
|
-
const poster = mainSource?.poster ?? this.config.poster
|
|
359
|
+
// const poster = mainSource?.poster ?? this.config.poster
|
|
360
|
+
const poster = this.config.poster
|
|
361
|
+
|
|
362
|
+
const source = this.selectMediaSource(); // TODO
|
|
358
363
|
|
|
359
364
|
this.rootNode = rootNode
|
|
360
365
|
|
|
@@ -366,7 +371,6 @@ export class Player {
|
|
|
366
371
|
events: this.events,
|
|
367
372
|
height: rootNode.clientHeight,
|
|
368
373
|
loop: this.config.loop,
|
|
369
|
-
multisources,
|
|
370
374
|
mute: this.config.mute,
|
|
371
375
|
playback: {
|
|
372
376
|
controls: false,
|
|
@@ -382,8 +386,8 @@ export class Player {
|
|
|
382
386
|
playbackType: this.config.playbackType,
|
|
383
387
|
poster,
|
|
384
388
|
width: rootNode.clientWidth,
|
|
385
|
-
|
|
386
|
-
sources: mediaSources,
|
|
389
|
+
source: source ? unwrapSource(source) : undefined,
|
|
390
|
+
// sources: mediaSources,
|
|
387
391
|
strings: this.config.strings,
|
|
388
392
|
}
|
|
389
393
|
return coreOptions
|
|
@@ -404,63 +408,8 @@ export class Player {
|
|
|
404
408
|
)
|
|
405
409
|
}
|
|
406
410
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
{
|
|
411
|
-
dash: ms.sourceDash,
|
|
412
|
-
master: ms.source,
|
|
413
|
-
hls: ms.hlsCmafUrl,
|
|
414
|
-
mpegts: ms.hlsMpegtsUrl,
|
|
415
|
-
}
|
|
416
|
-
switch (this.config.priorityTransport) {
|
|
417
|
-
case 'dash':
|
|
418
|
-
addDash()
|
|
419
|
-
break
|
|
420
|
-
case 'hls':
|
|
421
|
-
addHls()
|
|
422
|
-
break
|
|
423
|
-
case 'mpegts':
|
|
424
|
-
addMpegts()
|
|
425
|
-
break
|
|
426
|
-
case 'auto':
|
|
427
|
-
addDash()
|
|
428
|
-
addHls()
|
|
429
|
-
break
|
|
430
|
-
}
|
|
431
|
-
Object.values(sources).forEach((s) => {
|
|
432
|
-
if (s) {
|
|
433
|
-
msl.push(s)
|
|
434
|
-
}
|
|
435
|
-
})
|
|
436
|
-
return msl
|
|
437
|
-
|
|
438
|
-
function addMpegts() {
|
|
439
|
-
if (sources.mpegts) {
|
|
440
|
-
msl.push(sources.mpegts)
|
|
441
|
-
sources.mpegts = null
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
function addHls() {
|
|
446
|
-
if (sources.hls && HlsPlayback.canPlay(sources.hls)) {
|
|
447
|
-
msl.push(sources.hls)
|
|
448
|
-
sources.hls = null
|
|
449
|
-
}
|
|
450
|
-
if (
|
|
451
|
-
sources.master?.endsWith('.m3u8') &&
|
|
452
|
-
HlsPlayback.canPlay(sources.master)
|
|
453
|
-
) {
|
|
454
|
-
msl.push(sources.master)
|
|
455
|
-
sources.master = null
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
function addDash() {
|
|
460
|
-
if (sources.dash && DashPlayback.canPlay(sources.dash)) {
|
|
461
|
-
msl.push(sources.dash)
|
|
462
|
-
sources.dash = null
|
|
463
|
-
}
|
|
464
|
-
}
|
|
411
|
+
// Select a single source to play according to the priority transport and the modules support
|
|
412
|
+
private selectMediaSource(): PlayerMediaSource | undefined {
|
|
413
|
+
return buildSourcesPriorityList(buildSourcesSet(this.config.sources), this.config.priorityTransport)[0]
|
|
465
414
|
}
|
|
466
415
|
}
|
package/src/internal.types.ts
CHANGED
|
@@ -18,7 +18,7 @@ type MediacontrolStyles = {
|
|
|
18
18
|
buttons?: string;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
type PlayerMediaSourceDesc = {
|
|
21
|
+
export type PlayerMediaSourceDesc = {
|
|
22
22
|
mimeType?: string;
|
|
23
23
|
source: string;
|
|
24
24
|
}
|
|
@@ -116,7 +116,7 @@ export type CoreOptions = {
|
|
|
116
116
|
maxBufferLength?: number;
|
|
117
117
|
mediacontrol?: MediacontrolStyles;
|
|
118
118
|
mimeType?: string;
|
|
119
|
-
multisources: StreamMediaSource[];
|
|
119
|
+
// multisources: StreamMediaSource[];
|
|
120
120
|
mute?: boolean;
|
|
121
121
|
persistConfig?: boolean;
|
|
122
122
|
preload?: "auto" | "metadata" | "none";
|