@gcorevideo/player 2.6.0 → 2.6.2
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 +38 -211
- package/lib/plugins/dash-playback/DashPlayback.d.ts +0 -4
- package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -1
- package/lib/plugins/dash-playback/DashPlayback.js +38 -211
- package/package.json +1 -1
- package/src/plugins/dash-playback/DashPlayback.ts +40 -243
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -2,14 +2,8 @@
|
|
|
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
4
|
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
HTML5Video,
|
|
8
|
-
Log,
|
|
9
|
-
Playback,
|
|
10
|
-
Utils,
|
|
11
|
-
} from '@clappr/core'
|
|
12
|
-
import assert from 'assert' // uses Node.js's assert types
|
|
5
|
+
import { Events, HTML5Video, Log, Playback, Utils } from '@clappr/core'
|
|
6
|
+
import assert from 'assert'
|
|
13
7
|
import DASHJS, {
|
|
14
8
|
ErrorEvent as DashErrorEvent,
|
|
15
9
|
PlaybackErrorEvent as DashPlaybackErrorEvent,
|
|
@@ -50,16 +44,29 @@ export default class DashPlayback extends HTML5Video {
|
|
|
50
44
|
|
|
51
45
|
_currentLevel: number | null = null
|
|
52
46
|
|
|
47
|
+
// true when the actual duration is longer than hlsjs's live sync point
|
|
48
|
+
// when this is false playableRegionDuration will be the actual duration
|
|
49
|
+
// when this is true playableRegionDuration will exclude the time after the sync point
|
|
53
50
|
_durationExcludesAfterLiveSyncPoint: boolean = false
|
|
54
51
|
|
|
55
52
|
_isReadyState: boolean = false
|
|
56
53
|
|
|
54
|
+
// if content is removed from the beginning then this empty area should
|
|
55
|
+
// be ignored. "playableRegionDuration" excludes the empty area
|
|
57
56
|
_playableRegionDuration: number = 0
|
|
58
57
|
|
|
58
|
+
// for hls streams which have dvr with a sliding window,
|
|
59
|
+
// the content at the start of the playlist is removed as new
|
|
60
|
+
// content is appended at the end.
|
|
61
|
+
// this means the actual playable start time will increase as the
|
|
62
|
+
// start content is deleted
|
|
63
|
+
// For streams with dvr where the entire recording is kept from the
|
|
64
|
+
// beginning this should stay as 0
|
|
59
65
|
_playableRegionStartTime: number = 0
|
|
60
66
|
|
|
61
67
|
_playbackType: PlaybackType = Playback.VOD
|
|
62
68
|
|
|
69
|
+
// #EXT-X-PLAYLIST-TYPE
|
|
63
70
|
_playlistType: PlaylistType | null = null
|
|
64
71
|
|
|
65
72
|
// #EXT-X-PROGRAM-DATE-TIME
|
|
@@ -69,22 +76,20 @@ export default class DashPlayback extends HTML5Video {
|
|
|
69
76
|
|
|
70
77
|
_extrapolatedWindowDuration: number = 0
|
|
71
78
|
|
|
72
|
-
_extrapolatedWindowNumSegments: number = 0
|
|
79
|
+
// _extrapolatedWindowNumSegments: number = 0
|
|
73
80
|
|
|
74
81
|
_lastDuration: TimeValue | null = null
|
|
75
82
|
|
|
76
83
|
_lastTimeUpdate: TimePosition = { current: 0, total: 0 }
|
|
77
84
|
|
|
85
|
+
// {local, remote} remote is the time in the video element that should represent 0
|
|
86
|
+
// local is the system time when the 'remote' measurment took place
|
|
78
87
|
_localStartTimeCorrelation: LocalTimeCorrelation | null = null
|
|
79
88
|
|
|
89
|
+
// {local, remote} remote is the time in the video element that should represents the end
|
|
90
|
+
// local is the system time when the 'remote' measurment took place
|
|
80
91
|
_localEndTimeCorrelation: LocalTimeCorrelation | null = null
|
|
81
92
|
|
|
82
|
-
_recoverAttemptsRemaining: number = 0
|
|
83
|
-
|
|
84
|
-
_recoveredAudioCodecError = false
|
|
85
|
-
|
|
86
|
-
_recoveredDecodingError = false
|
|
87
|
-
|
|
88
93
|
startChangeQuality = false
|
|
89
94
|
|
|
90
95
|
manifestInfo: IManifestInfo | null = null
|
|
@@ -114,27 +119,23 @@ export default class DashPlayback extends HTML5Video {
|
|
|
114
119
|
return this._isReadyState
|
|
115
120
|
}
|
|
116
121
|
|
|
117
|
-
set currentLevel(id) {
|
|
122
|
+
set currentLevel(id: number) {
|
|
118
123
|
this._currentLevel = id
|
|
119
124
|
|
|
120
125
|
this.trigger(Events.PLAYBACK_LEVEL_SWITCH_START)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
ABRStrategy: 'abrL2A',
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
}
|
|
126
|
+
|
|
127
|
+
const settings = this.options.dash ? structuredClone(this.options.dash) : {}
|
|
128
|
+
settings.streaming = settings.streaming || {}
|
|
129
|
+
settings.streaming.abr = settings.streaming.abr || {}
|
|
130
|
+
settings.streaming.abr.autoSwitchBitrate = settings.streaming.abr.autoSwitchBitrate || {}
|
|
131
|
+
settings.streaming.abr.autoSwitchBitrate.video = id === -1
|
|
131
132
|
|
|
132
133
|
assert.ok(
|
|
133
134
|
this._dash,
|
|
134
135
|
'An instance of dashjs MediaPlayer is required to switch levels',
|
|
135
136
|
)
|
|
136
137
|
const dash = this._dash
|
|
137
|
-
|
|
138
|
+
dash.updateSettings(settings)
|
|
138
139
|
if (id !== -1) {
|
|
139
140
|
this._dash.setQualityFor('video', id)
|
|
140
141
|
}
|
|
@@ -213,52 +214,9 @@ export default class DashPlayback extends HTML5Video {
|
|
|
213
214
|
|
|
214
215
|
constructor(options: any, i18n: string, playerError?: any) {
|
|
215
216
|
super(options, i18n, playerError)
|
|
216
|
-
// backwards compatibility (TODO: remove on 0.3.0)
|
|
217
|
-
// this.options.playback || (this.options.playback = this.options);
|
|
218
|
-
// The size of the start time extrapolation window measured as a multiple of segments.
|
|
219
|
-
// Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
|
|
220
|
-
// removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
|
|
221
|
-
// added/removed every 5.
|
|
222
|
-
this._extrapolatedWindowNumSegments =
|
|
223
|
-
this.options.playback?.extrapolatedWindowNumSegments ?? 2
|
|
224
|
-
|
|
225
217
|
if (this.options.playbackType) {
|
|
226
218
|
this._playbackType = this.options.playbackType
|
|
227
219
|
}
|
|
228
|
-
// this._lastTimeUpdate = { current: 0, total: 0 };
|
|
229
|
-
// this._lastDuration = null;
|
|
230
|
-
// for hls streams which have dvr with a sliding window,
|
|
231
|
-
// the content at the start of the playlist is removed as new
|
|
232
|
-
// content is appended at the end.
|
|
233
|
-
// this means the actual playable start time will increase as the
|
|
234
|
-
// start content is deleted
|
|
235
|
-
// For streams with dvr where the entire recording is kept from the
|
|
236
|
-
// beginning this should stay as 0
|
|
237
|
-
// this._playableRegionStartTime = 0;
|
|
238
|
-
// {local, remote} remote is the time in the video element that should represent 0
|
|
239
|
-
// local is the system time when the 'remote' measurment took place
|
|
240
|
-
// this._localStartTimeCorrelation = null;
|
|
241
|
-
// {local, remote} remote is the time in the video element that should represents the end
|
|
242
|
-
// local is the system time when the 'remote' measurment took place
|
|
243
|
-
// this._localEndTimeCorrelation = null;
|
|
244
|
-
// if content is removed from the beginning then this empty area should
|
|
245
|
-
// be ignored. "playableRegionDuration" excludes the empty area
|
|
246
|
-
// this._playableRegionDuration = 0;
|
|
247
|
-
// #EXT-X-PROGRAM-DATE-TIME
|
|
248
|
-
// this._programDateTime = 0;
|
|
249
|
-
|
|
250
|
-
// this.manifestInfo = null;
|
|
251
|
-
// true when the actual duration is longer than hlsjs's live sync point
|
|
252
|
-
// when this is false playableRegionDuration will be the actual duration
|
|
253
|
-
// when this is true playableRegionDuration will exclude the time after the sync point
|
|
254
|
-
// this._durationExcludesAfterLiveSyncPoint = false;
|
|
255
|
-
// // #EXT-X-TARGETDURATION
|
|
256
|
-
// this._segmentTargetDuration = null;
|
|
257
|
-
// #EXT-X-PLAYLIST-TYPE
|
|
258
|
-
// this._playlistType = null;
|
|
259
|
-
if (this.options.hlsRecoverAttempts) {
|
|
260
|
-
this._recoverAttemptsRemaining = this.options.hlsRecoverAttempts
|
|
261
|
-
}
|
|
262
220
|
}
|
|
263
221
|
|
|
264
222
|
_setup() {
|
|
@@ -266,12 +224,18 @@ export default class DashPlayback extends HTML5Video {
|
|
|
266
224
|
this._dash = dash
|
|
267
225
|
this._dash.initialize()
|
|
268
226
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
227
|
+
if (this.options.dash) {
|
|
228
|
+
const settings = structuredClone(this.options.dash)
|
|
229
|
+
if (!settings.streaming) {
|
|
230
|
+
settings.streaming = {}
|
|
231
|
+
}
|
|
232
|
+
if (!settings.streaming.text) {
|
|
233
|
+
settings.streaming.text = {
|
|
234
|
+
defaultEnabled: false,
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
this._dash.updateSettings(this.options.dash)
|
|
238
|
+
}
|
|
275
239
|
|
|
276
240
|
this._dash.attachView(this.el)
|
|
277
241
|
|
|
@@ -338,30 +302,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
338
302
|
this.trigger(Events.PLAYBACK_READY, this.name)
|
|
339
303
|
}
|
|
340
304
|
|
|
341
|
-
// TODO
|
|
342
|
-
// _recover(evt, data, error) {
|
|
343
|
-
// console.warn('recover', evt, data, error);
|
|
344
|
-
// assert.ok(this._dash, 'An instance of dashjs MediaPlayer is required to recover');
|
|
345
|
-
// // TODO figure out what's going on here
|
|
346
|
-
// const dash = this._dash;
|
|
347
|
-
// if (!this._recoveredDecodingError) {
|
|
348
|
-
// this._recoveredDecodingError = true;
|
|
349
|
-
// // dash.recoverMediaError();
|
|
350
|
-
// } else if (!this._recoveredAudioCodecError) {
|
|
351
|
-
// this._recoveredAudioCodecError = true;
|
|
352
|
-
// // dash.swapAudioCodec();
|
|
353
|
-
// // dash.recoverMediaError();
|
|
354
|
-
// } else {
|
|
355
|
-
// // TODO what does it have to do with hlsjs?
|
|
356
|
-
// Log.error('hlsjs: failed to recover', { evt, data });
|
|
357
|
-
// error.level = PlayerError.Levels.FATAL;
|
|
358
|
-
// const formattedError = this.createError(error);
|
|
359
|
-
|
|
360
|
-
// this.trigger(Events.PLAYBACK_ERROR, formattedError);
|
|
361
|
-
// this.stop();
|
|
362
|
-
// }
|
|
363
|
-
// }
|
|
364
|
-
|
|
365
305
|
// override
|
|
366
306
|
_setupSrc() {
|
|
367
307
|
// this playback manages the src on the video element itself
|
|
@@ -453,7 +393,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
453
393
|
_updateSettings() {
|
|
454
394
|
if (this._playbackType === Playback.VOD) {
|
|
455
395
|
this.settings.left = ['playpause', 'position', 'duration']
|
|
456
|
-
// this.settings.left.push('playstop');
|
|
457
396
|
} else if (this.dvrEnabled) {
|
|
458
397
|
this.settings.left = ['playpause']
|
|
459
398
|
} else {
|
|
@@ -700,147 +639,6 @@ export default class DashPlayback extends HTML5Video {
|
|
|
700
639
|
this.trigger(Events.PLAYBACK_LEVELS_AVAILABLE, this._levels)
|
|
701
640
|
}
|
|
702
641
|
|
|
703
|
-
// _onLevelUpdated(_: any, data) {
|
|
704
|
-
// this._segmentTargetDuration = data.details.targetduration;
|
|
705
|
-
// this._playlistType = data.details.type || null;
|
|
706
|
-
|
|
707
|
-
// let startTimeChanged = false;
|
|
708
|
-
// let durationChanged = false;
|
|
709
|
-
// const fragments = data.details.fragments;
|
|
710
|
-
// const previousPlayableRegionStartTime = this._playableRegionStartTime;
|
|
711
|
-
// const previousPlayableRegionDuration = this._playableRegionDuration;
|
|
712
|
-
|
|
713
|
-
// if (fragments.length === 0) {
|
|
714
|
-
// return;
|
|
715
|
-
// }
|
|
716
|
-
|
|
717
|
-
// // #EXT-X-PROGRAM-DATE-TIME
|
|
718
|
-
// if (fragments[0].rawProgramDateTime) {
|
|
719
|
-
// this._programDateTime = fragments[0].rawProgramDateTime;
|
|
720
|
-
// }
|
|
721
|
-
|
|
722
|
-
// if (this._playableRegionStartTime !== fragments[0].start) {
|
|
723
|
-
// startTimeChanged = true;
|
|
724
|
-
// this._playableRegionStartTime = fragments[0].start;
|
|
725
|
-
// }
|
|
726
|
-
|
|
727
|
-
// if (startTimeChanged) {
|
|
728
|
-
// if (!this._localStartTimeCorrelation) {
|
|
729
|
-
// // set the correlation to map to middle of the extrapolation window
|
|
730
|
-
// this._localStartTimeCorrelation = {
|
|
731
|
-
// local: this._now,
|
|
732
|
-
// remote: (fragments[0].start + (this._extrapolatedWindowDuration / 2)) * 1000
|
|
733
|
-
// };
|
|
734
|
-
// } else {
|
|
735
|
-
// // check if the correlation still works
|
|
736
|
-
// const corr = this._localStartTimeCorrelation;
|
|
737
|
-
// const timePassed = this._now - corr.local;
|
|
738
|
-
// // this should point to a time within the extrapolation window
|
|
739
|
-
// const startTime = (corr.remote + timePassed) / 1000;
|
|
740
|
-
|
|
741
|
-
// if (startTime < fragments[0].start) {
|
|
742
|
-
// // our start time is now earlier than the first chunk
|
|
743
|
-
// // (maybe the chunk was removed early)
|
|
744
|
-
// // reset correlation so that it sits at the beginning of the first available chunk
|
|
745
|
-
// this._localStartTimeCorrelation = {
|
|
746
|
-
// local: this._now,
|
|
747
|
-
// remote: fragments[0].start * 1000
|
|
748
|
-
// };
|
|
749
|
-
// } else if (startTime > previousPlayableRegionStartTime + this._extrapolatedWindowDuration) {
|
|
750
|
-
// // start time was past the end of the old extrapolation window (so would have been capped)
|
|
751
|
-
// // see if now that time would be inside the window, and if it would be set the correlation
|
|
752
|
-
// // so that it resumes from the time it was at at the end of the old window
|
|
753
|
-
// // update the correlation so that the time starts counting again from the value it's on now
|
|
754
|
-
// this._localStartTimeCorrelation = {
|
|
755
|
-
// local: this._now,
|
|
756
|
-
// remote: Math.max(
|
|
757
|
-
// fragments[0].start,
|
|
758
|
-
// previousPlayableRegionStartTime + this._extrapolatedWindowDuration
|
|
759
|
-
// ) * 1000
|
|
760
|
-
// };
|
|
761
|
-
// }
|
|
762
|
-
// }
|
|
763
|
-
// }
|
|
764
|
-
|
|
765
|
-
// let newDuration = data.details.totalduration;
|
|
766
|
-
|
|
767
|
-
// // if it's a live stream then shorten the duration to remove access
|
|
768
|
-
// // to the area after hlsjs's live sync point
|
|
769
|
-
// // seeks to areas after this point sometimes have issues
|
|
770
|
-
// if (this._playbackType === Playback.LIVE) {
|
|
771
|
-
// const fragmentTargetDuration = data.details.targetduration;
|
|
772
|
-
// const hlsjsConfig = this.options.playback.hlsjsConfig || {};
|
|
773
|
-
// // eslint-disable-next-line no-undef
|
|
774
|
-
// const liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount || HLSJS.DefaultConfig.liveSyncDurationCount;
|
|
775
|
-
// const hiddenAreaDuration = fragmentTargetDuration * liveSyncDurationCount;
|
|
776
|
-
|
|
777
|
-
// if (hiddenAreaDuration <= newDuration) {
|
|
778
|
-
// newDuration -= hiddenAreaDuration;
|
|
779
|
-
// this._durationExcludesAfterLiveSyncPoint = true;
|
|
780
|
-
// } else {
|
|
781
|
-
// this._durationExcludesAfterLiveSyncPoint = false;
|
|
782
|
-
// }
|
|
783
|
-
// }
|
|
784
|
-
|
|
785
|
-
// if (newDuration !== this._playableRegionDuration) {
|
|
786
|
-
// durationChanged = true;
|
|
787
|
-
// this._playableRegionDuration = newDuration;
|
|
788
|
-
// }
|
|
789
|
-
|
|
790
|
-
// // Note the end time is not the playableRegionDuration
|
|
791
|
-
// // The end time will always increase even if content is removed from the beginning
|
|
792
|
-
// const endTime = fragments[0].start + newDuration;
|
|
793
|
-
// const previousEndTime = previousPlayableRegionStartTime + previousPlayableRegionDuration;
|
|
794
|
-
// const endTimeChanged = endTime !== previousEndTime;
|
|
795
|
-
|
|
796
|
-
// if (endTimeChanged) {
|
|
797
|
-
// if (!this._localEndTimeCorrelation) {
|
|
798
|
-
// // set the correlation to map to the end
|
|
799
|
-
// this._localEndTimeCorrelation = {
|
|
800
|
-
// local: this._now,
|
|
801
|
-
// remote: endTime * 1000
|
|
802
|
-
// };
|
|
803
|
-
// } else {
|
|
804
|
-
// // check if the correlation still works
|
|
805
|
-
// const corr = this._localEndTimeCorrelation;
|
|
806
|
-
// const timePassed = this._now - corr.local;
|
|
807
|
-
// // this should point to a time within the extrapolation window from the end
|
|
808
|
-
// const extrapolatedEndTime = (corr.remote + timePassed) / 1000;
|
|
809
|
-
|
|
810
|
-
// if (extrapolatedEndTime > endTime) {
|
|
811
|
-
// this._localEndTimeCorrelation = {
|
|
812
|
-
// local: this._now,
|
|
813
|
-
// remote: endTime * 1000
|
|
814
|
-
// };
|
|
815
|
-
// } else if (extrapolatedEndTime < endTime - this._extrapolatedWindowDuration) {
|
|
816
|
-
// // our extrapolated end time is now earlier than the extrapolation window from the actual end time
|
|
817
|
-
// // (maybe a chunk became available early)
|
|
818
|
-
// // reset correlation so that it sits at the beginning of the extrapolation window from the end time
|
|
819
|
-
// this._localEndTimeCorrelation = {
|
|
820
|
-
// local: this._now,
|
|
821
|
-
// remote: (endTime - this._extrapolatedWindowDuration) * 1000
|
|
822
|
-
// };
|
|
823
|
-
// } else if (extrapolatedEndTime > previousEndTime) {
|
|
824
|
-
// // end time was past the old end time (so would have been capped)
|
|
825
|
-
// // set the correlation so that it resumes from the time it was at at the end of the old window
|
|
826
|
-
// this._localEndTimeCorrelation = {
|
|
827
|
-
// local: this._now,
|
|
828
|
-
// remote: previousEndTime * 1000
|
|
829
|
-
// };
|
|
830
|
-
// }
|
|
831
|
-
// }
|
|
832
|
-
// }
|
|
833
|
-
|
|
834
|
-
// // now that the values have been updated call any methods that use on them so they get the updated values
|
|
835
|
-
// // immediately
|
|
836
|
-
// durationChanged && this._onDurationChange();
|
|
837
|
-
// startTimeChanged && this._onProgress();
|
|
838
|
-
// }
|
|
839
|
-
|
|
840
|
-
// _onFragmentLoaded(evt, data) {
|
|
841
|
-
// this.trigger(Events.PLAYBACK_FRAGMENT_LOADED, data);
|
|
842
|
-
// }
|
|
843
|
-
|
|
844
642
|
private onLevelSwitch(currentLevel: BitrateInfo) {
|
|
845
643
|
this.trigger(Events.PLAYBACK_BITRATE, {
|
|
846
644
|
height: currentLevel.height,
|
|
@@ -865,7 +663,6 @@ DashPlayback.canPlay = function (resource, mimeType) {
|
|
|
865
663
|
(resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'mpd') ||
|
|
866
664
|
mimeType === 'application/dash+xml' ||
|
|
867
665
|
mimeType === 'video/mp4'
|
|
868
|
-
// TODO check
|
|
869
666
|
const ms = window.MediaSource
|
|
870
667
|
const mms =
|
|
871
668
|
'ManagedMediaSource' in window ? window.ManagedMediaSource : undefined
|