@gcorevideo/player 2.19.15 → 2.20.1

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 (131) hide show
  1. package/assets/level-selector/list.ejs +1 -1
  2. package/dist/core.js +2 -2
  3. package/dist/index.css +1634 -1634
  4. package/dist/index.js +585 -416
  5. package/dist/player.d.ts +268 -72
  6. package/dist/plugins/index.css +1567 -1567
  7. package/dist/plugins/index.js +526 -357
  8. package/docs/api/player.clapprnerdstats.md +12 -259
  9. package/docs/api/player.dvrcontrols.md +5 -1
  10. package/docs/api/player.errorscreen.attributes.md +3 -0
  11. package/docs/api/player.errorscreen.bindevents.md +3 -0
  12. package/docs/api/player.errorscreen.container.md +3 -0
  13. package/docs/api/player.errorscreen.hide.md +3 -0
  14. package/docs/api/player.errorscreen.md +27 -0
  15. package/docs/api/player.errorscreen.name.md +3 -0
  16. package/docs/api/player.errorscreen.render.md +3 -0
  17. package/docs/api/player.errorscreen.show.md +3 -0
  18. package/docs/api/player.errorscreen.supportedversion.md +3 -0
  19. package/docs/api/player.errorscreen.template.md +3 -0
  20. package/docs/api/player.errorscreen.unbindevents.md +3 -0
  21. package/docs/api/{player.playbackrate.template.md → player.initeventdata.event.md} +3 -3
  22. package/docs/api/{player.playbackrate.updateplaybackrate.md → player.initeventdata.md} +15 -11
  23. package/docs/api/player.md +88 -5
  24. package/docs/api/player.pictureinpicture.md +9 -197
  25. package/docs/api/player.playbackrate.md +10 -314
  26. package/docs/api/{player.playbackrate.onplay.md → player.stalleventdata.count.md} +5 -7
  27. package/docs/api/{player.playbackrate.name.md → player.stalleventdata.event.md} +3 -3
  28. package/docs/api/player.stalleventdata.md +112 -0
  29. package/docs/api/player.stalleventdata.time.md +13 -0
  30. package/docs/api/player.stalleventdata.total_ms.md +13 -0
  31. package/docs/api/{player.pluginsettings.md → player.starteventdata.event.md} +3 -5
  32. package/docs/api/{player.playbackrate.onrateselect.md → player.starteventdata.md} +15 -11
  33. package/docs/api/{player.statistics._constructor_.md → player.telemetry._constructor_.md} +6 -3
  34. package/docs/api/player.telemetry.md +146 -0
  35. package/docs/api/{player.volumefade.name.md → player.telemetry.name.md} +4 -2
  36. package/docs/api/{player.clapprnerdstats.supportedversion.md → player.telemetry.supportedversion.md} +4 -2
  37. package/docs/api/player.telemetryevent.md +89 -0
  38. package/docs/api/player.telemetryeventdata.md +15 -0
  39. package/docs/api/player.telemetrypluginsettings.md +57 -0
  40. package/docs/api/player.telemetrypluginsettings.send.md +13 -0
  41. package/docs/api/player.telemetryrecord.md +17 -0
  42. package/docs/api/player.volumefade.md +0 -93
  43. package/docs/api/{player.pictureinpicture.name.md → player.watcheventdata.event.md} +3 -3
  44. package/docs/api/{player.playbackrate.setselectedrate.md → player.watcheventdata.md} +15 -11
  45. package/lib/index.plugins.d.ts +2 -2
  46. package/lib/index.plugins.d.ts.map +1 -1
  47. package/lib/index.plugins.js +2 -2
  48. package/lib/playback/hls-playback/HlsPlayback.js +1 -1
  49. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +38 -5
  50. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
  51. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +63 -17
  52. package/lib/plugins/dvr-controls/DvrControls.d.ts +5 -2
  53. package/lib/plugins/dvr-controls/DvrControls.d.ts.map +1 -1
  54. package/lib/plugins/dvr-controls/DvrControls.js +5 -2
  55. package/lib/plugins/error-screen/ErrorScreen.d.ts +5 -0
  56. package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -1
  57. package/lib/plugins/error-screen/ErrorScreen.js +5 -0
  58. package/lib/plugins/index.d.ts +2 -3
  59. package/lib/plugins/index.d.ts.map +1 -1
  60. package/lib/plugins/index.js +2 -3
  61. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts +32 -4
  62. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  63. package/lib/plugins/picture-in-picture/PictureInPicture.js +30 -2
  64. package/lib/plugins/playback-rate/PlaybackRate.d.ts +47 -14
  65. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  66. package/lib/plugins/playback-rate/PlaybackRate.js +38 -9
  67. package/lib/plugins/statistics/Statistics.d.ts +38 -3
  68. package/lib/plugins/statistics/Statistics.d.ts.map +1 -1
  69. package/lib/plugins/statistics/Statistics.js +51 -9
  70. package/lib/plugins/telemetry/Telemetry.d.ts +135 -0
  71. package/lib/plugins/telemetry/Telemetry.d.ts.map +1 -0
  72. package/lib/plugins/telemetry/Telemetry.js +180 -0
  73. package/lib/plugins/volume-fade/VolumeFade.d.ts +7 -1
  74. package/lib/plugins/volume-fade/VolumeFade.d.ts.map +1 -1
  75. package/lib/plugins/volume-fade/VolumeFade.js +8 -1
  76. package/package.json +1 -1
  77. package/src/index.plugins.ts +2 -2
  78. package/src/playback/hls-playback/HlsPlayback.ts +1 -1
  79. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +240 -173
  80. package/src/plugins/dvr-controls/DvrControls.ts +5 -2
  81. package/src/plugins/error-screen/ErrorScreen.ts +5 -0
  82. package/src/plugins/index.ts +2 -3
  83. package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +47 -26
  84. package/src/plugins/level-selector/__tests__/__snapshots__/LevelSelector.test.ts.snap +18 -18
  85. package/src/plugins/picture-in-picture/PictureInPicture.ts +35 -7
  86. package/src/plugins/playback-rate/PlaybackRate.ts +53 -24
  87. package/src/plugins/telemetry/Telemetry.ts +299 -0
  88. package/src/plugins/volume-fade/VolumeFade.ts +9 -2
  89. package/temp/player.api.json +2322 -3281
  90. package/tsconfig.tsbuildinfo +1 -1
  91. package/docs/api/player.clapprnerdstats.attributes.md +0 -17
  92. package/docs/api/player.clapprnerdstats.bindevents.md +0 -18
  93. package/docs/api/player.clapprnerdstats.events.md +0 -18
  94. package/docs/api/player.clapprnerdstats.name.md +0 -14
  95. package/docs/api/player.clapprnerdstats.playerheight.md +0 -14
  96. package/docs/api/player.clapprnerdstats.playerwidth.md +0 -14
  97. package/docs/api/player.clapprnerdstats.render.md +0 -18
  98. package/docs/api/player.clapprnerdstats.statsboxelem.md +0 -14
  99. package/docs/api/player.clapprnerdstats.statsboxwidththreshold.md +0 -14
  100. package/docs/api/player.clapprnerdstats.template.md +0 -14
  101. package/docs/api/player.pictureinpicture.bindevents.md +0 -15
  102. package/docs/api/player.pictureinpicture.events.md +0 -13
  103. package/docs/api/player.pictureinpicture.exitpictureinpicture.md +0 -15
  104. package/docs/api/player.pictureinpicture.render.md +0 -15
  105. package/docs/api/player.pictureinpicture.requestpictureinpicture.md +0 -15
  106. package/docs/api/player.pictureinpicture.supportedversion.md +0 -13
  107. package/docs/api/player.pictureinpicture.togglepictureinpicture.md +0 -15
  108. package/docs/api/player.pictureinpicture.version.md +0 -11
  109. package/docs/api/player.pictureinpicture.videoelement.md +0 -11
  110. package/docs/api/player.playbackrate.attributes.md +0 -14
  111. package/docs/api/player.playbackrate.bindevents.md +0 -15
  112. package/docs/api/player.playbackrate.events.md +0 -15
  113. package/docs/api/player.playbackrate.gettitle.md +0 -15
  114. package/docs/api/player.playbackrate.goback.md +0 -15
  115. package/docs/api/player.playbackrate.highlightcurrentrate.md +0 -15
  116. package/docs/api/player.playbackrate.onfinishad.md +0 -15
  117. package/docs/api/player.playbackrate.onshowmenu.md +0 -15
  118. package/docs/api/player.playbackrate.onstartad.md +0 -15
  119. package/docs/api/player.playbackrate.onstop.md +0 -15
  120. package/docs/api/player.playbackrate.reload.md +0 -15
  121. package/docs/api/player.playbackrate.render.md +0 -15
  122. package/docs/api/player.playbackrate.supportedversion.md +0 -13
  123. package/docs/api/player.playbackrate.unbindevents.md +0 -15
  124. package/docs/api/player.statistics.bindevents.md +0 -15
  125. package/docs/api/player.statistics.md +0 -141
  126. package/docs/api/player.statistics.name.md +0 -11
  127. package/docs/api/player.statistics.supportedversion.md +0 -13
  128. package/docs/api/player.volumefade.bindevents.md +0 -18
  129. package/docs/api/player.volumefade.unbindevents.md +0 -18
  130. package/src/plugins/statistics/Statistics.ts +0 -207
  131. /package/src/plugins/{statistics → telemetry}/Statistics copy.xts +0 -0
package/dist/index.js CHANGED
@@ -12459,7 +12459,7 @@ var PlaybackErrorCode;
12459
12459
  // license that can be found in the LICENSE file.
12460
12460
  const AUTO$2 = -1;
12461
12461
  const { now: now$2 } = Utils;
12462
- const T$e = 'playback.dash';
12462
+ const T$f = 'playback.dash';
12463
12463
  // @ts-expect-error
