@gcorevideo/player 2.10.0 → 2.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +13 -0
  2. package/coverage/clover.xml +6 -0
  3. package/coverage/coverage-final.json +1 -0
  4. package/coverage/lcov-report/base.css +224 -0
  5. package/coverage/lcov-report/block-navigation.js +87 -0
  6. package/coverage/lcov-report/favicon.png +0 -0
  7. package/coverage/lcov-report/index.html +101 -0
  8. package/coverage/lcov-report/prettify.css +1 -0
  9. package/coverage/lcov-report/prettify.js +2 -0
  10. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  11. package/coverage/lcov-report/sorter.js +196 -0
  12. package/coverage/lcov.info +0 -0
  13. package/dist/index.js +3115 -1209
  14. package/lib/Player.d.ts +3 -2
  15. package/lib/Player.d.ts.map +1 -1
  16. package/lib/Player.js +32 -24
  17. package/lib/index.d.ts +5 -5
  18. package/lib/index.d.ts.map +1 -1
  19. package/lib/index.js +5 -5
  20. package/lib/internal.types.d.ts +1 -10
  21. package/lib/internal.types.d.ts.map +1 -1
  22. package/lib/playback/index.d.ts +4 -0
  23. package/lib/playback/index.d.ts.map +1 -0
  24. package/lib/playback/index.js +13 -0
  25. package/lib/playback.types.d.ts +19 -0
  26. package/lib/playback.types.d.ts.map +1 -1
  27. package/lib/playback.types.js +9 -1
  28. package/lib/plugins/dash-playback/DashPlayback.d.ts +1 -1
  29. package/lib/plugins/dash-playback/DashPlayback.d.ts.map +1 -1
  30. package/lib/plugins/dash-playback/DashPlayback.js +39 -100
  31. package/lib/plugins/dash-playback/types.d.ts +6 -0
  32. package/lib/plugins/dash-playback/types.d.ts.map +1 -0
  33. package/lib/plugins/dash-playback/types.js +1 -0
  34. package/lib/plugins/hls-playback/HlsPlayback.d.ts +6 -7
  35. package/lib/plugins/hls-playback/HlsPlayback.d.ts.map +1 -1
  36. package/lib/plugins/hls-playback/HlsPlayback.js +131 -80
  37. package/lib/types.d.ts +3 -3
  38. package/lib/types.d.ts.map +1 -1
  39. package/lib/utils/mediaSources.d.ts +14 -6
  40. package/lib/utils/mediaSources.d.ts.map +1 -1
  41. package/lib/utils/mediaSources.js +56 -53
  42. package/lib/utils/testUtils.d.ts +3 -0
  43. package/lib/utils/testUtils.d.ts.map +1 -0
  44. package/lib/utils/testUtils.js +12 -0
  45. package/package.json +6 -4
  46. package/src/Player.ts +40 -31
  47. package/src/__tests__/Player.test.ts +357 -0
  48. package/src/index.ts +5 -5
  49. package/src/internal.types.ts +1 -12
  50. package/src/playback/index.ts +17 -0
  51. package/src/playback.types.ts +29 -8
  52. package/src/plugins/dash-playback/DashPlayback.ts +44 -120
  53. package/src/plugins/hls-playback/HlsPlayback.ts +544 -390
  54. package/src/types.ts +5 -3
  55. package/src/typings/@clappr/core/error_mixin.d.ts +0 -2
  56. package/src/typings/@clappr/core/index.d.ts +5 -0
  57. package/src/typings/@clappr/index.d.ts +1 -0
  58. package/src/utils/__tests__/mediaSources.test.ts +230 -0
  59. package/src/utils/mediaSources.ts +78 -64
  60. package/src/utils/testUtils.ts +15 -0
  61. package/tsconfig.json +0 -9
  62. package/tsconfig.tsbuildinfo +1 -1
  63. package/vitest.config.ts +8 -0
  64. package/licenses.json +0 -782
  65. package/src/utils/queryParams.ts +0 -5
@@ -1,11 +1,12 @@
1
1
  // Copyright 2014 Globo.com Player authors. All rights reserved.
2
2
  // Use of this source code is governed by a BSD-style
3
3
  // license that can be found in the LICENSE file.
4
- import { Events, HTML5Video, Log, Playback, PlayerError, Utils } from '@clappr/core';
4
+ import { Events, HTML5Video, Log, Playback, PlayerError, Utils, } from '@clappr/core';
5
+ import { trace } from '@gcorevideo/utils';
5
6
  import assert from 'assert';
6
7
  import HLSJS from 'hls.js';
