@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
@@ -31717,7 +31717,7 @@ const volumeOffIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fil
31717
31717
 
31718
31718
  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";
31719
31719
 
31720
- const T$8 = "plugins.big_mute_button";
31720
+ const T$9 = "plugins.big_mute_button";
31721
31721
  /**
31722
31722
  * @beta
31723
31723
  */
@@ -31746,7 +31746,7 @@ class BigMuteButton extends UICorePlugin {
31746
31746
  this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
31747
31747
  this.listenTo(this.core, 'core:advertisement:start', this.onStartAd);
31748
31748
  this.listenTo(this.core, 'core:advertisement:finish', this.onFinishAd);
31749
- trace(`${T$8} bindEvents`, {
31749
+ trace(`${T$9} bindEvents`, {
31750
31750
  mediacontrol: !!this.core.mediaControl,
31751
31751
  });
31752
31752
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED, this.mediaControlRendered);
@@ -31811,7 +31811,7 @@ class BigMuteButton extends UICorePlugin {
31811
31811
  }
31812
31812
  render() {
31813
31813
  if (this.shouldRender()) {
31814
- trace(`${T$8} render`, {
31814
+ trace(`${T$9} render`, {
31815
31815
  el: !!this.$el,
31816
31816
  });
31817
31817
  this.$el.html(this.template());
@@ -34962,7 +34962,7 @@ const qualityClasses = [
34962
34962
  'speedtest-quality-value-2',
34963
34963
  'speedtest-quality-value-3',
34964
34964
  'speedtest-quality-value-4',
34965
- 'speedtest-quality-value-5'
34965
+ 'speedtest-quality-value-5',
34966
34966
  ];
34967
34967
  const getDownloadQuality = (speedValue) => {
34968
34968
  if (speedValue < 3) {
@@ -35026,7 +35026,22 @@ const drawSummary = (customMetrics, vodContainer, liveContainer) => {
35026
35026
  };
35027
35027
  // const T = 'plugins.clappr_nerd_stats';
35028
35028
  /**
35029
+ * Displays useful network-related statistics.
35029
35030
  * @beta
35031
+ *
35032
+ * @remarks
35033
+ * Depends on:
35034
+ *
35035
+ * - {@link MediaControl}
35036
+ *
35037
+ * - {@link BottomGear}
35038
+ *
35039
+ * - {@link ClapprStats}
35040
+ *
35041
+ * The plugin is rendered as an item in the gear menu.
35042
+ *
35043
+ * When clicked, it shows an overlay window with the information about the network speed, latency, etc,
35044
+ * and recommended quality level.
35030
35045
  */
35031
35046
  class ClapprNerdStats extends UICorePlugin {
35032
35047
  container = null;
@@ -35039,21 +35054,31 @@ class ClapprNerdStats extends UICorePlugin {
35039
35054
  showing = false;
35040
35055
  shortcut;
35041
35056
  iconPosition;
35057
+ /**
35058
+ * @internal
35059
+ */
35042
35060
  get name() {
35043
35061
  return 'nerd_stats';
35044
35062
  }
35063
+ /**
35064
+ * @internal
35065
+ */
35045
35066
  get supportedVersion() {
35046
35067
  return { min: CLAPPR_VERSION };
35047
35068
  }
35048
- get template() {
35049
- return tmpl(pluginHtml$5);
35050
- }
35069
+ static template = tmpl(pluginHtml$5);
35070
+ /**
35071
+ * @internal
35072
+ */
35051
35073
  get attributes() {
35052
35074
  return {
35053
35075
  'data-clappr-nerd-stats': '',
35054
- 'class': 'clappr-nerd-stats'
35076
+ class: 'clappr-nerd-stats',
35055
35077
  };
35056
35078
  }
35079
+ /**
35080
+ * @internal
35081
+ */
35057
35082
  get events() {
35058
35083
  return {
35059
35084
  'click [data-show-stats-button]': 'showOrHide',
@@ -35075,8 +35100,12 @@ class ClapprNerdStats extends UICorePlugin {
35075
35100
  }
35076
35101
  constructor(core) {
35077
35102
  super(core);
35078
- this.shortcut = core.options.clapprNerdStats?.shortcut ?? ['command+shift+s', 'ctrl+shift+s'];
35079
- this.iconPosition = core.options.clapprNerdStats?.iconPosition ?? 'bottom-right';
35103
+ this.shortcut = core.options.clapprNerdStats?.shortcut ?? [
35104
+ 'command+shift+s',
35105
+ 'ctrl+shift+s',
35106
+ ];
35107
+ this.iconPosition =
35108
+ core.options.clapprNerdStats?.iconPosition ?? 'bottom-right';
35080
35109
  this.customMetrics = {
35081
35110
  connectionSpeed: 0,
35082
35111
  ping: 0,
@@ -35084,6 +35113,9 @@ class ClapprNerdStats extends UICorePlugin {
35084
35113
  };
35085
35114
  configureSpeedTest(core.options.clapprNerdStats?.speedTestServers ?? []);
35086
35115
  }
35116
+ /**
35117
+ * @internal
35118
+ */
35087
35119
  bindEvents() {
35088
35120
  const mediaControl = this.core.getPlugin('media_control');
35089
35121
  assert(mediaControl, 'media_control plugin is required');
@@ -35120,9 +35152,11 @@ class ClapprNerdStats extends UICorePlugin {
35120
35152
  this.core.$el.find(this.statsBoxElem).show();
35121
35153
  this.showing = true;
35122
35154
  this.refreshSpeedTest();
35123
- initSpeedTest(this.customMetrics).then(() => {
35155
+ initSpeedTest(this.customMetrics)
35156
+ .then(() => {
35124
35157
  startSpeedtest();
35125
- }).catch(e => {
35158
+ })
35159
+ .catch((e) => {
35126
35160
  this.disable();
35127
35161
  });
35128
35162
  }
@@ -35136,13 +35170,19 @@ class ClapprNerdStats extends UICorePlugin {
35136
35170
  }
35137
35171
  addGeneralMetrics() {
35138
35172
  this.metrics.general = {
35139
- displayResolution: (this.playerWidth + 'x' + this.playerHeight),
35140
- volume: this.container?.volume
35173
+ displayResolution: this.playerWidth + 'x' + this.playerHeight,
35174
+ volume: this.container?.volume,
35141
35175
  };
35142
35176
  }
35143
35177
  addCustomMetrics() {
35144
35178
  this.metrics.custom = this.customMetrics;
35145
- const videoQualityNames = ['SD (480p)', 'HD (720p)', 'Full HD (1080p)', '2K (1440p)', '4K (2160p)'];
35179
+ const videoQualityNames = [
35180
+ 'SD (480p)',
35181
+ 'HD (720p)',
35182
+ 'Full HD (1080p)',
35183
+ '2K (1440p)',
35184
+ '4K (2160p)',
35185
+ ];
35146
35186
  const { connectionSpeed, ping } = this.customMetrics;
35147
35187
  if (!connectionSpeed || !ping) {
35148
35188
  const calculatingText = 'Calculating... Please wait.';
@@ -35154,17 +35194,19 @@ class ClapprNerdStats extends UICorePlugin {
35154
35194
  const pingQuality = getPingQuality(ping);
35155
35195
  const liveQuality = Math.min(downloadQuality, pingQuality);
35156
35196
  const prefix = 'Optimal for ';
35157
- this.metrics.custom.vodQuality = prefix + videoQualityNames[downloadQuality - 1];
35158
- this.metrics.custom.liveQuality = prefix + videoQualityNames[liveQuality - 1];
35197
+ this.metrics.custom.vodQuality =
35198
+ prefix + videoQualityNames[downloadQuality - 1];
35199
+ this.metrics.custom.liveQuality =
35200
+ prefix + videoQualityNames[liveQuality - 1];
35159
35201
  }
35160
35202
  updateMetrics(metrics) {
35161
35203
  Object.assign(this.metrics, metrics);
35162
35204
  this.addGeneralMetrics();
35163
35205
  this.addCustomMetrics();
35164
35206
  const scrollTop = this.core.$el.find(this.statsBoxElem).scrollTop();
35165
- this.$el.html(this.template({
35207
+ this.$el.html(ClapprNerdStats.template({
35166
35208
  metrics: Formatter.format(this.metrics),
35167
- iconPosition: this.iconPosition
35209
+ iconPosition: this.iconPosition,
35168
35210
  }));
35169
35211
  this.setStatsBoxSize();
35170
35212
  drawSpeedTestResults();
@@ -35184,7 +35226,11 @@ class ClapprNerdStats extends UICorePlugin {
35184
35226
  this.$el.find(this.statsBoxElem).addClass('narrow');
35185
35227
  }
35186
35228
  }
35229
+ /**
35230
+ * @internal
35231
+ */
35187
35232
  render() {
35233
+ // TODO append to the container
35188
35234
  this.core.$el.append(this.$el[0]);
35189
35235
  this.hide();
35190
35236
  return this;
@@ -35986,8 +36032,11 @@ const dvrHTML = "<div class=\"live-info\"><%= live %></div>\n<button type=\"butt
35986
36032
  * @beta
35987
36033
  *
35988
36034
  * @remarks
35989
- * The plugin is rendered in the {@link MediaControl | media control} UI.
35990
- * It renders the live stream indicator and the DVR seek bar if DVR is enabled.
36035
+ * Depends on:
36036
+ *
36037
+ * - {@link MediaControl | media_control}
36038
+ *
36039
+ * The plugin renders the live stream indicator and the DVR seek bar, if DVR is enabled, in the media control UI.
35991
36040
  */
35992
36041
  class DvrControls extends UICorePlugin {
35993
36042
  static template = tmpl(dvrHTML);
@@ -36122,6 +36171,11 @@ const templateHtml = "<div class=\"player-error-screen__content\" data-error-scr
36122
36171
 
36123
36172
  const TIME_FOR_UPDATE = 10000;
36124
36173
  const MAX_RETRY = 10;
36174
+ /**
36175
+ * Displays a descriptive error in the overlay on top of the player.
36176
+ * @beta
36177
+ * TODO
36178
+ */
36125
36179
  class ErrorScreen extends UICorePlugin {
36126
36180
  _retry = 0;
36127
36181
  err = null;
@@ -36711,7 +36765,7 @@ function keyName(keyCode) {
36711
36765
 
36712
36766
  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";
36713
36767
 
36714
- 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";
36768
+ 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";
36715
36769
 
36716
36770
  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";
36717
36771
 
@@ -36721,7 +36775,7 @@ const arrowLeftIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fil
36721
36775
 
36722
36776
  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";
36723
36777
 
36724
- const T$7 = 'plugins.level_selector';
36778
+ const T$8 = 'plugins.level_selector';
36725
36779
  const VERSION$4 = '2.19.4';
36726
36780
  /**
36727
36781
  * A {@link MediaControl | media control} plugin that provides a UI to control the quality level of the playback.
@@ -36825,7 +36879,7 @@ class LevelSelector extends UICorePlugin {
36825
36879
  onStop() {
36826
36880
  const currentPlayback = this.core.activePlayback;
36827
36881
  this.listenToOnce(currentPlayback, Events$1.PLAYBACK_PLAY, () => {
36828
- trace(`${T$7} on PLAYBACK_PLAY after stop`, { selectedLevelId: this.selectedLevelId });
36882
+ trace(`${T$8} on PLAYBACK_PLAY after stop`, { selectedLevelId: this.selectedLevelId });
36829
36883
  if (currentPlayback.getPlaybackType() === 'live') {
36830
36884
  if (this.selectedLevelId !== -1) {
36831
36885
  currentPlayback.currentLevel = this.selectedLevelId;
@@ -36980,7 +37034,7 @@ class LevelSelector extends UICorePlugin {
36980
37034
  this.highlightCurrentLevel();
36981
37035
  }
36982
37036
  highlightCurrentLevel() {
36983
- trace(`${T$7} highlightCurrentLevel`, {
37037
+ trace(`${T$8} highlightCurrentLevel`, {
36984
37038
  selectedLevelId: this.selectedLevelId,
36985
37039
  });
36986
37040
  this.allLevelElements().removeClass('current');
@@ -38305,7 +38359,7 @@ const streamsMomentoIcon = "<svg id=\"Слой_1\" data-name=\"Слой 1\" xmln
38305
38359
  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";
38306
38360
 
38307
38361
  const VERSION$3 = '0.0.1';
38308
- const T$6 = 'plugins.media_control_multicamera';
38362
+ const T$7 = 'plugins.media_control_multicamera';
38309
38363
  class MultiCamera extends UICorePlugin {
38310
38364
  currentCamera = null;
38311
38365
  currentTime = 0;
@@ -38574,7 +38628,7 @@ class MultiCamera extends UICorePlugin {
38574
38628
  // TODO figure out what this does
38575
38629
  playbackOptions.recycleVideo = Browser.isMobile;
38576
38630
  this.currentCamera = this.findElementById(id) ?? null;
38577
- trace(`${T$6} changeById`, { currentCamera: this.currentCamera, multicamera: this.multicamera });
38631
+ trace(`${T$7} changeById`, { currentCamera: this.currentCamera, multicamera: this.multicamera });
38578
38632
  if (!this.currentCamera) {
38579
38633
  return;
38580
38634
  }
@@ -38590,7 +38644,7 @@ class MultiCamera extends UICorePlugin {
38590
38644
  // TODO remove?
38591
38645
  // for html5 playback:
38592
38646
  this.options.dvrEnabled = this.currentCamera.dvr;
38593
- trace(`${T$6} changeById`, { currentCamera: this.currentCamera });
38647
+ trace(`${T$7} changeById`, { currentCamera: this.currentCamera });
38594
38648
  // TODO
38595
38649
  this.core.configure({
38596
38650
  playback: playbackOptions,
@@ -38648,17 +38702,39 @@ const pipIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"no
38648
38702
  const buttonHtml$1 = "<button class=\"gplayer-lite-btn gcore-skin-button-color\">\n <span><%= pipIcon %></span>\n</button>\n";
38649
38703
 
38650
38704
  const VERSION$2 = '0.0.1';
38651
- const T$5 = `plugins.media_control_pip`;
38705
+ const T$6 = `plugins.pip`;
38706
+ /**
38707
+ * Enables picture in picture mode.
38708
+ * @beta
38709
+ * @remarks
38710
+ * Depends on:
38711
+ *
38712
+ * - {@link MediaControl}
38713
+ *
38714
+ * It renders a button to toggle picture in picture mode in the media control UI.
38715
+ */
38652
38716
  class PictureInPicture extends UICorePlugin {
38717
+ /**
38718
+ * @internal
38719
+ */
38653
38720
  get name() {
38654
- return 'media_control_pip';
38721
+ return 'pip';
38655
38722
  }
38723
+ /**
38724
+ * @internal
38725
+ */
38656
38726
  get supportedVersion() {
38657
38727
  return { min: CLAPPR_VERSION };
38658
38728
  }
38729
+ /**
38730
+ * @internal
38731
+ */
38659
38732
  static get version() {
38660
38733
  return VERSION$2;
38661
38734
  }
38735
+ /**
38736
+ * @internal
38737
+ */
38662
38738
  get events() {
38663
38739
  return {
38664
38740
  'click button': 'togglePictureInPicture',
@@ -38667,12 +38743,18 @@ class PictureInPicture extends UICorePlugin {
38667
38743
  get videoElement() {
38668
38744
  return this.core.activePlayback.el;
38669
38745
  }
38746
+ /**
38747
+ * @internal
38748
+ */
38670
38749
  bindEvents() {
38671
38750
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED, this.render);
38672
38751
  }
38673
38752
  isPiPSupported() {
38674
38753
  return document.pictureInPictureEnabled && !!HTMLVideoElement.prototype.requestPictureInPicture;
38675
38754
  }
38755
+ /**
38756
+ * @internal
38757
+ */
38676
38758
  render() {
38677
38759
  if (!this.isPiPSupported()) {
38678
38760
  return this;
@@ -38694,7 +38776,7 @@ class PictureInPicture extends UICorePlugin {
38694
38776
  }
38695
38777
  }
38696
38778
  requestPictureInPicture() {
38697
- trace(`${T$5} requestPictureInPicture`, {
38779
+ trace(`${T$6} requestPictureInPicture`, {
38698
38780
  videoElement: !!this.videoElement,
38699
38781
  });
38700
38782
  this.videoElement.requestPictureInPicture();
@@ -38724,26 +38806,51 @@ const DEFAULT_PLAYBACK_RATES = [
38724
38806
  const DEFAULT_PLAYBACK_RATE = '1.0';
38725
38807
  // TODO
38726
38808
  const MEDIACONTROL_PLAYBACKRATE = 'playbackRate';
38809
+ /**
38810
+ * Allows changing the playback speed of the video.
38811
+ * @beta
38812
+ *
38813
+ * @remarks
38814
+ * Depends on:
38815
+ *
38816
+ * - {@link MediaControl | media_control}
38817
+ *
38818
+ * - {@link BottomGear | bottom_gear}
38819
+ *
38820
+ * It renders a button in the gear menu, which opens a dropdown with the available playback rates.
38821
+ */
38727
38822
  class PlaybackRate extends UICorePlugin {
38728
38823
  currentPlayback = null;
38729
38824
  playbackRates = DEFAULT_PLAYBACK_RATES;
38730
38825
  prevSelectedRate;
38731
38826
  selectedRate = DEFAULT_PLAYBACK_RATE;
38827
+ /**
38828
+ * @internal
38829
+ */
38732
38830
  get name() {
38733
- return 'media_control_playback_rate';
38831
+ return 'playback_rate';
38734
38832
  }
38833
+ /**
38834
+ * @internal
38835
+ */
38735
38836
  get supportedVersion() {
38736
38837
  return { min: CLAPPR_VERSION };
38737
38838
  }
38738
- get template() {
38739
- return tmpl(pluginHtml$3);
38740
- }
38839
+ static template = tmpl(pluginHtml$3);
38840
+ static buttonTemplate = tmpl(buttonHtml);
38841
+ static listTemplate = tmpl(listHtml);
38842
+ /**
38843
+ * @internal
38844
+ */
38741
38845
  get attributes() {
38742
38846
  return {
38743
38847
  'class': this.name,
38744
38848
  'data-playback-rate-select': ''
38745
38849
  };
38746
38850
  }
38851
+ /**
38852
+ * @internal
38853
+ */
38747
38854
  get events() {
38748
38855
  return {
38749
38856
  'click .gear-sub-menu_btn': 'onRateSelect',
@@ -38751,8 +38858,12 @@ class PlaybackRate extends UICorePlugin {
38751
38858
  'click .go-back': 'goBack',
38752
38859
  };
38753
38860
  }
38861
+ /**
38862
+ * @internal
38863
+ */
38754
38864
  bindEvents() {
38755
38865
  this.listenTo(this.core, 'gear:rendered', this.render);
38866
+ // TODO this.core.getPlugin('media_control'), bottom_gear
38756
38867
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_CONTAINERCHANGED, this.reload);
38757
38868
  this.listenTo(this.core.mediaControl, MEDIACONTROL_PLAYBACKRATE, this.updatePlaybackRate);
38758
38869
  this.listenTo(this.core, 'core:advertisement:start', this.onStartAd);
@@ -38806,6 +38917,9 @@ class PlaybackRate extends UICorePlugin {
38806
38917
  this.currentPlayback = this.core.activePlayback;
38807
38918
  return !(this.currentPlayback?.tagName !== 'video' && this.currentPlayback?.tagName !== 'audio');
38808
38919
  }
38920
+ /**
38921
+ * @internal
38922
+ */
38809
38923
  render() {
38810
38924
  const container = this.core.activeContainer;
38811
38925
  if (this.core.getPlaybackType() === Playback.LIVE && !container.isDvrEnabled()) {
@@ -38819,9 +38933,7 @@ class PlaybackRate extends UICorePlugin {
38819
38933
  this.selectedRate = cfg.defaultValue || DEFAULT_PLAYBACK_RATE;
38820
38934
  }
38821
38935
  if (this.shouldRender()) {
38822
- const t = tmpl(buttonHtml);
38823
- // const html = t({ playbackRates: this.playbackRates, title: this.getTitle() });
38824
- const button = t({
38936
+ const button = PlaybackRate.buttonTemplate({
38825
38937
  title: this.getTitle(),
38826
38938
  speedIcon,
38827
38939
  arrowRightIcon,
@@ -38869,8 +38981,7 @@ class PlaybackRate extends UICorePlugin {
38869
38981
  return false;
38870
38982
  }
38871
38983
  onShowMenu() {
38872
- const t = tmpl(listHtml);
38873
- this.$el.html(t({
38984
+ this.$el.html(PlaybackRate.listTemplate({
38874
38985
  playbackRates: this.playbackRates,
38875
38986
  arrowLeftIcon,
38876
38987
  checkIcon,
@@ -38914,7 +39025,7 @@ const posterHTML = "<div class=\"play-wrapper\" data-poster></div>\n";
38914
39025
  //Copyright 2014 Globo.com Player authors. All rights reserved.
38915
39026
  // Use of this source code is governed by a BSD-style
38916
39027
  // license that can be found in the LICENSE file.
38917
- const T$4 = 'plugins.poster_custom';
39028
+ const T$5 = 'plugins.poster_custom';
38918
39029
  /**
38919
39030
  * Displays a poster image in the background and a big play button on top when playback is stopped
38920
39031
  * @beta
@@ -39022,7 +39133,7 @@ class Poster extends UIContainerPlugin {
39022
39133
  super.disable();
39023
39134
  }
39024
39135
  onError(error) {
39025
- trace(`${T$4} onError`, {
39136
+ trace(`${T$5} onError`, {
39026
39137
  enabled: this.enabled,
39027
39138
  });
39028
39139
  this.hasFatalError = error.level === PlayerError.Levels.FATAL;
@@ -39043,7 +39154,7 @@ class Poster extends UIContainerPlugin {
39043
39154
  this.update();
39044
39155
  }
39045
39156
  onStop() {
39046
- trace(`${T$4} onStop`, {
39157
+ trace(`${T$5} onStop`, {
39047
39158
  enabled: this.enabled,
39048
39159
  });
39049
39160
  this.hasStartedPlaying = false;
@@ -39051,7 +39162,7 @@ class Poster extends UIContainerPlugin {
39051
39162
  this.update();
39052
39163
  }
39053
39164
  updatePlayButton(show) {
39054
- trace(`${T$4} updatePlayButton`, {
39165
+ trace(`${T$5} updatePlayButton`, {
39055
39166
  chromeless: this.options.chromeless,
39056
39167
  allowUserInteraction: this.options.allowUserInteraction,
39057
39168
  });
@@ -39079,7 +39190,7 @@ class Poster extends UIContainerPlugin {
39079
39190
  this.$el.removeClass('clickable');
39080
39191
  }
39081
39192
  clicked() {
39082
- trace(`${T$4} clicked`, {
39193
+ trace(`${T$5} clicked`, {
39083
39194
  hasStartedPlaying: this.hasStartedPlaying,
39084
39195
  chromeless: this.options.chromeless,
39085
39196
  allowUserInteraction: this.options.allowUserInteraction,
@@ -39103,7 +39214,7 @@ class Poster extends UIContainerPlugin {
39103
39214
  return !this.container.playback.isAudioOnly;
39104
39215
  }
39105
39216
  update() {
39106
- trace(`${T$4} update`, {
39217
+ trace(`${T$5} update`, {
39107
39218
  shouldRender: this.shouldRender,
39108
39219
  });
39109
39220
  if (!this.shouldRender) {
@@ -39116,7 +39227,7 @@ class Poster extends UIContainerPlugin {
39116
39227
  this.updatePoster();
39117
39228
  }
39118
39229
  updatePoster() {
39119
- trace(`${T$4} updatePoster`, {
39230
+ trace(`${T$5} updatePoster`, {
39120
39231
  hasStartedPlaying: this.hasStartedPlaying,
39121
39232
  });
39122
39233
  if (!this.hasStartedPlaying) {
@@ -39131,7 +39242,7 @@ class Poster extends UIContainerPlugin {
39131
39242
  this.$el.show();
39132
39243
  }
39133
39244
  hidePoster() {
39134
- trace(`${T$4} hidePoster`, {
39245
+ trace(`${T$5} hidePoster`, {
39135
39246
  shouldHideOnPlay: this.shouldHideOnPlay(),
39136
39247
  });
39137
39248
  if (!this.options.disableMediaControl) {
@@ -39568,7 +39679,7 @@ const spinnerHTML = "<div data-bounce1></div>\n<div data-bounce2></div>\n<div da
39568
39679
  // Copyright 2014 Globo.com Player authors. All rights reserved.
39569
39680
  // Use of this source code is governed by a BSD-style
39570
39681
  // license that can be found in the LICENSE file.
39571
- const T$3 = 'plugins.spinner';
39682
+ const T$4 = 'plugins.spinner';
39572
39683
  /**
39573
39684
  * Custom events emitted by the plugin
39574
39685
  */
@@ -39636,7 +39747,7 @@ class SpinnerThreeBounce extends UIContainerPlugin {
39636
39747
  this.hide();
39637
39748
  }
39638
39749
  onStop() {
39639
- trace(`${T$3} onStop`, {
39750
+ trace(`${T$4} onStop`, {
39640
39751
  showOnError: this.options.spinner?.showOnError,
39641
39752
  hasFatalError: this.hasFatalError,
39642
39753
  });
@@ -39646,7 +39757,7 @@ class SpinnerThreeBounce extends UIContainerPlugin {
39646
39757
  }
39647
39758
  onError(e) {
39648
39759
  this.hasFatalError = e.code === PlaybackErrorCode.MediaSourceUnavailable;
39649
- trace(`${T$3} onError`, {
39760
+ trace(`${T$4} onError`, {
39650
39761
  showOnError: this.options.spinner?.showOnError,
39651
39762
  hasFatalError: this.hasFatalError,
39652
39763
  error: e.code,
@@ -39679,7 +39790,7 @@ class SpinnerThreeBounce extends UIContainerPlugin {
39679
39790
  */
39680
39791
  render() {
39681
39792
  const showOnStart = this.options.spinner?.showOnStart;
39682
- trace(`${T$3} render`, {
39793
+ trace(`${T$4} render`, {
39683
39794
  buffering: this.container.buffering});
39684
39795
  this.$el.html(this.template());
39685
39796
  this.el.firstElementChild?.addEventListener('animationiteration', () => {
@@ -39696,128 +39807,192 @@ class SpinnerThreeBounce extends UIContainerPlugin {
39696
39807
  }
39697
39808
  }
39698
39809
 
39699
- // An example implementation of client side performancestatistics
39700
- const CUSTOM_EVENTS_CONTAINER_START = 'container:start';
39701
- const WATCH_CUTOFF = 5;
39702
- const HEATMAP_INTERVAL = 10;
39703
- // TODO rewrite as core plugin
39704
- class Statistics extends ContainerPlugin {
39810
+ const T$3 = 'plugins.source_controller';
39811
+ const INITIAL_RETRY_DELAY = 1000;
39812
+ const MAX_RETRY_DELAY = 5000;
39813
+ const RETRY_DELAY_BLUR = 500;
39814
+ const VERSION$1 = '0.0.1';
39815
+ function noSync(cb) {
39816
+ queueMicrotask(cb);
39817
+ }
39818
+ /**
39819
+ * This plugin is responsible for managing the automatic failover between sources.
39820
+ * @beta
39821
+ * @remarks
39822
+ * Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
39823
+ * on how sources ordering and selection works.
39824
+ *
39825
+ * This plugin does not expose any public methods apart from required by the Clappr plugin interface.
39826
+ * It is supposed to work autonomously.
39827
+ *
39828
+ * @example
39829
+ * ```ts
39830
+ * import { SourceController } from '@gcorevideo/player'
39831
+ *
39832
+ * Player.registerPlugin(SourceController)
39833
+ * ```
39834
+ */
39835
+ class SourceController extends CorePlugin {
39836
+ /*
39837
+ * The Logic itself is quite simple:
39838
+ * * Here is the short diagram:
39839
+ *
39840
+ * sources_list:
39841
+ * - a.mpd | +--------------------+
39842
+ * - b.m3u8 |--->| init |
39843
+ * - ... | |--------------------|
39844
+ * | current_source = 0 |
39845
+ * +--------------------+
39846
+ * |
39847
+ * | source = a.mpd
39848
+ * | playback = dash.js
39849
+ * v
39850
+ * +------------------+
39851
+ * +-->| load source |
39852
+ * | +---------|--------+
39853
+ * | v
39854
+ * | +------------------+
39855
+ * | | play |
39856
+ * | +---------|--------+
39857
+ * | |
39858
+ * | v
39859
+ * | +-----------------------+
39860
+ * | | on playback_error |
39861
+ * | |-----------------------|
39862
+ * | | current_source = |
39863
+ * | | (current_source + 1) |
39864
+ * | | % len sources_list |
39865
+ * | | |
39866
+ * | | delay 1..3s |
39867
+ * | +---------------|-------+
39868
+ * | |
39869
+ * | source=b.m3u8 |
39870
+ * | playback=hls.js |
39871
+ * +-------------------+
39872
+ *
39873
+ */
39874
+ sourcesList = [];
39875
+ currentSourceIndex = 0;
39876
+ sourcesDelay = {};
39877
+ active = false;
39878
+ sync = noSync;
39879
+ /**
39880
+ * @internal
39881
+ */
39705
39882
  get name() {
39706
- return 'statistics_gplayer';
39883
+ return 'source_controller';
39707
39884
  }
39885
+ /**
39886
+ * @internal
39887
+ */
39708
39888
  get supportedVersion() {
39709
39889
  return { min: CLAPPR_VERSION };
39710
39890
  }
39711
- started = false;
39712
- timeStart = 0;
39713
- heatmapSent = false;
39714
- heatmapLastTime = 0;
39715
- watchSent = false;
39716
- bufTracking = false;
39717
- lags = 0;
39718
- /**
39719
- * The time when buffering last started.
39720
- */
39721
- bufLastStarted = 0;
39891
+ constructor(core) {
39892
+ super(core);
39893
+ this.sourcesList = this.core.options.sources;
39894
+ if (this.core.options.source !== undefined) {
39895
+ // prevent Clappr from loading all sources simultaneously
39896
+ this.core.options.sources = [this.core.options.source];
39897
+ }
39898
+ else {
39899
+ this.core.options.sources = this.core.options.sources.slice(0, 1);
39900
+ }
39901
+ }
39722
39902
  /**
39723
- * The accumulated buffering duration.
39903
+ * @internal
39724
39904
  */
39725
- bufAccDuration = 0;
39726
- constructor(container) {
39727
- super(container);
39728
- assert(this.options.statistics &&
39729
- typeof this.options.statistics.send === 'function', 'Statistics plugin requires statistics options');
39730
- }
39731
39905
  bindEvents() {
39732
- // TODO remove this
39733
- this.listenToOnce(this.container, CUSTOM_EVENTS_CONTAINER_START, this.onStart);
39734
- this.listenToOnce(this.container, Events$1.CONTAINER_READY, this.onReady);
39735
- this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERING, this.onBuffering);
39736
- this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERFULL, this.onBufferFull);
39737
- this.listenTo(this.container.playback, Events$1.PLAYBACK_TIMEUPDATE, this.onTimeUpdateLive);
39738
- this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_START, this.startLevelSwitch);
39739
- this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_END, this.stopLevelSwitch);
39740
- }
39741
- startLevelSwitch() {
39742
- this.bufTracking = false;
39743
- }
39744
- stopLevelSwitch() {
39745
- this.bufTracking = true;
39746
- }
39747
- onBuffering() {
39748
- if (this.bufTracking) {
39749
- this.bufLastStarted = performance.now();
39750
- }
39751
- }
39752
- onBufferFull() {
39753
- if (this.bufTracking && this.bufLastStarted) {
39754
- this.bufAccDuration += performance.now() - this.bufLastStarted;
39755
- this.lags++;
39756
- }
39757
- this.bufTracking = true;
39906
+ super.bindEvents();
39907
+ this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, () => this.onReady());
39758
39908
  }
39759
39909
  onReady() {
39760
- this.initEvent();
39761
- if (this.options.autoPlay) {
39762
- this.onStart();
39763
- }
39764
- }
39765
- initEvent() {
39766
- this.sendMessage('init');
39767
- }
39768
- sendMessage(state) {
39769
- this.send(state, {
39770
- // embed_url: this.options.referer,
39771
- // user_agent: Browser.userAgent
39772
- });
39773
- }
39774
- send(event, data = {}) {
39775
- this.options.statistics.send({
39776
- event,
39777
- type: this.container.getPlaybackType(),
39778
- ...data,
39910
+ trace(`${T$3} onReady`, {
39911
+ retrying: this.active,
39912
+ currentSource: this.sourcesList[this.currentSourceIndex],
39779
39913
  });
39780
- }
39781
- sendHeatmap(time) {
39782
- const res = {
39783
- buffering: Math.round(this.bufAccDuration),
39784
- lags: this.lags,
39785
- };
39786
- this.bufAccDuration = 0;
39787
- this.lags = 0;
39788
- if (this.container.getPlaybackType() === Playback.VOD) {
39789
- res.timestamp = time;
39790
- }
39791
- this.send('heatmap', res);
39792
- this.heatmapSent = true;
39793
- this.heatmapLastTime = time;
39794
- }
39795
- onTimeUpdateLive({ current }) {
39796
- // TODO check the `current` values for the live streams
39797
- if (!this.timeStart) {
39798
- this.timeStart = current;
39799
- }
39800
- try {
39801
- const elapsed = current - this.timeStart;
39802
- const heatmapElapsed = current - this.heatmapLastTime;
39803
- // TODO check if the heatmap is only needed for the live streams
39804
- if (!this.heatmapSent || heatmapElapsed >= HEATMAP_INTERVAL) {
39805
- this.sendHeatmap(current);
39806
- }
39807
- if (!this.watchSent && elapsed >= WATCH_CUTOFF) {
39808
- this.watchSent = true;
39809
- this.sendMessage('watch');
39810
- }
39914
+ const spinner = this.core.activeContainer?.getPlugin('spinner');
39915
+ if (spinner) {
39916
+ this.sync = (cb) => {
39917
+ spinner.once(SpinnerEvents.SYNC, cb);
39918
+ };
39811
39919
  }
39812
- catch (error) {
39920
+ else {
39921
+ this.sync = noSync;
39813
39922
  }
39814
- }
39815
- onStart() {
39816
- if (this.started) {
39817
- return;
39923
+ this.bindContainerEventListeners();
39924
+ if (this.active) {
39925
+ this.core.activeContainer?.getPlugin('poster_custom')?.disable();
39926
+ spinner?.show();
39818
39927
  }
39819
- this.started = true;
39820
- this.sendMessage('start');
39928
+ }
39929
+ bindContainerEventListeners() {
39930
+ this.core.activePlayback.on(Events$1.PLAYBACK_ERROR, (error) => {
39931
+ trace(`${T$3} on PLAYBACK_ERROR`, {
39932
+ error: {
39933
+ code: error?.code,
39934
+ description: error?.description,
39935
+ level: error?.level,
39936
+ },
39937
+ retrying: this.active,
39938
+ currentSource: this.sourcesList[this.currentSourceIndex],
39939
+ });
39940
+ switch (error.code) {
39941
+ case PlaybackErrorCode.MediaSourceUnavailable:
39942
+ this.core.activeContainer?.getPlugin('poster_custom')?.disable();
39943
+ this.retryPlayback();
39944
+ break;
39945
+ }
39946
+ });
39947
+ this.core.activePlayback.on(Events$1.PLAYBACK_PLAY, () => {
39948
+ trace(`${T$3} on PLAYBACK_PLAY`, {
39949
+ currentSource: this.sourcesList[this.currentSourceIndex],
39950
+ retrying: this.active,
39951
+ });
39952
+ if (this.active) {
39953
+ this.reset();
39954
+ // TODO make poster reset its state on enable
39955
+ this.core.activeContainer?.getPlugin('poster_custom')?.enable();
39956
+ this.core.activeContainer?.getPlugin('spinner')?.hide();
39957
+ }
39958
+ });
39959
+ }
39960
+ reset() {
39961
+ this.active = false;
39962
+ this.sourcesDelay = {};
39963
+ }
39964
+ retryPlayback() {
39965
+ trace(`${T$3} retryPlayback enter`, {
39966
+ currentSourceIndex: this.currentSourceIndex,
39967
+ currentSource: this.sourcesList[this.currentSourceIndex],
39968
+ });
39969
+ this.active = true;
39970
+ this.getNextMediaSource().then((nextSource) => {
39971
+ const rnd = RETRY_DELAY_BLUR * Math.random();
39972
+ this.sync(() => {
39973
+ this.core.load(nextSource.source, nextSource.mimeType);
39974
+ setTimeout(() => {
39975
+ // this.core.activePlayback.consent()
39976
+ this.core.activePlayback.play();
39977
+ }, rnd);
39978
+ });
39979
+ });
39980
+ }
39981
+ getNextMediaSource() {
39982
+ return new Promise((resolve) => {
39983
+ this.sourcesDelay[this.currentSourceIndex] = Math.min(MAX_RETRY_DELAY, (this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY) * 2);
39984
+ this.currentSourceIndex =
39985
+ (this.currentSourceIndex + 1) % this.sourcesList.length;
39986
+ const delay = this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY;
39987
+ const s = this.sourcesList[this.currentSourceIndex];
39988
+ setTimeout(() => resolve(s), delay);
39989
+ });
39990
+ }
39991
+ /**
39992
+ * @internal
39993
+ */
39994
+ static get version() {
39995
+ return VERSION$1;
39821
39996
  }
39822
39997
  }
39823
39998
 
@@ -39829,7 +40004,7 @@ const comboboxHTML = "<button data-subtitles-button class='media-control-button
39829
40004
 
39830
40005
  const stringHTML = "<div class=\"subtitle-string\">\n <p></p>\n</div>\n";
39831
40006
 
39832
- const VERSION$1 = '2.19.14';
40007
+ const VERSION = '2.19.14';
39833
40008
  const LOCAL_STORAGE_SUBTITLES_ID = 'gplayer.plugins.subtitles.selected';
39834
40009
  const T$2 = 'plugins.subtitles';
39835
40010
  const NO_TRACK = { language: 'off' };
@@ -39883,7 +40058,7 @@ class Subtitles extends UICorePlugin {
39883
40058
  * @internal
39884
40059
  */
39885
40060
  static get version() {
39886
- return VERSION$1;
40061
+ return VERSION;
39887
40062
  }
39888
40063
  static template = tmpl(comboboxHTML);
39889
40064
  static templateString = tmpl(stringHTML);
@@ -40190,6 +40365,182 @@ class Subtitles extends UICorePlugin {
40190
40365
  }
40191
40366
  }
40192
40367
 
40368
+ // An example implementation of client side performancestatistics
40369
+ const WATCH_CUTOFF = 5;
40370
+ const STALL_MEASURE_PERIOD = 10;
40371
+ const T$1 = 'plugins.telemetry';
40372
+ /**
40373
+ * Telemetry event type
40374
+ */
40375
+ var TelemetryEvent;
40376
+ (function (TelemetryEvent) {
40377
+ TelemetryEvent[TelemetryEvent["Init"] = 1] = "Init";
40378
+ TelemetryEvent[TelemetryEvent["Start"] = 2] = "Start";
40379
+ TelemetryEvent[TelemetryEvent["Watch"] = 3] = "Watch";
40380
+ TelemetryEvent[TelemetryEvent["Stall"] = 4] = "Stall";
40381
+ })(TelemetryEvent || (TelemetryEvent = {}));
40382
+ /**
40383
+ * Collects and reports the performance statistics.
40384
+ * @beta
40385
+ * @remarks
40386
+ * This plugin is experimental and its API is likely to change.
40387
+ *
40388
+ * Configuration options {@link TelemetryPluginSettings}
40389
+ *
40390
+ * @example
40391
+ * ```ts
40392
+ * import { Statistics } from '@gcorevideo/player'
40393
+ *
40394
+ * Player.registerPlugin(Statistics)
40395
+ *
40396
+ * const player = new Player({
40397
+ * statistics: {
40398
+ * send: (data) => {
40399
+ * fetch('/stats', {
40400
+ * method: 'POST',
40401
+ * body: JSON.stringify(data),
40402
+ * headers: { 'content-type': 'application/json' },
40403
+ * })
40404
+ * },
40405
+ * },
40406
+ * ...
40407
+ * })
40408
+ * ```
40409
+ */
40410
+ class Telemetry extends ContainerPlugin {
40411
+ /**
40412
+ * The name of the plugin.
40413
+ */
40414
+ get name() {
40415
+ return 'telemetry';
40416
+ }
40417
+ /**
40418
+ * The supported version of the plugin.
40419
+ */
40420
+ get supportedVersion() {
40421
+ return { min: CLAPPR_VERSION };
40422
+ }
40423
+ started = false;
40424
+ timeStart = 0;
40425
+ stallSent = false;
40426
+ stallLastTime = 0;
40427
+ watchSent = false;
40428
+ bufTracking = false;
40429
+ numStalls = 0;
40430
+ /**
40431
+ * The time when buffering last started.
40432
+ */
40433
+ bufLastStarted = 0;
40434
+ /**
40435
+ * The accumulated buffering duration.
40436
+ */
40437
+ stallAcc = 0;
40438
+ constructor(container) {
40439
+ super(container);
40440
+ assert(this.options.telemetry &&
40441
+ typeof this.options.telemetry.send === 'function', 'Telemetry plugin configuration is invalid: `send` option is required');
40442
+ }
40443
+ /**
40444
+ * @internal
40445
+ */
40446
+ bindEvents() {
40447
+ // TODO remove this
40448
+ // this.listenToOnce(
40449
+ // this.container,
40450
+ // CUSTOM_EVENTS_CONTAINER_START,
40451
+ // this.onStart,
40452
+ // )
40453
+ this.listenToOnce(this.container, Events$1.CONTAINER_READY, this.onReady);
40454
+ this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERING, this.onBuffering);
40455
+ this.listenTo(this.container, Events$1.CONTAINER_STATE_BUFFERFULL, this.onBufferFull);
40456
+ this.listenTo(this.container.playback, Events$1.PLAYBACK_TIMEUPDATE, this.onTimeUpdate);
40457
+ this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_START, this.startLevelSwitch);
40458
+ this.listenTo(this.container.playback, Events$1.PLAYBACK_LEVEL_SWITCH_END, this.endLevelSwitch);
40459
+ }
40460
+ startLevelSwitch() {
40461
+ this.bufTracking = false;
40462
+ }
40463
+ endLevelSwitch() {
40464
+ this.bufTracking = true;
40465
+ }
40466
+ onBuffering() {
40467
+ if (this.bufTracking) {
40468
+ this.bufLastStarted = performance.now();
40469
+ }
40470
+ }
40471
+ onBufferFull() {
40472
+ if (this.bufTracking && this.bufLastStarted) {
40473
+ this.stallAcc += performance.now() - this.bufLastStarted;
40474
+ this.numStalls++;
40475
+ }
40476
+ this.bufTracking = true;
40477
+ }
40478
+ onReady() {
40479
+ this.sendInit();
40480
+ trace(`${T$1} onReady`, {
40481
+ autoPlay: this.options.autoPlay,
40482
+ });
40483
+ if (this.options.autoPlay) {
40484
+ this.onStart();
40485
+ }
40486
+ else {
40487
+ this.listenToOnce(this.container.playback, Events$1.PLAYBACK_PLAY_INTENT, this.onStart);
40488
+ }
40489
+ }
40490
+ sendInit() {
40491
+ this.send({ event: TelemetryEvent.Init });
40492
+ }
40493
+ send(event) {
40494
+ this.options.telemetry.send({
40495
+ type: this.container.getPlaybackType(),
40496
+ ...event,
40497
+ });
40498
+ }
40499
+ sendStall(time) {
40500
+ // TODO don't send if no stalls?
40501
+ const res = {
40502
+ event: TelemetryEvent.Stall,
40503
+ count: this.numStalls,
40504
+ time,
40505
+ total_ms: Math.round(this.stallAcc * 1000),
40506
+ };
40507
+ this.stallAcc = 0;
40508
+ this.numStalls = 0;
40509
+ this.send(res);
40510
+ this.stallSent = true;
40511
+ this.stallLastTime = time;
40512
+ }
40513
+ onTimeUpdate({ current }) {
40514
+ if (!this.timeStart) {
40515
+ this.timeStart = current;
40516
+ }
40517
+ try {
40518
+ const elapsed = current - this.timeStart;
40519
+ const stallElapsed = current - this.stallLastTime;
40520
+ if (!this.stallSent || stallElapsed >= STALL_MEASURE_PERIOD) {
40521
+ this.sendStall(current);
40522
+ }
40523
+ if (!this.watchSent && elapsed >= WATCH_CUTOFF) {
40524
+ this.watchSent = true;
40525
+ this.send({
40526
+ event: TelemetryEvent.Watch,
40527
+ });
40528
+ }
40529
+ }
40530
+ catch (error) {
40531
+ }
40532
+ }
40533
+ onStart() {
40534
+ if (this.started) {
40535
+ return;
40536
+ }
40537
+ this.started = true;
40538
+ this.send({
40539
+ event: TelemetryEvent.Start,
40540
+ });
40541
+ }
40542
+ }
40543
+
40193
40544
  var parseSrt$1 = {exports: {}};
40194
40545
 
40195
40546
  var parseSrt = parseSrt$1.exports;
@@ -40306,7 +40657,7 @@ const parseSRT = /*@__PURE__*/getDefaultExportFromCjs(parseSrtExports);
40306
40657
 
40307
40658
  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";
40308
40659
 
40309
- const T$1 = 'plugins.media_control_thumbnails';
40660
+ const T = 'plugins.media_control_thumbnails';
40310
40661
  class Thumbnails extends UICorePlugin {
40311
40662
  _$spotlight = null;
40312
40663
  _$backdrop = null;
@@ -40576,7 +40927,7 @@ class Thumbnails extends UICorePlugin {
40576
40927
  // calculate how far along the carousel should currently be slid
40577
40928
  // depending on where the user is hovering on the progress bar
40578
40929
  _updateCarousel() {
40579
- trace(`${T$1} _updateCarousel`, {
40930
+ trace(`${T} _updateCarousel`, {
40580
40931
  backdropHeight: this._getOptions().backdropHeight,
40581
40932
  });
40582
40933
  if (!this._getOptions().backdropHeight) {
@@ -40635,7 +40986,7 @@ class Thumbnails extends UICorePlugin {
40635
40986
  }
40636
40987
  }
40637
40988
  _updateSpotlightThumb() {
40638
- trace(`${T$1} _updateSpotlightThumb`, {
40989
+ trace(`${T} _updateSpotlightThumb`, {
40639
40990
  spotlightHeight: this._getOptions().spotlightHeight,
40640
40991
  });
40641
40992
  if (!this._getOptions().spotlightHeight) {
@@ -40680,7 +41031,7 @@ class Thumbnails extends UICorePlugin {
40680
41031
  return 0;
40681
41032
  }
40682
41033
  _renderPlugin() {
40683
- trace(`${T$1} _renderPlugin`, {
41034
+ trace(`${T} _renderPlugin`, {
40684
41035
  show: this._show,
40685
41036
  thumbsLoaded: this._thumbsLoaded,
40686
41037
  thumbs: this._thumbs.length,
@@ -40712,195 +41063,6 @@ class Thumbnails extends UICorePlugin {
40712
41063
  }
40713
41064
  }
40714
41065
 
40715
- const T = 'plugins.source_controller';
40716
- const INITIAL_RETRY_DELAY = 1000;
40717
- const MAX_RETRY_DELAY = 5000;
40718
- const RETRY_DELAY_BLUR = 500;
40719
- const VERSION = '0.0.1';
40720
- function noSync(cb) {
40721
- queueMicrotask(cb);
40722
- }
40723
- /**
40724
- * This plugin is responsible for managing the automatic failover between sources.
40725
- * @beta
40726
- * @remarks
40727
- * Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
40728
- * on how sources ordering and selection works.
40729
- *
40730
- * This plugin does not expose any public methods apart from required by the Clappr plugin interface.
40731
- * It is supposed to work autonomously.
40732
- *
40733
- * @example
40734
- * ```ts
40735
- * import { SourceController } from '@gcorevideo/player'
40736
- *
40737
- * Player.registerPlugin(SourceController)
40738
- * ```
40739
- */
40740
- class SourceController extends CorePlugin {
40741
- /*
40742
- * The Logic itself is quite simple:
40743
- * * Here is the short diagram:
40744
- *
40745
- * sources_list:
40746
- * - a.mpd | +--------------------+
40747
- * - b.m3u8 |--->| init |
40748
- * - ... | |--------------------|
40749
- * | current_source = 0 |
40750
- * +--------------------+
40751
- * |
40752
- * | source = a.mpd
40753
- * | playback = dash.js
40754
- * v
40755
- * +------------------+
40756
- * +-->| load source |
40757
- * | +---------|--------+
40758
- * | v
40759
- * | +------------------+
40760
- * | | play |
40761
- * | +---------|--------+
40762
- * | |
40763
- * | v
40764
- * | +-----------------------+
40765
- * | | on playback_error |
40766
- * | |-----------------------|
40767
- * | | current_source = |
40768
- * | | (current_source + 1) |
40769
- * | | % len sources_list |
40770
- * | | |
40771
- * | | delay 1..3s |
40772
- * | +---------------|-------+
40773
- * | |
40774
- * | source=b.m3u8 |
40775
- * | playback=hls.js |
40776
- * +-------------------+
40777
- *
40778
- */
40779
- sourcesList = [];
40780
- currentSourceIndex = 0;
40781
- sourcesDelay = {};
40782
- active = false;
40783
- sync = noSync;
40784
- /**
40785
- * @internal
40786
- */
40787
- get name() {
40788
- return 'source_controller';
40789
- }
40790
- /**
40791
- * @internal
40792
- */
40793
- get supportedVersion() {
40794
- return { min: CLAPPR_VERSION };
40795
- }
40796
- constructor(core) {
40797
- super(core);
40798
- this.sourcesList = this.core.options.sources;
40799
- if (this.core.options.source !== undefined) {
40800
- // prevent Clappr from loading all sources simultaneously
40801
- this.core.options.sources = [this.core.options.source];
40802
- }
40803
- else {
40804
- this.core.options.sources = this.core.options.sources.slice(0, 1);
40805
- }
40806
- }
40807
- /**
40808
- * @internal
40809
- */
40810
- bindEvents() {
40811
- super.bindEvents();
40812
- this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, () => this.onReady());
40813
- }
40814
- onReady() {
40815
- trace(`${T} onReady`, {
40816
- retrying: this.active,
40817
- currentSource: this.sourcesList[this.currentSourceIndex],
40818
- });
40819
- const spinner = this.core.activeContainer?.getPlugin('spinner');
40820
- if (spinner) {
40821
- this.sync = (cb) => {
40822
- spinner.once(SpinnerEvents.SYNC, cb);
40823
- };
40824
- }
40825
- else {
40826
- this.sync = noSync;
40827
- }
40828
- this.bindContainerEventListeners();
40829
- if (this.active) {
40830
- this.core.activeContainer?.getPlugin('poster_custom')?.disable();
40831
- spinner?.show();
40832
- }
40833
- }
40834
- bindContainerEventListeners() {
40835
- this.core.activePlayback.on(Events$1.PLAYBACK_ERROR, (error) => {
40836
- trace(`${T} on PLAYBACK_ERROR`, {
40837
- error: {
40838
- code: error?.code,
40839
- description: error?.description,
40840
- level: error?.level,
40841
- },
40842
- retrying: this.active,
40843
- currentSource: this.sourcesList[this.currentSourceIndex],
40844
- });
40845
- switch (error.code) {
40846
- case PlaybackErrorCode.MediaSourceUnavailable:
40847
- this.core.activeContainer?.getPlugin('poster_custom')?.disable();
40848
- this.retryPlayback();
40849
- break;
40850
- }
40851
- });
40852
- this.core.activePlayback.on(Events$1.PLAYBACK_PLAY, () => {
40853
- trace(`${T} on PLAYBACK_PLAY`, {
40854
- currentSource: this.sourcesList[this.currentSourceIndex],
40855
- retrying: this.active,
40856
- });
40857
- if (this.active) {
40858
- this.reset();
40859
- // TODO make poster reset its state on enable
40860
- this.core.activeContainer?.getPlugin('poster_custom')?.enable();
40861
- this.core.activeContainer?.getPlugin('spinner')?.hide();
40862
- }
40863
- });
40864
- }
40865
- reset() {
40866
- this.active = false;
40867
- this.sourcesDelay = {};
40868
- }
40869
- retryPlayback() {
40870
- trace(`${T} retryPlayback enter`, {
40871
- currentSourceIndex: this.currentSourceIndex,
40872
- currentSource: this.sourcesList[this.currentSourceIndex],
40873
- });
40874
- this.active = true;
40875
- this.getNextMediaSource().then((nextSource) => {
40876
- const rnd = RETRY_DELAY_BLUR * Math.random();
40877
- this.sync(() => {
40878
- this.core.load(nextSource.source, nextSource.mimeType);
40879
- setTimeout(() => {
40880
- // this.core.activePlayback.consent()
40881
- this.core.activePlayback.play();
40882
- }, rnd);
40883
- });
40884
- });
40885
- }
40886
- getNextMediaSource() {
40887
- return new Promise((resolve) => {
40888
- this.sourcesDelay[this.currentSourceIndex] = Math.min(MAX_RETRY_DELAY, (this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY) * 2);
40889
- this.currentSourceIndex =
40890
- (this.currentSourceIndex + 1) % this.sourcesList.length;
40891
- const delay = this.sourcesDelay[this.currentSourceIndex] || INITIAL_RETRY_DELAY;
40892
- const s = this.sourcesList[this.currentSourceIndex];
40893
- setTimeout(() => resolve(s), delay);
40894
- });
40895
- }
40896
- /**
40897
- * @internal
40898
- */
40899
- static get version() {
40900
- return VERSION;
40901
- }
40902
- }
40903
-
40904
41066
  var VolumeFadeEvents;
40905
41067
  (function (VolumeFadeEvents) {
40906
41068
  VolumeFadeEvents["FADE"] = "core:volume:fade";
@@ -40913,15 +41075,22 @@ class VolumeFade extends UICorePlugin {
40913
41075
  container = null;
40914
41076
  delay = 0;
40915
41077
  interval = null;
41078
+ /**
41079
+ * @internal
41080
+ */
40916
41081
  get name() {
40917
41082
  return 'volume_fade';
40918
41083
  }
41084
+ /**
41085
+ * @internal
41086
+ */
40919
41087
  bindEvents() {
41088
+ // TODO on container changed
40920
41089
  this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
40921
41090
  if (this.core.mediaControl) {
40922
41091
  this.listenTo(this.core.mediaControl, 'mediacontrol:volume:user', this._onUserChangeVolume);
40923
41092
  }
40924
- this.listenTo(this.core, 'core:volume:config', this._onVolumeConfig);
41093
+ // this.listenTo(this.core, 'core:volume:config', this._onVolumeConfig);
40925
41094
  }
40926
41095
  unBindEvents() {
40927
41096
  this.core.$el.off('mouseleave.volume');
@@ -40991,4 +41160,4 @@ class VolumeFade extends UICorePlugin {
40991
41160
  }
40992
41161
  }
40993
41162
 
40994
- export { AudioSelector, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause, ClipsPlugin, ContextMenu, DisableControls, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, Kibo, LevelSelector, Logo, MediaControl, MultiCamera, PictureInPicture, PlaybackRate, Poster, SeekTime, Share, SkipTime, SourceController, SpinnerEvents, SpinnerThreeBounce, Statistics, Subtitles, Thumbnails, VolumeFade, VolumeFadeEvents };
41163
+ export { AudioSelector, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause, ClipsPlugin, ContextMenu, DisableControls, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, Kibo, LevelSelector, Logo, MediaControl, MultiCamera, PictureInPicture, PlaybackRate, Poster, SeekTime, Share, SkipTime, SourceController, SpinnerEvents, SpinnerThreeBounce, Subtitles, Telemetry, TelemetryEvent, Thumbnails, VolumeFade, VolumeFadeEvents };