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