@clappr/hlsjs-playback 1.0.1 → 1.2.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/hlsjs-playback.esm.js +19779 -23676
- package/dist/hlsjs-playback.external.js +309 -168
- package/dist/hlsjs-playback.external.min.js +1 -1
- package/dist/hlsjs-playback.external.min.js.map +1 -1
- package/dist/hlsjs-playback.js +19780 -23677
- package/dist/hlsjs-playback.min.js +72 -268
- package/dist/hlsjs-playback.min.js.map +1 -1
- package/package.json +3 -2
- package/src/hls.js +73 -64
- package/src/hls.test.js +12 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('@clappr/core'), require('hls.js')) :
|
|
3
3
|
typeof define === 'function' && define.amd ? define(['@clappr/core', 'hls.js'], factory) :
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.HlsjsPlayback = factory(global.Clappr, global.Hls));
|
|
5
|
-
}
|
|
5
|
+
}(this, (function (core, HLSJS) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
@@ -10,49 +10,65 @@
|
|
|
10
10
|
|
|
11
11
|
function ownKeys(object, enumerableOnly) {
|
|
12
12
|
var keys = Object.keys(object);
|
|
13
|
+
|
|
13
14
|
if (Object.getOwnPropertySymbols) {
|
|
14
15
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
|
|
17
|
+
if (enumerableOnly) {
|
|
18
|
+
symbols = symbols.filter(function (sym) {
|
|
19
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
keys.push.apply(keys, symbols);
|
|
18
24
|
}
|
|
25
|
+
|
|
19
26
|
return keys;
|
|
20
27
|
}
|
|
28
|
+
|
|
21
29
|
function _objectSpread2(target) {
|
|
22
30
|
for (var i = 1; i < arguments.length; i++) {
|
|
23
|
-
var source =
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
31
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
32
|
+
|
|
33
|
+
if (i % 2) {
|
|
34
|
+
ownKeys(Object(source), true).forEach(function (key) {
|
|
35
|
+
_defineProperty(target, key, source[key]);
|
|
36
|
+
});
|
|
37
|
+
} else if (Object.getOwnPropertyDescriptors) {
|
|
38
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
39
|
+
} else {
|
|
40
|
+
ownKeys(Object(source)).forEach(function (key) {
|
|
41
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
29
44
|
}
|
|
45
|
+
|
|
30
46
|
return target;
|
|
31
47
|
}
|
|
48
|
+
|
|
32
49
|
function _classCallCheck(instance, Constructor) {
|
|
33
50
|
if (!(instance instanceof Constructor)) {
|
|
34
51
|
throw new TypeError("Cannot call a class as a function");
|
|
35
52
|
}
|
|
36
53
|
}
|
|
54
|
+
|
|
37
55
|
function _defineProperties(target, props) {
|
|
38
56
|
for (var i = 0; i < props.length; i++) {
|
|
39
57
|
var descriptor = props[i];
|
|
40
58
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
41
59
|
descriptor.configurable = true;
|
|
42
60
|
if ("value" in descriptor) descriptor.writable = true;
|
|
43
|
-
Object.defineProperty(target,
|
|
61
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
44
62
|
}
|
|
45
63
|
}
|
|
64
|
+
|
|
46
65
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
47
66
|
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
48
67
|
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
49
|
-
Object.defineProperty(Constructor, "prototype", {
|
|
50
|
-
writable: false
|
|
51
|
-
});
|
|
52
68
|
return Constructor;
|
|
53
69
|
}
|
|
70
|
+
|
|
54
71
|
function _defineProperty(obj, key, value) {
|
|
55
|
-
key = _toPropertyKey(key);
|
|
56
72
|
if (key in obj) {
|
|
57
73
|
Object.defineProperty(obj, key, {
|
|
58
74
|
value: value,
|
|
@@ -63,12 +79,15 @@
|
|
|
63
79
|
} else {
|
|
64
80
|
obj[key] = value;
|
|
65
81
|
}
|
|
82
|
+
|
|
66
83
|
return obj;
|
|
67
84
|
}
|
|
85
|
+
|
|
68
86
|
function _inherits(subClass, superClass) {
|
|
69
87
|
if (typeof superClass !== "function" && superClass !== null) {
|
|
70
88
|
throw new TypeError("Super expression must either be null or a function");
|
|
71
89
|
}
|
|
90
|
+
|
|
72
91
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
73
92
|
constructor: {
|
|
74
93
|
value: subClass,
|
|
@@ -76,28 +95,30 @@
|
|
|
76
95
|
configurable: true
|
|
77
96
|
}
|
|
78
97
|
});
|
|
79
|
-
Object.defineProperty(subClass, "prototype", {
|
|
80
|
-
writable: false
|
|
81
|
-
});
|
|
82
98
|
if (superClass) _setPrototypeOf(subClass, superClass);
|
|
83
99
|
}
|
|
100
|
+
|
|
84
101
|
function _getPrototypeOf(o) {
|
|
85
|
-
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf
|
|
102
|
+
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
|
|
86
103
|
return o.__proto__ || Object.getPrototypeOf(o);
|
|
87
104
|
};
|
|
88
105
|
return _getPrototypeOf(o);
|
|
89
106
|
}
|
|
107
|
+
|
|
90
108
|
function _setPrototypeOf(o, p) {
|
|
91
|
-
_setPrototypeOf = Object.setPrototypeOf
|
|
109
|
+
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
|
|
92
110
|
o.__proto__ = p;
|
|
93
111
|
return o;
|
|
94
112
|
};
|
|
113
|
+
|
|
95
114
|
return _setPrototypeOf(o, p);
|
|
96
115
|
}
|
|
116
|
+
|
|
97
117
|
function _isNativeReflectConstruct() {
|
|
98
118
|
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
|
|
99
119
|
if (Reflect.construct.sham) return false;
|
|
100
120
|
if (typeof Proxy === "function") return true;
|
|
121
|
+
|
|
101
122
|
try {
|
|
102
123
|
Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
|
|
103
124
|
return true;
|
|
@@ -105,66 +126,84 @@
|
|
|
105
126
|
return false;
|
|
106
127
|
}
|
|
107
128
|
}
|
|
129
|
+
|
|
108
130
|
function _assertThisInitialized(self) {
|
|
109
131
|
if (self === void 0) {
|
|
110
132
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
111
133
|
}
|
|
134
|
+
|
|
112
135
|
return self;
|
|
113
136
|
}
|
|
137
|
+
|
|
114
138
|
function _possibleConstructorReturn(self, call) {
|
|
115
139
|
if (call && (typeof call === "object" || typeof call === "function")) {
|
|
116
140
|
return call;
|
|
117
|
-
} else if (call !== void 0) {
|
|
118
|
-
throw new TypeError("Derived constructors may only return object or undefined");
|
|
119
141
|
}
|
|
142
|
+
|
|
120
143
|
return _assertThisInitialized(self);
|
|
121
144
|
}
|
|
145
|
+
|
|
122
146
|
function _createSuper(Derived) {
|
|
123
147
|
var hasNativeReflectConstruct = _isNativeReflectConstruct();
|
|
148
|
+
|
|
124
149
|
return function _createSuperInternal() {
|
|
125
150
|
var Super = _getPrototypeOf(Derived),
|
|
126
|
-
|
|
151
|
+
result;
|
|
152
|
+
|
|
127
153
|
if (hasNativeReflectConstruct) {
|
|
128
154
|
var NewTarget = _getPrototypeOf(this).constructor;
|
|
155
|
+
|
|
129
156
|
result = Reflect.construct(Super, arguments, NewTarget);
|
|
130
157
|
} else {
|
|
131
158
|
result = Super.apply(this, arguments);
|
|
132
159
|
}
|
|
160
|
+
|
|
133
161
|
return _possibleConstructorReturn(this, result);
|
|
134
162
|
};
|
|
135
163
|
}
|
|
164
|
+
|
|
136
165
|
function _superPropBase(object, property) {
|
|
137
166
|
while (!Object.prototype.hasOwnProperty.call(object, property)) {
|
|
138
167
|
object = _getPrototypeOf(object);
|
|
139
168
|
if (object === null) break;
|
|
140
169
|
}
|
|
170
|
+
|
|
141
171
|
return object;
|
|
142
172
|
}
|
|
143
|
-
|
|
173
|
+
|
|
174
|
+
function _get(target, property, receiver) {
|
|
144
175
|
if (typeof Reflect !== "undefined" && Reflect.get) {
|
|
145
|
-
_get = Reflect.get
|
|
176
|
+
_get = Reflect.get;
|
|
146
177
|
} else {
|
|
147
178
|
_get = function _get(target, property, receiver) {
|
|
148
179
|
var base = _superPropBase(target, property);
|
|
180
|
+
|
|
149
181
|
if (!base) return;
|
|
150
182
|
var desc = Object.getOwnPropertyDescriptor(base, property);
|
|
183
|
+
|
|
151
184
|
if (desc.get) {
|
|
152
|
-
return desc.get.call(
|
|
185
|
+
return desc.get.call(receiver);
|
|
153
186
|
}
|
|
187
|
+
|
|
154
188
|
return desc.value;
|
|
155
189
|
};
|
|
156
190
|
}
|
|
157
|
-
|
|
191
|
+
|
|
192
|
+
return _get(target, property, receiver || target);
|
|
158
193
|
}
|
|
194
|
+
|
|
159
195
|
function _toConsumableArray(arr) {
|
|
160
196
|
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
|
|
161
197
|
}
|
|
198
|
+
|
|
162
199
|
function _arrayWithoutHoles(arr) {
|
|
163
200
|
if (Array.isArray(arr)) return _arrayLikeToArray(arr);
|
|
164
201
|
}
|
|
202
|
+
|
|
165
203
|
function _iterableToArray(iter) {
|
|
166
204
|
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
167
205
|
}
|
|
206
|
+
|
|
168
207
|
function _unsupportedIterableToArray(o, minLen) {
|
|
169
208
|
if (!o) return;
|
|
170
209
|
if (typeof o === "string") return _arrayLikeToArray(o, minLen);
|
|
@@ -173,90 +212,48 @@
|
|
|
173
212
|
if (n === "Map" || n === "Set") return Array.from(o);
|
|
174
213
|
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
|
|
175
214
|
}
|
|
215
|
+
|
|
176
216
|
function _arrayLikeToArray(arr, len) {
|
|
177
217
|
if (len == null || len > arr.length) len = arr.length;
|
|
218
|
+
|
|
178
219
|
for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
|
|
220
|
+
|
|
179
221
|
return arr2;
|
|
180
222
|
}
|
|
223
|
+
|
|
181
224
|
function _nonIterableSpread() {
|
|
182
225
|
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
183
226
|
}
|
|
184
|
-
function _toPrimitive(input, hint) {
|
|
185
|
-
if (typeof input !== "object" || input === null) return input;
|
|
186
|
-
var prim = input[Symbol.toPrimitive];
|
|
187
|
-
if (prim !== undefined) {
|
|
188
|
-
var res = prim.call(input, hint || "default");
|
|
189
|
-
if (typeof res !== "object") return res;
|
|
190
|
-
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
191
|
-
}
|
|
192
|
-
return (hint === "string" ? String : Number)(input);
|
|
193
|
-
}
|
|
194
|
-
function _toPropertyKey(arg) {
|
|
195
|
-
var key = _toPrimitive(arg, "string");
|
|
196
|
-
return typeof key === "symbol" ? key : String(key);
|
|
197
|
-
}
|
|
198
227
|
|
|
199
228
|
var now = core.Utils.now,
|
|
200
|
-
|
|
201
|
-
listContainsIgnoreCase = core.Utils.listContainsIgnoreCase;
|
|
229
|
+
listContainsIgnoreCase = core.Utils.listContainsIgnoreCase;
|
|
202
230
|
var AUTO = -1;
|
|
231
|
+
var DEFAULT_RECOVER_ATTEMPTS = 16;
|
|
203
232
|
core.Events.register('PLAYBACK_FRAGMENT_CHANGED');
|
|
204
233
|
core.Events.register('PLAYBACK_FRAGMENT_PARSING_METADATA');
|
|
234
|
+
|
|
205
235
|
var HlsjsPlayback = /*#__PURE__*/function (_HTML5Video) {
|
|
206
236
|
_inherits(HlsjsPlayback, _HTML5Video);
|
|
237
|
+
|
|
207
238
|
var _super = _createSuper(HlsjsPlayback);
|
|
239
|
+
|
|
208
240
|
function HlsjsPlayback() {
|
|
209
241
|
var _this;
|
|
242
|
+
|
|
210
243
|
_classCallCheck(this, HlsjsPlayback);
|
|
244
|
+
|
|
211
245
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
212
246
|
args[_key] = arguments[_key];
|
|
213
247
|
}
|
|
248
|
+
|
|
214
249
|
_this = _super.call.apply(_super, [this].concat(args));
|
|
215
|
-
// backwards compatibility (TODO: remove on 0.3.0)
|
|
216
|
-
_this.options.playback = _objectSpread2(_objectSpread2({}, _this.options), _this.options.playback);
|
|
217
250
|
_this.options.hlsPlayback = _objectSpread2(_objectSpread2({}, _this.defaultOptions), _this.options.hlsPlayback);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
|
|
222
|
-
// added/removed every 5.
|
|
223
|
-
_this._extrapolatedWindowNumSegments = !_this.options.playback || typeof _this.options.playback.extrapolatedWindowNumSegments === 'undefined' ? 2 : _this.options.playback.extrapolatedWindowNumSegments;
|
|
224
|
-
_this._playbackType = core.Playback.VOD;
|
|
225
|
-
_this._lastTimeUpdate = {
|
|
226
|
-
current: 0,
|
|
227
|
-
total: 0
|
|
228
|
-
};
|
|
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
|
-
// true when the actual duration is longer than hlsjs's live sync point
|
|
250
|
-
// when this is false playableRegionDuration will be the actual duration
|
|
251
|
-
// when this is true playableRegionDuration will exclude the time after the sync point
|
|
252
|
-
_this._durationExcludesAfterLiveSyncPoint = false;
|
|
253
|
-
// #EXT-X-TARGETDURATION
|
|
254
|
-
_this._segmentTargetDuration = null;
|
|
255
|
-
// #EXT-X-PLAYLIST-TYPE
|
|
256
|
-
_this._playlistType = null;
|
|
257
|
-
_this._recoverAttemptsRemaining = _this.options.hlsRecoverAttempts || 16;
|
|
251
|
+
|
|
252
|
+
_this._setInitialState();
|
|
253
|
+
|
|
258
254
|
return _this;
|
|
259
255
|
}
|
|
256
|
+
|
|
260
257
|
_createClass(HlsjsPlayback, [{
|
|
261
258
|
key: "name",
|
|
262
259
|
get: function get() {
|
|
@@ -266,7 +263,7 @@
|
|
|
266
263
|
key: "supportedVersion",
|
|
267
264
|
get: function get() {
|
|
268
265
|
return {
|
|
269
|
-
min: "0.4.
|
|
266
|
+
min: "0.4.18"
|
|
270
267
|
};
|
|
271
268
|
}
|
|
272
269
|
}, {
|
|
@@ -289,6 +286,16 @@
|
|
|
289
286
|
get: function get() {
|
|
290
287
|
return this._isReadyState;
|
|
291
288
|
}
|
|
289
|
+
}, {
|
|
290
|
+
key: "latency",
|
|
291
|
+
get: function get() {
|
|
292
|
+
return this._hls.latency;
|
|
293
|
+
}
|
|
294
|
+
}, {
|
|
295
|
+
key: "currentProgramDateTime",
|
|
296
|
+
get: function get() {
|
|
297
|
+
return this._hls.playingDate;
|
|
298
|
+
}
|
|
292
299
|
}, {
|
|
293
300
|
key: "_startTime",
|
|
294
301
|
get: function get() {
|
|
@@ -299,40 +306,36 @@
|
|
|
299
306
|
key: "_now",
|
|
300
307
|
get: function get() {
|
|
301
308
|
return now();
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
// the time in the video element which should represent the start of the sliding window
|
|
309
|
+
} // the time in the video element which should represent the start of the sliding window
|
|
305
310
|
// extrapolated to increase in real time (instead of jumping as the early segments are removed)
|
|
311
|
+
|
|
306
312
|
}, {
|
|
307
313
|
key: "_extrapolatedStartTime",
|
|
308
314
|
get: function get() {
|
|
309
315
|
if (!this._localStartTimeCorrelation) return this._playableRegionStartTime;
|
|
310
316
|
var corr = this._localStartTimeCorrelation;
|
|
311
317
|
var timePassed = this._now - corr.local;
|
|
312
|
-
var extrapolatedWindowStartTime = (corr.remote + timePassed) / 1000;
|
|
313
|
-
// cap at the end of the extrapolated window duration
|
|
314
|
-
return Math.min(extrapolatedWindowStartTime, this._playableRegionStartTime + this._extrapolatedWindowDuration);
|
|
315
|
-
}
|
|
318
|
+
var extrapolatedWindowStartTime = (corr.remote + timePassed) / 1000; // cap at the end of the extrapolated window duration
|
|
316
319
|
|
|
317
|
-
|
|
320
|
+
return Math.min(extrapolatedWindowStartTime, this._playableRegionStartTime + this._extrapolatedWindowDuration);
|
|
321
|
+
} // the time in the video element which should represent the end of the content
|
|
318
322
|
// extrapolated to increase in real time (instead of jumping as segments are added)
|
|
323
|
+
|
|
319
324
|
}, {
|
|
320
325
|
key: "_extrapolatedEndTime",
|
|
321
326
|
get: function get() {
|
|
322
327
|
var actualEndTime = this._playableRegionStartTime + this._playableRegionDuration;
|
|
323
328
|
if (!this._localEndTimeCorrelation) return actualEndTime;
|
|
324
|
-
var
|
|
325
|
-
var timePassed = this._now -
|
|
326
|
-
var extrapolatedEndTime = (
|
|
329
|
+
var correlation = this._localEndTimeCorrelation;
|
|
330
|
+
var timePassed = this._now - correlation.local;
|
|
331
|
+
var extrapolatedEndTime = (correlation.remote + timePassed) / 1000;
|
|
327
332
|
return Math.max(actualEndTime - this._extrapolatedWindowDuration, Math.min(extrapolatedEndTime, actualEndTime));
|
|
328
333
|
}
|
|
329
334
|
}, {
|
|
330
335
|
key: "_duration",
|
|
331
336
|
get: function get() {
|
|
332
337
|
return this._extrapolatedEndTime - this._startTime;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Returns the duration (seconds) of the window that the extrapolated start time is allowed
|
|
338
|
+
} // Returns the duration (seconds) of the window that the extrapolated start time is allowed
|
|
336
339
|
// to move in before being capped.
|
|
337
340
|
// The extrapolated start time should never reach the cap at the end of the window as the
|
|
338
341
|
// window should slide as chunks are removed from the start.
|
|
@@ -349,6 +352,7 @@
|
|
|
349
352
|
// . . . --> |
|
|
350
353
|
// . . . .
|
|
351
354
|
// extrapolatedStartTime
|
|
355
|
+
|
|
352
356
|
}, {
|
|
353
357
|
key: "_extrapolatedWindowDuration",
|
|
354
358
|
get: function get() {
|
|
@@ -372,55 +376,152 @@
|
|
|
372
376
|
get: function get() {
|
|
373
377
|
return this.options.hlsPlayback && this.options.hlsPlayback.customListeners || [];
|
|
374
378
|
}
|
|
379
|
+
}, {
|
|
380
|
+
key: "sourceMedia",
|
|
381
|
+
get: function get() {
|
|
382
|
+
return this.options.src;
|
|
383
|
+
}
|
|
384
|
+
}, {
|
|
385
|
+
key: "_setInitialState",
|
|
386
|
+
value: function _setInitialState() {
|
|
387
|
+
this._minDvrSize = typeof this.options.hlsMinimumDvrSize === 'undefined' ? 60 : this.options.hlsMinimumDvrSize; // The size of the start time extrapolation window measured as a multiple of segments.
|
|
388
|
+
// Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
|
|
389
|
+
// removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
|
|
390
|
+
// added/removed every 5.
|
|
391
|
+
|
|
392
|
+
this._extrapolatedWindowNumSegments = !this.options.playback || typeof this.options.playback.extrapolatedWindowNumSegments === 'undefined' ? 2 : this.options.playback.extrapolatedWindowNumSegments;
|
|
393
|
+
this._playbackType = core.Playback.VOD;
|
|
394
|
+
this._lastTimeUpdate = {
|
|
395
|
+
current: 0,
|
|
396
|
+
total: 0
|
|
397
|
+
};
|
|
398
|
+
this._lastDuration = null; // for hls streams which have dvr with a sliding window,
|
|
399
|
+
// the content at the start of the playlist is removed as new
|
|
400
|
+
// content is appended at the end.
|
|
401
|
+
// this means the actual playable start time will increase as the
|
|
402
|
+
// start content is deleted
|
|
403
|
+
// For streams with dvr where the entire recording is kept from the
|
|
404
|
+
// beginning this should stay as 0
|
|
405
|
+
|
|
406
|
+
this._playableRegionStartTime = 0; // {local, remote} remote is the time in the video element that should represent 0
|
|
407
|
+
// local is the system time when the 'remote' measurment took place
|
|
408
|
+
|
|
409
|
+
this._localStartTimeCorrelation = null; // {local, remote} remote is the time in the video element that should represents the end
|
|
410
|
+
// local is the system time when the 'remote' measurment took place
|
|
411
|
+
|
|
412
|
+
this._localEndTimeCorrelation = null; // if content is removed from the beginning then this empty area should
|
|
413
|
+
// be ignored. "playableRegionDuration" excludes the empty area
|
|
414
|
+
|
|
415
|
+
this._playableRegionDuration = 0; // #EXT-X-PROGRAM-DATE-TIME
|
|
416
|
+
|
|
417
|
+
this._programDateTime = 0; // true when the actual duration is longer than hlsjs's live sync point
|
|
418
|
+
// when this is false playableRegionDuration will be the actual duration
|
|
419
|
+
// when this is true playableRegionDuration will exclude the time after the sync point
|
|
420
|
+
|
|
421
|
+
this._durationExcludesAfterLiveSyncPoint = false; // #EXT-X-TARGETDURATION
|
|
422
|
+
|
|
423
|
+
this._segmentTargetDuration = null; // #EXT-X-PLAYLIST-TYPE
|
|
424
|
+
|
|
425
|
+
this._playlistType = null;
|
|
426
|
+
this._recoverAttemptsRemaining = this.options.hlsRecoverAttempts || DEFAULT_RECOVER_ATTEMPTS;
|
|
427
|
+
}
|
|
375
428
|
}, {
|
|
376
429
|
key: "_setup",
|
|
377
430
|
value: function _setup() {
|
|
378
|
-
|
|
431
|
+
this._destroyHLSInstance();
|
|
432
|
+
|
|
433
|
+
this._createHLSInstance();
|
|
434
|
+
|
|
435
|
+
this._listenHLSEvents();
|
|
436
|
+
|
|
437
|
+
this._attachHLSMedia();
|
|
438
|
+
}
|
|
439
|
+
}, {
|
|
440
|
+
key: "_destroyHLSInstance",
|
|
441
|
+
value: function _destroyHLSInstance() {
|
|
442
|
+
if (!this._hls) return;
|
|
379
443
|
this._manifestParsed = false;
|
|
380
444
|
this._ccIsSetup = false;
|
|
381
445
|
this._ccTracksUpdated = false;
|
|
382
|
-
|
|
383
|
-
this.
|
|
384
|
-
|
|
446
|
+
|
|
447
|
+
this._setInitialState();
|
|
448
|
+
|
|
449
|
+
this._hls.destroy();
|
|
450
|
+
|
|
451
|
+
this._hls = null;
|
|
452
|
+
}
|
|
453
|
+
}, {
|
|
454
|
+
key: "_createHLSInstance",
|
|
455
|
+
value: function _createHLSInstance() {
|
|
456
|
+
var config = _objectSpread2({}, this.options.playback.hlsjsConfig);
|
|
457
|
+
|
|
458
|
+
this._hls = new HLSJS__default['default'](config);
|
|
459
|
+
}
|
|
460
|
+
}, {
|
|
461
|
+
key: "_attachHLSMedia",
|
|
462
|
+
value: function _attachHLSMedia() {
|
|
463
|
+
if (!this._hls) return;
|
|
464
|
+
|
|
465
|
+
this._hls.attachMedia(this.el);
|
|
466
|
+
}
|
|
467
|
+
}, {
|
|
468
|
+
key: "_listenHLSEvents",
|
|
469
|
+
value: function _listenHLSEvents() {
|
|
470
|
+
var _this2 = this;
|
|
471
|
+
|
|
472
|
+
if (!this._hls) return;
|
|
473
|
+
|
|
474
|
+
this._hls.once(HLSJS__default['default'].Events.MEDIA_ATTACHED, function () {
|
|
385
475
|
_this2.options.hlsPlayback.preload && _this2._hls.loadSource(_this2.options.src);
|
|
386
476
|
});
|
|
387
|
-
|
|
477
|
+
|
|
478
|
+
this._hls.on(HLSJS__default['default'].Events.MANIFEST_PARSED, function () {
|
|
388
479
|
return _this2._manifestParsed = true;
|
|
389
480
|
});
|
|
390
|
-
|
|
481
|
+
|
|
482
|
+
this._hls.on(HLSJS__default['default'].Events.LEVEL_LOADED, function (evt, data) {
|
|
391
483
|
return _this2._updatePlaybackType(evt, data);
|
|
392
484
|
});
|
|
393
|
-
|
|
485
|
+
|
|
486
|
+
this._hls.on(HLSJS__default['default'].Events.LEVEL_UPDATED, function (evt, data) {
|
|
394
487
|
return _this2._onLevelUpdated(evt, data);
|
|
395
488
|
});
|
|
396
|
-
|
|
489
|
+
|
|
490
|
+
this._hls.on(HLSJS__default['default'].Events.LEVEL_SWITCHING, function (evt, data) {
|
|
397
491
|
return _this2._onLevelSwitch(evt, data);
|
|
398
492
|
});
|
|
399
|
-
|
|
493
|
+
|
|
494
|
+
this._hls.on(HLSJS__default['default'].Events.FRAG_CHANGED, function (evt, data) {
|
|
400
495
|
return _this2._onFragmentChanged(evt, data);
|
|
401
496
|
});
|
|
402
|
-
|
|
497
|
+
|
|
498
|
+
this._hls.on(HLSJS__default['default'].Events.FRAG_LOADED, function (evt, data) {
|
|
403
499
|
return _this2._onFragmentLoaded(evt, data);
|
|
404
500
|
});
|
|
405
|
-
|
|
501
|
+
|
|
502
|
+
this._hls.on(HLSJS__default['default'].Events.FRAG_PARSING_METADATA, function (evt, data) {
|
|
406
503
|
return _this2._onFragmentParsingMetadata(evt, data);
|
|
407
504
|
});
|
|
408
|
-
|
|
505
|
+
|
|
506
|
+
this._hls.on(HLSJS__default['default'].Events.ERROR, function (evt, data) {
|
|
409
507
|
return _this2._onHLSJSError(evt, data);
|
|
410
508
|
});
|
|
411
|
-
|
|
509
|
+
|
|
510
|
+
this._hls.on(HLSJS__default['default'].Events.SUBTITLE_TRACK_LOADED, function (evt, data) {
|
|
412
511
|
return _this2._onSubtitleLoaded(evt, data);
|
|
413
512
|
});
|
|
414
|
-
|
|
513
|
+
|
|
514
|
+
this._hls.on(HLSJS__default['default'].Events.SUBTITLE_TRACKS_UPDATED, function () {
|
|
415
515
|
return _this2._ccTracksUpdated = true;
|
|
416
516
|
});
|
|
517
|
+
|
|
417
518
|
this.bindCustomListeners();
|
|
418
|
-
this._hls.attachMedia(this.el);
|
|
419
519
|
}
|
|
420
520
|
}, {
|
|
421
521
|
key: "bindCustomListeners",
|
|
422
522
|
value: function bindCustomListeners() {
|
|
423
523
|
var _this3 = this;
|
|
524
|
+
|
|
424
525
|
this.customListeners.forEach(function (item) {
|
|
425
526
|
var requestedEventName = item.eventName;
|
|
426
527
|
var typeOfListener = item.once ? 'once' : 'on';
|
|
@@ -431,6 +532,7 @@
|
|
|
431
532
|
key: "unbindCustomListeners",
|
|
432
533
|
value: function unbindCustomListeners() {
|
|
433
534
|
var _this4 = this;
|
|
535
|
+
|
|
434
536
|
this.customListeners.forEach(function (item) {
|
|
435
537
|
var requestedEventName = item.eventName;
|
|
436
538
|
requestedEventName && _this4._hls.off(requestedEventName, item.callback);
|
|
@@ -448,6 +550,7 @@
|
|
|
448
550
|
key: "render",
|
|
449
551
|
value: function render() {
|
|
450
552
|
this._ready();
|
|
553
|
+
|
|
451
554
|
return _get(_getPrototypeOf(HlsjsPlayback.prototype), "render", this).call(this);
|
|
452
555
|
}
|
|
453
556
|
}, {
|
|
@@ -463,10 +566,13 @@
|
|
|
463
566
|
value: function _recover(evt, data, error) {
|
|
464
567
|
if (!this._recoveredDecodingError) {
|
|
465
568
|
this._recoveredDecodingError = true;
|
|
569
|
+
|
|
466
570
|
this._hls.recoverMediaError();
|
|
467
571
|
} else if (!this._recoveredAudioCodecError) {
|
|
468
572
|
this._recoveredAudioCodecError = true;
|
|
573
|
+
|
|
469
574
|
this._hls.swapAudioCodec();
|
|
575
|
+
|
|
470
576
|
this._hls.recoverMediaError();
|
|
471
577
|
} else {
|
|
472
578
|
core.Log.error('hlsjs: failed to recover', {
|
|
@@ -478,21 +584,22 @@
|
|
|
478
584
|
this.trigger(core.Events.PLAYBACK_ERROR, formattedError);
|
|
479
585
|
this.stop();
|
|
480
586
|
}
|
|
481
|
-
}
|
|
587
|
+
} // override
|
|
588
|
+
// this playback manages the src on the video element itself
|
|
482
589
|
|
|
483
|
-
// override
|
|
484
590
|
}, {
|
|
485
591
|
key: "_setupSrc",
|
|
486
|
-
value: function _setupSrc(srcUrl) {// eslint-disable-line no-unused-vars
|
|
487
|
-
|
|
488
|
-
}
|
|
592
|
+
value: function _setupSrc(srcUrl) {} // eslint-disable-line no-unused-vars
|
|
593
|
+
|
|
489
594
|
}, {
|
|
490
595
|
key: "_startTimeUpdateTimer",
|
|
491
596
|
value: function _startTimeUpdateTimer() {
|
|
492
597
|
var _this5 = this;
|
|
598
|
+
|
|
493
599
|
if (this._timeUpdateTimer) return;
|
|
494
600
|
this._timeUpdateTimer = setInterval(function () {
|
|
495
601
|
_this5._onDurationChange();
|
|
602
|
+
|
|
496
603
|
_this5._onTimeUpdate();
|
|
497
604
|
}, 100);
|
|
498
605
|
}
|
|
@@ -507,10 +614,10 @@
|
|
|
507
614
|
key: "getProgramDateTime",
|
|
508
615
|
value: function getProgramDateTime() {
|
|
509
616
|
return this._programDateTime;
|
|
510
|
-
}
|
|
511
|
-
// the duration on the video element itself should not be used
|
|
617
|
+
} // the duration on the video element itself should not be used
|
|
512
618
|
// as this does not necesarily represent the duration of the stream
|
|
513
619
|
// https://github.com/clappr/clappr/issues/668#issuecomment-157036678
|
|
620
|
+
|
|
514
621
|
}, {
|
|
515
622
|
key: "getDuration",
|
|
516
623
|
value: function getDuration() {
|
|
@@ -523,11 +630,10 @@
|
|
|
523
630
|
// eventually they will then be kicked to the end by hlsjs if they run out of buffer
|
|
524
631
|
// before the official start time
|
|
525
632
|
return Math.max(0, this.el.currentTime - this._startTime);
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
// the time that "0" now represents relative to when playback started
|
|
633
|
+
} // the time that "0" now represents relative to when playback started
|
|
529
634
|
// for a stream with a sliding window this will increase as content is
|
|
530
635
|
// removed from the beginning
|
|
636
|
+
|
|
531
637
|
}, {
|
|
532
638
|
key: "getStartTimeOffset",
|
|
533
639
|
value: function getStartTimeOffset() {
|
|
@@ -536,8 +642,7 @@
|
|
|
536
642
|
}, {
|
|
537
643
|
key: "seekPercentage",
|
|
538
644
|
value: function seekPercentage(percentage) {
|
|
539
|
-
var seekTo = this._duration;
|
|
540
|
-
if (percentage > 0) seekTo = this._duration * (percentage / 100);
|
|
645
|
+
var seekTo = percentage > 0 ? this._duration * (percentage / 100) : this._duration;
|
|
541
646
|
this.seek(seekTo);
|
|
542
647
|
}
|
|
543
648
|
}, {
|
|
@@ -546,8 +651,9 @@
|
|
|
546
651
|
if (time < 0) {
|
|
547
652
|
core.Log.warn('Attempt to seek to a negative time. Resetting to live point. Use seekToLivePoint() to seek to the live point.');
|
|
548
653
|
time = this.getDuration();
|
|
549
|
-
}
|
|
550
|
-
|
|
654
|
+
} // assume live if time within 3 seconds of end of stream
|
|
655
|
+
|
|
656
|
+
|
|
551
657
|
this.dvrEnabled && this._updateDvr(time < this.getDuration() - 3);
|
|
552
658
|
time += this._startTime;
|
|
553
659
|
this.el.currentTime = time;
|
|
@@ -581,23 +687,24 @@
|
|
|
581
687
|
raw: data
|
|
582
688
|
};
|
|
583
689
|
var formattedError;
|
|
584
|
-
if (data.response) error.description += ", response: ".concat(JSON.stringify(data.response));
|
|
585
|
-
// only report/handle errors if they are fatal
|
|
690
|
+
if (data.response) error.description += ", response: ".concat(JSON.stringify(data.response)); // only report/handle errors if they are fatal
|
|
586
691
|
// hlsjs should automatically handle non fatal errors
|
|
692
|
+
|
|
587
693
|
if (data.fatal) {
|
|
588
694
|
if (this._recoverAttemptsRemaining > 0) {
|
|
589
695
|
this._recoverAttemptsRemaining -= 1;
|
|
696
|
+
|
|
590
697
|
switch (data.type) {
|
|
591
|
-
case HLSJS__default[
|
|
698
|
+
case HLSJS__default['default'].ErrorTypes.NETWORK_ERROR:
|
|
592
699
|
switch (data.details) {
|
|
593
700
|
// The following network errors cannot be recovered with HLS.startLoad()
|
|
594
701
|
// For more details, see https://github.com/video-dev/hls.js/blob/master/doc/design.md#error-detection-and-handling
|
|
595
702
|
// For "level load" fatal errors, see https://github.com/video-dev/hls.js/issues/1138
|
|
596
|
-
case HLSJS__default[
|
|
597
|
-
case HLSJS__default[
|
|
598
|
-
case HLSJS__default[
|
|
599
|
-
case HLSJS__default[
|
|
600
|
-
case HLSJS__default[
|
|
703
|
+
case HLSJS__default['default'].ErrorDetails.MANIFEST_LOAD_ERROR:
|
|
704
|
+
case HLSJS__default['default'].ErrorDetails.MANIFEST_LOAD_TIMEOUT:
|
|
705
|
+
case HLSJS__default['default'].ErrorDetails.MANIFEST_PARSING_ERROR:
|
|
706
|
+
case HLSJS__default['default'].ErrorDetails.LEVEL_LOAD_ERROR:
|
|
707
|
+
case HLSJS__default['default'].ErrorDetails.LEVEL_LOAD_TIMEOUT:
|
|
601
708
|
core.Log.error('hlsjs: unrecoverable network fatal error.', {
|
|
602
709
|
evt: evt,
|
|
603
710
|
data: data
|
|
@@ -606,24 +713,32 @@
|
|
|
606
713
|
this.trigger(core.Events.PLAYBACK_ERROR, formattedError);
|
|
607
714
|
this.stop();
|
|
608
715
|
break;
|
|
716
|
+
|
|
609
717
|
default:
|
|
610
718
|
core.Log.warn('hlsjs: trying to recover from network error.', {
|
|
611
719
|
evt: evt,
|
|
612
720
|
data: data
|
|
613
721
|
});
|
|
614
722
|
error.level = core.PlayerError.Levels.WARN;
|
|
723
|
+
|
|
615
724
|
this._hls.startLoad();
|
|
725
|
+
|
|
616
726
|
break;
|
|
617
727
|
}
|
|
728
|
+
|
|
618
729
|
break;
|
|
619
|
-
|
|
730
|
+
|
|
731
|
+
case HLSJS__default['default'].ErrorTypes.MEDIA_ERROR:
|
|
620
732
|
core.Log.warn('hlsjs: trying to recover from media error.', {
|
|
621
733
|
evt: evt,
|
|
622
734
|
data: data
|
|
623
735
|
});
|
|
624
736
|
error.level = core.PlayerError.Levels.WARN;
|
|
737
|
+
|
|
625
738
|
this._recover(evt, data, error);
|
|
739
|
+
|
|
626
740
|
break;
|
|
741
|
+
|
|
627
742
|
default:
|
|
628
743
|
core.Log.error('hlsjs: could not recover from error.', {
|
|
629
744
|
evt: evt,
|
|
@@ -658,6 +773,7 @@
|
|
|
658
773
|
this.stop();
|
|
659
774
|
return;
|
|
660
775
|
}
|
|
776
|
+
|
|
661
777
|
error.level = core.PlayerError.Levels.WARN;
|
|
662
778
|
core.Log.warn('hlsjs: non-fatal error occurred', {
|
|
663
779
|
evt: evt,
|
|
@@ -668,7 +784,7 @@
|
|
|
668
784
|
}, {
|
|
669
785
|
key: "_keyIsDenied",
|
|
670
786
|
value: function _keyIsDenied(data) {
|
|
671
|
-
return data.type === HLSJS__default[
|
|
787
|
+
return data.type === HLSJS__default['default'].ErrorTypes.NETWORK_ERROR && data.details === HLSJS__default['default'].ErrorDetails.KEY_LOAD_ERROR && data.response && data.response.code >= 400;
|
|
672
788
|
}
|
|
673
789
|
}, {
|
|
674
790
|
key: "_onTimeUpdate",
|
|
@@ -689,6 +805,7 @@
|
|
|
689
805
|
var duration = this.getDuration();
|
|
690
806
|
if (this._lastDuration === duration) return;
|
|
691
807
|
this._lastDuration = duration;
|
|
808
|
+
|
|
692
809
|
_get(_getPrototypeOf(HlsjsPlayback.prototype), "_onDurationChange", this).call(this);
|
|
693
810
|
}
|
|
694
811
|
}, {
|
|
@@ -697,6 +814,7 @@
|
|
|
697
814
|
if (!this.el.buffered.length) return;
|
|
698
815
|
var buffered = [];
|
|
699
816
|
var bufferedPos = 0;
|
|
817
|
+
|
|
700
818
|
for (var i = 0; i < this.el.buffered.length; i++) {
|
|
701
819
|
buffered = [].concat(_toConsumableArray(buffered), [{
|
|
702
820
|
// for a stream with sliding window dvr something that is buffered my slide off the start of the timeline
|
|
@@ -705,6 +823,7 @@
|
|
|
705
823
|
}]);
|
|
706
824
|
if (this.el.currentTime >= buffered[i].start && this.el.currentTime <= buffered[i].end) bufferedPos = i;
|
|
707
825
|
}
|
|
826
|
+
|
|
708
827
|
var progress = {
|
|
709
828
|
start: buffered[bufferedPos].start,
|
|
710
829
|
current: buffered[bufferedPos].end,
|
|
@@ -712,12 +831,23 @@
|
|
|
712
831
|
};
|
|
713
832
|
this.trigger(core.Events.PLAYBACK_PROGRESS, progress, buffered);
|
|
714
833
|
}
|
|
834
|
+
}, {
|
|
835
|
+
key: "load",
|
|
836
|
+
value: function load(url) {
|
|
837
|
+
this._stopTimeUpdateTimer();
|
|
838
|
+
|
|
839
|
+
this.options.src = url;
|
|
840
|
+
|
|
841
|
+
this._setup();
|
|
842
|
+
}
|
|
715
843
|
}, {
|
|
716
844
|
key: "play",
|
|
717
845
|
value: function play() {
|
|
718
846
|
!this._hls && this._setup();
|
|
719
847
|
!this._manifestParsed && !this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src);
|
|
848
|
+
|
|
720
849
|
_get(_getPrototypeOf(HlsjsPlayback.prototype), "play", this).call(this);
|
|
850
|
+
|
|
721
851
|
this._startTimeUpdateTimer();
|
|
722
852
|
}
|
|
723
853
|
}, {
|
|
@@ -731,29 +861,28 @@
|
|
|
731
861
|
key: "stop",
|
|
732
862
|
value: function stop() {
|
|
733
863
|
this._stopTimeUpdateTimer();
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
}
|
|
864
|
+
|
|
865
|
+
if (this._hls) _get(_getPrototypeOf(HlsjsPlayback.prototype), "stop", this).call(this);
|
|
866
|
+
|
|
867
|
+
this._destroyHLSInstance();
|
|
739
868
|
}
|
|
740
869
|
}, {
|
|
741
870
|
key: "destroy",
|
|
742
871
|
value: function destroy() {
|
|
743
872
|
this._stopTimeUpdateTimer();
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
}
|
|
873
|
+
|
|
874
|
+
this._destroyHLSInstance();
|
|
875
|
+
|
|
748
876
|
_get(_getPrototypeOf(HlsjsPlayback.prototype), "destroy", this).call(this);
|
|
749
877
|
}
|
|
750
878
|
}, {
|
|
751
879
|
key: "_updatePlaybackType",
|
|
752
880
|
value: function _updatePlaybackType(evt, data) {
|
|
753
881
|
this._playbackType = data.details.live ? core.Playback.LIVE : core.Playback.VOD;
|
|
754
|
-
this._onLevelUpdated(evt, data);
|
|
755
882
|
|
|
756
|
-
// Live stream subtitle tracks detection hack (may not immediately available)
|
|
883
|
+
this._onLevelUpdated(evt, data); // Live stream subtitle tracks detection hack (may not immediately available)
|
|
884
|
+
|
|
885
|
+
|
|
757
886
|
if (this._ccTracksUpdated && this._playbackType === core.Playback.LIVE && this.hasClosedCaptionsTracks) this._onSubtitleLoaded();
|
|
758
887
|
}
|
|
759
888
|
}, {
|
|
@@ -778,14 +907,15 @@
|
|
|
778
907
|
var fragments = data.details.fragments;
|
|
779
908
|
var previousPlayableRegionStartTime = this._playableRegionStartTime;
|
|
780
909
|
var previousPlayableRegionDuration = this._playableRegionDuration;
|
|
781
|
-
if (fragments.length === 0) return;
|
|
910
|
+
if (fragments.length === 0) return; // #EXT-X-PROGRAM-DATE-TIME
|
|
782
911
|
|
|
783
|
-
// #EXT-X-PROGRAM-DATE-TIME
|
|
784
912
|
if (fragments[0].rawProgramDateTime) this._programDateTime = fragments[0].rawProgramDateTime;
|
|
913
|
+
|
|
785
914
|
if (this._playableRegionStartTime !== fragments[0].start) {
|
|
786
915
|
startTimeChanged = true;
|
|
787
916
|
this._playableRegionStartTime = fragments[0].start;
|
|
788
917
|
}
|
|
918
|
+
|
|
789
919
|
if (startTimeChanged) {
|
|
790
920
|
if (!this._localStartTimeCorrelation) {
|
|
791
921
|
// set the correlation to map to middle of the extrapolation window
|
|
@@ -796,9 +926,10 @@
|
|
|
796
926
|
} else {
|
|
797
927
|
// check if the correlation still works
|
|
798
928
|
var corr = this._localStartTimeCorrelation;
|
|
799
|
-
var timePassed = this._now - corr.local;
|
|
800
|
-
|
|
929
|
+
var timePassed = this._now - corr.local; // this should point to a time within the extrapolation window
|
|
930
|
+
|
|
801
931
|
var startTime = (corr.remote + timePassed) / 1000;
|
|
932
|
+
|
|
802
933
|
if (startTime < fragments[0].start) {
|
|
803
934
|
// our start time is now earlier than the first chunk
|
|
804
935
|
// (maybe the chunk was removed early)
|
|
@@ -819,15 +950,17 @@
|
|
|
819
950
|
}
|
|
820
951
|
}
|
|
821
952
|
}
|
|
822
|
-
|
|
823
|
-
// if it's a live stream then shorten the duration to remove access
|
|
953
|
+
|
|
954
|
+
var newDuration = data.details.totalduration; // if it's a live stream then shorten the duration to remove access
|
|
824
955
|
// to the area after hlsjs's live sync point
|
|
825
956
|
// seeks to areas after this point sometimes have issues
|
|
957
|
+
|
|
826
958
|
if (this._playbackType === core.Playback.LIVE) {
|
|
827
959
|
var fragmentTargetDuration = data.details.targetduration;
|
|
828
960
|
var hlsjsConfig = this.options.playback.hlsjsConfig || {};
|
|
829
|
-
var liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount || HLSJS__default[
|
|
961
|
+
var liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount || HLSJS__default['default'].DefaultConfig.liveSyncDurationCount;
|
|
830
962
|
var hiddenAreaDuration = fragmentTargetDuration * liveSyncDurationCount;
|
|
963
|
+
|
|
831
964
|
if (hiddenAreaDuration <= newDuration) {
|
|
832
965
|
newDuration -= hiddenAreaDuration;
|
|
833
966
|
this._durationExcludesAfterLiveSyncPoint = true;
|
|
@@ -835,16 +968,18 @@
|
|
|
835
968
|
this._durationExcludesAfterLiveSyncPoint = false;
|
|
836
969
|
}
|
|
837
970
|
}
|
|
971
|
+
|
|
838
972
|
if (newDuration !== this._playableRegionDuration) {
|
|
839
973
|
durationChanged = true;
|
|
840
974
|
this._playableRegionDuration = newDuration;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
|
-
// Note the end time is not the playableRegionDuration
|
|
975
|
+
} // Note the end time is not the playableRegionDuration
|
|
844
976
|
// The end time will always increase even if content is removed from the beginning
|
|
977
|
+
|
|
978
|
+
|
|
845
979
|
var endTime = fragments[0].start + newDuration;
|
|
846
980
|
var previousEndTime = previousPlayableRegionStartTime + previousPlayableRegionDuration;
|
|
847
981
|
var endTimeChanged = endTime !== previousEndTime;
|
|
982
|
+
|
|
848
983
|
if (endTimeChanged) {
|
|
849
984
|
if (!this._localEndTimeCorrelation) {
|
|
850
985
|
// set the correlation to map to the end
|
|
@@ -855,9 +990,12 @@
|
|
|
855
990
|
} else {
|
|
856
991
|
// check if the correlation still works
|
|
857
992
|
var _corr = this._localEndTimeCorrelation;
|
|
858
|
-
|
|
859
|
-
// this should point to a time within the extrapolation window from the end
|
|
993
|
+
|
|
994
|
+
var _timePassed = this._now - _corr.local; // this should point to a time within the extrapolation window from the end
|
|
995
|
+
|
|
996
|
+
|
|
860
997
|
var extrapolatedEndTime = (_corr.remote + _timePassed) / 1000;
|
|
998
|
+
|
|
861
999
|
if (extrapolatedEndTime > endTime) {
|
|
862
1000
|
this._localEndTimeCorrelation = {
|
|
863
1001
|
local: this._now,
|
|
@@ -880,10 +1018,10 @@
|
|
|
880
1018
|
};
|
|
881
1019
|
}
|
|
882
1020
|
}
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
// now that the values have been updated call any methods that use on them so they get the updated values
|
|
1021
|
+
} // now that the values have been updated call any methods that use on them so they get the updated values
|
|
886
1022
|
// immediately
|
|
1023
|
+
|
|
1024
|
+
|
|
887
1025
|
durationChanged && this._onDurationChange();
|
|
888
1026
|
startTimeChanged && this._onProgress();
|
|
889
1027
|
}
|
|
@@ -916,6 +1054,7 @@
|
|
|
916
1054
|
this.trigger(core.Events.PLAYBACK_LEVEL_SWITCH_END);
|
|
917
1055
|
this.trigger(core.Events.PLAYBACK_LEVEL_SWITCH, data);
|
|
918
1056
|
var currentLevel = this._hls.levels[data.level];
|
|
1057
|
+
|
|
919
1058
|
if (currentLevel) {
|
|
920
1059
|
// TODO should highDefinition be private and maybe have a read only accessor if it's used somewhere
|
|
921
1060
|
this.highDefinition = currentLevel.height >= 720 || currentLevel.bitrate / 1000 >= 2000;
|
|
@@ -951,17 +1090,19 @@
|
|
|
951
1090
|
}], [{
|
|
952
1091
|
key: "HLSJS",
|
|
953
1092
|
get: function get() {
|
|
954
|
-
return HLSJS__default[
|
|
1093
|
+
return HLSJS__default['default'];
|
|
955
1094
|
}
|
|
956
1095
|
}]);
|
|
1096
|
+
|
|
957
1097
|
return HlsjsPlayback;
|
|
958
1098
|
}(core.HTML5Video);
|
|
1099
|
+
|
|
959
1100
|
HlsjsPlayback.canPlay = function (resource, mimeType) {
|
|
960
1101
|
var resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
|
|
961
1102
|
var isHls = resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8' || listContainsIgnoreCase(mimeType, ['application/vnd.apple.mpegurl', 'application/x-mpegURL']);
|
|
962
|
-
return !!(HLSJS__default[
|
|
1103
|
+
return !!(HLSJS__default['default'].isSupported() && isHls);
|
|
963
1104
|
};
|
|
964
1105
|
|
|
965
1106
|
return HlsjsPlayback;
|
|
966
1107
|
|
|
967
|
-
}));
|
|
1108
|
+
})));
|