@clappr/hlsjs-playback 1.8.3 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clappr/hlsjs-playback",
3
- "version": "1.8.3",
3
+ "version": "1.9.0",
4
4
  "description": "HLS Playback based on hls.js",
5
5
  "main": "./dist/hlsjs-playback.js",
6
6
  "module": "./dist/hlsjs-playback.esm.js",
@@ -42,7 +42,7 @@
42
42
  "devDependencies": {
43
43
  "@babel/core": "^7.14.2",
44
44
  "@babel/preset-env": "^7.14.2",
45
- "@clappr/core": "^0.12.0",
45
+ "@clappr/core": "^0.13.0",
46
46
  "@rollup/plugin-babel": "^5.3.0",
47
47
  "@rollup/plugin-commonjs": "^19.0.0",
48
48
  "@rollup/plugin-node-resolve": "^13.0.0",
@@ -74,6 +74,5 @@
74
74
  ]
75
75
  }
76
76
  }
77
- },
78
- "gitHead": "20261f4b956c071733625fc303e5b607f75befd7"
77
+ }
79
78
  }
package/src/hls.js CHANGED
@@ -13,18 +13,24 @@ Events.register('PLAYBACK_FRAGMENT_CHANGED')
13
13
  Events.register('PLAYBACK_FRAGMENT_PARSING_METADATA')
14
14
 
