@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.
@@ -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,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
- enumerableOnly && (symbols = symbols.filter(function (sym) {
16
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
17
- })), keys.push.apply(keys, symbols);
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 = 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
- });
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, _toPropertyKey(descriptor.key), descriptor);
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.bind() : function _getPrototypeOf(o) {
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 ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) {
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
- result;
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
- function _get() {
173
+
174
+ function _get(target, property, receiver) {
144
175
  if (typeof Reflect !== "undefined" && Reflect.get) {
145
- _get = Reflect.get.bind();
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(arguments.length < 3 ? target : receiver);
185
+ return desc.get.call(receiver);
153
186
  }
187
+
154
188
  return desc.value;
155
189
  };
156
190
  }
157
- return _get.apply(this, arguments);
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
- assign = core.Utils.assign,
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
- _this._minDvrSize = typeof _this.options.hlsMinimumDvrSize === 'undefined' ? 60 : _this.options.hlsMinimumDvrSize;
219
- // The size of the start time extrapolation window measured as a multiple of segments.
220
- // Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
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.27"
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
- // the time in the video element which should represent the end of the content
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 corr = this._localEndTimeCorrelation;
325
- var timePassed = this._now - corr.local;
326
- var extrapolatedEndTime = (corr.remote + timePassed) / 1000;
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
- var _this2 = this;
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
- this._hls && this._hls.destroy();
383
- this._hls = new HLSJS__default["default"](assign({}, this.options.playback.hlsjsConfig));
384
- this._hls.once(HLSJS__default["default"].Events.MEDIA_ATTACHED, function () {
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
- this._hls.on(HLSJS__default["default"].Events.MANIFEST_PARSED, function () {
477
+
478
+ this._hls.on(HLSJS__default['default'].Events.MANIFEST_PARSED, function () {
388
479
  return _this2._manifestParsed = true;
389
480
  });
390
- this._hls.on(HLSJS__default["default"].Events.LEVEL_LOADED, function (evt, data) {
481
+
482
+ this._hls.on(HLSJS__default['default'].Events.LEVEL_LOADED, function (evt, data) {
391
483
  return _this2._updatePlaybackType(evt, data);
392
484
  });
393
- this._hls.on(HLSJS__default["default"].Events.LEVEL_UPDATED, function (evt, data) {
485
+
486
+ this._hls.on(HLSJS__default['default'].Events.LEVEL_UPDATED, function (evt, data) {
394
487
  return _this2._onLevelUpdated(evt, data);
395
488
  });
396
- this._hls.on(HLSJS__default["default"].Events.LEVEL_SWITCHING, function (evt, data) {
489
+
490
+ this._hls.on(HLSJS__default['default'].Events.LEVEL_SWITCHING, function (evt, data) {
397
491
  return _this2._onLevelSwitch(evt, data);
398
492
  });
399
- this._hls.on(HLSJS__default["default"].Events.FRAG_CHANGED, function (evt, data) {
493
+
494
+ this._hls.on(HLSJS__default['default'].Events.FRAG_CHANGED, function (evt, data) {
400
495
  return _this2._onFragmentChanged(evt, data);
401
496
  });
402
- this._hls.on(HLSJS__default["default"].Events.FRAG_LOADED, function (evt, data) {
497
+
498
+ this._hls.on(HLSJS__default['default'].Events.FRAG_LOADED, function (evt, data) {
403
499
  return _this2._onFragmentLoaded(evt, data);
404
500
  });
405
- this._hls.on(HLSJS__default["default"].Events.FRAG_PARSING_METADATA, function (evt, data) {
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
- this._hls.on(HLSJS__default["default"].Events.ERROR, function (evt, data) {
505
+
506
+ this._hls.on(HLSJS__default['default'].Events.ERROR, function (evt, data) {
409
507
  return _this2._onHLSJSError(evt, data);
410
508
  });
411
- this._hls.on(HLSJS__default["default"].Events.SUBTITLE_TRACK_LOADED, function (evt, data) {
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
- this._hls.on(HLSJS__default["default"].Events.SUBTITLE_TRACKS_UPDATED, function () {
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
- // this playback manages the src on the video element itself
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
- // assume live if time within 3 seconds of end of stream
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["default"].ErrorTypes.NETWORK_ERROR:
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["default"].ErrorDetails.MANIFEST_LOAD_ERROR:
597
- case HLSJS__default["default"].ErrorDetails.MANIFEST_LOAD_TIMEOUT:
598
- case HLSJS__default["default"].ErrorDetails.MANIFEST_PARSING_ERROR:
599
- case HLSJS__default["default"].ErrorDetails.LEVEL_LOAD_ERROR:
600
- case HLSJS__default["default"].ErrorDetails.LEVEL_LOAD_TIMEOUT:
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
- case HLSJS__default["default"].ErrorTypes.MEDIA_ERROR:
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["default"].ErrorTypes.NETWORK_ERROR && data.details === HLSJS__default["default"].ErrorDetails.KEY_LOAD_ERROR && data.response && data.response.code >= 400;
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
- if (this._hls) {
735
- _get(_getPrototypeOf(HlsjsPlayback.prototype), "stop", this).call(this);
736
- this._hls.destroy();
737
- delete this._hls;
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
- if (this._hls) {
745
- this._hls.destroy();
746
- delete this._hls;
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
- // this should point to a time within the extrapolation window
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
- var newDuration = data.details.totalduration;
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["default"].DefaultConfig.liveSyncDurationCount;
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
- var _timePassed = this._now - _corr.local;
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["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["default"].isSupported() && isHls);
1103
+ return !!(HLSJS__default['default'].isSupported() && isHls);
963
1104
  };
964
1105
 
965
1106
  return HlsjsPlayback;
966
1107
 
967
- }));
1108
+ })));