7
- import { trace } from '@gcorevideo/utils';
8
- import { CLAPPR_VERSION } from "../../build.js";
8
+ import { PlaybackErrorCode } from '../../playback.types.js';
9
+ import { CLAPPR_VERSION } from '../../build.js';
9
10
  const { now, listContainsIgnoreCase } = Utils;
10
11
  const AUTO = -1;
11
12
  const DEFAULT_RECOVER_ATTEMPTS = 16;
@@ -75,7 +76,8 @@ export default class HlsPlayback extends HTML5Video {
75
76
  return this._hls.playingDate;
76
77
  }
77
78
  get _startTime() {
78
- if (this._playbackType === Playback.LIVE && this._playlistType !== 'EVENT') {
79
+ if (this._playbackType === Playback.LIVE &&
80
+ this._playlistType !== 'EVENT') {
79
81
  return this._extrapolatedStartTime;
80
82
  }
81
83
  return this._playableRegionStartTime;
@@ -140,7 +142,8 @@ export default class HlsPlayback extends HTML5Video {
140
142
  return { preload: true };
141
143
  }
142
144
  get customListeners() {
143
- return this.options.hlsPlayback && this.options.hlsPlayback.customListeners || [];
145
+ return ((this.options.hlsPlayback && this.options.hlsPlayback.customListeners) ||
146
+ []);
144
147
  }
145
148
  get sourceMedia() {
146
149
  return this.options.src;
@@ -162,17 +165,27 @@ export default class HlsPlayback extends HTML5Video {
162
165
  constructor(...args) {
163
166
  // @ts-ignore
164
167
  super(...args);
165
- this.options.hlsPlayback = { ...this.defaultOptions, ...this.options.hlsPlayback };
168
+ this.options.hlsPlayback = {
169
+ ...this.defaultOptions,
170
+ ...this.options.hlsPlayback,
171
+ };
166
172
  this._setInitialState();
167
173
  }
168
174
  _setInitialState() {
169
175
  // @ts-ignore
170
- this._minDvrSize = typeof (this.options.hlsMinimumDvrSize) === 'undefined' ? 60 : this.options.hlsMinimumDvrSize;
176
+ this._minDvrSize =
177
+ typeof this.options.hlsMinimumDvrSize === 'undefined'
178
+ ? 60
179
+ : this.options.hlsMinimumDvrSize;
171
180
  // The size of the start time extrapolation window measured as a multiple of segments.
172
181
  // Should be 2 or higher, or 0 to disable. Should only need to be increased above 2 if more than one segment is
173
182
  // removed from the start of the playlist at a time. E.g if the playlist is cached for 10 seconds and new chunks are
174
183
  // added/removed every 5.
175
- this._extrapolatedWindowNumSegments = !this.options.playback || typeof (this.options.playback.extrapolatedWindowNumSegments) === 'undefined' ? 2 : this.options.playback.extrapolatedWindowNumSegments;
184
+ this._extrapolatedWindowNumSegments =
185
+ !this.options.playback ||
186
+ typeof this.options.playback.extrapolatedWindowNumSegments === 'undefined'
187
+ ? 2
188
+ : this.options.playback.extrapolatedWindowNumSegments;
176
189
  this._playbackType = Playback.VOD;
177
190
  this._lastTimeUpdate = { current: 0, total: 0 };
178
191
  this._lastDuration = null;
@@ -204,7 +217,8 @@ export default class HlsPlayback extends HTML5Video {
204
217
  // #EXT-X-PLAYLIST-TYPE
205
218
  this._playlistType = null;
206
219
  // TODO options.hlsRecoverAttempts
207
- this._recoverAttemptsRemaining = this.options.hlsRecoverAttempts || DEFAULT_RECOVER_ATTEMPTS;
220
+ this._recoverAttemptsRemaining =
221
+ this.options.hlsRecoverAttempts || DEFAULT_RECOVER_ATTEMPTS;
208
222
  }
209
223
  _setup() {
210
224
  this._destroyHLSInstance();
@@ -247,13 +261,15 @@ export default class HlsPlayback extends HTML5Video {
247
261
  });
248
262
  const onPlaying = () => {
249
263
  if (this._hls) {
250
- this._hls.config.maxBufferLength = this.options.hlsPlayback.maxBufferLength || 30;
251
- this._hls.config.maxMaxBufferLength = this.options.hlsPlayback.maxMaxBufferLength || 60;
264
+ this._hls.config.maxBufferLength =
265
+ this.options.hlsPlayback.maxBufferLength || 30;
266
+ this._hls.config.maxMaxBufferLength =
267
+ this.options.hlsPlayback.maxMaxBufferLength || 60;
252
268
  }
253
269
  this.el.removeEventListener('playing', onPlaying);
254
270
  };
255
271
  this.el.addEventListener('playing', onPlaying);
256
- this._hls.on(HLSJS.Events.MANIFEST_PARSED, () => this._manifestParsed = true);
272
+ this._hls.on(HLSJS.Events.MANIFEST_PARSED, () => (this._manifestParsed = true));
257
273
  this._hls.on(HLSJS.Events.LEVEL_LOADED, (evt, data) => this._updatePlaybackType(evt, data));
258
274
  this._hls.on(HLSJS.Events.LEVEL_UPDATED, (evt, data) => this._onLevelUpdated(evt, data));
259
275
  this._hls.on(HLSJS.Events.LEVEL_SWITCHING, (evt, data) => this._onLevelSwitch(evt, data));
@@ -263,7 +279,7 @@ export default class HlsPlayback extends HTML5Video {
263
279
  this._hls.on(HLSJS.Events.ERROR, (evt, data) => this._onHLSJSError(evt, data));
264
280
  // this._hls.on(HLSJS.Events.SUBTITLE_TRACK_LOADED, (evt, data) => this._onSubtitleLoaded(evt, data));
265
281
  this._hls.on(HLSJS.Events.SUBTITLE_TRACK_LOADED, () => this._onSubtitleLoaded());
266
- this._hls.on(HLSJS.Events.SUBTITLE_TRACKS_UPDATED, () => this._ccTracksUpdated = true);
282
+ this._hls.on(HLSJS.Events.SUBTITLE_TRACKS_UPDATED, () => (this._ccTracksUpdated = true));
267
283
  this.bindCustomListeners();
268
284
  }
269
285
  bindCustomListeners() {
@@ -271,7 +287,8 @@ export default class HlsPlayback extends HTML5Video {
271
287
  const requestedEventName = item.eventName;
272
288
  const typeOfListener = item.once ? 'once' : 'on';
273
289
  assert.ok(this._hls, 'Hls.js instance is not available');
274
- requestedEventName && this._hls[`${typeOfListener}`](requestedEventName, item.callback);
290
+ requestedEventName &&
291
+ this._hls[`${typeOfListener}`](requestedEventName, item.callback);
275
292
  });
276
293
  }
277
294
  unbindCustomListeners() {
@@ -283,7 +300,10 @@ export default class HlsPlayback extends HTML5Video {
283
300
  }
284
301
  _onFragmentParsingMetadata(evt, data) {
285
302
  // @ts-ignore
286
- this.trigger(Events.Custom.PLAYBACK_FRAGMENT_PARSING_METADATA, { evt, data });
303
+ this.trigger(Events.Custom.PLAYBACK_FRAGMENT_PARSING_METADATA, {
304
+ evt,
305
+ data,
306
+ });
287
307
  }
288
308
  render() {
289
309
  this._ready();
@@ -311,12 +331,9 @@ export default class HlsPlayback extends HTML5Video {
311
331
  else {
312
332
  Log.error('hlsjs: failed to recover', { evt, data });
313
333
  error.level = PlayerError.Levels.FATAL;
314
- const formattedError = this.createError(error);
315
- this.trigger(Events.PLAYBACK_ERROR, formattedError);
316
- this.stop();
334
+ this.triggerError(error);
317
335
  }
318
336
  }
319
- // override
320
337
  // this playback manages the src on the video element itself
321
338
  _setupSrc(srcUrl) { } // eslint-disable-line no-unused-vars
322
339
  _startTimeUpdateTimer() {
@@ -336,7 +353,7 @@ export default class HlsPlayback extends HTML5Video {
336
353
  this._timeUpdateTimer = null;
337
354
  }
338
355
  getProgramDateTime() {
339
- return this._programDateTime;
356
+ return this._programDateTime ?? 0;
340
357
  }
341
358
  // the duration on the video element itself should not be used
342
359
  // as this does not necesarily represent the duration of the stream
@@ -357,9 +374,7 @@ export default class HlsPlayback extends HTML5Video {
357
374
  return this._startTime;
358
375
  }
359
376
  seekPercentage(percentage) {
360
- const seekTo = (percentage > 0)
361
- ? this._duration * (percentage / 100)
362
- : this._duration;
377
+ const seekTo = percentage > 0 ? this._duration * (percentage / 100) : this._duration;
363
378
  this.seek(seekTo);
364
379
  }
365
380
  seek(time) {
@@ -377,7 +392,7 @@ export default class HlsPlayback extends HTML5Video {
377
392
  }
378
393
  _updateDvr(status) {
379
394
  this.trigger(Events.PLAYBACK_DVR, status);
380
- this.trigger(Events.PLAYBACK_STATS_ADD, { 'dvr': status });
395
+ this.trigger(Events.PLAYBACK_STATS_ADD, { dvr: status });
381
396
  }
382
397
  _updateSettings() {
383
398
  if (this._playbackType === Playback.VOD) {
@@ -398,11 +413,11 @@ export default class HlsPlayback extends HTML5Video {
398
413
  }
399
414
  _onHLSJSError(evt, data) {
400
415
  const error = {
401
- code: `${data.type}_${data.details}`,
402
- description: `${this.name} error: type: ${data.type}, details: ${data.details}`,
403
- raw: data,
416
+ code: PlaybackErrorCode.Generic,
417
+ description: `${this.name} error: type: ${data.type}, details: ${data.details} fatal: ${data.fatal}`,
418
+ level: data.fatal ? PlayerError.Levels.FATAL : PlayerError.Levels.WARN,
419
+ message: `${this.name} error: type: ${data.type}, details: ${data.details}`,
404
420
  };
405
- let formattedError;
406
421
  if (data.response) {
407
422
  error.description += `, response: ${JSON.stringify(data.response)}`;
408
423
  }
@@ -422,37 +437,41 @@ export default class HlsPlayback extends HTML5Video {
422
437
  case HLSJS.ErrorDetails.MANIFEST_PARSING_ERROR:
423
438
  case HLSJS.ErrorDetails.LEVEL_LOAD_ERROR:
424
439
  case HLSJS.ErrorDetails.LEVEL_LOAD_TIMEOUT:
425
- Log.error('hlsjs: unrecoverable network fatal error.', { evt, data });
426
- formattedError = this.createError(error);
427
- this.trigger(Events.PLAYBACK_ERROR, formattedError);
428
- this.stop();
440
+ Log.error('hlsjs: unrecoverable network fatal error.', {
441
+ evt,
442
+ data,
443
+ });
444
+ error.code = PlaybackErrorCode.MediaSourceUnavailable;
445
+ this.triggerError(error);
429
446
  break;
430
447
  default:
431
- Log.warn('hlsjs: trying to recover from network error.', { evt, data });
448
+ Log.warn('hlsjs: trying to recover from network error.', {
449
+ evt,
450
+ data,
451
+ });
432
452
  error.level = PlayerError.Levels.WARN;
433
- assert(this._hls, 'Hls.js instance is not available');
434
- this._hls.startLoad();
453
+ this._hls?.startLoad();
435
454
  break;
436
455
  }
437
456
  break;
438
457
  case HLSJS.ErrorTypes.MEDIA_ERROR:
439
- Log.warn('hlsjs: trying to recover from media error.', { evt, data });
458
+ Log.warn('hlsjs: trying to recover from media error.', {
459
+ evt,
460
+ data,
461
+ });
440
462
  error.level = PlayerError.Levels.WARN;
441
463
  this._recover(evt, data, error);
442
464
  break;
443
465
  default:
444
466
  Log.error('hlsjs: could not recover from error.', { evt, data });
445
- formattedError = this.createError(error);
446
- this.trigger(Events.PLAYBACK_ERROR, formattedError);
447
- this.stop();
467
+ this.triggerError(error);
448
468
  break;
449
469
  }
450
470
  }
451
471
  else {
452
472
  Log.error('hlsjs: could not recover from error after maximum number of attempts.', { evt, data });
453
- formattedError = this.createError(error);
454
- this.trigger(Events.PLAYBACK_ERROR, formattedError);
455
- this.stop();
473
+ // TODO
474
+ this.triggerError(error);
456
475
  }
457
476
  }
458
477
  else {
@@ -460,28 +479,31 @@ export default class HlsPlayback extends HTML5Video {
460
479
  // playback fatal error if triggerFatalErrorOnResourceDenied playback
461
480
  // option is set. HLSJS.ErrorTypes.KEY_SYSTEM_ERROR are fatal errors
462
481
  // and therefore already handled.
463
- if (this.options.playback.triggerFatalErrorOnResourceDenied && this._keyIsDenied(data)) {
482
+ if (this.options.playback.triggerFatalErrorOnResourceDenied &&
483
+ this._keyIsDenied(data)) {
464
484
  Log.error('hlsjs: could not load decrypt key.', { evt, data });
465
- formattedError = this.createError(error);
466
- this.trigger(Events.PLAYBACK_ERROR, formattedError);
467
- this.stop();
485
+ this.triggerError(error);
468
486
  return;
469
487
  }
470
- error.level = PlayerError.Levels.WARN;
471
488
  Log.warn('hlsjs: non-fatal error occurred', { evt, data });
472
489
  }
473
490
  }
474
491
  _keyIsDenied(data) {
475
- return data.type === HLSJS.ErrorTypes.NETWORK_ERROR
476
- && data.details === HLSJS.ErrorDetails.KEY_LOAD_ERROR
477
- && data.response
478
- && data.response.code
479
- && data.response.code >= 400;
492
+ return (data.type === HLSJS.ErrorTypes.NETWORK_ERROR &&
493
+ data.details === HLSJS.ErrorDetails.KEY_LOAD_ERROR &&
494
+ data.response &&
495
+ data.response.code &&
496
+ data.response.code >= 400);
480
497
  }
481
498
  _onTimeUpdate() {
482
- const update = { current: this.getCurrentTime(), total: this.getDuration(), firstFragDateTime: this.getProgramDateTime() };
483
- const isSame = this._lastTimeUpdate && (update.current === this._lastTimeUpdate.current &&
484
- update.total === this._lastTimeUpdate.total);
499
+ const update = {
500
+ current: this.getCurrentTime(),
501
+ total: this.getDuration(),
502
+ firstFragDateTime: this.getProgramDateTime(),
503
+ };
504
+ const isSame = this._lastTimeUpdate &&
505
+ update.current === this._lastTimeUpdate.current &&
506
+ update.total === this._lastTimeUpdate.total;
485
507
  if (isSame) {
486
508
  return;
487
509
  }
@@ -503,19 +525,25 @@ export default class HlsPlayback extends HTML5Video {
503
525
  let buffered = [];
504
526
  let bufferedPos = 0;
505
527
  for (let i = 0; i < this.el.buffered.length; i++) {
506
- buffered = [...buffered, {
528
+ buffered = [
529
+ ...buffered,
530
+ {
507
531
  // for a stream with sliding window dvr something that is buffered my slide off the start of the timeline
508
- start: Math.max(0, this.el.buffered.start(i) - this._playableRegionStartTime),
509
- end: Math.max(0, this.el.buffered.end(i) - this._playableRegionStartTime)
510
- }];
511
- if (this.el.currentTime >= buffered[i].start && this.el.currentTime <= buffered[i].end) {
532
+ start: Math.max(0, this.el.buffered.start(i) -
533
+ this._playableRegionStartTime),
534
+ end: Math.max(0, this.el.buffered.end(i) -
535
+ this._playableRegionStartTime),
536
+ },
537
+ ];
538
+ if (this.el.currentTime >= buffered[i].start &&
539
+ this.el.currentTime <= buffered[i].end) {
512
540
  bufferedPos = i;
513
541
  }
514
542
  }
515
543
  const progress = {
516
544
  start: buffered[bufferedPos].start,
517
545
  current: buffered[bufferedPos].end,
518
- total: this.getDuration()
546
+ total: this.getDuration(),
519
547
  };
520
548
  this.trigger(Events.PLAYBACK_PROGRESS, progress, buffered);
521
549
  }
@@ -528,7 +556,9 @@ export default class HlsPlayback extends HTML5Video {
528
556
  trace(`${T} play`, { hls: !!this._hls, ...this.options.hlsPlayback });
529
557
  !this._hls && this._setup();
530
558
  assert.ok(this._hls, 'Hls.js instance is not available');
531
- !this._manifestParsed && !this.options.hlsPlayback.preload && this._hls.loadSource(this.options.src);
559
+ !this._manifestParsed &&
560
+ !this.options.hlsPlayback.preload &&
561
+ this._hls.loadSource(this.options.src);
532
562
  super.play();
533
563
  this._startTimeUpdateTimer();
534
564
  }
@@ -536,6 +566,7 @@ export default class HlsPlayback extends HTML5Video {
536
566
  if (!this._hls) {
537
567
  return;
538
568
  }
569
+ ;
539
570
  this.el.pause();
540
571
  if (this.dvrEnabled) {
541
572
  this._updateDvr(true);
@@ -558,7 +589,9 @@ export default class HlsPlayback extends HTML5Video {
558
589
  this._playbackType = (data.details.live ? Playback.LIVE : Playback.VOD);
559
590
  this._onLevelUpdated(evt, data);
560
591
  // Live stream subtitle tracks detection hack (may not immediately available)
561
- if (this._ccTracksUpdated && this._playbackType === Playback.LIVE && this.hasClosedCaptionsTracks) {
592
+ if (this._ccTracksUpdated &&
593
+ this._playbackType === Playback.LIVE &&
594
+ this.hasClosedCaptionsTracks) {
562
595
  this._onSubtitleLoaded();
563
596
  }
564
597
  if (prevPlaybackType !== this._playbackType) {
@@ -590,7 +623,7 @@ export default class HlsPlayback extends HTML5Video {
590
623
  }
591
624
  // #EXT-X-PROGRAM-DATE-TIME
592
625
  if (fragments[0].rawProgramDateTime) {
593
- this._programDateTime = fragments[0].rawProgramDateTime;
626
+ this._programDateTime = Number(fragments[0].rawProgramDateTime);
594
627
  }
595
628
  if (this._playableRegionStartTime !== fragments[0].start) {
596
629
  startTimeChanged = true;
@@ -601,7 +634,7 @@ export default class HlsPlayback extends HTML5Video {
601
634
  // set the correlation to map to middle of the extrapolation window
602
635
  this._localStartTimeCorrelation = {
603
636
  local: this._now,
604
- remote: (fragments[0].start + (this._extrapolatedWindowDuration / 2)) * 1000
637
+ remote: (fragments[0].start + this._extrapolatedWindowDuration / 2) * 1000,
605
638
  };
606
639
  }
607
640
  else {
@@ -616,17 +649,19 @@ export default class HlsPlayback extends HTML5Video {
616
649
  // reset correlation so that it sits at the beginning of the first available chunk
617
650
  this._localStartTimeCorrelation = {
618
651
  local: this._now,
619
- remote: fragments[0].start * 1000
652
+ remote: fragments[0].start * 1000,
620
653
  };
621
654
  }
622
- else if (startTime > previousPlayableRegionStartTime + this._extrapolatedWindowDuration) {
655
+ else if (startTime >
656
+ previousPlayableRegionStartTime + this._extrapolatedWindowDuration) {
623
657
  // start time was past the end of the old extrapolation window (so would have been capped)
624
658
  // see if now that time would be inside the window, and if it would be set the correlation
625
659
  // so that it resumes from the time it was at at the end of the old window
626
660
  // update the correlation so that the time starts counting again from the value it's on now
627
661
  this._localStartTimeCorrelation = {
628
662
  local: this._now,
629
- remote: Math.max(fragments[0].start, previousPlayableRegionStartTime + this._extrapolatedWindowDuration) * 1000
663
+ remote: Math.max(fragments[0].start, previousPlayableRegionStartTime +
664
+ this._extrapolatedWindowDuration) * 1000,
630
665
  };
631
666
  }
632
667
  }
@@ -638,7 +673,8 @@ export default class HlsPlayback extends HTML5Video {
638
673
  if (this._playbackType === Playback.LIVE) {
639
674
  const fragmentTargetDuration = data.details.targetduration;
640
675
  const hlsjsConfig = this.options.playback.hlsjsConfig || {};
641
- const liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount || HLSJS.DefaultConfig.liveSyncDurationCount;
676
+ const liveSyncDurationCount = hlsjsConfig.liveSyncDurationCount ||
677
+ HLSJS.DefaultConfig.liveSyncDurationCount;
642
678
  const hiddenAreaDuration = fragmentTargetDuration * liveSyncDurationCount;
643
679
  if (hiddenAreaDuration <= newDuration) {
644
680
  newDuration -= hiddenAreaDuration;
@@ -662,7 +698,7 @@ export default class HlsPlayback extends HTML5Video {
662
698
  // set the correlation to map to the end
663
699
  this._localEndTimeCorrelation = {
664
700
  local: this._now,
665
- remote: endTime * 1000
701
+ remote: endTime * 1000,
666
702
  };
667
703
  }
668
704
  else {
@@ -674,16 +710,17 @@ export default class HlsPlayback extends HTML5Video {
674
710
  if (extrapolatedEndTime > endTime) {
675
711
  this._localEndTimeCorrelation = {
676
712
  local: this._now,
677
- remote: endTime * 1000
713
+ remote: endTime * 1000,
678
714
  };
679
715
  }
680
- else if (extrapolatedEndTime < endTime - this._extrapolatedWindowDuration) {
716
+ else if (extrapolatedEndTime <
717
+ endTime - this._extrapolatedWindowDuration) {
681
718
  // our extrapolated end time is now earlier than the extrapolation window from the actual end time
682
719
  // (maybe a chunk became available early)
683
720
  // reset correlation so that it sits at the beginning of the extrapolation window from the end time
684
721
  this._localEndTimeCorrelation = {
685
722
  local: this._now,
686
- remote: (endTime - this._extrapolatedWindowDuration) * 1000
723
+ remote: (endTime - this._extrapolatedWindowDuration) * 1000,
687
724
  };
688
725
  }
689
726
  else if (extrapolatedEndTime > previousEndTime) {
@@ -691,7 +728,7 @@ export default class HlsPlayback extends HTML5Video {
691
728
  // set the correlation so that it resumes from the time it was at at the end of the old window
692
729
  this._localEndTimeCorrelation = {
693
730
  local: this._now,
694
- remote: previousEndTime * 1000
731
+ remote: previousEndTime * 1000,
695
732
  };
696
733
  }
697
734
  }
@@ -729,13 +766,14 @@ export default class HlsPlayback extends HTML5Video {
729
766
  const currentLevel = this._hls.levels[data.level];
730
767
  if (currentLevel) {
731
768
  // TODO should highDefinition be private and maybe have a read only accessor if it's used somewhere
732
- this.highDefinition = (currentLevel.height >= 720 || (currentLevel.bitrate / 1000) >= 2000);
769
+ this.highDefinition =
770
+ currentLevel.height >= 720 || currentLevel.bitrate / 1000 >= 2000;
733
771
  this.trigger(Events.PLAYBACK_HIGHDEFINITIONUPDATE, this.highDefinition);
734
772
  this.trigger(Events.PLAYBACK_BITRATE, {
735
773
  height: currentLevel.height,
736
774
  width: currentLevel.width,
737
775
  bitrate: currentLevel.bitrate,
738
- level: data.level
776
+ level: data.level,
739
777
  });
740
778
  }
741
779
  }
@@ -744,21 +782,34 @@ export default class HlsPlayback extends HTML5Video {
744
782
  // - the duration does not include content after hlsjs's live sync point
745
783
  // - the playable region duration is longer than the configured duration to enable dvr after
746
784
  // - the playback type is LIVE.
747
- return (this._durationExcludesAfterLiveSyncPoint && this._duration >= this._minDvrSize && this.getPlaybackType() === Playback.LIVE);
785
+ return (this._durationExcludesAfterLiveSyncPoint &&
786
+ this._duration >= this._minDvrSize &&
787
+ this.getPlaybackType() === Playback.LIVE);
748
788
  }
749
789
  getPlaybackType() {
750
790
  return this._playbackType;
751
791
  }
752
792
  isSeekEnabled() {
753
- return (this._playbackType === Playback.VOD || this.dvrEnabled);
793
+ return this._playbackType === Playback.VOD || this.dvrEnabled;
794
+ }
795
+ triggerError(error) {
796
+ trace(`${T} triggerError`, { error });
797
+ this.trigger(Events.PLAYBACK_ERROR, error);
798
+ this.stop();
754
799
  }
755
800
  }
756
801
  HlsPlayback.canPlay = function (resource, mimeType) {
757
802
  const resourceParts = resource.split('?')[0].match(/.*\.(.*)$/) || [];
758
- const isHls = ((resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8') || listContainsIgnoreCase(mimeType, ['application/vnd.apple.mpegurl', 'application/x-mpegURL']));
803
+ const isHls = (resourceParts.length > 1 && resourceParts[1].toLowerCase() === 'm3u8') ||
804
+ listContainsIgnoreCase(mimeType, [
805
+ 'application/vnd.apple.mpegurl',
806
+ 'application/x-mpegURL',
807
+ ]);
759
808
  const hasSupport = HLSJS.isSupported();
760
809
  trace(`${T} canPlay`, {
761
- hasSupport, isHls, resource,
810
+ hasSupport,
811
+ isHls,
812
+ resource,
762
813
  });
763
814
  return !!(hasSupport && isHls);
764
815
  };
package/lib/types.d.ts CHANGED
@@ -38,7 +38,7 @@ export type PlaybackType = 'live' | 'vod';
38
38
  /**
39
39
  * @beta
40
40
  */
41
- export type MediaTransport = 'dash' | 'hls' | 'mpegts';
41
+ export type MediaTransport = 'dash' | 'hls';
42
42
  /**
43
43
  * @beta
44
44
  */
@@ -49,7 +49,7 @@ export type TransportPreference = MediaTransport | 'auto';
49
49
  */
50
50
  export type PlayerPlugin = {
51
51
  new (...args: any[]): unknown;
52
- type: 'core' | 'container';
52
+ name: string;
53
53
  };
54
54
  /**
55
55
  * Configuration options for the player
@@ -143,7 +143,7 @@ export interface PlayerConfig extends Record<string, unknown> {
143
143
  /**
144
144
  * Localization strings for the player UI.
145
145
  */
146
- strings: TranslationSettings;
146
+ strings?: TranslationSettings;
147
147
  }
148
148
  /**
149
149
  * @beta
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,qBAAqB,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;AAEvE;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,OAAO,CAAA;AAE1D;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAA;AAEzC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAA;AAEtD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,MAAM,CAAA;AAEzD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;IAC7B,IAAI,EAAE,MAAM,GAAG,WAAW,CAAA;CAC3B,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,WAAW,YAAa,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;OAIG;IACH,IAAI,CAAC,EAAE,YAAY,CAAA;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,mBAAmB,CAAA;IAE3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAE3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,mBAAmB,CAAA;IAEvC;;OAEG;IACH,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAE5B;;OAEG;IACH,OAAO,EAAE,mBAAmB,CAAA;CAC7B;AAED;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAA;AAE5B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAA;AAEnC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAElD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACvC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAChD,CAAA;AAED;;;GAGG;AACH,oBAAY,WAAW;IACrB;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,KAAK,UAAU;CAChB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,qBAAqB,CAAA;AAE9D;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;AAEvE;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,OAAO,CAAA;AAE1D;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,KAAK,CAAA;AAEzC;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAA;AAE3C;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,MAAM,CAAA;AAEzD;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAA;IAC7B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,MAAM,WAAW,YAAa,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC3D;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;OAIG;IACH,IAAI,CAAC,EAAE,YAAY,CAAA;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,mBAAmB,CAAA;IAE3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IAEd;;;;OAIG;IACH,YAAY,CAAC,EAAE,YAAY,CAAA;IAE3B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,mBAAmB,CAAA;IAEvC;;OAEG;IACH,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAE5B;;OAEG;IACH,OAAO,CAAC,EAAE,mBAAmB,CAAA;CAC9B;AAED;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG,MAAM,CAAA;AAE5B;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAA;AAEnC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAElD;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,CACvC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC,CAChD,CAAA;AAED;;;GAGG;AACH,oBAAY,WAAW;IACrB;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,KAAK,UAAU;IACf;;OAEG;IACH,IAAI,SAAS;IACb;;OAEG;IACH,KAAK,UAAU;CAChB"}
@@ -1,11 +1,19 @@
1
- import type { PlayerMediaSource, TransportPreference } from '../types';
1
+ import type { PlayerMediaSource, PlayerMediaSourceDesc, TransportPreference } from '../types';
2
2
  export type SourceVariants = {
3
- dash: string | null;
4
- master: string | null;
5
- hls: string | null;
6
- mpegts: string | null;
3
+ dash: PlayerMediaSourceDesc | null;
4
+ hls: PlayerMediaSourceDesc | null;
5
+ mpegts: PlayerMediaSourceDesc | null;
7
6
  };
7
+ /**
8
+ *
9
+ * @param sources
10
+ * @deprecated
11
+ * @returns
12
+ */
8
13
  export declare function buildSourcesSet(sources: PlayerMediaSource[]): SourceVariants;
9
- export declare function buildSourcesPriorityList(sources: SourceVariants, priorityTransport?: TransportPreference): PlayerMediaSource[];
14
+ export declare function buildMediaSourcesList(sources: PlayerMediaSourceDesc[], priorityTransport?: TransportPreference): PlayerMediaSourceDesc[];
10
15
  export declare function unwrapSource(s: PlayerMediaSource): string;
16
+ export declare function wrapSource(s: PlayerMediaSource): PlayerMediaSourceDesc;
17
+ export declare function isDashSource(source: string, mimeType?: string): boolean;
18
+ export declare function isHlsSource(source: string, mimeType?: string): boolean;
11
19
  //# sourceMappingURL=mediaSources.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mediaSources.d.ts","sourceRoot":"","sources":["../../src/utils/mediaSources.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEtE,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB,CAAA;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,cAAc,CAkB5E;AAED,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,cAAc,EACvB,iBAAiB,GAAE,mBAA4B,GAC9C,iBAAiB,EAAE,CAmDrB;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAEzD"}
1
+ {"version":3,"file":"mediaSources.d.ts","sourceRoot":"","sources":["../../src/utils/mediaSources.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,qBAAqB,EACrB,mBAAmB,EACpB,MAAM,UAAU,CAAA;AAGjB,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,qBAAqB,GAAG,IAAI,CAAA;IAClC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CAAA;IACjC,MAAM,EAAE,qBAAqB,GAAG,IAAI,CAAA;CACrC,CAAA;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,iBAAiB,EAAE,GAAG,cAAc,CAiB5E;AAED,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,qBAAqB,EAAE,EAChC,iBAAiB,GAAE,mBAA4B,GAC9C,qBAAqB,EAAE,CA4BzB;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAEzD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,iBAAiB,GAAG,qBAAqB,CAEtE;AAYD,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,WAK7D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,WAO5D"}