15
15
  export default class HlsjsPlayback extends HTML5Video {
16
- get name() { return 'hls' }
16
+ get name() {
17
+ return 'hls'
18
+ }
17
19
 
18
- get supportedVersion() { return { min: CLAPPR_CORE_VERSION } }
20
+ get supportedVersion() {
21
+ return { min: CLAPPR_CORE_VERSION }
22
+ }
19
23
 
20
- get levels() { return this._levels || [] }
24
+ get levels() {
25
+ return this._levels || []
26
+ }
21
27
 
22
28
  get currentLevel() {
23
- if (this._currentLevel === null || this._currentLevel === undefined)
29
+ if (this._currentLevel === null || this._currentLevel === undefined) {
24
30
  return AUTO
25
- else
26
- return this._currentLevel //0 is a valid level ID
27
-
31
+ } else {
32
+ return this._currentLevel
33
+ } // 0 is a valid level ID
28
34
  }
29
35
 
30
36
  get isReady() {
@@ -34,10 +40,11 @@ export default class HlsjsPlayback extends HTML5Video {
34
40
  set currentLevel(id) {
35
41
  this._currentLevel = id
36
42
  this.trigger(Events.PLAYBACK_LEVEL_SWITCH_START)
37
- if (this.options.playback.hlsUseNextLevel)
43
+ if (this.options.playback.hlsUseNextLevel) {
38
44
  this._hls.nextLevel = this._currentLevel
39
- else
45
+ } else {
40
46
  this._hls.currentLevel = this._currentLevel
47
+ }
41
48
  }
42
49
 
43
50
  get latency() {
@@ -53,8 +60,9 @@ export default class HlsjsPlayback extends HTML5Video {
53
60
  }
54
61
 
55
62
  get _startTime() {
56
- if (this._playbackType === Playback.LIVE && this._playlistType !== 'EVENT')
63
+ if (this._playbackType === Playback.LIVE && this._playlistType !== 'EVENT') {
57
64
  return this._extrapolatedStartTime
65
+ }
58
66
 
59
67
  return this._playableRegionStartTime
60
68
  }
@@ -66,25 +74,32 @@ export default class HlsjsPlayback extends HTML5Video {
66
74
  // the time in the video element which should represent the start of the sliding window
67
75
  // extrapolated to increase in real time (instead of jumping as the early segments are removed)
68
76
  get _extrapolatedStartTime() {
69
- if (!this._localStartTimeCorrelation)
77
+ if (!this._localStartTimeCorrelation) {
70
78
  return this._playableRegionStartTime
79
+ }
71
80
 
72
- let corr = this._localStartTimeCorrelation
73
- let timePassed = this._now - corr.local
74
- let extrapolatedWindowStartTime = (corr.remote + timePassed) / 1000
81
+ const corr = this._localStartTimeCorrelation
82
+ const timePassed = this._now - corr.local
83
+ const extrapolatedWindowStartTime = (corr.remote + timePassed) / 1000
75
84
  // cap at the end of the extrapolated window duration
76
- return Math.min(extrapolatedWindowStartTime, this._playableRegionStartTime + this._extrapolatedWindowDuration)
85
+ return Math.min(
86
+ extrapolatedWindowStartTime,
87
+ this._playableRegionStartTime + this._extrapolatedWindowDuration
88
+ )
77
89
  }
78
90
 
79
91
  // the time in the video element which should represent the end of the content
80
92
  // extrapolated to increase in real time (instead of jumping as segments are added)
81
93
  get _extrapolatedEndTime() {
82
- let actualEndTime = this._playableRegionStartTime + this._playableRegionDuration
94
+ const actualEndTime = this._playableRegionStartTime + this._playableRegionDuration
83
95
  if (!this._localEndTimeCorrelation) return actualEndTime
84
96
  const correlation = this._localEndTimeCorrelation
85
97
  const timePassed = this._now - correlation.local
86
98
  const extrapolatedEndTime = (correlation.remote + timePassed) / 1000
87
- return Math.max(actualEndTime - this._extrapolatedWindowDuration, Math.min(extrapolatedEndTime, actualEndTime))
99
+ return Math.max(
100
+ actualEndTime - this._extrapolatedWindowDuration,
101
+ Math.min(extrapolatedEndTime, actualEndTime)
102
+ )
88
103
  }
89
104
 
90
105
  get _duration() {
@@ -109,8 +124,9 @@ export default class HlsjsPlayback extends HTML5Video {
109
124
  // . . . .
110
125
  // extrapolatedStartTime
111
126
  get _extrapolatedWindowDuration() {
112
- if (this._segmentTargetDuration === null)
127
+ if (this._segmentTargetDuration === null) {
113
128
  return 0
129
+ }
114
130
 
115
131
  return this._extrapolatedWindowNumSegments * this._segmentTargetDuration
116
132
  }
@@ -124,7 +140,7 @@ export default class HlsjsPlayback extends HTML5Video {
124
140
  }
125
141
 
126
142
  get customListeners() {
127
- return this.options.hlsPlayback && this.options.hlsPlayback.customListeners || []
143
+ return (this.options.hlsPlayback && this.options.hlsPlayback.customListeners) || []
128
144
  }
129
145
 
130
146
  get sourceMedia() {
@@ -154,12 +170,17 @@ export default class HlsjsPlayback extends HTML5Video {
154
170
  }
155
171
 
156
172
  _setInitialState() {
157
- this._minDvrSize = typeof (this.options.hlsMinimumDvrSize) === 'undefined' ? 60 : this.options.hlsMinimumDvrSize
173
+ this._minDvrSize =
174
+ typeof this.options.hlsMinimumDvrSize === 'undefined' ? 60 : this.options.hlsMinimumDvrSize
158
175
  // The size of the start time extrapolation window measured as a multiple of segments.
159
176
  // Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
160
177
  // removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
161
178
  // added/removed every 5.
162
- this._extrapolatedWindowNumSegments = !this.options.playback || typeof (this.options.playback.extrapolatedWindowNumSegments) === 'undefined' ? 2 : this.options.playback.extrapolatedWindowNumSegments
179
+ this._extrapolatedWindowNumSegments =
180
+ !this.options.playback ||
181
+ typeof this.options.playback.extrapolatedWindowNumSegments === 'undefined'
182
+ ? 2
183
+ : this.options.playback.extrapolatedWindowNumSegments
163
184
 
164
185
  this._playbackType = Playback.VOD
165
186
  this._lastTimeUpdate = { current: 0, total: 0, firstFragDateTime: 0 }
@@ -224,25 +245,33 @@ export default class HlsjsPlayback extends HTML5Video {
224
245
 
225
246
  _listenHLSEvents() {
226
247
  if (!this._hls) return
227
- this._hls.once(HLSJS.Events.MEDIA_ATTACHED, () => { this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src) })
228
- this._hls.on(HLSJS.Events.MANIFEST_LOADING, () => this._manifestLoading = true)
248
+ this._hls.once(HLSJS.Events.MEDIA_ATTACHED, () => {
249
+ this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src)
250
+ })
251
+ this._hls.on(HLSJS.Events.MANIFEST_LOADING, () => {
252
+ this._manifestLoading = true
253
+ })
229
254
  this._hls.on(HLSJS.Events.LEVEL_LOADED, (evt, data) => this._updatePlaybackType(evt, data))
230
255
  this._hls.on(HLSJS.Events.LEVEL_UPDATED, (evt, data) => this._onLevelUpdated(evt, data))
231
- this._hls.on(HLSJS.Events.LEVEL_SWITCHED, (evt,data) => this._onLevelSwitch(evt, data))
256
+ this._hls.on(HLSJS.Events.LEVEL_SWITCHED, (evt, data) => this._onLevelSwitch(evt, data))
232
257
  this._hls.on(HLSJS.Events.FRAG_CHANGED, (evt, data) => this._onFragmentChanged(evt, data))
233
258
  this._hls.on(HLSJS.Events.FRAG_LOADED, (evt, data) => this._onFragmentLoaded(evt, data))
234
259
  this._hls.on(HLSJS.Events.FRAG_BUFFERED, (evt, data) => this._onFragmentBuffered(evt, data))
235
- this._hls.on(HLSJS.Events.FRAG_PARSING_METADATA, (evt, data) => this._onFragmentParsingMetadata(evt, data))
260
+ this._hls.on(HLSJS.Events.FRAG_PARSING_METADATA, (evt, data) =>
261
+ this._onFragmentParsingMetadata(evt, data)
262
+ )
236
263
  this._hls.on(HLSJS.Events.ERROR, (evt, data) => this._onHLSJSError(evt, data))
237
- this._hls.on(HLSJS.Events.SUBTITLE_TRACK_LOADED, (evt, data) => this._onSubtitleLoaded(evt, data))
238
- this._hls.on(HLSJS.Events.SUBTITLE_TRACKS_UPDATED, () => this._ccTracksUpdated = true)
264
+ this._hls.on(HLSJS.Events.SUBTITLE_TRACK_LOADED, (evt, data) =>
265
+ this._onSubtitleLoaded(evt, data)
266
+ )
267
+ this._hls.on(HLSJS.Events.SUBTITLE_TRACKS_UPDATED, () => (this._ccTracksUpdated = true))
239
268
  this.bindCustomListeners()
240
269
  }
241
270
 
242
271
  bindCustomListeners() {
243
272
  this.customListeners.forEach(item => {
244
273
  const requestedEventName = item.eventName
245
- const typeOfListener = item.once ? 'once': 'on'
274
+ const typeOfListener = item.once ? 'once' : 'on'
246
275
  requestedEventName && this._hls[`${typeOfListener}`](requestedEventName, item.callback)
247
276
  })
248
277
  }
@@ -318,6 +347,16 @@ export default class HlsjsPlayback extends HTML5Video {
318
347
  return this._duration
319
348
  }
320
349
 
350
+ // the frame rate should be retrieved from the HLS.js level information
351
+ // as it is not necessarily exposed directly by the video element
352
+ getFrameRate() {
353
+ if (this._hls && this._hls.levels && this._hls.currentLevel >= 0) {
354
+ const level = this._hls.levels[this._hls.currentLevel]
355
+ return level && level.frameRate ? level.frameRate : null
356
+ }
357
+ return null
358
+ }
359
+
321
360
  getCurrentTime() {
322
361
  // e.g. can be < 0 if user pauses near the start
323
362
  // eventually they will then be kicked to the end by hlsjs if they run out of buffer
@@ -333,15 +372,15 @@ export default class HlsjsPlayback extends HTML5Video {
333
372
  }
334
373
 
335
374
  seekPercentage(percentage) {
336
- const seekTo = (percentage > 0)
337
- ? this._duration * (percentage / 100)
338
- : this._duration
375
+ const seekTo = percentage > 0 ? this._duration * (percentage / 100) : this._duration
339
376
  this.seek(seekTo)
340
377
  }
341
378
 
342
379
  seek(time) {
343
380
  if (time < 0) {
344
- Log.warn('Attempt to seek to a negative time. Resetting to live point. Use seekToLivePoint() to seek to the live point.')
381
+ Log.warn(
382
+ 'Attempt to seek to a negative time. Resetting to live point. Use seekToLivePoint() to seek to the live point.'
383
+ )
345
384
  time = this.getDuration()
346
385
  }
347
386
  time += this._startTime
@@ -353,12 +392,13 @@ export default class HlsjsPlayback extends HTML5Video {
353
392
  }
354
393
 
355
394
  _updateSettings() {
356
- if (this._playbackType === Playback.VOD)
395
+ if (this._playbackType === Playback.VOD) {
357
396
  this.settings.left = ['playpause', 'position', 'duration']
358
- else if (this.dvrEnabled)
397
+ } else if (this.dvrEnabled) {
359
398
  this.settings.left = ['playpause']
360
- else
399
+ } else {
361
400
  this.settings.left = ['playstop']
401
+ }
362
402
 
363
403
  this.settings.seekEnabled = this.isSeekEnabled()
364
404
  this.trigger(Events.PLAYBACK_SETTINGSUPDATE)
@@ -368,7 +408,7 @@ export default class HlsjsPlayback extends HTML5Video {
368
408
  const error = {
369
409
  code: `${data.type}_${data.details}`,
370
410
  description: `${this.name} error: type: ${data.type}, details: ${data.details}`,
371
- raw: data,
411
+ raw: data
372
412
  }
373
413
  let formattedError
374
414
  if (data.response) error.description += `, response: ${JSON.stringify(data.response)}`
@@ -378,42 +418,45 @@ export default class HlsjsPlayback extends HTML5Video {
378
418
  if (this._recoverAttemptsRemaining > 0) {
379
419
  this._recoverAttemptsRemaining -= 1
380
420
  switch (data.type) {
381
- case HLSJS.ErrorTypes.NETWORK_ERROR:
382
- switch (data.details) {
383
- // The following network errors cannot be recovered with HLS.startLoad()
384
- // For more details, see https://github.com/video-dev/hls.js/blob/master/doc/design.md#error-detection-and-handling
385
- // For "level load" fatal errors, see https://github.com/video-dev/hls.js/issues/1138
386
- case HLSJS.ErrorDetails.MANIFEST_LOAD_ERROR:
387
- case HLSJS.ErrorDetails.MANIFEST_LOAD_TIMEOUT:
388
- case HLSJS.ErrorDetails.MANIFEST_PARSING_ERROR:
389
- case HLSJS.ErrorDetails.LEVEL_LOAD_ERROR:
390
- case HLSJS.ErrorDetails.LEVEL_LOAD_TIMEOUT:
391
- Log.error('hlsjs: unrecoverable network fatal error.', { evt, data })
421
+ case HLSJS.ErrorTypes.NETWORK_ERROR:
422
+ switch (data.details) {
423
+ // The following network errors cannot be recovered with HLS.startLoad()
424
+ // For more details, see https://github.com/video-dev/hls.js/blob/master/doc/design.md#error-detection-and-handling
425
+ // For "level load" fatal errors, see https://github.com/video-dev/hls.js/issues/1138
426
+ case HLSJS.ErrorDetails.MANIFEST_LOAD_ERROR:
427
+ case HLSJS.ErrorDetails.MANIFEST_LOAD_TIMEOUT:
428
+ case HLSJS.ErrorDetails.MANIFEST_PARSING_ERROR:
429
+ case HLSJS.ErrorDetails.LEVEL_LOAD_ERROR:
430
+ case HLSJS.ErrorDetails.LEVEL_LOAD_TIMEOUT:
431
+ Log.error('hlsjs: unrecoverable network fatal error.', { evt, data })
432
+ formattedError = this.createError(error)
433
+ this.trigger(Events.PLAYBACK_ERROR, formattedError)
434
+ this.stop()
435
+ break
436
+ default:
437
+ Log.warn('hlsjs: trying to recover from network error.', { evt, data })
438
+ error.level = PlayerError.Levels.WARN
439
+ this._hls.startLoad()
440
+ break
441
+ }
442
+ break
443
+ case HLSJS.ErrorTypes.MEDIA_ERROR:
444
+ Log.warn('hlsjs: trying to recover from media error.', { evt, data })
445
+ error.level = PlayerError.Levels.WARN
446
+ this._recover(evt, data, error)
447
+ break
448
+ default:
449
+ Log.error('hlsjs: could not recover from error.', { evt, data })
392
450
  formattedError = this.createError(error)
393
451
  this.trigger(Events.PLAYBACK_ERROR, formattedError)
394
452
  this.stop()
395
453
  break
396
- default:
397
- Log.warn('hlsjs: trying to recover from network error.', { evt, data })
398
- error.level = PlayerError.Levels.WARN
399
- this._hls.startLoad()
400
- break
401
- }
402
- break
403
- case HLSJS.ErrorTypes.MEDIA_ERROR:
404
- Log.warn('hlsjs: trying to recover from media error.', { evt, data })
405
- error.level = PlayerError.Levels.WARN
406
- this._recover(evt, data, error)
407
- break
408
- default:
409
- Log.error('hlsjs: could not recover from error.', { evt, data })
410
- formattedError = this.createError(error)
411
- this.trigger(Events.PLAYBACK_ERROR, formattedError)
412
- this.stop()
413
- break
414
454
  }
415
455
  } else {
416
- Log.error('hlsjs: could not recover from error after maximum number of attempts.', { evt, data })
456
+ Log.error('hlsjs: could not recover from error after maximum number of attempts.', {
457
+ evt,
458
+ data
459
+ })
417
460
  formattedError = this.createError(error)
418
461
  this.trigger(Events.PLAYBACK_ERROR, formattedError)
419
462
  this.stop()
@@ -437,14 +480,20 @@ export default class HlsjsPlayback extends HTML5Video {
437
480
  }
438
481
 
439
482
  _keyIsDenied(data) {
440
- return data.type === HLSJS.ErrorTypes.NETWORK_ERROR
441
- && data.details === HLSJS.ErrorDetails.KEY_LOAD_ERROR
442
- && data.response
443
- && data.response.code >= 400
483
+ return (
484
+ data.type === HLSJS.ErrorTypes.NETWORK_ERROR &&
485
+ data.details === HLSJS.ErrorDetails.KEY_LOAD_ERROR &&
486
+ data.response &&
487
+ data.response.code >= 400
488
+ )
444
489
  }
445
490
 
446
491
  _onTimeUpdate() {
447
- const update = { current: this.getCurrentTime(), total: this.getDuration(), firstFragDateTime: this.getProgramDateTime() }
492
+ const update = {
493
+ current: this.getCurrentTime(),
494
+ total: this.getDuration(),
495
+ firstFragDateTime: this.getProgramDateTime()
496
+ }
448
497
  const shouldThrottle = this._shouldThrottleTimeUpdate(update)
449
498
  if (shouldThrottle) return
450
499
  this._lastTimeUpdate = update
@@ -453,9 +502,12 @@ export default class HlsjsPlayback extends HTML5Video {
453
502
  }
454
503
 
455
504
  _shouldThrottleTimeUpdate(update) {
456
- const isSameTime = Math.abs(update.current - this._lastTimeUpdate.current) < this._timeUpdateFiringRate
457
- const isSameDuration = Math.abs(update.total - this._lastTimeUpdate.total) < this._durationChangeMinOffset
458
- const isSameFirstFragDateTime = update.firstFragDateTime === this._lastTimeUpdate.firstFragDateTime
505
+ const isSameTime =
506
+ Math.abs(update.current - this._lastTimeUpdate.current) < this._timeUpdateFiringRate
507
+ const isSameDuration =
508
+ Math.abs(update.total - this._lastTimeUpdate.total) < this._durationChangeMinOffset
509
+ const isSameFirstFragDateTime =
510
+ update.firstFragDateTime === this._lastTimeUpdate.firstFragDateTime
459
511
  const isSameEventPayload = isSameTime && isSameDuration && isSameFirstFragDateTime
460
512
  const isThrottled = this._now - this._lastTimeUpdateFiredTime < this._timeUpdateThrottleDelay
461
513
 
@@ -475,14 +527,17 @@ export default class HlsjsPlayback extends HTML5Video {
475
527
  let buffered = []
476
528
  let bufferedPos = 0
477
529
  for (let i = 0; i < this.el.buffered.length; i++) {
478
- buffered = [...buffered, {
479
- // for a stream with sliding window dvr something that is buffered my slide off the start of the timeline
480
- start: Math.max(0, this.el.buffered.start(i) - this._playableRegionStartTime),
481
- end: Math.max(0, this.el.buffered.end(i) - this._playableRegionStartTime)
482
- }]
483
- if (this.el.currentTime >= buffered[i].start && this.el.currentTime <= buffered[i].end)
530
+ buffered = [
531
+ ...buffered,
532
+ {
533
+ // for a stream with sliding window dvr something that is buffered my slide off the start of the timeline
534
+ start: Math.max(0, this.el.buffered.start(i) - this._playableRegionStartTime),
535
+ end: Math.max(0, this.el.buffered.end(i) - this._playableRegionStartTime)
536
+ }
537
+ ]
538
+ if (this.el.currentTime >= buffered[i].start && this.el.currentTime <= buffered[i].end) {
484
539
  bufferedPos = i
485
-
540
+ }
486
541
  }
487
542
  const progress = {
488
543
  start: buffered[bufferedPos].start,
@@ -492,7 +547,7 @@ export default class HlsjsPlayback extends HTML5Video {
492
547
  this.trigger(Events.PLAYBACK_PROGRESS, progress, buffered)
493
548
  }
494
549
 
495
- load(url) {
550
+ load(url) {
496
551
  this._stopTimeUpdateTimer()
497
552
  this.options.src = url
498
553
  this._setup()
@@ -500,7 +555,9 @@ export default class HlsjsPlayback extends HTML5Video {
500
555
 
501
556
  play() {
502
557
  !this._hls && this._setup()
503
- !this._manifestLoading && !this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src)
558
+ !this._manifestLoading &&
559
+ !this.options.hlsPlayback.preload &&
560
+ this._hls.loadSource(this.options.src)
504
561
  super.play()
505
562
  this._startTimeUpdateTimer()
506
563
  }
@@ -526,14 +583,18 @@ export default class HlsjsPlayback extends HTML5Video {
526
583
  this._playbackType = data.details.live ? Playback.LIVE : Playback.VOD
527
584
  this._onLevelUpdated(evt, data)
528
585
  // Live stream subtitle tracks detection hack (may not immediately available)
529
- if (this._ccTracksUpdated && this._playbackType === Playback.LIVE && this.hasClosedCaptionsTracks)
586
+ if (
587
+ this._ccTracksUpdated &&
588
+ this._playbackType === Playback.LIVE &&
589
+ this.hasClosedCaptionsTracks
590
+ ) {
530
591
  this._onSubtitleLoaded()
531
-
592
+ }
532
593
  }
533
594
 
534
595
  _fillLevels() {
535
596
  this._levels = this._hls.levels.map((level, index) => {
536
- return { id: index, level: level, label: `${level.bitrate/1000}Kbps` }
597
+ return { id: index, level: level, label: `${level.bitrate / 1000}Kbps` }
537
598
  })
538
599
  this.trigger(Events.PLAYBACK_LEVELS_AVAILABLE, this._levels)
539
600
  }
@@ -543,13 +604,14 @@ export default class HlsjsPlayback extends HTML5Video {
543
604
  this._playlistType = data.details.type || null
544
605
  let startTimeChanged = false
545
606
  let durationChanged = false
546
- let fragments = data.details.fragments
547
- let previousPlayableRegionStartTime = this._playableRegionStartTime
548
- let previousPlayableRegionDuration = this._playableRegionDuration
607
+ const fragments = data.details.fragments
608
+ const previousPlayableRegionStartTime = this._playableRegionStartTime
609
+ const previousPlayableRegionDuration = this._playableRegionDuration
549
610
  if (fragments.length === 0) return
550
611
  // #EXT-X-PROGRAM-DATE-TIME
551
- if (fragments[0].rawProgramDateTime)
612
+ if (fragments[0].rawProgramDateTime) {
552
613
  this._programDateTime = fragments[0].rawProgramDateTime
614
+ }
553
615
  if (this._playableRegionStartTime !== fragments[0].start) {
554
616
  startTimeChanged = true
555
617
  this._playableRegionStartTime = fragments[0].start
@@ -560,14 +622,14 @@ export default class HlsjsPlayback extends HTML5Video {
560
622
  // set the correlation to map to middle of the extrapolation window
561
623
  this._localStartTimeCorrelation = {
562
624
  local: this._now,
563
- remote: (fragments[0].start + (this._extrapolatedWindowDuration/2)) * 1000
625
+ remote: (fragments[0].start + this._extrapolatedWindowDuration / 2) * 1000
564
626
  }
565
627
  } else {
566
628
  // check if the correlation still works
567
- let corr = this._localStartTimeCorrelation
568
- let timePassed = this._now - corr.local
629
+ const corr = this._localStartTimeCorrelation
630
+ const timePassed = this._now - corr.local
569
631
  // this should point to a time within the extrapolation window
570
- let startTime = (corr.remote + timePassed) / 1000
632
+ const startTime = (corr.remote + timePassed) / 1000
571
633
  if (startTime < fragments[0].start) {
572
634
  // our start time is now earlier than the first chunk
573
635
  // (maybe the chunk was removed early)
@@ -583,26 +645,32 @@ export default class HlsjsPlayback extends HTML5Video {
583
645
  // update the correlation so that the time starts counting again from the value it's on now
584
646
  this._localStartTimeCorrelation = {
585
647
  local: this._now,
586
- remote: Math.max(fragments[0].start, previousPlayableRegionStartTime + this._extrapolatedWindowDuration) * 1000
648
+ remote:
649
+ Math.max(
650
+ fragments[0].start,
651
+ previousPlayableRegionStartTime + this._extrapolatedWindowDuration
652
+ ) * 1000
587
653
  }
588
654
  }
589
655
  }
590
656
  }
591
-
657
+
592
658
  let newDuration = data.details.totalduration
593
659
  // if it's a live stream then shorten the duration to remove access
594
660
  // to the area after hlsjs's live sync point
595
661
  // seeks to areas after this point sometimes have issues
596
662
  if (this._playbackType === Playback.LIVE) {
597
- let fragmentTargetDuration = data.details.targetduration
598
- let hlsjsConfig = this.options.playback.hlsjsConfig || {}
599
- let liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount || HLSJS.DefaultConfig.liveSyncDurationCount
600
- let hiddenAreaDuration = fragmentTargetDuration * liveSyncDurationCount
663
+ const fragmentTargetDuration = data.details.targetduration
664
+ const hlsjsConfig = this.options.playback.hlsjsConfig || {}
665
+ const liveSyncDurationCount =
666
+ hlsjsConfig.liveSyncDurationCount || HLSJS.DefaultConfig.liveSyncDurationCount
667
+ const hiddenAreaDuration = fragmentTargetDuration * liveSyncDurationCount
601
668
  if (hiddenAreaDuration <= newDuration) {
602
669
  newDuration -= hiddenAreaDuration
603
670
  this._durationExcludesAfterLiveSyncPoint = true
604
- } else { this._durationExcludesAfterLiveSyncPoint = false }
605
-
671
+ } else {
672
+ this._durationExcludesAfterLiveSyncPoint = false
673
+ }
606
674
  }
607
675
  if (newDuration !== this._playableRegionDuration) {
608
676
  durationChanged = true
@@ -610,9 +678,9 @@ export default class HlsjsPlayback extends HTML5Video {
610
678
  }
611
679
  // Note the end time is not the playableRegionDuration
612
680
  // The end time will always increase even if content is removed from the beginning
613
- let endTime = fragments[0].start + newDuration
614
- let previousEndTime = previousPlayableRegionStartTime + previousPlayableRegionDuration
615
- let endTimeChanged = endTime !== previousEndTime
681
+ const endTime = fragments[0].start + newDuration
682
+ const previousEndTime = previousPlayableRegionStartTime + previousPlayableRegionDuration
683
+ const endTimeChanged = endTime !== previousEndTime
616
684
  if (endTimeChanged) {
617
685
  if (!this._localEndTimeCorrelation) {
618
686
  // set the correlation to map to the end
@@ -622,10 +690,10 @@ export default class HlsjsPlayback extends HTML5Video {
622
690
  }
623
691
  } else {
624
692
  // check if the correlation still works
625
- let corr = this._localEndTimeCorrelation
626
- let timePassed = this._now - corr.local
693
+ const corr = this._localEndTimeCorrelation
694
+ const timePassed = this._now - corr.local
627
695
  // this should point to a time within the extrapolation window from the end
628
- let extrapolatedEndTime = (corr.remote + timePassed) / 1000
696
+ const extrapolatedEndTime = (corr.remote + timePassed) / 1000
629
697
  if (extrapolatedEndTime > endTime) {
630
698
  this._localEndTimeCorrelation = {
631
699
  local: this._now,
@@ -684,10 +752,10 @@ export default class HlsjsPlayback extends HTML5Video {
684
752
  if (!this.levels.length) this._fillLevels()
685
753
  this.trigger(Events.PLAYBACK_LEVEL_SWITCH_END)
686
754
  this.trigger(Events.PLAYBACK_LEVEL_SWITCH, data)
687
- let currentLevel = this._hls.levels[data.level]
755
+ const currentLevel = this._hls.levels[data.level]
688
756
  if (currentLevel) {
689
757
  // TODO should highDefinition be private and maybe have a read only accessor if it's used somewhere
690
- this.highDefinition = (currentLevel.height >= 720 || (currentLevel.bitrate / 1000) >= 2000)
758
+ this.highDefinition = currentLevel.height >= 720 || currentLevel.bitrate / 1000 >= 2000
691
759
  this.trigger(Events.PLAYBACK_HIGHDEFINITIONUPDATE, this.highDefinition)
692
760
  this.trigger(Events.PLAYBACK_BITRATE, {
693
761
  height: currentLevel.height,
@@ -704,7 +772,11 @@ export default class HlsjsPlayback extends HTML5Video {
704
772
  // - the duration does not include content after hlsjs's live sync point
705
773
  // - the playable region duration is longer than the configured duration to enable dvr after
706
774
  // - the playback type is LIVE.
707
- return (this._durationExcludesAfterLiveSyncPoint && this._duration >= this._minDvrSize && this.getPlaybackType() === Playback.LIVE)
775
+ return (
776
+ this._durationExcludesAfterLiveSyncPoint &&
777
+ this._duration >= this._minDvrSize &&
778
+ this.getPlaybackType() === Playback.LIVE
779
+ )
708
780
  }
709
781
 
710
782
  getPlaybackType() {
@@ -712,12 +784,14 @@ export default class HlsjsPlayback extends HTML5Video {
712
784
  }
713
785
 
714
786
  isSeekEnabled() {
715
- return (this._playbackType === Playback.VOD || this.dvrEnabled)
787
+ return this._playbackType === Playback.VOD || this.dvrEnabled
716
788
  }
717
789
  }
718
790
 
719
- HlsjsPlayback.canPlay = function(resource, mimeType) {
791
+ HlsjsPlayback.canPlay = function (resource, mimeType) {
720
792
  const resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || []
721
- const isHls = ((resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8') || listContainsIgnoreCase(mimeType, ['application/vnd.apple.mpegurl', 'application/x-mpegURL']))
793
+ const isHls =
794
+ (resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8') ||
795
+ listContainsIgnoreCase(mimeType, ['application/vnd.apple.mpegurl', 'application/x-mpegURL'])
722
796
  return !!(HLSJS.isSupported() && isHls)
723
797
  }