@gcorevideo/player 2.28.27 → 2.28.28
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/core.js +49 -65
- package/dist/index.css +135 -135
- package/dist/index.embed.js +45 -63
- package/dist/index.js +49 -65
- package/lib/playback/dash-playback/DashPlayback.d.ts +5 -5
- package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/playback/dash-playback/DashPlayback.js +42 -44
- package/package.json +2 -2
- package/src/playback/dash-playback/DashPlayback.ts +56 -51
- package/src/playback/hls-playback/HlsPlayback.ts +7 -7
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Playback } from '@clappr/core';
|
|
2
|
-
import
|
|
2
|
+
import { IManifestInfo, MediaPlayerClass, Representation } from 'dashjs';
|
|
3
3
|
import { QualityLevel, TimePosition, TimeValue } from '../../playback.types.js';
|
|
4
4
|
import { BasePlayback } from '../BasePlayback.js';
|
|
5
5
|
import { AudioTrack } from '@clappr/core/types/base/playback/playback.js';
|
|
@@ -10,8 +10,8 @@ type LocalTimeCorrelation = {
|
|
|
10
10
|
remote: number;
|
|
11
11
|
};
|
|
12
12
|
export default class DashPlayback extends BasePlayback {
|
|
13
|
-
_levels: QualityLevel[]
|
|
14
|
-
_currentLevel: number
|
|
13
|
+
_levels: QualityLevel[];
|
|
14
|
+
_currentLevel: number;
|
|
15
15
|
_durationExcludesAfterLiveSyncPoint: boolean;
|
|
16
16
|
_isReadyState: boolean;
|
|
17
17
|
_playableRegionDuration: number;
|
|
@@ -19,7 +19,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
19
19
|
_playbackType: PlaybackType;
|
|
20
20
|
_playlistType: PlaylistType | null;
|
|
21
21
|
_programDateTime: TimeValue;
|
|
22
|
-
_dash:
|
|
22
|
+
_dash: MediaPlayerClass | null;
|
|
23
23
|
_extrapolatedWindowDuration: number;
|
|
24
24
|
_lastDuration: TimeValue | null;
|
|
25
25
|
_lastTimeUpdate: TimePosition;
|
|
@@ -66,7 +66,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
66
66
|
private destroyInstance;
|
|
67
67
|
destroy(): void;
|
|
68
68
|
_updatePlaybackType(): void;
|
|
69
|
-
_fillLevels(levels:
|
|
69
|
+
_fillLevels(levels: Representation[]): void;
|
|
70
70
|
private onLevelSwitch;
|
|
71
71
|
private onLevelSwitchEnd;
|
|
72
72
|
getPlaybackType(): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashPlayback.d.ts","sourceRoot":"","sources":["../../../src/playback/dash-playback/DashPlayback.ts"],"names":[],"mappings":"AAKA,OAAO,EAAe,QAAQ,EAAyB,MAAM,cAAc,CAAA;AAG3E,OAAO,
|
|
1
|
+
{"version":3,"file":"DashPlayback.d.ts","sourceRoot":"","sources":["../../../src/playback/dash-playback/DashPlayback.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { Events, Log, Playback, PlayerError, Utils, $ } from '@clappr/core';
|
|
6
6
|
import { trace } from '@gcorevideo/utils';
|
|
7
7
|
import assert from 'assert';
|
|
8
|
-
import
|
|
8
|
+
import { MediaPlayer, } from 'dashjs';
|
|
9
9
|
import { PlaybackErrorCode, } from '../../playback.types.js';
|
|
10
10
|
import { isDashSource } from '../../utils/mediaSources.js';
|
|
11
11
|
import { BasePlayback } from '../BasePlayback.js';
|
|
@@ -14,8 +14,8 @@ const AUTO = -1;
|
|
|
14
14
|
const { now } = Utils;
|
|
15
15
|
const T = 'playback.dash';
|
|
16
16
|
export default class DashPlayback extends BasePlayback {
|
|
17
|
-
_levels =
|
|
18
|
-
_currentLevel =
|
|
17
|
+
_levels = [];
|
|
18
|
+
_currentLevel = AUTO;
|
|
19
19
|
// true when the actual duration is longer than hlsjs's live sync point
|
|
20
20
|
// when this is false playableRegionDuration will be the actual duration
|
|
21
21
|
// when this is true playableRegionDuration will exclude the time after the sync point
|
|
@@ -53,13 +53,9 @@ export default class DashPlayback extends BasePlayback {
|
|
|
53
53
|
return 'dash';
|
|
54
54
|
}
|
|
55
55
|
get levels() {
|
|
56
|
-
return this._levels
|
|
56
|
+
return this._levels;
|
|
57
57
|
}
|
|
58
58
|
get currentLevel() {
|
|
59
|
-
if (this._currentLevel === null) {
|
|
60
|
-
return AUTO;
|
|
61
|
-
}
|
|
62
|
-
// 0 is a valid level ID
|
|
63
59
|
return this._currentLevel;
|
|
64
60
|
}
|
|
65
61
|
get isReady() {
|
|
@@ -81,7 +77,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
81
77
|
});
|
|
82
78
|
dash.updateSettings(settings);
|
|
83
79
|
if (id !== -1) {
|
|
84
|
-
this._dash.
|
|
80
|
+
this._dash.setRepresentationForTypeByIndex('video', id);
|
|
85
81
|
}
|
|
86
82
|
if (this._playbackType === Playback.VOD) {
|
|
87
83
|
const curr_time = this._dash.time();
|
|
@@ -141,7 +137,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
141
137
|
}
|
|
142
138
|
}
|
|
143
139
|
_setup() {
|
|
144
|
-
const dash =
|
|
140
|
+
const dash = MediaPlayer().create();
|
|
145
141
|
this._dash = dash;
|
|
146
142
|
this._dash.initialize();
|
|
147
143
|
if (this.options.dash) {
|
|
@@ -154,30 +150,31 @@ export default class DashPlayback extends BasePlayback {
|
|
|
154
150
|
}, this.options.dash);
|
|
155
151
|
this._dash.updateSettings(settings);
|
|
156
152
|
}
|
|
153
|
+
assert.ok(this.el instanceof HTMLMediaElement, 'el must be an HTMLMediaElement');
|
|
157
154
|
this._dash.attachView(this.el);
|
|
158
155
|
this._dash.setAutoPlay(false);
|
|
159
156
|
this._dash.attachSource(this.options.src);
|
|
160
|
-
this._dash.on(
|
|
161
|
-
this._dash.on(
|
|
162
|
-
this._dash.on(
|
|
163
|
-
const bitrates = dash.
|
|
157
|
+
this._dash.on(MediaPlayer.events.ERROR, this._onDASHJSSError);
|
|
158
|
+
this._dash.on(MediaPlayer.events.PLAYBACK_ERROR, this._onPlaybackError);
|
|
159
|
+
this._dash.on(MediaPlayer.events.STREAM_INITIALIZED, () => {
|
|
160
|
+
const bitrates = dash.getRepresentationsByType('video');
|
|
164
161
|
this._updatePlaybackType();
|
|
165
162
|
this._fillLevels(bitrates);
|
|
166
|
-
const currentLevel = dash.
|
|
167
|
-
if (currentLevel
|
|
168
|
-
this.trigger(Events.PLAYBACK_BITRATE, this.getLevel(currentLevel));
|
|
163
|
+
const currentLevel = dash.getCurrentRepresentationForType('video');
|
|
164
|
+
if (currentLevel) {
|
|
165
|
+
this.trigger(Events.PLAYBACK_BITRATE, this.getLevel(currentLevel.index));
|
|
169
166
|
}
|
|
170
|
-
dash.on(
|
|
171
|
-
const newLevel = this.getLevel(evt.
|
|
167
|
+
dash.on(MediaPlayer.events.QUALITY_CHANGE_REQUESTED, (evt) => {
|
|
168
|
+
const newLevel = this.getLevel(evt.newRepresentation.index);
|
|
172
169
|
this.onLevelSwitch(newLevel);
|
|
173
170
|
});
|
|
174
171
|
this.checkAudioTracks();
|
|
175
172
|
});
|
|
176
|
-
this._dash.on(
|
|
177
|
-
const currentLevel = this.getLevel(evt.
|
|
173
|
+
this._dash.on(MediaPlayer.events.QUALITY_CHANGE_RENDERED, (evt) => {
|
|
174
|
+
const currentLevel = this.getLevel(evt.newRepresentation.index);
|
|
178
175
|
this.onLevelSwitchEnd(currentLevel);
|
|
179
176
|
});
|
|
180
|
-
this._dash.on(
|
|
177
|
+
this._dash.on(MediaPlayer.events.METRIC_ADDED, (e) => {
|
|
181
178
|
// Listen for the first manifest request in order to update player UI
|
|
182
179
|
if (e.metric === 'DVRInfo') {
|
|
183
180
|
// TODO fix typings
|
|
@@ -189,10 +186,10 @@ export default class DashPlayback extends BasePlayback {
|
|
|
189
186
|
}
|
|
190
187
|
}
|
|
191
188
|
});
|
|
192
|
-
this._dash.on(
|
|
189
|
+
this._dash.on(MediaPlayer.events.PLAYBACK_RATE_CHANGED, (e) => {
|
|
193
190
|
this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate);
|
|
194
191
|
});
|
|
195
|
-
this._dash.on(
|
|
192
|
+
this._dash.on(MediaPlayer.events.TRACK_CHANGE_RENDERED, (e) => {
|
|
196
193
|
if (e.mediaType === 'audio') {
|
|
197
194
|
this.trigger(Events.PLAYBACK_AUDIO_CHANGED, toClapprTrack(e.newMediaInfo));
|
|
198
195
|
}
|
|
@@ -294,17 +291,17 @@ export default class DashPlayback extends BasePlayback {
|
|
|
294
291
|
const e = event.error;
|
|
295
292
|
switch (e.code) {
|
|
296
293
|
// TODO test handling of these errors
|
|
297
|
-
case
|
|
298
|
-
case
|
|
299
|
-
case
|
|
300
|
-
case
|
|
301
|
-
case
|
|
294
|
+
case MediaPlayer.errors.MANIFEST_LOADER_PARSING_FAILURE_ERROR_CODE:
|
|
295
|
+
case MediaPlayer.errors.MANIFEST_LOADER_LOADING_FAILURE_ERROR_CODE:
|
|
296
|
+
case MediaPlayer.errors.DOWNLOAD_ERROR_ID_MANIFEST_CODE:
|
|
297
|
+
case MediaPlayer.errors.DOWNLOAD_ERROR_ID_CONTENT_CODE:
|
|
298
|
+
case MediaPlayer.errors.DOWNLOAD_ERROR_ID_INITIALIZATION_CODE:
|
|
302
299
|
// TODO these probably indicate a broken manifest and should be treated by removing the source
|
|
303
|
-
case
|
|
304
|
-
case
|
|
305
|
-
case
|
|
306
|
-
case
|
|
307
|
-
case
|
|
300
|
+
case MediaPlayer.errors.MANIFEST_ERROR_ID_NOSTREAMS_CODE:
|
|
301
|
+
case MediaPlayer.errors.MANIFEST_ERROR_ID_PARSE_CODE:
|
|
302
|
+
case MediaPlayer.errors.MANIFEST_ERROR_ID_MULTIPLEXED_CODE:
|
|
303
|
+
case MediaPlayer.errors.MEDIASOURCE_TYPE_UNSUPPORTED_CODE:
|
|
304
|
+
case MediaPlayer.errors.SEGMENT_BASE_LOADER_ERROR_CODE:
|
|
308
305
|
this.triggerError({
|
|
309
306
|
code: PlaybackErrorCode.MediaSourceUnavailable,
|
|
310
307
|
message: e.message,
|
|
@@ -363,7 +360,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
363
360
|
if (!this._dash) {
|
|
364
361
|
return false;
|
|
365
362
|
}
|
|
366
|
-
return (this._dash?.
|
|
363
|
+
return (this._dash?.getDvrWindow()?.size >= this._minDvrSize &&
|
|
367
364
|
this.getPlaybackType() === Playback.LIVE);
|
|
368
365
|
}
|
|
369
366
|
_onProgress() {
|
|
@@ -402,9 +399,9 @@ export default class DashPlayback extends BasePlayback {
|
|
|
402
399
|
}
|
|
403
400
|
destroyInstance() {
|
|
404
401
|
if (this._dash) {
|
|
405
|
-
this._dash.off(
|
|
406
|
-
this._dash.off(
|
|
407
|
-
this._dash.off(
|
|
402
|
+
this._dash.off(MediaPlayer.events.ERROR, this._onDASHJSSError);
|
|
403
|
+
this._dash.off(MediaPlayer.events.PLAYBACK_ERROR, this._onPlaybackError);
|
|
404
|
+
this._dash.off(MediaPlayer.events.MANIFEST_LOADED, this.getDuration);
|
|
408
405
|
this._dash.reset();
|
|
409
406
|
this._dash = null;
|
|
410
407
|
}
|
|
@@ -423,11 +420,12 @@ export default class DashPlayback extends BasePlayback {
|
|
|
423
420
|
}
|
|
424
421
|
}
|
|
425
422
|
_fillLevels(levels) {
|
|
426
|
-
// TOOD check that levels[i].
|
|
423
|
+
// TOOD check that levels[i].index === i
|
|
424
|
+
trace(`${T} _fillLevels`, { levels });
|
|
427
425
|
this._levels = levels.map((level) => {
|
|
428
426
|
return {
|
|
429
|
-
level: level.
|
|
430
|
-
bitrate: level.
|
|
427
|
+
level: level.index,
|
|
428
|
+
bitrate: level.bitrateInKbit * 1000,
|
|
431
429
|
width: level.width,
|
|
432
430
|
height: level.height,
|
|
433
431
|
};
|
|
@@ -451,9 +449,9 @@ export default class DashPlayback extends BasePlayback {
|
|
|
451
449
|
return this._playbackType === Playback.VOD || this.dvrEnabled;
|
|
452
450
|
}
|
|
453
451
|
getLevel(quality) {
|
|
454
|
-
const
|
|
455
|
-
assert.ok(
|
|
456
|
-
return
|
|
452
|
+
const level = this.levels.find((level) => level.level === quality);
|
|
453
|
+
assert.ok(level, 'Invalid quality level');
|
|
454
|
+
return level;
|
|
457
455
|
}
|
|
458
456
|
setPlaybackRate(rate) {
|
|
459
457
|
this._dash?.setPlaybackRate(rate);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gcorevideo/player",
|
|
3
|
-
"version": "2.28.
|
|
3
|
+
"version": "2.28.28",
|
|
4
4
|
"description": "Gcore JavaScript video player",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"@clappr/core": "^0.13.0",
|
|
62
62
|
"@gcorevideo/utils": "^0.7.1",
|
|
63
63
|
"@sentry/types": "^8.47.0",
|
|
64
|
-
"dashjs": "^
|
|
64
|
+
"dashjs": "^5.1.1",
|
|
65
65
|
"hls.js": "^1.6.15",
|
|
66
66
|
"human-format": "^1.2.1",
|
|
67
67
|
"mousetrap": "^1.6.5",
|
|
@@ -6,13 +6,20 @@
|
|
|
6
6
|
import { Events, Log, Playback, PlayerError, Utils, $ } from '@clappr/core'
|
|
7
7
|
import { trace } from '@gcorevideo/utils'
|
|
8
8
|
import assert from 'assert'
|
|
9
|
-
import
|
|
9
|
+
import {
|
|
10
10
|
ErrorEvent as DashErrorEvent,
|
|
11
11
|
MediaPlayerErrorEvent,
|
|
12
12
|
PlaybackErrorEvent as DashPlaybackErrorEvent,
|
|
13
13
|
type BitrateInfo as DashBitrateInfo,
|
|
14
14
|
MetricEvent as DashMetricEvent,
|
|
15
15
|
IManifestInfo,
|
|
16
|
+
MediaPlayerClass,
|
|
17
|
+
MediaPlayer,
|
|
18
|
+
PlaybackRateChangedEvent,
|
|
19
|
+
TrackChangeRenderedEvent,
|
|
20
|
+
MediaInfo,
|
|
21
|
+
Representation,
|
|
22
|
+
QualityChangeRenderedEvent,
|
|
16
23
|
} from 'dashjs'
|
|
17
24
|
|
|
18
25
|
import {
|
|
@@ -47,9 +54,9 @@ type LocalTimeCorrelation = {
|
|
|
47
54
|
const T = 'playback.dash'
|
|
48
55
|
|
|
49
56
|
export default class DashPlayback extends BasePlayback {
|
|
50
|
-
_levels: QualityLevel[]
|
|
57
|
+
_levels: QualityLevel[] = []
|
|
51
58
|
|
|
52
|
-
_currentLevel: number
|
|
59
|
+
_currentLevel: number = AUTO
|
|
53
60
|
|
|
54
61
|
// true when the actual duration is longer than hlsjs's live sync point
|
|
55
62
|
// when this is false playableRegionDuration will be the actual duration
|
|
@@ -78,7 +85,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
78
85
|
|
|
79
86
|
_programDateTime: TimeValue = 0
|
|
80
87
|
|
|
81
|
-
_dash:
|
|
88
|
+
_dash: MediaPlayerClass | null = null
|
|
82
89
|
|
|
83
90
|
_extrapolatedWindowDuration: number = 0
|
|
84
91
|
|
|
@@ -105,14 +112,10 @@ export default class DashPlayback extends BasePlayback {
|
|
|
105
112
|
}
|
|
106
113
|
|
|
107
114
|
get levels(): QualityLevel[] {
|
|
108
|
-
return this._levels
|
|
115
|
+
return this._levels
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
get currentLevel(): number {
|
|
112
|
-
if (this._currentLevel === null) {
|
|
113
|
-
return AUTO
|
|
114
|
-
}
|
|
115
|
-
// 0 is a valid level ID
|
|
116
119
|
return this._currentLevel
|
|
117
120
|
}
|
|
118
121
|
|
|
@@ -143,7 +146,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
143
146
|
|
|
144
147
|
dash.updateSettings(settings)
|
|
145
148
|
if (id !== -1) {
|
|
146
|
-
this._dash.
|
|
149
|
+
this._dash.setRepresentationForTypeByIndex('video', id)
|
|
147
150
|
}
|
|
148
151
|
if (this._playbackType === Playback.VOD) {
|
|
149
152
|
const curr_time = this._dash.time()
|
|
@@ -226,7 +229,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
226
229
|
}
|
|
227
230
|
|
|
228
231
|
_setup() {
|
|
229
|
-
const dash =
|
|
232
|
+
const dash = MediaPlayer().create()
|
|
230
233
|
this._dash = dash
|
|
231
234
|
this._dash.initialize()
|
|
232
235
|
|
|
@@ -245,29 +248,30 @@ export default class DashPlayback extends BasePlayback {
|
|
|
245
248
|
this._dash.updateSettings(settings)
|
|
246
249
|
}
|
|
247
250
|
|
|
251
|
+
assert.ok(this.el instanceof HTMLMediaElement, 'el must be an HTMLMediaElement')
|
|
248
252
|
this._dash.attachView(this.el)
|
|
249
253
|
|
|
250
254
|
this._dash.setAutoPlay(false)
|
|
251
255
|
this._dash.attachSource(this.options.src)
|
|
252
256
|
|
|
253
|
-
this._dash.on(
|
|
257
|
+
this._dash.on(MediaPlayer.events.ERROR, this._onDASHJSSError)
|
|
254
258
|
this._dash.on(
|
|
255
|
-
|
|
259
|
+
MediaPlayer.events.PLAYBACK_ERROR,
|
|
256
260
|
this._onPlaybackError,
|
|
257
261
|
)
|
|
258
262
|
|
|
259
|
-
this._dash.on(
|
|
260
|
-
const bitrates = dash.
|
|
263
|
+
this._dash.on(MediaPlayer.events.STREAM_INITIALIZED, () => {
|
|
264
|
+
const bitrates = dash.getRepresentationsByType('video')
|
|
261
265
|
|
|
262
266
|
this._updatePlaybackType()
|
|
263
267
|
this._fillLevels(bitrates)
|
|
264
|
-
const currentLevel = dash.
|
|
265
|
-
if (currentLevel
|
|
266
|
-
this.trigger(Events.PLAYBACK_BITRATE, this.getLevel(currentLevel))
|
|
268
|
+
const currentLevel = dash.getCurrentRepresentationForType('video')
|
|
269
|
+
if (currentLevel) {
|
|
270
|
+
this.trigger(Events.PLAYBACK_BITRATE, this.getLevel(currentLevel.index))
|
|
267
271
|
}
|
|
268
272
|
|
|
269
|
-
dash.on(
|
|
270
|
-
const newLevel = this.getLevel(evt.
|
|
273
|
+
dash.on(MediaPlayer.events.QUALITY_CHANGE_REQUESTED, (evt) => {
|
|
274
|
+
const newLevel = this.getLevel(evt.newRepresentation.index)
|
|
271
275
|
this.onLevelSwitch(newLevel)
|
|
272
276
|
})
|
|
273
277
|
|
|
@@ -275,15 +279,15 @@ export default class DashPlayback extends BasePlayback {
|
|
|
275
279
|
})
|
|
276
280
|
|
|
277
281
|
this._dash.on(
|
|
278
|
-
|
|
279
|
-
(evt:
|
|
280
|
-
const currentLevel = this.getLevel(evt.
|
|
282
|
+
MediaPlayer.events.QUALITY_CHANGE_RENDERED,
|
|
283
|
+
(evt: QualityChangeRenderedEvent) => {
|
|
284
|
+
const currentLevel = this.getLevel(evt.newRepresentation.index)
|
|
281
285
|
this.onLevelSwitchEnd(currentLevel)
|
|
282
286
|
},
|
|
283
287
|
)
|
|
284
288
|
|
|
285
289
|
this._dash.on(
|
|
286
|
-
|
|
290
|
+
MediaPlayer.events.METRIC_ADDED,
|
|
287
291
|
(e: DashMetricEvent) => {
|
|
288
292
|
// Listen for the first manifest request in order to update player UI
|
|
289
293
|
if ((e.metric as string) === 'DVRInfo') {
|
|
@@ -302,14 +306,14 @@ export default class DashPlayback extends BasePlayback {
|
|
|
302
306
|
)
|
|
303
307
|
|
|
304
308
|
this._dash.on(
|
|
305
|
-
|
|
306
|
-
(e:
|
|
309
|
+
MediaPlayer.events.PLAYBACK_RATE_CHANGED,
|
|
310
|
+
(e: PlaybackRateChangedEvent) => {
|
|
307
311
|
this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate)
|
|
308
312
|
},
|
|
309
313
|
)
|
|
310
314
|
|
|
311
|
-
this._dash.on(
|
|
312
|
-
if ((e as
|
|
315
|
+
this._dash.on(MediaPlayer.events.TRACK_CHANGE_RENDERED, (e: any) => {
|
|
316
|
+
if ((e as TrackChangeRenderedEvent).mediaType === 'audio') {
|
|
313
317
|
this.trigger(
|
|
314
318
|
Events.PLAYBACK_AUDIO_CHANGED,
|
|
315
319
|
toClapprTrack(e.newMediaInfo),
|
|
@@ -442,17 +446,17 @@ export default class DashPlayback extends BasePlayback {
|
|
|
442
446
|
const e = (event as MediaPlayerErrorEvent).error
|
|
443
447
|
switch (e.code) {
|
|
444
448
|
// TODO test handling of these errors
|
|
445
|
-
case
|
|
446
|
-
case
|
|
447
|
-
case
|
|
448
|
-
case
|
|
449
|
-
case
|
|
449
|
+
case MediaPlayer.errors.MANIFEST_LOADER_PARSING_FAILURE_ERROR_CODE:
|
|
450
|
+
case MediaPlayer.errors.MANIFEST_LOADER_LOADING_FAILURE_ERROR_CODE:
|
|
451
|
+
case MediaPlayer.errors.DOWNLOAD_ERROR_ID_MANIFEST_CODE:
|
|
452
|
+
case MediaPlayer.errors.DOWNLOAD_ERROR_ID_CONTENT_CODE:
|
|
453
|
+
case MediaPlayer.errors.DOWNLOAD_ERROR_ID_INITIALIZATION_CODE:
|
|
450
454
|
// TODO these probably indicate a broken manifest and should be treated by removing the source
|
|
451
|
-
case
|
|
452
|
-
case
|
|
453
|
-
case
|
|
454
|
-
case
|
|
455
|
-
case
|
|
455
|
+
case MediaPlayer.errors.MANIFEST_ERROR_ID_NOSTREAMS_CODE:
|
|
456
|
+
case MediaPlayer.errors.MANIFEST_ERROR_ID_PARSE_CODE:
|
|
457
|
+
case MediaPlayer.errors.MANIFEST_ERROR_ID_MULTIPLEXED_CODE:
|
|
458
|
+
case MediaPlayer.errors.MEDIASOURCE_TYPE_UNSUPPORTED_CODE:
|
|
459
|
+
case MediaPlayer.errors.SEGMENT_BASE_LOADER_ERROR_CODE:
|
|
456
460
|
this.triggerError({
|
|
457
461
|
code: PlaybackErrorCode.MediaSourceUnavailable,
|
|
458
462
|
message: e.message,
|
|
@@ -525,7 +529,7 @@ export default class DashPlayback extends BasePlayback {
|
|
|
525
529
|
return false
|
|
526
530
|
}
|
|
527
531
|
return (
|
|
528
|
-
this._dash?.
|
|
532
|
+
this._dash?.getDvrWindow()?.size >= this._minDvrSize &&
|
|
529
533
|
this.getPlaybackType() === Playback.LIVE
|
|
530
534
|
)
|
|
531
535
|
}
|
|
@@ -572,13 +576,13 @@ export default class DashPlayback extends BasePlayback {
|
|
|
572
576
|
|
|
573
577
|
private destroyInstance() {
|
|
574
578
|
if (this._dash) {
|
|
575
|
-
this._dash.off(
|
|
579
|
+
this._dash.off(MediaPlayer.events.ERROR, this._onDASHJSSError)
|
|
576
580
|
this._dash.off(
|
|
577
|
-
|
|
581
|
+
MediaPlayer.events.PLAYBACK_ERROR,
|
|
578
582
|
this._onPlaybackError,
|
|
579
583
|
)
|
|
580
584
|
this._dash.off(
|
|
581
|
-
|
|
585
|
+
MediaPlayer.events.MANIFEST_LOADED,
|
|
582
586
|
this.getDuration,
|
|
583
587
|
)
|
|
584
588
|
this._dash.reset()
|
|
@@ -601,12 +605,13 @@ export default class DashPlayback extends BasePlayback {
|
|
|
601
605
|
}
|
|
602
606
|
}
|
|
603
607
|
|
|
604
|
-
_fillLevels(levels:
|
|
605
|
-
// TOOD check that levels[i].
|
|
608
|
+
_fillLevels(levels: Representation[]) {
|
|
609
|
+
// TOOD check that levels[i].index === i
|
|
610
|
+
trace(`${T} _fillLevels`, { levels })
|
|
606
611
|
this._levels = levels.map((level) => {
|
|
607
612
|
return {
|
|
608
|
-
level: level.
|
|
609
|
-
bitrate: level.
|
|
613
|
+
level: level.index,
|
|
614
|
+
bitrate: level.bitrateInKbit * 1000,
|
|
610
615
|
width: level.width,
|
|
611
616
|
height: level.height,
|
|
612
617
|
}
|
|
@@ -635,10 +640,10 @@ export default class DashPlayback extends BasePlayback {
|
|
|
635
640
|
return this._playbackType === Playback.VOD || this.dvrEnabled
|
|
636
641
|
}
|
|
637
642
|
|
|
638
|
-
private getLevel(quality: number) {
|
|
639
|
-
const
|
|
640
|
-
assert.ok(
|
|
641
|
-
return
|
|
643
|
+
private getLevel(quality: number): QualityLevel {
|
|
644
|
+
const level = this.levels.find((level) => level.level === quality)
|
|
645
|
+
assert.ok(level, 'Invalid quality level')
|
|
646
|
+
return level
|
|
642
647
|
}
|
|
643
648
|
|
|
644
649
|
setPlaybackRate(rate: number) {
|
|
@@ -707,7 +712,7 @@ DashPlayback.canPlay = function (resource, mimeType) {
|
|
|
707
712
|
return typeof ctor === 'function'
|
|
708
713
|
}
|
|
709
714
|
|
|
710
|
-
function toClapprTrack(t:
|
|
715
|
+
function toClapprTrack(t: MediaInfo): AudioTrack {
|
|
711
716
|
return {
|
|
712
717
|
id: t.id,
|
|
713
718
|
kind: t.roles && t.roles?.length > 0 ? t.roles[0] : 'main', // TODO
|
|
@@ -305,7 +305,7 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
305
305
|
// added/removed every 5.
|
|
306
306
|
this._extrapolatedWindowNumSegments =
|
|
307
307
|
!this.options.playback ||
|
|
308
|
-
|
|
308
|
+
typeof this.options.playback.extrapolatedWindowNumSegments === 'undefined'
|
|
309
309
|
? 2
|
|
310
310
|
: this.options.playback.extrapolatedWindowNumSegments
|
|
311
311
|
|
|
@@ -527,7 +527,7 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
527
527
|
}
|
|
528
528
|
|
|
529
529
|
// this playback manages the src on the video element itself
|
|
530
|
-
protected override _setupSrc(srcUrl: string) {} // eslint-disable-line no-unused-vars
|
|
530
|
+
protected override _setupSrc(srcUrl: string) { } // eslint-disable-line no-unused-vars
|
|
531
531
|
|
|
532
532
|
private _startTimeUpdateTimer() {
|
|
533
533
|
if (this._timeUpdateTimer) {
|
|
@@ -592,7 +592,7 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
592
592
|
// assume live if time within 3 seconds of end of stream
|
|
593
593
|
this.dvrEnabled && this._updateDvr(time < this.getDuration() - 3)
|
|
594
594
|
time += this._startTime
|
|
595
|
-
|
|
595
|
+
; (this.el as HTMLMediaElement).currentTime = time
|
|
596
596
|
}
|
|
597
597
|
|
|
598
598
|
seekToLivePoint() {
|
|
@@ -781,12 +781,12 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
781
781
|
start: Math.max(
|
|
782
782
|
0,
|
|
783
783
|
(this.el as HTMLMediaElement).buffered.start(i) -
|
|
784
|
-
|
|
784
|
+
this._playableRegionStartTime,
|
|
785
785
|
),
|
|
786
786
|
end: Math.max(
|
|
787
787
|
0,
|
|
788
788
|
(this.el as HTMLMediaElement).buffered.end(i) -
|
|
789
|
-
|
|
789
|
+
this._playableRegionStartTime,
|
|
790
790
|
),
|
|
791
791
|
},
|
|
792
792
|
]
|
|
@@ -826,7 +826,7 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
826
826
|
if (!this._hls) {
|
|
827
827
|
return
|
|
828
828
|
}
|
|
829
|
-
;(this.el as HTMLMediaElement).pause()
|
|
829
|
+
; (this.el as HTMLMediaElement).pause()
|
|
830
830
|
if (this.dvrEnabled) {
|
|
831
831
|
this._updateDvr(true)
|
|
832
832
|
}
|
|
@@ -942,7 +942,7 @@ export default class HlsPlayback extends BasePlayback {
|
|
|
942
942
|
Math.max(
|
|
943
943
|
fragments[0].start,
|
|
944
944
|
previousPlayableRegionStartTime +
|
|
945
|
-
|
|
945
|
+
this._extrapolatedWindowDuration,
|
|
946
946
|
) * 1000,
|
|
947
947
|
}
|
|
948
948
|
}
|