12464
12464
  class DashPlayback extends HTML5Video {
12465
12465
  _levels = null;
@@ -12729,10 +12729,10 @@ class DashPlayback extends HTML5Video {
12729
12729
  }
12730
12730
  _onPlaybackError = (event) => {
12731
12731
  // TODO
12732
- trace(`${T$e} _onPlaybackError`, { event });
12732
+ trace(`${T$f} _onPlaybackError`, { event });
12733
12733
  };
12734
12734
  _onDASHJSSError = (event) => {
12735
- trace(`${T$e} _onDASHJSSError`, { event });
12735
+ trace(`${T$f} _onDASHJSSError`, { event });
12736
12736
  this._stopTimeUpdateTimer();
12737
12737
  // Note that the other error types are deprecated
12738
12738
  const e = event.error;
@@ -12767,7 +12767,7 @@ class DashPlayback extends HTML5Video {
12767
12767
  }
12768
12768
  };
12769
12769
  triggerError(error) {
12770
- trace(`${T$e} triggerError`, { error });
12770
+ trace(`${T$f} triggerError`, { error });
12771
12771
  this.trigger(Events$1.PLAYBACK_ERROR, {
12772
12772
  ...error,
12773
12773
  origin: this.name,
@@ -12807,7 +12807,7 @@ class DashPlayback extends HTML5Video {
12807
12807
  }
12808
12808
  get dvrEnabled() {
12809
12809
  if (!this._dash) {
12810
- trace(`${T$e} dvrEnable no dash player instance`);
12810
+ trace(`${T$f} dvrEnable no dash player instance`);
12811
12811
  return false;
12812
12812
  }
12813
12813
  return (this._dash?.getDVRWindowSize() >= this._minDvrSize &&
@@ -12829,7 +12829,7 @@ class DashPlayback extends HTML5Video {
12829
12829
  this.trigger(Events$1.PLAYBACK_PROGRESS, progress, {});
12830
12830
  }
12831
12831
  play() {
12832
- trace(`${T$e} play`, { dash: !!this._dash });
12832
+ trace(`${T$f} play`, { dash: !!this._dash });
12833
12833
  if (!this._dash) {
12834
12834
  this._setup();
12835
12835
  }
@@ -41576,7 +41576,7 @@ const AUTO$1 = -1;
41576
41576
  const DEFAULT_RECOVER_ATTEMPTS = 16;
41577
41577
  Events$1.register('PLAYBACK_FRAGMENT_CHANGED');
41578
41578
  Events$1.register('PLAYBACK_FRAGMENT_PARSING_METADATA');
41579
- const T$d = 'playback.hls';
41579
+ const T$e = 'playback.hls';
41580
41580
  // @ts-expect-error
41581
41581
  class HlsPlayback extends HTML5Video {
41582
41582
  _ccIsSetup = false;
@@ -41806,7 +41806,7 @@ class HlsPlayback extends HTML5Video {
41806
41806
  maxBufferLength: 2,
41807
41807
  maxMaxBufferLength: 4,
41808
41808
  }, this.options.playback.hlsjsConfig);
41809
- trace(`${T$d} _createHLSInstance`, { config });
41809
+ trace(`${T$e} _createHLSInstance`, { config });
41810
41810
  this._hls = new Hls(config);
41811
41811
  }
41812
41812
  _attachHLSMedia() {
@@ -41895,7 +41895,7 @@ class HlsPlayback extends HTML5Video {
41895
41895
  }
41896
41896
  else {
41897
41897
  Log.error('hlsjs: failed to recover', { evt, data });
41898
- trace(`${T$d} _recover failed to recover`, {
41898
+ trace(`${T$e} _recover failed to recover`, {
41899
41899
  type: data.type,
41900
41900
  details: data.details,
41901
41901
  });
@@ -41981,7 +41981,7 @@ class HlsPlayback extends HTML5Video {
41981
41981
  this.trigger(Events$1.PLAYBACK_SETTINGSUPDATE);
41982
41982
  }
41983
41983
  _onHLSJSError(evt, data) {
41984
- trace(`${T$d} _onHLSJSError`, {
41984
+ trace(`${T$e} _onHLSJSError`, {
41985
41985
  fatal: data.fatal,
41986
41986
  type: data.type,
41987
41987
  details: data.details,
@@ -42029,7 +42029,7 @@ class HlsPlayback extends HTML5Video {
42029
42029
  evt,
42030
42030
  data,
42031
42031
  });
42032
- trace(`${T$d} _onHLSJSError trying to recover from network error`, {
42032
+ trace(`${T$e} _onHLSJSError trying to recover from network error`, {
42033
42033
  details: data.details,
42034
42034
  });
42035
42035
  error.level = PlayerError.Levels.WARN;
@@ -42042,7 +42042,7 @@ class HlsPlayback extends HTML5Video {
42042
42042
  evt,
42043
42043
  data,
42044
42044
  });
42045
- trace(`${T$d} _onHLSJSError trying to recover from media error`, {
42045
+ trace(`${T$e} _onHLSJSError trying to recover from media error`, {
42046
42046
  details: data.details,
42047
42047
  });
42048
42048
  error.level = PlayerError.Levels.WARN;
@@ -42072,7 +42072,7 @@ class HlsPlayback extends HTML5Video {
42072
42072
  return;
42073
42073
  }
42074
42074
  Log.warn('hlsjs: non-fatal error occurred', { evt, data });
42075
- trace(`${T$d} _onHLSJSError non-fatal error occurred`, {
42075
+ trace(`${T$e} _onHLSJSError non-fatal error occurred`, {
42076
42076
  type: data.type,
42077
42077
  details: data.details,
42078
42078
  });
@@ -42144,9 +42144,9 @@ class HlsPlayback extends HTML5Video {
42144
42144
  }
42145
42145
  play() {
42146
42146
  !this._hls && this._setup();
42147
- assert.ok(this._hls, 'Hls.js instance is not available');
42148
42147
  !this._manifestParsed &&
42149
42148
  !this.options.hlsPlayback.preload &&
42149
+ // @ts-expect-error
42150
42150
  this._hls.loadSource(this.options.src);
42151
42151
  super.play();
42152
42152
  this._startTimeUpdateTimer();
@@ -42400,7 +42400,7 @@ function registerPlaybacks() {
42400
42400
  Loader.registerPlayback(DashPlayback);
42401
42401
  }
42402
42402
 
42403
- const T$c = 'GPlayer';
42403
+ const T$d = 'GPlayer';
42404
42404
  const DEFAULT_OPTIONS = {
42405
42405
  autoPlay: false,
42406
42406
  debug: 'none',
@@ -42495,7 +42495,7 @@ class Player {
42495
42495
  }
42496
42496
  const coreOpts = this.buildCoreOptions(playerElement);
42497
42497
  const { core, container } = Loader.registeredPlugins;
42498
- trace(`${T$c} init`, {
42498
+ trace(`${T$d} init`, {
42499
42499
  registeredPlaybacks: Loader.registeredPlaybacks.map((p) => p.name),
42500
42500
  });
42501
42501
  coreOpts.plugins = {
@@ -42509,7 +42509,7 @@ class Player {
42509
42509
  * Destroys the player, releasing all resources and unmounting its UI from the DOM.
42510
42510
  */
42511
42511
  destroy() {
42512
- trace(`${T$c} destroy`, {
42512
+ trace(`${T$d} destroy`, {
42513
42513
  player: !!this.player,
42514
42514
  });
42515
42515
  if (this.player) {
@@ -42669,7 +42669,7 @@ class Player {
42669
42669
  this.config = $.extend(true, this.config, config);
42670
42670
  }
42671
42671
  initPlayer(coreOptions) {
42672
- trace(`${T$c} initPlayer`, {
42672
+ trace(`${T$d} initPlayer`, {
42673
42673
  autoPlay: coreOptions.autoPlay,
42674
42674
  sources: coreOptions.sources,
42675
42675
  // TODO selected options
@@ -42694,7 +42694,7 @@ class Player {
42694
42694
  }
42695
42695
  }
42696
42696
  triggerAutoPlay() {
42697
- trace(`${T$c} triggerAutoPlay`);
42697
+ trace(`${T$d} triggerAutoPlay`);
42698
42698
  setTimeout(() => {
42699
42699
  this.player?.play({
42700
42700
  autoPlay: true,
@@ -42712,7 +42712,7 @@ class Player {
42712
42712
  // TODO test
42713
42713
  events = {
42714
42714
  onReady: () => {
42715
- trace(`${T$c} onReady`, {
42715
+ trace(`${T$d} onReady`, {
42716
42716
  ready: this.ready,
42717
42717
  });
42718
42718
  if (this.ready) {
@@ -42746,7 +42746,7 @@ class Player {
42746
42746
  buildCoreOptions(rootNode) {
42747
42747
  const sources = this.buildMediaSourcesList();
42748
42748
  const source = sources[0];
42749
- trace(`${T$c} buildCoreOptions`, {
42749
+ trace(`${T$d} buildCoreOptions`, {
42750
42750
  source,
42751
42751
  sources,
42752
42752
  });
@@ -42805,7 +42805,7 @@ class Player {
42805
42805
  bindCoreListeners() {
42806
42806
  const core = this.player?.core;
42807
42807
  core?.on(Events$1.CORE_SCREEN_ORIENTATION_CHANGED, ({ orientation }) => {
42808
- trace(`${T$c} on CORE_SCREEN_ORIENTATION_CHANGED`, {
42808
+ trace(`${T$d} on CORE_SCREEN_ORIENTATION_CHANGED`, {
42809
42809
  orientation,
42810
42810
  rootNode: {
42811
42811
  width: this.rootNode?.clientWidth,
@@ -42820,14 +42820,14 @@ class Player {
42820
42820
  }
42821
42821
  }, null);
42822
42822
  core?.on(Events$1.CORE_RESIZE, ({ width, height }) => {
42823
- trace(`${T$c} on CORE_RESIZE`, {
42823
+ trace(`${T$d} on CORE_RESIZE`, {
42824
42824
  width,
42825
42825
  height,
42826
42826
  });
42827
42827
  this.safeTriggerEvent(PlayerEvent.Resize, { width, height });
42828
42828
  }, null);
42829
42829
  core?.on(Events$1.CORE_FULLSCREEN, (isFullscreen) => {
42830
- trace(`${T$c} CORE_FULLSCREEN`, {
42830
+ trace(`${T$d} CORE_FULLSCREEN`, {
42831
42831
  isFullscreen,
42832
42832
  });
42833
42833
  this.safeTriggerEvent(PlayerEvent.Fullscreen, isFullscreen);
@@ -42835,7 +42835,7 @@ class Player {
42835
42835
  }
42836
42836
  }
42837
42837
 
42838
- var version$1 = "2.19.15";
42838
+ var version$1 = "2.20.1";
42839
42839
 
42840
42840
  var packages = {
42841
42841
  "node_modules/@clappr/core": {
@@ -43141,7 +43141,7 @@ const volumeOffIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fil
43141
43141
 
43142
43142
  const pluginHtml$7 = "<div class=\"big-mute-icon-wrapper\" data-big-mute>\n <div class=\"big-mute-icon gcore-skin-border-color\" data-big-mute-icon></div>\n</div>\n";
43143
43143
 
43144
- const T$b = "plugins.big_mute_button";
43144
+ const T$c = "plugins.big_mute_button";
43145
43145
  /**
43146
43146
  * @beta
43147
43147
  */
@@ -43170,7 +43170,7 @@ class BigMuteButton extends UICorePlugin {
43170
43170
  this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
43171
43171
  this.listenTo(this.core, 'core:advertisement:start', this.onStartAd);
43172
43172
  this.listenTo(this.core, 'core:advertisement:finish', this.onFinishAd);
43173
- trace(`${T$b} bindEvents`, {
43173
+ trace(`${T$c} bindEvents`, {
43174
43174
  mediacontrol: !!this.core.mediaControl,
43175
43175
  });
43176
43176
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED, this.mediaControlRendered);
@@ -43206,12 +43206,12 @@ class BigMuteButton extends UICorePlugin {
43206
43206
  }
43207
43207
  mediaControlRendered() {
43208
43208
  const container = this.core.activeContainer;
43209
- trace(`${T$b} mediaControlRendered`, {
43209
+ trace(`${T$c} mediaControlRendered`, {
43210
43210
  container: !!container,
43211
43211
  });
43212
43212
  if (container) {
43213
43213
  this.listenTo(container.playback, Events$1.PLAYBACK_PLAY, () => {
43214
- trace(`${T$b} PLAYBACK_PLAY`);
43214
+ trace(`${T$c} PLAYBACK_PLAY`);
43215
43215
  this.render();
43216
43216
  });
43217
43217
  }
@@ -43235,7 +43235,7 @@ class BigMuteButton extends UICorePlugin {
43235
43235
  }
43236
43236
  const { autoPlay, wasMuted } = this.options;
43237
43237
  const volume = container.volume;
43238
- trace(`${T$b} shouldRender`, {
43238
+ trace(`${T$c} shouldRender`, {
43239
43239
  autoPlay,
43240
43240
  wasMuted,
43241
43241
  volume,
@@ -43244,7 +43244,7 @@ class BigMuteButton extends UICorePlugin {
43244
43244
  }
43245
43245
  render() {
43246
43246
  if (this.shouldRender()) {
43247
- trace(`${T$b} render`, {
43247
+ trace(`${T$c} render`, {
43248
43248
  el: !!this.$el,
43249
43249
  });
43250
43250
  this.$el.html(this.template());
@@ -43290,7 +43290,7 @@ const gearIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"n
43290
43290
  const gearHdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_28_1567)\">\n <path\n d=\"M19.14 12.94C19.18 12.64 19.2 12.33 19.2 12C19.2 11.68 19.18 11.36 19.13 11.06L21.16 9.47999C21.34 9.33999 21.39 9.06999 21.28 8.86999L19.36 5.54999C19.24 5.32999 18.99 5.25999 18.77 5.32999L16.38 6.28999C15.88 5.90999 15.35 5.58999 14.76 5.34999L14.4 2.80999C14.36 2.56999 14.16 2.39999 13.92 2.39999H10.08C9.83999 2.39999 9.64999 2.56999 9.60999 2.80999L9.24999 5.34999C8.65999 5.58999 8.11999 5.91999 7.62999 6.28999L5.23999 5.32999C5.01999 5.24999 4.76999 5.32999 4.64999 5.54999L2.73999 8.86999C2.61999 9.07999 2.65999 9.33999 2.85999 9.47999L4.88999 11.06C4.83999 11.36 4.79999 11.69 4.79999 12C4.79999 12.31 4.81999 12.64 4.86999 12.94L2.83999 14.52C2.65999 14.66 2.60999 14.93 2.71999 15.13L4.63999 18.45C4.75999 18.67 5.00999 18.74 5.22999 18.67L7.61999 17.71C8.11999 18.09 8.64999 18.41 9.23999 18.65L9.59999 21.19C9.64999 21.43 9.83999 21.6 10.08 21.6H13.92C14.16 21.6 14.36 21.43 14.39 21.19L14.75 18.65C15.34 18.41 15.88 18.09 16.37 17.71L18.76 18.67C18.98 18.75 19.23 18.67 19.35 18.45L21.27 15.13C21.39 14.91 21.34 14.66 21.15 14.52L19.14 12.94ZM12 15.6C10.02 15.6 8.39999 13.98 8.39999 12C8.39999 10.02 10.02 8.39999 12 8.39999C13.98 8.39999 15.6 10.02 15.6 12C15.6 13.98 13.98 15.6 12 15.6Z\"\n fill=\"#C9C9C9\"/>\n <rect x=\"13\" width=\"11\" height=\"7\" rx=\"1\" fill=\"#F6413B\"/>\n <path\n d=\"M14.6962 6V1.63636H15.3546V3.53267H17.53V1.63636H18.1905V6H17.53V4.0973H15.3546V6H14.6962ZM20.562 6H19.1493V1.63636H20.6067C21.0343 1.63636 21.4015 1.72372 21.7083 1.89844C22.0151 2.07173 22.2502 2.32102 22.4135 2.64631C22.5783 2.97017 22.6607 3.35866 22.6607 3.81179C22.6607 4.26634 22.5776 4.65696 22.4114 4.98366C22.2466 5.31037 22.008 5.56179 21.6955 5.73793C21.383 5.91264 21.0051 6 20.562 6ZM19.8077 5.42472H20.5257C20.8581 5.42472 21.1344 5.36222 21.3546 5.23722C21.5748 5.1108 21.7395 4.92827 21.8489 4.68963C21.9583 4.44957 22.013 4.15696 22.013 3.81179C22.013 3.46946 21.9583 3.17898 21.8489 2.94034C21.7409 2.7017 21.5797 2.5206 21.3652 2.39702C21.1507 2.27344 20.8844 2.21165 20.5662 2.21165H19.8077V5.42472Z\"\n fill=\"#C9C9C9\"/>\n </g>\n <defs>\n <clipPath id=\"clip0_28_1567\">\n <rect width=\"24\" height=\"24\" fill=\"white\"/>\n </clipPath>\n </defs>\n</svg>\n";
43291
43291
 
43292
43292
  const VERSION$5 = '2.19.12';
43293
- const T$a = 'plugins.bottom_gear';
43293
+ const T$b = 'plugins.bottom_gear';
43294
43294
  /**
43295
43295
  * Custom events emitted by the plugin
43296
43296
  */
@@ -43375,11 +43375,11 @@ class BottomGear extends UICorePlugin {
43375
43375
  this.$el.find('.gear-wrapper').html(content);
43376
43376
  }
43377
43377
  onActiveContainerChanged() {
43378
- trace(`${T$a} onActiveContainerChanged`);
43378
+ trace(`${T$b} onActiveContainerChanged`);
43379
43379
  this.bindContainerEvents();
43380
43380
  }
43381
43381
  bindContainerEvents() {
43382
- trace(`${T$a} bindContainerEvents`);
43382
+ trace(`${T$b} bindContainerEvents`);
43383
43383
  this.listenTo(this.core.activeContainer, Events$1.CONTAINER_HIGHDEFINITIONUPDATE, this.highDefinitionUpdate);
43384
43384
  }
43385
43385
  highDefinitionUpdate(isHd) {
@@ -45499,7 +45499,7 @@ const qualityClasses = [
45499
45499
  'speedtest-quality-value-2',
45500
45500
  'speedtest-quality-value-3',
45501
45501
  'speedtest-quality-value-4',
45502
- 'speedtest-quality-value-5'
45502
+ 'speedtest-quality-value-5',
45503
45503
  ];
45504
45504
  const getDownloadQuality = (speedValue) => {
45505
45505
  if (speedValue < 3) {
@@ -45563,7 +45563,22 @@ const drawSummary = (customMetrics, vodContainer, liveContainer) => {
45563
45563
  };
45564
45564
  // const T = 'plugins.clappr_nerd_stats';
45565
45565
  /**
45566
+ * Displays useful network-related statistics.
45566
45567
  * @beta
45568
+ *
45569
+ * @remarks
45570
+ * Depends on:
45571
+ *
45572
+ * - {@link MediaControl}
45573
+ *
45574
+ * - {@link BottomGear}
45575
+ *
45576
+ * - {@link ClapprStats}
45577
+ *
45578
+ * The plugin is rendered as an item in the gear menu.
45579
+ *
45580
+ * When clicked, it shows an overlay window with the information about the network speed, latency, etc,
45581
+ * and recommended quality level.
45567
45582
  */
45568
45583
  class ClapprNerdStats extends UICorePlugin {
45569
45584
  container = null;
@@ -45576,21 +45591,31 @@ class ClapprNerdStats extends UICorePlugin {
45576
45591
  showing = false;
45577
45592
  shortcut;
45578
45593
  iconPosition;
45594
+ /**
45595
+ * @internal
45596
+ */
45579
45597
  get name() {
45580
45598
  return 'nerd_stats';
45581
45599
  }
45600
+ /**
45601
+ * @internal
45602
+ */
45582
45603
  get supportedVersion() {
45583
45604
  return { min: CLAPPR_VERSION };
45584
45605
  }
45585
- get template() {
45586
- return tmpl(pluginHtml$5);
45587
- }
45606
+ static template = tmpl(pluginHtml$5);
45607
+ /**
45608
+ * @internal
45609
+ */
45588
45610
  get attributes() {
45589
45611
  return {
45590
45612
  'data-clappr-nerd-stats': '',
45591
- 'class': 'clappr-nerd-stats'
45613
+ class: 'clappr-nerd-stats',
45592
45614
  };
45593
45615
  }
45616
+ /**
45617
+ * @internal
45618
+ */
45594
45619
  get events() {
45595
45620
  return {
45596
45621
  'click [data-show-stats-button]': 'showOrHide',
@@ -45612,8 +45637,12 @@ class ClapprNerdStats extends UICorePlugin {
45612
45637
  }
45613
45638
  constructor(core) {
45614
45639
  super(core);
45615
- this.shortcut = core.options.clapprNerdStats?.shortcut ?? ['command+shift+s', 'ctrl+shift+s'];
45616
- this.iconPosition = core.options.clapprNerdStats?.iconPosition ?? 'bottom-right';
45640
+ this.shortcut = core.options.clapprNerdStats?.shortcut ?? [
45641
+ 'command+shift+s',
45642
+ 'ctrl+shift+s',
45643
+ ];
45644
+ this.iconPosition =
45645
+ core.options.clapprNerdStats?.iconPosition ?? 'bottom-right';
45617
45646
  this.customMetrics = {
45618
45647
  connectionSpeed: 0,
45619
45648
  ping: 0,
@@ -45621,6 +45650,9 @@ class ClapprNerdStats extends UICorePlugin {
45621
45650
  };
45622
45651
  configureSpeedTest(core.options.clapprNerdStats?.speedTestServers ?? []);
45623
45652
  }
45653
+ /**
45654
+ * @internal
45655
+ */
45624
45656
  bindEvents() {
45625
45657
  const mediaControl = this.core.getPlugin('media_control');
45626
45658
  assert(mediaControl, 'media_control plugin is required');
@@ -45660,9 +45692,11 @@ class ClapprNerdStats extends UICorePlugin {
45660
45692
  this.core.$el.find(this.statsBoxElem).show();
45661
45693
  this.showing = true;
45662
45694
  this.refreshSpeedTest();
45663
- initSpeedTest(this.customMetrics).then(() => {
45695
+ initSpeedTest(this.customMetrics)
45696
+ .then(() => {
45664
45697
  startSpeedtest();
45665
- }).catch(e => {
45698
+ })
45699
+ .catch((e) => {
45666
45700
  reportError(e);
45667
45701
  this.disable();
45668
45702
  });
@@ -45677,13 +45711,19 @@ class ClapprNerdStats extends UICorePlugin {
45677
45711
  }
45678
45712
  addGeneralMetrics() {
45679
45713
  this.metrics.general = {
45680
- displayResolution: (this.playerWidth + 'x' + this.playerHeight),
45681
- volume: this.container?.volume
45714
+ displayResolution: this.playerWidth + 'x' + this.playerHeight,
45715
+ volume: this.container?.volume,
45682
45716
  };
45683
45717
  }
45684
45718
  addCustomMetrics() {
45685
45719
  this.metrics.custom = this.customMetrics;
45686
- const videoQualityNames = ['SD (480p)', 'HD (720p)', 'Full HD (1080p)', '2K (1440p)', '4K (2160p)'];
45720
+ const videoQualityNames = [
45721
+ 'SD (480p)',
45722
+ 'HD (720p)',
45723
+ 'Full HD (1080p)',
45724
+ '2K (1440p)',
45725
+ '4K (2160p)',
45726
+ ];
45687
45727
  const { connectionSpeed, ping } = this.customMetrics;
45688
45728
  if (!connectionSpeed || !ping) {
45689
45729
  const calculatingText = 'Calculating... Please wait.';
@@ -45695,17 +45735,19 @@ class ClapprNerdStats extends UICorePlugin {
45695
45735
  const pingQuality = getPingQuality(ping);
45696
45736
  const liveQuality = Math.min(downloadQuality, pingQuality);
45697
45737
  const prefix = 'Optimal for ';
45698
- this.metrics.custom.vodQuality = prefix + videoQualityNames[downloadQuality - 1];
45699
- this.metrics.custom.liveQuality = prefix + videoQualityNames[liveQuality - 1];
45738
+ this.metrics.custom.vodQuality =
45739
+ prefix + videoQualityNames[downloadQuality - 1];
45740
+ this.metrics.custom.liveQuality =
45741
+ prefix + videoQualityNames[liveQuality - 1];
45700
45742
  }
45701
45743
  updateMetrics(metrics) {
45702
45744
  Object.assign(this.metrics, metrics);
45703
45745
  this.addGeneralMetrics();
45704
45746
  this.addCustomMetrics();
45705
45747
  const scrollTop = this.core.$el.find(this.statsBoxElem).scrollTop();
45706
- this.$el.html(this.template({
45748
+ this.$el.html(ClapprNerdStats.template({
45707
45749
  metrics: Formatter.format(this.metrics),
45708
- iconPosition: this.iconPosition
45750
+ iconPosition: this.iconPosition,
45709
45751
  }));
45710
45752
  this.setStatsBoxSize();
45711
45753
  drawSpeedTestResults();
@@ -45725,7 +45767,11 @@ class ClapprNerdStats extends UICorePlugin {
45725
45767
  this.$el.find(this.statsBoxElem).addClass('narrow');
45726
45768
  }
45727
45769
  }
45770
+ /**
45771
+ * @internal
45772
+ */
45728
45773
  render() {
45774
+ // TODO append to the container
45729
45775
  this.core.$el.append(this.$el[0]);
45730
45776
  this.hide();
45731
45777
  return this;
@@ -46108,7 +46154,7 @@ class ClapprStats extends ContainerPlugin {
46108
46154
  //Copyright 2014 Globo.com Player authors. All rights reserved.
46109
46155
  // Use of this source code is governed by a BSD-style
46110
46156
  // license that can be found in the LICENSE file.
46111
- const T$9 = 'plugins.click_to_pause_custom';
46157
+ const T$a = 'plugins.click_to_pause_custom';
46112
46158
  class ClickToPause extends ContainerPlugin {
46113
46159
  pointerEnabled = false;
46114
46160
  timer = null;
@@ -46128,7 +46174,7 @@ class ClickToPause extends ContainerPlugin {
46128
46174
  click() {
46129
46175
  const isLivePlayback = this.container.getPlaybackType() === Playback.LIVE;
46130
46176
  const isDvrEnabled = this.container.isDvrEnabled();
46131
- trace(`${T$9} click`, {
46177
+ trace(`${T$a} click`, {
46132
46178
  isLivePlayback,
46133
46179
  isDvrEnabled,
46134
46180
  });
@@ -46146,7 +46192,7 @@ class ClickToPause extends ContainerPlugin {
46146
46192
  settingsUpdate() {
46147
46193
  const isLivePlayback = this.container.getPlaybackType() === Playback.LIVE;
46148
46194
  const pointerEnabled = !isLivePlayback || this.container.isDvrEnabled();
46149
- trace(`${T$9} settingsUpdate`, {
46195
+ trace(`${T$a} settingsUpdate`, {
46150
46196
  isLivePlayback,
46151
46197
  pointerEnabled,
46152
46198
  });
@@ -46537,8 +46583,11 @@ const dvrHTML = "<div class=\"live-info\"><%= live %></div>\n<button type=\"butt
46537
46583
  * @beta
46538
46584
  *
46539
46585
  * @remarks
46540
- * The plugin is rendered in the {@link MediaControl | media control} UI.
46541
- * It renders the live stream indicator and the DVR seek bar if DVR is enabled.
46586
+ * Depends on:
46587
+ *
46588
+ * - {@link MediaControl | media_control}
46589
+ *
46590
+ * The plugin renders the live stream indicator and the DVR seek bar, if DVR is enabled, in the media control UI.
46542
46591
  */
46543
46592
  class DvrControls extends UICorePlugin {
46544
46593
  static template = tmpl(dvrHTML);
@@ -46673,7 +46722,12 @@ const templateHtml = "<div class=\"player-error-screen__content\" data-error-scr
46673
46722
 
46674
46723
  const TIME_FOR_UPDATE = 10000;
46675
46724
  const MAX_RETRY = 10;
46676
- const T$8 = 'plugins.error_screen';
46725
+ const T$9 = 'plugins.error_screen';
46726
+ /**
46727
+ * Displays a descriptive error in the overlay on top of the player.
46728
+ * @beta
46729
+ * TODO
46730
+ */
46677
46731
  class ErrorScreen extends UICorePlugin {
46678
46732
  _retry = 0;
46679
46733
  err = null;
@@ -46706,17 +46760,17 @@ class ErrorScreen extends UICorePlugin {
46706
46760
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_CONTAINERCHANGED, this.onContainerChanged);
46707
46761
  }
46708
46762
  onCoreReady() {
46709
- trace(`${T$8} onCoreReady`);
46763
+ trace(`${T$9} onCoreReady`);
46710
46764
  if (this.core.activePlayback) {
46711
46765
  this.listenTo(this.core.activePlayback, Events$1.PLAYBACK_PLAY, this.onPlay);
46712
46766
  }
46713
46767
  }
46714
46768
  onPlay() {
46715
- trace(`${T$8} onPlay`);
46769
+ trace(`${T$9} onPlay`);
46716
46770
  this.destroyError();
46717
46771
  }
46718
46772
  destroyError() {
46719
- trace(`${T$8} destroyError`);
46773
+ trace(`${T$9} destroyError`);
46720
46774
  this._retry = 0;
46721
46775
  this.err = null;
46722
46776
  if (this.timeout !== null) {
@@ -46772,7 +46826,7 @@ class ErrorScreen extends UICorePlugin {
46772
46826
  }
46773
46827
  }
46774
46828
  onError(err) {
46775
- trace(`${T$8} onError`, { err });
46829
+ trace(`${T$9} onError`, { err });
46776
46830
  if (err.level === PlayerError.Levels.FATAL ||
46777
46831
  err.details === 'bufferStalledError' ||
46778
46832
  err.details === 'manifestParsingError') {
@@ -47267,7 +47321,7 @@ function keyName(keyCode) {
47267
47321
 
47268
47322
  const buttonHtml$2 = "<button class='gplayer-lite-btn gcore-skin-text-color gear-option'>\n <% if (isHd) { %>\n <span class=\"gear-option_hd-icon\"><%= hdIcon %></span>\n <% } %>\n <span>Quality</span>\n <span class=\"gear-option_arrow-right-icon\"><%= arrowRightIcon %></span>\n <span class='gear-option_value'><%= currentText %></span>\n</button>\n";
47269
47323
 
47270
- const listHtml$1 = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n Quality\n</button>\n<ul class=\"gear-sub-menu\">\n <% if (!removeAuto) { %>\n <li>\n <a href=\"#\" class='gear-sub-menu_btn gcore-skin-text-color' data-id=\"-1\" id=\"level_selector_auto\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n Auto\n </a>\n </li>\n <% } %>\n <% for (const level of levels.slice().reverse()) { %>\n <li <% if (maxLevel >= 0 && level.level > maxLevel) { %>class=\"level-disabled\"<% } %>>\n <a href=\"#\" class='gear-sub-menu_btn gcore-skin-text-color' data-id=\"<%= level.level %>\" id=\"level_selector_<%= level.level %>\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= labels[level.level] %>\n </a>\n </li>\n <% } %>\n</ul>\n";
47324
+ const listHtml$1 = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n Quality\n</button>\n<ul class=\"gear-sub-menu\">\n <% if (!removeAuto) { %>\n <li>\n <a href=\"#\" class='gear-sub-menu_btn gcore-skin-text-color' data-id=\"-1\" id=\"level_selector_auto\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n Auto\n </a>\n </li>\n <% } %>\n <% for (const level of levels.slice().reverse()) { %>\n <li <% if (maxLevel >= 0 && level.level > maxLevel) { %>class=\"level-disabled\"<% } %>>\n <a href=\"#\" class='gear-sub-menu_btn gcore-skin-text-color' data-id=\"<%= level.level %>\" id=\"level_selector_<%= level.height %>\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= labels[level.level] %>\n </a>\n </li>\n <% } %>\n</ul>\n";
47271
47325
 
47272
47326
  const hdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.9562 8.22232H13.9961V15.1873H14.9562C15.8914 15.1873 16.766 14.8253 17.4195 14.1676C18.0786 13.5037 18.4415 12.6281 18.4415 11.7026C18.4415 9.7837 16.8781 8.22253 14.9561 8.22253L14.9562 8.22232Z\"\n fill=\"#C9C9C9\"/>\n <path\n d=\"M22.0801 4H1.91994C0.859222 4 0 4.86406 0 5.91994V17.4878C0 18.5437 0.859222 19.4078 1.91994 19.4078H22.0801C23.1408 19.4078 24 18.5437 24 17.4878V5.91994C24 4.86406 23.1408 4 22.0801 4ZM10.3975 15.3473C10.3975 15.6124 10.1827 15.8272 9.91754 15.8272C9.65216 15.8272 9.43761 15.6122 9.43761 15.3473V12.0239H5.55956V15.3473C5.55956 15.6124 5.34481 15.8272 5.07963 15.8272C4.81425 15.8272 4.5997 15.6122 4.5997 15.3473L4.59949 7.74042C4.59949 7.47524 4.81425 7.26049 5.07943 7.26049C5.34481 7.26049 5.55936 7.47544 5.55936 7.74042V11.0636H9.43741V7.74042C9.43741 7.47524 9.65216 7.26049 9.91734 7.26049C10.1827 7.26049 10.3973 7.47544 10.3973 7.74042L10.3975 15.3473ZM18.1005 14.8438C17.2652 15.6844 16.1486 16.1472 14.9561 16.1472H13.5161C13.2507 16.1472 13.0361 15.9323 13.0361 15.6673V7.74263C13.0361 7.47745 13.2509 7.26269 13.5161 7.26269H14.9561C17.4072 7.26269 19.4013 9.25438 19.4013 11.7027C19.4013 12.8835 18.9392 13.9991 18.1005 14.844V14.8438Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
47273
47327
 
@@ -47277,7 +47331,7 @@ const arrowLeftIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fil
47277
47331
 
47278
47332
  const checkIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M20.5793 4.19296C20.1216 3.86696 19.4777 3.96396 19.1424 4.40896L9.37295 17.3809L4.81634 12.107C4.45222 11.683 3.80218 11.6289 3.36709 11.9839C2.932 12.3389 2.87543 12.97 3.2416 13.393L8.64165 19.643C8.83708 19.869 9.12506 20 9.42849 20C9.4398 20 9.45114 20 9.46246 19.999C9.77926 19.989 10.0724 19.838 10.2586 19.59L20.8015 5.58996C21.1368 5.14496 21.0371 4.51896 20.5793 4.19296Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
47279
47333
 
47280
- const T$7 = 'plugins.level_selector';
47334
+ const T$8 = 'plugins.level_selector';
47281
47335
  const VERSION$4 = '2.19.4';
47282
47336
  /**
47283
47337
  * A {@link MediaControl | media control} plugin that provides a UI to control the quality level of the playback.
@@ -47379,10 +47433,10 @@ class LevelSelector extends UICorePlugin {
47379
47433
  }
47380
47434
  }
47381
47435
  onStop() {
47382
- trace(`${T$7} onStop`);
47436
+ trace(`${T$8} onStop`);
47383
47437
  const currentPlayback = this.core.activePlayback;
47384
47438
  this.listenToOnce(currentPlayback, Events$1.PLAYBACK_PLAY, () => {
47385
- trace(`${T$7} on PLAYBACK_PLAY after stop`, { selectedLevelId: this.selectedLevelId });
47439
+ trace(`${T$8} on PLAYBACK_PLAY after stop`, { selectedLevelId: this.selectedLevelId });
47386
47440
  if (currentPlayback.getPlaybackType() === 'live') {
47387
47441
  if (this.selectedLevelId !== -1) {
47388
47442
  currentPlayback.currentLevel = this.selectedLevelId;
@@ -47478,13 +47532,13 @@ class LevelSelector extends UICorePlugin {
47478
47532
  return false;
47479
47533
  }
47480
47534
  goBack() {
47481
- trace(`${T$7} goBack`);
47535
+ trace(`${T$8} goBack`);
47482
47536
  this.isOpen = false;
47483
47537
  this.core.trigger('gear:refresh');
47484
47538
  this.deferRender();
47485
47539
  }
47486
47540
  setLevel(index) {
47487
- trace(`${T$7} setIndexLevel`, { index });
47541
+ trace(`${T$8} setIndexLevel`, { index });
47488
47542
  this.selectedLevelId = index;
47489
47543
  if (!this.core.activePlayback) {
47490
47544
  return;
@@ -47502,7 +47556,7 @@ class LevelSelector extends UICorePlugin {
47502
47556
  this.deferRender();
47503
47557
  }
47504
47558
  onShowLevelSelectMenu() {
47505
- trace(`${T$7} onShowLevelSelectMenu`);
47559
+ trace(`${T$8} onShowLevelSelectMenu`);
47506
47560
  this.isOpen = true;
47507
47561
  this.renderDropdown();
47508
47562
  this.highlightCurrentLevel();
@@ -47538,11 +47592,11 @@ class LevelSelector extends UICorePlugin {
47538
47592
  return this.levelLabels[index] ?? formatLevelLabel(this.levels[index]);
47539
47593
  }
47540
47594
  updateCurrentLevel(info) {
47541
- trace(`${T$7} updateCurrentLevel`, { info });
47595
+ trace(`${T$8} updateCurrentLevel`, { info });
47542
47596
  this.highlightCurrentLevel();
47543
47597
  }
47544
47598
  highlightCurrentLevel() {
47545
- trace(`${T$7} highlightCurrentLevel`, {
47599
+ trace(`${T$8} highlightCurrentLevel`, {
47546
47600
  selectedLevelId: this.selectedLevelId,
47547
47601
  });
47548
47602
  this.allLevelElements().removeClass('current');
@@ -48868,7 +48922,7 @@ const streamsMomentoIcon = "<svg id=\"Слой_1\" data-name=\"Слой 1\" xmln
48868
48922
  const streamsWhiteNightsIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"50\" height=\"50\" viewBox=\"0 0 50 50\">\n <defs>\n <clipPath id=\"clip-Icon\">\n <rect width=\"50\" height=\"50\"/>\n </clipPath>\n </defs>\n <g id=\"Icon\" clip-path=\"url(#clip-Icon)\">\n <g id=\"icon2\" transform=\"translate(-0.041 0)\">\n <path id=\"Контур_77\" data-name=\"Контур 77\" d=\"M6.493,13v8.266h6.275V19.74H8.31V17.714h4.006V16.3H8.31V14.53h4.365V13Zm7.5,0v8.266h1.7V15.732h.023l3.438,5.534h1.818V13h-1.7v5.545h-.023L15.8,13Z\" fill=\"#fff\"/>\n <path id=\"Контур_76\" data-name=\"Контур 76\" d=\"M29.949,29.1V26.774H31.94a1.4,1.4,0,0,1,.938.272,1.1,1.1,0,0,1,.313.874,1.155,1.155,0,0,1-.313.9,1.375,1.375,0,0,1-.938.278ZM28.132,25.36v8.266h1.817V30.4h1.818a1.353,1.353,0,0,1,.984.3,1.637,1.637,0,0,1,.394.949c.046.333.079.681.1,1.042a3.2,3.2,0,0,0,.185.938h1.819a1.218,1.218,0,0,1-.191-.423,3.611,3.611,0,0,1-.093-.527c-.019-.185-.033-.367-.041-.544s-.016-.332-.023-.463a5.052,5.052,0,0,0-.087-.625,2.109,2.109,0,0,0-.2-.573,1.586,1.586,0,0,0-.359-.451,1.414,1.414,0,0,0-.556-.284v-.023a1.926,1.926,0,0,0,1-.81,2.494,2.494,0,0,0,.307-1.262,2.308,2.308,0,0,0-.165-.88,2.128,2.128,0,0,0-.486-.724,2.3,2.3,0,0,0-.764-.492,2.67,2.67,0,0,0-1-.179ZM43.506,30.5V25.36H41.689V30.5a2.065,2.065,0,0,1-.37,1.36,1.7,1.7,0,0,1-1.343.434,2.086,2.086,0,0,1-.886-.156,1.283,1.283,0,0,1-.758-.978,3.748,3.748,0,0,1-.058-.66V25.36H36.456V30.5a3.16,3.16,0,0,0,.92,2.5,3.807,3.807,0,0,0,2.6.81,3.82,3.82,0,0,0,2.593-.816,3.132,3.132,0,0,0,.937-2.492Z\" fill=\"#fff\"/>\n <path id=\"Контур_80\" data-name=\"Контур 80\" d=\"M22.646,31.2H4.689a4.505,4.505,0,0,1-4.5-4.5V8.5A4.505,4.505,0,0,1,4.689,4h18.2a4.505,4.505,0,0,1,4.5,4.5v8.445l-.893.1a3.184,3.184,0,0,0-2.846,3.177V30.5l-.465.7ZM4.689,6a2.5,2.5,0,0,0-2.5,2.5V26.7a2.5,2.5,0,0,0,2.5,2.5H21.65V20.22a5.18,5.18,0,0,1,3.739-4.992V8.5a2.5,2.5,0,0,0-2.5-2.5Z\" fill=\"#fff\"/>\n <path id=\"Контур_81\" data-name=\"Контур 81\" d=\"M30.127,47.884a1,1,0,0,1-1-1V43.267H26.846a5.206,5.206,0,0,1-5.2-5.2V20.222a5.206,5.206,0,0,1,5.2-5.2H44.692a5.206,5.206,0,0,1,5.2,5.2V38.068a5.206,5.206,0,0,1-5.2,5.2H35.058l-4.216,4.316A1,1,0,0,1,30.127,47.884ZM26.846,17.022a3.2,3.2,0,0,0-3.2,3.2V38.067a3.2,3.2,0,0,0,3.2,3.2h3.281a1,1,0,0,1,1,1v2.162l2.8-2.86a1,1,0,0,1,.715-.3H44.692a3.2,3.2,0,0,0,3.2-3.2V20.222a3.2,3.2,0,0,0-3.2-3.2Z\" fill=\"#fff\"/>\n </g>\n </g>\n</svg>\n";
48869
48923
 
48870
48924
  const VERSION$3 = '0.0.1';
48871
- const T$6 = 'plugins.media_control_multicamera';
48925
+ const T$7 = 'plugins.media_control_multicamera';
48872
48926
  class MultiCamera extends UICorePlugin {
48873
48927
  currentCamera = null;
48874
48928
  currentTime = 0;
@@ -49010,7 +49064,7 @@ class MultiCamera extends UICorePlugin {
49010
49064
  }
49011
49065
  onCameraSelect(event) {
49012
49066
  const value = event.currentTarget.dataset.multicameraSelectorSelect;
49013
- trace(`${T$6} onCameraSelect`, { value });
49067
+ trace(`${T$7} onCameraSelect`, { value });
49014
49068
  if (value !== undefined) {
49015
49069
  this.changeById(parseInt(value, 10));
49016
49070
  }
@@ -49137,13 +49191,13 @@ class MultiCamera extends UICorePlugin {
49137
49191
  }
49138
49192
  }
49139
49193
  changeById(id) {
49140
- trace(`${T$6} changeById`, { id });
49194
+ trace(`${T$7} changeById`, { id });
49141
49195
  queueMicrotask(() => {
49142
49196
  const playbackOptions = this.core.options.playback || {};
49143
49197
  // TODO figure out what this does
49144
49198
  playbackOptions.recycleVideo = Browser.isMobile;
49145
49199
  this.currentCamera = this.findElementById(id) ?? null;
49146
- trace(`${T$6} changeById`, { id, currentCamera: this.currentCamera, multicamera: this.multicamera });
49200
+ trace(`${T$7} changeById`, { id, currentCamera: this.currentCamera, multicamera: this.multicamera });
49147
49201
  if (!this.currentCamera) {
49148
49202
  return;
49149
49203
  }
@@ -49160,7 +49214,7 @@ class MultiCamera extends UICorePlugin {
49160
49214
  // TODO remove?
49161
49215
  // for html5 playback:
49162
49216
  this.options.dvrEnabled = this.currentCamera.dvr;
49163
- trace(`${T$6} changeById`, { currentCamera: this.currentCamera });
49217
+ trace(`${T$7} changeById`, { currentCamera: this.currentCamera });
49164
49218
  // TODO
49165
49219
  this.core.configure({
49166
49220
  playback: playbackOptions,
@@ -49218,17 +49272,39 @@ const pipIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"no
49218
49272
  const buttonHtml$1 = "<button class=\"gplayer-lite-btn gcore-skin-button-color\">\n <span><%= pipIcon %></span>\n</button>\n";
49219
49273
 
49220
49274
  const VERSION$2 = '0.0.1';
49221
- const T$5 = `plugins.media_control_pip`;
49275
+ const T$6 = `plugins.pip`;
49276
+ /**
49277
+ * Enables picture in picture mode.
49278
+ * @beta
49279
+ * @remarks
49280
+ * Depends on:
49281
+ *
49282
+ * - {@link MediaControl}
49283
+ *
49284
+ * It renders a button to toggle picture in picture mode in the media control UI.
49285
+ */
49222
49286
  class PictureInPicture extends UICorePlugin {
49287
+ /**
49288
+ * @internal
49289
+ */
49223
49290
  get name() {
49224
- return 'media_control_pip';
49291
+ return 'pip';
49225
49292
  }
49293
+ /**
49294
+ * @internal
49295
+ */
49226
49296
  get supportedVersion() {
49227
49297
  return { min: CLAPPR_VERSION };
49228
49298
  }
49299
+ /**
49300
+ * @internal
49301
+ */
49229
49302
  static get version() {
49230
49303
  return VERSION$2;
49231
49304
  }
49305
+ /**
49306
+ * @internal
49307
+ */
49232
49308
  get events() {
49233
49309
  return {
49234
49310
  'click button': 'togglePictureInPicture',
@@ -49237,16 +49313,22 @@ class PictureInPicture extends UICorePlugin {
49237
49313
  get videoElement() {
49238
49314
  return this.core.activePlayback.el;
49239
49315
  }
49316
+ /**
49317
+ * @internal
49318
+ */
49240
49319
  bindEvents() {
49241
49320
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED, this.render);
49242
49321
  }
49243
49322
  isPiPSupported() {
49244
- trace(`${T$5} isPiPSupported`, {
49323
+ trace(`${T$6} isPiPSupported`, {
49245
49324
  pictureInPictureEnabled: document.pictureInPictureEnabled,
49246
49325
  requestPictureInPicture: HTMLVideoElement.prototype.requestPictureInPicture,
49247
49326
  });
49248
49327
  return document.pictureInPictureEnabled && !!HTMLVideoElement.prototype.requestPictureInPicture;
49249
49328
  }
49329
+ /**
49330
+ * @internal
49331
+ */
49250
49332
  render() {
49251
49333
  if (!this.isPiPSupported()) {
49252
49334
  return this;
@@ -49260,7 +49342,7 @@ class PictureInPicture extends UICorePlugin {
49260
49342
  return this;
49261
49343
  }
49262
49344
  togglePictureInPicture() {
49263
- trace(`${T$5} togglePictureInPicture`);
49345
+ trace(`${T$6} togglePictureInPicture`);
49264
49346
  if (this.videoElement !== document.pictureInPictureElement) {
49265
49347
  this.requestPictureInPicture();
49266
49348
  }
@@ -49269,13 +49351,13 @@ class PictureInPicture extends UICorePlugin {
49269
49351
  }
49270
49352
  }
49271
49353
  requestPictureInPicture() {
49272
- trace(`${T$5} requestPictureInPicture`, {
49354
+ trace(`${T$6} requestPictureInPicture`, {
49273
49355
  videoElement: !!this.videoElement,
49274
49356
  });
49275
49357
  this.videoElement.requestPictureInPicture();
49276
49358
  }
49277
49359
  exitPictureInPicture() {
49278
- trace(`${T$5} exitPictureInPicture`);
49360
+ trace(`${T$6} exitPictureInPicture`);
49279
49361
  document.exitPictureInPicture();
49280
49362
  }
49281
49363
  }
@@ -49300,26 +49382,51 @@ const DEFAULT_PLAYBACK_RATES = [
49300
49382
  const DEFAULT_PLAYBACK_RATE = '1.0';
49301
49383
  // TODO
49302
49384
  const MEDIACONTROL_PLAYBACKRATE = 'playbackRate';
49385
+ /**
49386
+ * Allows changing the playback speed of the video.
49387
+ * @beta
49388
+ *
49389
+ * @remarks
49390
+ * Depends on:
49391
+ *
49392
+ * - {@link MediaControl | media_control}
49393
+ *
49394
+ * - {@link BottomGear | bottom_gear}
49395
+ *
49396
+ * It renders a button in the gear menu, which opens a dropdown with the available playback rates.
49397
+ */
49303
49398
  class PlaybackRate extends UICorePlugin {
49304
49399
  currentPlayback = null;
49305
49400
  playbackRates = DEFAULT_PLAYBACK_RATES;
49306
49401
  prevSelectedRate;
49307
49402
  selectedRate = DEFAULT_PLAYBACK_RATE;
49403
+ /**
49404
+ * @internal
49405
+ */
49308
49406
  get name() {
49309
- return 'media_control_playback_rate';
49407
+ return 'playback_rate';
49310
49408
  }
49409
+ /**
49410
+ * @internal
49411
+ */
49311
49412
  get supportedVersion() {
49312
49413
  return { min: CLAPPR_VERSION };
49313
49414
  }
49314
- get template() {
49315
- return tmpl(pluginHtml$3);
49316
- }
49415
+ static template = tmpl(pluginHtml$3);
49416
+ static buttonTemplate = tmpl(buttonHtml);
49417
+ static listTemplate = tmpl(listHtml);
49418
+ /**
49419
+ * @internal
49420
+ */
49317
49421
  get attributes() {
49318
49422
  return {
49319
49423
  'class': this.name,
49320
49424
  'data-playback-rate-select': ''
49321
49425
  };
49322
49426
  }
49427
+ /**
49428
+ * @internal
49429
+ */
49323
49430
  get events() {
49324
49431
  return {
49325
49432
  'click .gear-sub-menu_btn': 'onRateSelect',
@@ -49327,8 +49434,12 @@ class PlaybackRate extends UICorePlugin {
49327
49434
  'click .go-back': 'goBack',
49328
49435
  };
49329
49436
  }
49437
+ /**
49438
+ * @internal
49439
+ */
49330
49440
  bindEvents() {
49331
49441
  this.listenTo(this.core, 'gear:rendered', this.render);
49442
+ // TODO this.core.getPlugin('media_control'), bottom_gear
49332
49443
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_CONTAINERCHANGED, this.reload);
49333
49444
  this.listenTo(this.core.mediaControl, MEDIACONTROL_PLAYBACKRATE, this.updatePlaybackRate);
49334
49445
  this.listenTo(this.core, 'core:advertisement:start', this.onStartAd);
@@ -49382,6 +49493,9 @@ class PlaybackRate extends UICorePlugin {
49382
49493
  this.currentPlayback = this.core.activePlayback;
49383
49494
  return !(this.currentPlayback?.tagName !== 'video' && this.currentPlayback?.tagName !== 'audio');
49384
49495
  }
49496
+ /**
49497
+ * @internal
49498
+ */
49385
49499
  render() {
49386
49500
  const container = this.core.activeContainer;
49387
49501
  if (this.core.getPlaybackType() === Playback.LIVE && !container.isDvrEnabled()) {
@@ -49395,9 +49509,7 @@ class PlaybackRate extends UICorePlugin {
49395
49509
  this.selectedRate = cfg.defaultValue || DEFAULT_PLAYBACK_RATE;
49396
49510
  }
49397
49511
  if (this.shouldRender()) {
49398
- const t = tmpl(buttonHtml);
49399
- // const html = t({ playbackRates: this.playbackRates, title: this.getTitle() });
49400
- const button = t({
49512
+ const button = PlaybackRate.buttonTemplate({
49401
49513
  title: this.getTitle(),
49402
49514
  speedIcon,
49403
49515
  arrowRightIcon,
@@ -49445,8 +49557,7 @@ class PlaybackRate extends UICorePlugin {
49445
49557
  return false;
49446
49558
  }
49447
49559
  onShowMenu() {
49448
- const t = tmpl(listHtml);
49449
- this.$el.html(t({
49560
+ this.$el.html(PlaybackRate.listTemplate({
49450
49561
  playbackRates: this.playbackRates,
49451
49562
  arrowLeftIcon,
49452
49563
  checkIcon,
@@ -49490,7 +49601,7 @@ const posterHTML = "<div class=\"play-wrapper\" data-poster></div>\n";
49490
49601
  //Copyright 2014 Globo.com Player authors. All rights reserved.
49491
49602
  // Use of this source code is governed by a BSD-style
49492
49603
  // license that can be found in the LICENSE file.
49493
- const T$4 = 'plugins.poster_custom';
49604
+ const T$5 = 'plugins.poster_custom';
49494
49605
  /**
49495
49606
  * Displays a poster image in the background and a big play button on top when playback is stopped
49496
49607
  * @beta
@@ -49593,13 +49704,13 @@ class Poster extends UIContainerPlugin {
49593
49704
  * Disables the plugin, unmounting it from the DOM
49594
49705
  */
49595
49706
  disable() {
49596
- trace(`${T$4} disable`);
49707
+ trace(`${T$5} disable`);
49597
49708
  this.hasStartedPlaying = false;
49598
49709
  this.playRequested = false;
49599
49710
  super.disable();
49600
49711
  }
49601
49712
  onError(error) {
49602
- trace(`${T$4} onError`, {
49713
+ trace(`${T$5} onError`, {
49603
49714
  error,
49604
49715
  enabled: this.enabled,
49605
49716
  });
@@ -49612,18 +49723,18 @@ class Poster extends UIContainerPlugin {
49612
49723
  }
49613
49724
  }
49614
49725
  onPlay() {
49615
- trace(`${T$4} onPlay`);
49726
+ trace(`${T$5} onPlay`);
49616
49727
  this.hasStartedPlaying = true;
49617
49728
  this.playRequested = false;
49618
49729
  this.update();
49619
49730
  }
49620
49731
  onPlayIntent() {
49621
- trace(`${T$4} onPlayIntent`);
49732
+ trace(`${T$5} onPlayIntent`);
49622
49733
  this.playRequested = true;
49623
49734
  this.update();
49624
49735
  }
49625
49736
  onStop() {
49626
- trace(`${T$4} onStop`, {
49737
+ trace(`${T$5} onStop`, {
49627
49738
  enabled: this.enabled,
49628
49739
  });
49629
49740
  this.hasStartedPlaying = false;
@@ -49631,7 +49742,7 @@ class Poster extends UIContainerPlugin {
49631
49742
  this.update();
49632
49743
  }
49633
49744
  updatePlayButton(show) {
49634
- trace(`${T$4} updatePlayButton`, {
49745
+ trace(`${T$5} updatePlayButton`, {
49635
49746
  show,
49636
49747
  chromeless: this.options.chromeless,
49637
49748
  allowUserInteraction: this.options.allowUserInteraction,
@@ -49660,7 +49771,7 @@ class Poster extends UIContainerPlugin {
49660
49771
  this.$el.removeClass('clickable');
49661
49772
  }
49662
49773
  clicked() {
49663
- trace(`${T$4} clicked`, {
49774
+ trace(`${T$5} clicked`, {
49664
49775
  hasStartedPlaying: this.hasStartedPlaying,
49665
49776
  chromeless: this.options.chromeless,
49666
49777
  allowUserInteraction: this.options.allowUserInteraction,
@@ -49684,7 +49795,7 @@ class Poster extends UIContainerPlugin {
49684
49795
  return !this.container.playback.isAudioOnly;
49685
49796
  }
49686
49797
  update() {
49687
- trace(`${T$4} update`, {
49798
+ trace(`${T$5} update`, {
49688
49799
  shouldRender: this.shouldRender,
49689
49800
  });
49690
49801
  if (!this.shouldRender) {
@@ -49697,7 +49808,7 @@ class Poster extends UIContainerPlugin {
49697
49808
  this.updatePoster();
49698
49809
  }
49699
49810
  updatePoster() {
49700
- trace(`${T$4} updatePoster`, {
49811
+ trace(`${T$5} updatePoster`, {
49701
49812
  hasStartedPlaying: this.hasStartedPlaying,
49702
49813
  });
49703
49814
  if (!this.hasStartedPlaying) {
@@ -49712,7 +49823,7 @@ class Poster extends UIContainerPlugin {
49712
49823
  this.$el.show();
49713
49824
  }
49714
49825
  hidePoster() {
49715
- trace(`${T$4} hidePoster`, {
49826
+ trace(`${T$5} hidePoster`, {
49716
49827
  shouldHideOnPlay: this.shouldHideOnPlay(),
49717
49828
  });
49718
49829
  if (!this.options.disableMediaControl) {
@@ -50129,7 +50240,7 @@ const spinnerHTML = "<div data-bounce1></div>\n<div data-bounce2></div>\n<div da
50129
50240
  // Copyright 2014 Globo.com Player authors. All rights reserved.
50130
50241
  // Use of this source code is governed by a BSD-style
50131
50242
  // license that can be found in the LICENSE file.
50132
- const T$3 = 'plugins.spinner';
50243
+ const T$4 = 'plugins.spinner';
50133
50244
  /**
50134
50245
  * Custom events emitted by the plugin
50135
50246
  */
@@ -50194,11 +50305,11 @@ class SpinnerThreeBounce extends UIContainerPlugin {
50194
50305
  this.hasBuffering = false;
50195
50306
  }
50196
50307
  onPlay() {
50197
- trace(`${T$3} onPlay`);
50308
+ trace(`${T$4} onPlay`);
50198
50309
  this.hide();
50199
50310
  }
50200
50311
  onStop() {
50201
- trace(`${T$3} onStop`, {
50312
+ trace(`${T$4} onStop`, {
50202
50313
  showOnError: this.options.spinner?.showOnError,
50203
50314
  hasFatalError: this.hasFatalError,
50204
50315
  });
@@ -50208,7 +50319,7 @@ class SpinnerThreeBounce extends UIContainerPlugin {
50208
50319
  }
50209
50320
  onError(e) {
50210
50321
  this.hasFatalError = e.code === PlaybackErrorCode.MediaSourceUnavailable;
50211
- trace(`${T$3} onError`, {
50322
+ trace(`${T$4} onError`, {
50212
50323
  e,
50213
50324
  showOnError: this.options.spinner?.showOnError,
50214
50325
  hasFatalError: this.hasFatalError,
@@ -50242,7 +50353,7 @@ class SpinnerThreeBounce extends UIContainerPlugin {
50242
50353
  */
50243
50354
  render() {
50244
50355
  const showOnStart = this.options.spinner?.showOnStart;
50245
- trace(`${T$3} render`, {
50356
+ trace(`${T$4} render`, {
50246
50357
  buffering: this.container.buffering,
50247
50358
  showOnStart,
50248
50359
  });
@@ -50261,129 +50372,200 @@ class SpinnerThreeBounce extends UIContainerPlugin {
50261
50372
  }
50262
50373
  }
50263
50374
 
50264
- // An example implementation of client side performancestatistics
50265
- const CUSTOM_EVENTS_CONTAINER_START = 'container:start';
50266
- const WATCH_CUTOFF = 5;
50267
- const HEATMAP_INTERVAL = 10;
50268
- // TODO rewrite as core plugin
50269
- class Statistics extends ContainerPlugin {
50375
+ const T$3 = 'plugins.source_controller';
50376
+ const INITIAL_RETRY_DELAY = 1000;
50377
+ const MAX_RETRY_DELAY = 5000;
50378
+ const RETRY_DELAY_BLUR = 500;
50379
+ const VERSION$1 = '0.0.1';
50380
+ function noSync(cb) {
50381
+ queueMicrotask(cb);
50382
+ }
50383
+ /**
50384
+ * This plugin is responsible for managing the automatic failover between sources.
50385
+ * @beta
50386
+ * @remarks
50387
+ * Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
50388
+ * on how sources ordering and selection works.
50389
+ *
50390
+ * This plugin does not expose any public methods apart from required by the Clappr plugin interface.
50391
+ * It is supposed to work autonomously.
50392
+ *
50393
+ * @example
50394
+ * ```ts
50395
+ * import { SourceController } from '@gcorevideo/player'
50396
+ *
50397
+ * Player.registerPlugin(SourceController)
50398
+ * ```
50399
+ */
50400
+ class SourceController extends CorePlugin {
50401
+ /*
50402
+ * The Logic itself is quite simple:
50403
+ * * Here is the short diagram:
50404
+ *
50405
+ * sources_list:
50406
+ * - a.mpd | +--------------------+
50407
+ * - b.m3u8 |--->| init |
50408
+ * - ... | |--------------------|
50409
+ * | current_source = 0 |
50410
+ * +--------------------+
50411
+ * |
50412
+ * | source = a.mpd
50413
+ * | playback = dash.js
50414
+ * v
50415
+ * +------------------+
50416
+ * +-->| load source |
50417
+ * | +---------|--------+
50418
+ * | v
50419
+ * | +------------------+
50420
+ * | | play |
50421
+ * | +---------|--------+
50422
+ * | |
50423
+ * | v
50424
+ * | +-----------------------+
50425
+ * | | on playback_error |
50426
+ * | |-----------------------|
50427
+ * | | current_source = |
50428
+ * | | (current_source + 1) |
50429
+ * | | % len sources_list |
50430
+ * | | |
50431
+ * | | delay 1..3s |
50432
+ * | +---------------|-------+
50433
+ * | |
50434
+ * | source=b.m3u8 |
50435
+ * | playback=hls.js |
50436
+ * +-------------------+
50437
+ *
50438
+ */
50439
+ sourcesList = [];
50440
+ currentSourceIndex = 0;
50441
+ sourcesDelay = {};
50442
+ active = false;
50443
+ sync = noSync;
50444
+ /**
50445
+ * @internal
50446
+ */
50270
50447
  get name() {
50271
- return 'statistics_gplayer';
50448
+ return 'source_controller';
50272
50449
  }
50450
+ /**
50451
+ * @internal
50452
+ */
50273
50453
  get supportedVersion() {
50274
50454
  return { min: CLAPPR_VERSION };
50275
50455
  }
50276
- started = false;
50277
- timeStart = 0;
50278
- heatmapSent = false;
50279
- heatmapLastTime = 0;
50280
- watchSent = false;
50281
- bufTracking = false;
50282
- lags = 0;
50283
- /**
50284
- * The time when buffering last started.
50285
- */
50286
- bufLastStarted = 0;
50456
+ constructor(core) {
50457
+ super(core);
50458
+ this.sourcesList = this.core.options.sources;
50459
+ if (this.core.options.source !== undefined) {
50460
+ // prevent Clappr from loading all sources simultaneously
50461
+ this.core.options.sources = [this.core.options.source];
50462
+ }
50463
+ else {
50464
+ this.core.options.sources = this.core.options.sources.slice(0, 1);
50465
+ }
50466
+ }
50287
50467
  /**
50288
- * The accumulated buffering duration.
50468
+ * @internal
50289
50469
  */
50290
- bufAccDuration = 0;
50291
- constructor(container) {
50292
- super(container);
50293
- assert(this.options.statistics &&
50294
- typeof this.options.statistics.send === 'function', 'Statistics plugin requires statistics options');
50295
- }
50296
50470
  bindEvents() {
50297
- // TODO remove this
50298
- this.listenToOnce(this.container, CUSTOM_EVENTS_CONTAINER_START, this.onStart);
50299
- this.listenToOnce(this.container, Events$1.CONTAINER_READY, this.onReady);
50300
- this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERING, this.onBuffering);
50301
- this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERFULL, this.onBufferFull);
50302
- this.listenTo(this.container.playback, Events$1.PLAYBACK_TIMEUPDATE, this.onTimeUpdateLive);
50303
- this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_START, this.startLevelSwitch);
50304
- this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_END, this.stopLevelSwitch);
50305
- }
50306
- startLevelSwitch() {
50307
- this.bufTracking = false;
50308
- }
50309
- stopLevelSwitch() {
50310
- this.bufTracking = true;
50471
+ super.bindEvents();
50472
+ this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, () => this.onReady());
50311
50473
  }
50312
- onBuffering() {
50313
- if (this.bufTracking) {
50314
- this.bufLastStarted = performance.now();
50474
+ onReady() {
50475
+ trace(`${T$3} onReady`, {
50476
+ retrying: this.active,
50477
+ currentSource: this.sourcesList[this.currentSourceIndex],
50478
+ });
50479
+ const spinner = this.core.activeContainer?.getPlugin('spinner');
50480
+ if (spinner) {
50481
+ this.sync = (cb) => {
50482
+ spinner.once(SpinnerEvents.SYNC, cb);
50483
+ };
50315
50484
  }
50316
- }
50317
- onBufferFull() {
50318
- if (this.bufTracking && this.bufLastStarted) {
50319
- this.bufAccDuration += performance.now() - this.bufLastStarted;
50320
- this.lags++;
50485
+ else {
50486
+ this.sync = noSync;
50321
50487
  }
50322
- this.bufTracking = true;
50323
- }
50324
- onReady() {
50325
- this.initEvent();
50326
- if (this.options.autoPlay) {
50327
- this.onStart();
50488
+ this.bindContainerEventListeners();
50489
+ if (this.active) {
50490
+ this.core.activeContainer?.getPlugin('poster_custom')?.disable();
50491
+ spinner?.show();
50328
50492
  }
50329
50493
  }
50330
- initEvent() {
50331
- this.sendMessage('init');
50332
- }
50333
- sendMessage(state) {
50334
- this.send(state, {
50335
- // embed_url: this.options.referer,
50336
- // user_agent: Browser.userAgent
50494
+ bindContainerEventListeners() {
50495
+ this.core.activePlayback.on(Events$1.PLAYBACK_ERROR, (error) => {
50496
+ trace(`${T$3} on PLAYBACK_ERROR`, {
50497
+ error: {
50498
+ code: error?.code,
50499
+ description: error?.description,
50500
+ level: error?.level,
50501
+ },
50502
+ retrying: this.active,
50503
+ currentSource: this.sourcesList[this.currentSourceIndex],
50504
+ });
50505
+ switch (error.code) {
50506
+ case PlaybackErrorCode.MediaSourceUnavailable:
50507
+ this.core.activeContainer?.getPlugin('poster_custom')?.disable();
50508
+ this.retryPlayback();
50509
+ break;
50510
+ }
50337
50511
  });
50338
- }
50339
- send(event, data = {}) {
50340
- this.options.statistics.send({
50341
- event,
50342
- type: this.container.getPlaybackType(),
50343
- ...data,
50512
+ this.core.activePlayback.on(Events$1.PLAYBACK_PLAY, () => {
50513
+ trace(`${T$3} on PLAYBACK_PLAY`, {
50514
+ currentSource: this.sourcesList[this.currentSourceIndex],
50515
+ retrying: this.active,
50516
+ });
50517
+ if (this.active) {
50518
+ this.reset();
50519
+ // TODO make poster reset its state on enable
50520
+ this.core.activeContainer?.getPlugin('poster_custom')?.enable();
50521
+ this.core.activeContainer?.getPlugin('spinner')?.hide();
50522
+ }
50344
50523
  });
50345
50524
  }
50346
- sendHeatmap(time) {
50347
- const res = {
50348
- buffering: Math.round(this.bufAccDuration),
50349
- lags: this.lags,
50350
- };
50351
- this.bufAccDuration = 0;
50352
- this.lags = 0;
50353
- if (this.container.getPlaybackType() === Playback.VOD) {
50354
- res.timestamp = time;
50355
- }
50356
- this.send('heatmap', res);
50357
- this.heatmapSent = true;
50358
- this.heatmapLastTime = time;
50525
+ reset() {
50526
+ this.active = false;
50527
+ this.sourcesDelay = {};
50359
50528
  }
50360
- onTimeUpdateLive({ current }) {
50361
- // TODO check the `current` values for the live streams
50362
- if (!this.timeStart) {
50363
- this.timeStart = current;
50364
- }
50365
- try {
50366
- const elapsed = current - this.timeStart;
50367
- const heatmapElapsed = current - this.heatmapLastTime;
50368
- // TODO check if the heatmap is only needed for the live streams
50369
- if (!this.heatmapSent || heatmapElapsed >= HEATMAP_INTERVAL) {
50370
- this.sendHeatmap(current);
50371
- }
50372
- if (!this.watchSent && elapsed >= WATCH_CUTOFF) {
50373
- this.watchSent = true;
50374
- this.sendMessage('watch');
50375
- }
50376
- }
50377
- catch (error) {
50378
- reportError(error);
50379
- }
50529
+ retryPlayback() {
50530
+ trace(`${T$3} retryPlayback enter`, {
50531
+ currentSourceIndex: this.currentSourceIndex,
50532
+ currentSource: this.sourcesList[this.currentSourceIndex],
50533
+ });
50534
+ this.active = true;
50535
+ this.getNextMediaSource().then((nextSource) => {
50536
+ trace(`${T$3} retryPlayback syncing...`, {
50537
+ nextSource,
50538
+ });
50539
+ const rnd = RETRY_DELAY_BLUR * Math.random();
50540
+ this.sync(() => {
50541
+ trace(`${T$3} retryPlayback loading...`);
50542
+ this.core.load(nextSource.source, nextSource.mimeType);
50543
+ trace(`${T$3} retryPlayback loaded`, {
50544
+ nextSource,
50545
+ });
50546
+ setTimeout(() => {
50547
+ // this.core.activePlayback.consent()
50548
+ this.core.activePlayback.play();
50549
+ trace(`${T$3} retryPlayback playing`);
50550
+ }, rnd);
50551
+ });
50552
+ });
50380
50553
  }
50381
- onStart() {
50382
- if (this.started) {
50383
- return;
50384
- }
50385
- this.started = true;
50386
- this.sendMessage('start');
50554
+ getNextMediaSource() {
50555
+ return new Promise((resolve) => {
50556
+ this.sourcesDelay[this.currentSourceIndex] = Math.min(MAX_RETRY_DELAY, (this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY) * 2);
50557
+ this.currentSourceIndex =
50558
+ (this.currentSourceIndex + 1) % this.sourcesList.length;
50559
+ const delay = this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY;
50560
+ const s = this.sourcesList[this.currentSourceIndex];
50561
+ setTimeout(() => resolve(s), delay);
50562
+ });
50563
+ }
50564
+ /**
50565
+ * @internal
50566
+ */
50567
+ static get version() {
50568
+ return VERSION$1;
50387
50569
  }
50388
50570
  }
50389
50571
 
@@ -50395,7 +50577,7 @@ const comboboxHTML = "<button data-subtitles-button class='media-control-button
50395
50577
 
50396
50578
  const stringHTML = "<div class=\"subtitle-string\">\n <p></p>\n</div>\n";
50397
50579
 
50398
- const VERSION$1 = '2.19.14';
50580
+ const VERSION = '2.19.14';
50399
50581
  const LOCAL_STORAGE_SUBTITLES_ID = 'gplayer.plugins.subtitles.selected';
50400
50582
  const T$2 = 'plugins.subtitles';
50401
50583
  const NO_TRACK = { language: 'off' };
@@ -50449,7 +50631,7 @@ class Subtitles extends UICorePlugin {
50449
50631
  * @internal
50450
50632
  */
50451
50633
  static get version() {
50452
- return VERSION$1;
50634
+ return VERSION;
50453
50635
  }
50454
50636
  static template = tmpl(comboboxHTML);
50455
50637
  static templateString = tmpl(stringHTML);
@@ -50761,6 +50943,183 @@ class Subtitles extends UICorePlugin {
50761
50943
  }
50762
50944
  }
50763
50945
 
50946
+ // An example implementation of client side performancestatistics
50947
+ const WATCH_CUTOFF = 5;
50948
+ const STALL_MEASURE_PERIOD = 10;
50949
+ const T$1 = 'plugins.telemetry';
50950
+ /**
50951
+ * Telemetry event type
50952
+ */
50953
+ var TelemetryEvent;
50954
+ (function (TelemetryEvent) {
50955
+ TelemetryEvent[TelemetryEvent["Init"] = 1] = "Init";
50956
+ TelemetryEvent[TelemetryEvent["Start"] = 2] = "Start";
50957
+ TelemetryEvent[TelemetryEvent["Watch"] = 3] = "Watch";
50958
+ TelemetryEvent[TelemetryEvent["Stall"] = 4] = "Stall";
50959
+ })(TelemetryEvent || (TelemetryEvent = {}));
50960
+ /**
50961
+ * Collects and reports the performance statistics.
50962
+ * @beta
50963
+ * @remarks
50964
+ * This plugin is experimental and its API is likely to change.
50965
+ *
50966
+ * Configuration options {@link TelemetryPluginSettings}
50967
+ *
50968
+ * @example
50969
+ * ```ts
50970
+ * import { Statistics } from '@gcorevideo/player'
50971
+ *
50972
+ * Player.registerPlugin(Statistics)
50973
+ *
50974
+ * const player = new Player({
50975
+ * statistics: {
50976
+ * send: (data) => {
50977
+ * fetch('/stats', {
50978
+ * method: 'POST',
50979
+ * body: JSON.stringify(data),
50980
+ * headers: { 'content-type': 'application/json' },
50981
+ * })
50982
+ * },
50983
+ * },
50984
+ * ...
50985
+ * })
50986
+ * ```
50987
+ */
50988
+ class Telemetry extends ContainerPlugin {
50989
+ /**
50990
+ * The name of the plugin.
50991
+ */
50992
+ get name() {
50993
+ return 'telemetry';
50994
+ }
50995
+ /**
50996
+ * The supported version of the plugin.
50997
+ */
50998
+ get supportedVersion() {
50999
+ return { min: CLAPPR_VERSION };
51000
+ }
51001
+ started = false;
51002
+ timeStart = 0;
51003
+ stallSent = false;
51004
+ stallLastTime = 0;
51005
+ watchSent = false;
51006
+ bufTracking = false;
51007
+ numStalls = 0;
51008
+ /**
51009
+ * The time when buffering last started.
51010
+ */
51011
+ bufLastStarted = 0;
51012
+ /**
51013
+ * The accumulated buffering duration.
51014
+ */
51015
+ stallAcc = 0;
51016
+ constructor(container) {
51017
+ super(container);
51018
+ assert(this.options.telemetry &&
51019
+ typeof this.options.telemetry.send === 'function', 'Telemetry plugin configuration is invalid: `send` option is required');
51020
+ }
51021
+ /**
51022
+ * @internal
51023
+ */
51024
+ bindEvents() {
51025
+ // TODO remove this
51026
+ // this.listenToOnce(
51027
+ // this.container,
51028
+ // CUSTOM_EVENTS_CONTAINER_START,
51029
+ // this.onStart,
51030
+ // )
51031
+ this.listenToOnce(this.container, Events$1.CONTAINER_READY, this.onReady);
51032
+ this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERING, this.onBuffering);
51033
+ this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERFULL, this.onBufferFull);
51034
+ this.listenTo(this.container.playback, Events$1.PLAYBACK_TIMEUPDATE, this.onTimeUpdate);
51035
+ this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_START, this.startLevelSwitch);
51036
+ this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_END, this.endLevelSwitch);
51037
+ }
51038
+ startLevelSwitch() {
51039
+ this.bufTracking = false;
51040
+ }
51041
+ endLevelSwitch() {
51042
+ this.bufTracking = true;
51043
+ }
51044
+ onBuffering() {
51045
+ if (this.bufTracking) {
51046
+ this.bufLastStarted = performance.now();
51047
+ }
51048
+ }
51049
+ onBufferFull() {
51050
+ if (this.bufTracking && this.bufLastStarted) {
51051
+ this.stallAcc += performance.now() - this.bufLastStarted;
51052
+ this.numStalls++;
51053
+ }
51054
+ this.bufTracking = true;
51055
+ }
51056
+ onReady() {
51057
+ this.sendInit();
51058
+ trace(`${T$1} onReady`, {
51059
+ autoPlay: this.options.autoPlay,
51060
+ });
51061
+ if (this.options.autoPlay) {
51062
+ this.onStart();
51063
+ }
51064
+ else {
51065
+ this.listenToOnce(this.container.playback, Events$1.PLAYBACK_PLAY_INTENT, this.onStart);
51066
+ }
51067
+ }
51068
+ sendInit() {
51069
+ this.send({ event: TelemetryEvent.Init });
51070
+ }
51071
+ send(event) {
51072
+ this.options.telemetry.send({
51073
+ type: this.container.getPlaybackType(),
51074
+ ...event,
51075
+ });
51076
+ }
51077
+ sendStall(time) {
51078
+ // TODO don't send if no stalls?
51079
+ const res = {
51080
+ event: TelemetryEvent.Stall,
51081
+ count: this.numStalls,
51082
+ time,
51083
+ total_ms: Math.round(this.stallAcc * 1000),
51084
+ };
51085
+ this.stallAcc = 0;
51086
+ this.numStalls = 0;
51087
+ this.send(res);
51088
+ this.stallSent = true;
51089
+ this.stallLastTime = time;
51090
+ }
51091
+ onTimeUpdate({ current }) {
51092
+ if (!this.timeStart) {
51093
+ this.timeStart = current;
51094
+ }
51095
+ try {
51096
+ const elapsed = current - this.timeStart;
51097
+ const stallElapsed = current - this.stallLastTime;
51098
+ if (!this.stallSent || stallElapsed >= STALL_MEASURE_PERIOD) {
51099
+ this.sendStall(current);
51100
+ }
51101
+ if (!this.watchSent && elapsed >= WATCH_CUTOFF) {
51102
+ this.watchSent = true;
51103
+ this.send({
51104
+ event: TelemetryEvent.Watch,
51105
+ });
51106
+ }
51107
+ }
51108
+ catch (error) {
51109
+ reportError(error);
51110
+ }
51111
+ }
51112
+ onStart() {
51113
+ if (this.started) {
51114
+ return;
51115
+ }
51116
+ this.started = true;
51117
+ this.send({
51118
+ event: TelemetryEvent.Start,
51119
+ });
51120
+ }
51121
+ }
51122
+
50764
51123
  var parseSrt$1 = {exports: {}};
50765
51124
 
50766
51125
  var parseSrt = parseSrt$1.exports;
@@ -50877,7 +51236,7 @@ const parseSRT = /*@__PURE__*/getDefaultExportFromCjs$1(parseSrtExports);
50877
51236
 
50878
51237
  const pluginHtml = "<div class=\"thumbnails-text\"></div>\n<% if (backdropHeight) { %>\n <div class=\"backdrop\" style=\"height: <%= backdropHeight %>px;\">\n <div class=\"carousel\"></div>\n </div>\n<% }; %>\n<% if (spotlightHeight) { %>\n <div class=\"spotlight\" style=\"height: <%= spotlightHeight %>px;\">\n </div>\n<% }; %>\n";
50879
51238
 
50880
- const T$1 = 'plugins.media_control_thumbnails';
51239
+ const T = 'plugins.media_control_thumbnails';
50881
51240
  class Thumbnails extends UICorePlugin {
50882
51241
  _$spotlight = null;
50883
51242
  _$backdrop = null;
@@ -51148,7 +51507,7 @@ class Thumbnails extends UICorePlugin {
51148
51507
  // calculate how far along the carousel should currently be slid
51149
51508
  // depending on where the user is hovering on the progress bar
51150
51509
  _updateCarousel() {
51151
- trace(`${T$1} _updateCarousel`, {
51510
+ trace(`${T} _updateCarousel`, {
51152
51511
  backdropHeight: this._getOptions().backdropHeight,
51153
51512
  });
51154
51513
  if (!this._getOptions().backdropHeight) {
@@ -51207,7 +51566,7 @@ class Thumbnails extends UICorePlugin {
51207
51566
  }
51208
51567
  }
51209
51568
  _updateSpotlightThumb() {
51210
- trace(`${T$1} _updateSpotlightThumb`, {
51569
+ trace(`${T} _updateSpotlightThumb`, {
51211
51570
  spotlightHeight: this._getOptions().spotlightHeight,
51212
51571
  });
51213
51572
  if (!this._getOptions().spotlightHeight) {
@@ -51252,7 +51611,7 @@ class Thumbnails extends UICorePlugin {
51252
51611
  return 0;
51253
51612
  }
51254
51613
  _renderPlugin() {
51255
- trace(`${T$1} _renderPlugin`, {
51614
+ trace(`${T} _renderPlugin`, {
51256
51615
  show: this._show,
51257
51616
  thumbsLoaded: this._thumbsLoaded,
51258
51617
  thumbs: this._thumbs.length,
@@ -51270,7 +51629,7 @@ class Thumbnails extends UICorePlugin {
51270
51629
  }
51271
51630
  }
51272
51631
  _createElements() {
51273
- trace(`${T$1} _createElements`);
51632
+ trace(`${T} _createElements`);
51274
51633
  this.$el.html(this.template({
51275
51634
  'backdropHeight': this._getOptions().backdropHeight,
51276
51635
  'spotlightHeight': this._getOptions().spotlightHeight
@@ -51285,203 +51644,6 @@ class Thumbnails extends UICorePlugin {
51285
51644
  }
51286
51645
  }
51287
51646
 
51288
- const T = 'plugins.source_controller';
51289
- const INITIAL_RETRY_DELAY = 1000;
51290
- const MAX_RETRY_DELAY = 5000;
51291
- const RETRY_DELAY_BLUR = 500;
51292
- const VERSION = '0.0.1';
51293
- function noSync(cb) {
51294
- queueMicrotask(cb);
51295
- }
51296
- /**
51297
- * This plugin is responsible for managing the automatic failover between sources.
51298
- * @beta
51299
- * @remarks
51300
- * Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
51301
- * on how sources ordering and selection works.
51302
- *
51303
- * This plugin does not expose any public methods apart from required by the Clappr plugin interface.
51304
- * It is supposed to work autonomously.
51305
- *
51306
- * @example
51307
- * ```ts
51308
- * import { SourceController } from '@gcorevideo/player'
51309
- *
51310
- * Player.registerPlugin(SourceController)
51311
- * ```
51312
- */
51313
- class SourceController extends CorePlugin {
51314
- /*
51315
- * The Logic itself is quite simple:
51316
- * * Here is the short diagram:
51317
- *
51318
- * sources_list:
51319
- * - a.mpd | +--------------------+
51320
- * - b.m3u8 |--->| init |
51321
- * - ... | |--------------------|
51322
- * | current_source = 0 |
51323
- * +--------------------+
51324
- * |
51325
- * | source = a.mpd
51326
- * | playback = dash.js
51327
- * v
51328
- * +------------------+
51329
- * +-->| load source |
51330
- * | +---------|--------+
51331
- * | v
51332
- * | +------------------+
51333
- * | | play |
51334
- * | +---------|--------+
51335
- * | |
51336
- * | v
51337
- * | +-----------------------+
51338
- * | | on playback_error |
51339
- * | |-----------------------|
51340
- * | | current_source = |
51341
- * | | (current_source + 1) |
51342
- * | | % len sources_list |
51343
- * | | |
51344
- * | | delay 1..3s |
51345
- * | +---------------|-------+
51346
- * | |
51347
- * | source=b.m3u8 |
51348
- * | playback=hls.js |
51349
- * +-------------------+
51350
- *
51351
- */
51352
- sourcesList = [];
51353
- currentSourceIndex = 0;
51354
- sourcesDelay = {};
51355
- active = false;
51356
- sync = noSync;
51357
- /**
51358
- * @internal
51359
- */
51360
- get name() {
51361
- return 'source_controller';
51362
- }
51363
- /**
51364
- * @internal
51365
- */
51366
- get supportedVersion() {
51367
- return { min: CLAPPR_VERSION };
51368
- }
51369
- constructor(core) {
51370
- super(core);
51371
- this.sourcesList = this.core.options.sources;
51372
- if (this.core.options.source !== undefined) {
51373
- // prevent Clappr from loading all sources simultaneously
51374
- this.core.options.sources = [this.core.options.source];
51375
- }
51376
- else {
51377
- this.core.options.sources = this.core.options.sources.slice(0, 1);
51378
- }
51379
- }
51380
- /**
51381
- * @internal
51382
- */
51383
- bindEvents() {
51384
- super.bindEvents();
51385
- this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, () => this.onReady());
51386
- }
51387
- onReady() {
51388
- trace(`${T} onReady`, {
51389
- retrying: this.active,
51390
- currentSource: this.sourcesList[this.currentSourceIndex],
51391
- });
51392
- const spinner = this.core.activeContainer?.getPlugin('spinner');
51393
- if (spinner) {
51394
- this.sync = (cb) => {
51395
- spinner.once(SpinnerEvents.SYNC, cb);
51396
- };
51397
- }
51398
- else {
51399
- this.sync = noSync;
51400
- }
51401
- this.bindContainerEventListeners();
51402
- if (this.active) {
51403
- this.core.activeContainer?.getPlugin('poster_custom')?.disable();
51404
- spinner?.show();
51405
- }
51406
- }
51407
- bindContainerEventListeners() {
51408
- this.core.activePlayback.on(Events$1.PLAYBACK_ERROR, (error) => {
51409
- trace(`${T} on PLAYBACK_ERROR`, {
51410
- error: {
51411
- code: error?.code,
51412
- description: error?.description,
51413
- level: error?.level,
51414
- },
51415
- retrying: this.active,
51416
- currentSource: this.sourcesList[this.currentSourceIndex],
51417
- });
51418
- switch (error.code) {
51419
- case PlaybackErrorCode.MediaSourceUnavailable:
51420
- this.core.activeContainer?.getPlugin('poster_custom')?.disable();
51421
- this.retryPlayback();
51422
- break;
51423
- }
51424
- });
51425
- this.core.activePlayback.on(Events$1.PLAYBACK_PLAY, () => {
51426
- trace(`${T} on PLAYBACK_PLAY`, {
51427
- currentSource: this.sourcesList[this.currentSourceIndex],
51428
- retrying: this.active,
51429
- });
51430
- if (this.active) {
51431
- this.reset();
51432
- // TODO make poster reset its state on enable
51433
- this.core.activeContainer?.getPlugin('poster_custom')?.enable();
51434
- this.core.activeContainer?.getPlugin('spinner')?.hide();
51435
- }
51436
- });
51437
- }
51438
- reset() {
51439
- this.active = false;
51440
- this.sourcesDelay = {};
51441
- }
51442
- retryPlayback() {
51443
- trace(`${T} retryPlayback enter`, {
51444
- currentSourceIndex: this.currentSourceIndex,
51445
- currentSource: this.sourcesList[this.currentSourceIndex],
51446
- });
51447
- this.active = true;
51448
- this.getNextMediaSource().then((nextSource) => {
51449
- trace(`${T} retryPlayback syncing...`, {
51450
- nextSource,
51451
- });
51452
- const rnd = RETRY_DELAY_BLUR * Math.random();
51453
- this.sync(() => {
51454
- trace(`${T} retryPlayback loading...`);
51455
- this.core.load(nextSource.source, nextSource.mimeType);
51456
- trace(`${T} retryPlayback loaded`, {
51457
- nextSource,
51458
- });
51459
- setTimeout(() => {
51460
- // this.core.activePlayback.consent()
51461
- this.core.activePlayback.play();
51462
- trace(`${T} retryPlayback playing`);
51463
- }, rnd);
51464
- });
51465
- });
51466
- }
51467
- getNextMediaSource() {
51468
- return new Promise((resolve) => {
51469
- this.sourcesDelay[this.currentSourceIndex] = Math.min(MAX_RETRY_DELAY, (this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY) * 2);
51470
- this.currentSourceIndex =
51471
- (this.currentSourceIndex + 1) % this.sourcesList.length;
51472
- const delay = this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY;
51473
- const s = this.sourcesList[this.currentSourceIndex];
51474
- setTimeout(() => resolve(s), delay);
51475
- });
51476
- }
51477
- /**
51478
- * @internal
51479
- */
51480
- static get version() {
51481
- return VERSION;
51482
- }
51483
- }
51484
-
51485
51647
  var VolumeFadeEvents;
51486
51648
  (function (VolumeFadeEvents) {
51487
51649
  VolumeFadeEvents["FADE"] = "core:volume:fade";
@@ -51494,15 +51656,22 @@ class VolumeFade extends UICorePlugin {
51494
51656
  container = null;
51495
51657
  delay = 0;
51496
51658
  interval = null;
51659
+ /**
51660
+ * @internal
51661
+ */
51497
51662
  get name() {
51498
51663
  return 'volume_fade';
51499
51664
  }
51665
+ /**
51666
+ * @internal
51667
+ */
51500
51668
  bindEvents() {
51669
+ // TODO on container changed
51501
51670
  this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
51502
51671
  if (this.core.mediaControl) {
51503
51672
  this.listenTo(this.core.mediaControl, 'mediacontrol:volume:user', this._onUserChangeVolume);
51504
51673
  }
51505
- this.listenTo(this.core, 'core:volume:config', this._onVolumeConfig);
51674
+ // this.listenTo(this.core, 'core:volume:config', this._onVolumeConfig);
51506
51675
  }
51507
51676
  unBindEvents() {
51508
51677
  this.core.$el.off('mouseleave.volume');
@@ -51574,4 +51743,4 @@ class VolumeFade extends UICorePlugin {
51574
51743
  }
51575
51744
  }
51576
51745
 
51577
- export { AudioSelector, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause, ClipsPlugin, ContextMenu, DisableControls, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, Kibo, LevelSelector, LogTracer, Logger, Logo, MediaControl, MultiCamera, PictureInPicture, PlaybackErrorCode, PlaybackRate, Player, PlayerEvent, Poster, SeekTime, SentryTracer, Share, SkipTime, SourceController, SpinnerEvents, SpinnerThreeBounce, Statistics, Subtitles, Thumbnails, VolumeFade, VolumeFadeEvents, reportError, setTracer, trace, version };
51746
+ export { AudioSelector, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause, ClipsPlugin, ContextMenu, DisableControls, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, Kibo, LevelSelector, LogTracer, Logger, Logo, MediaControl, MultiCamera, PictureInPicture, PlaybackErrorCode, PlaybackRate, Player, PlayerEvent, Poster, SeekTime, SentryTracer, Share, SkipTime, SourceController, SpinnerEvents, SpinnerThreeBounce, Subtitles, Telemetry, TelemetryEvent, Thumbnails, VolumeFade, VolumeFadeEvents, reportError, setTracer, trace, version };