@gcorevideo/player 2.30.0 → 2.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/assets/audio-tracks/template.ejs +1 -1
  2. package/dist/core.js +65 -21
  3. package/dist/index.css +265 -265
  4. package/dist/index.embed.js +99 -34
  5. package/dist/index.js +125 -53
  6. package/docs/api/player.md +37 -0
  7. package/docs/api/player.player.getplugin.md +59 -0
  8. package/docs/api/player.player.md +14 -0
  9. package/docs/api/player.tokenrefreshoptions.gettoken.md +13 -0
  10. package/docs/api/player.tokenrefreshoptions.ipbound.md +13 -0
  11. package/docs/api/player.tokenrefreshoptions.md +115 -0
  12. package/docs/api/player.tokenrefreshoptions.ontokenrefreshed.md +13 -0
  13. package/docs/api/player.tokenrefreshoptions.refreshleadseconds.md +13 -0
  14. package/docs/api/player.tokenrefreshplugin.md +50 -0
  15. package/docs/api/player.tokenresponse.client_ip.md +13 -0
  16. package/docs/api/player.tokenresponse.expires.md +13 -0
  17. package/docs/api/player.tokenresponse.md +153 -0
  18. package/docs/api/player.tokenresponse.token.md +13 -0
  19. package/docs/api/player.tokenresponse.token_ip.md +13 -0
  20. package/docs/api/player.tokenresponse.url.md +13 -0
  21. package/docs/api/player.tokenresponse.url_ip.md +13 -0
  22. package/lib/playback/hls-playback/HlsPlayback.d.ts +1 -1
  23. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  24. package/lib/playback/hls-playback/HlsPlayback.js +23 -20
  25. package/lib/playback/hls-playback/RangesList.d.ts +7 -0
  26. package/lib/playback/hls-playback/RangesList.d.ts.map +1 -0
  27. package/lib/playback/hls-playback/RangesList.js +41 -0
  28. package/lib/plugins/audio-selector/AudioTracks.d.ts +4 -0
  29. package/lib/plugins/audio-selector/AudioTracks.d.ts.map +1 -1
  30. package/lib/plugins/audio-selector/AudioTracks.js +42 -12
  31. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  32. package/lib/plugins/subtitles/ClosedCaptions.js +0 -2
  33. package/package.json +1 -1
  34. package/src/playback/hls-playback/HlsPlayback.ts +40 -37
  35. package/src/playback/hls-playback/RangesList.ts +45 -0
  36. package/src/playback/hls-playback/__tests__/RangesList.test.ts +60 -0
  37. package/src/plugins/audio-selector/AudioTracks.ts +51 -16
  38. package/src/plugins/audio-selector/__tests__/__snapshots__/AudioTracks.test.ts.snap +9 -9
  39. package/src/plugins/subtitles/ClosedCaptions.ts +0 -5
  40. package/tsconfig.tsbuildinfo +1 -1
@@ -49867,6 +49867,48 @@ Hls.defaultConfig = void 0;
49867
49867
  // export const CLAPPR_VERSION: string = process.env.CLAPPR_VERSION || '0.11.3';
49868
49868
  const CLAPPR_VERSION$1 = '0.13.0';
49869
49869
 
49870
+ class RangesList {
49871
+ // TODO write an efficient implementation
49872
+ items = [];
49873
+ insert(start, end, value) {
49874
+ const index = this.findIndex((start + end) / 2);
49875
+ this.items.splice(index, 0, [start, end, value]);
49876
+ }
49877
+ find(position) {
49878
+ const index = this.findIndex(position);
49879
+ const item = this.items[index];
49880
+ if (!item || item[0] > position || item[1] < position) {
49881
+ return null;
49882
+ }
49883
+ return item[2];
49884
+ }
49885
+ findIndex(position) {
49886
+ let low = 0;
49887
+ let high = this.items.length;
49888
+ let index = 0;
49889
+ while (low < high) {
49890
+ index = low + Math.floor((high - low) / 2);
49891
+ const item = this.items[index];
49892
+ if (item[0] > position) {
49893
+ if (index === low) {
49894
+ return index;
49895
+ }
49896
+ high = index;
49897
+ continue;
49898
+ }
49899
+ if (item[1] <= position) {
49900
+ if (index === high - 1) {
49901
+ return index + 1;
49902
+ }
49903
+ low = index + 1;
49904
+ continue;
49905
+ }
49906
+ break;
49907
+ }
49908
+ return index;
49909
+ }
49910
+ }
49911
+
49870
49912
  // Copyright 2014 Globo.com Player authors. All rights reserved.
49871
49913
  // Use of this source code is governed by a BSD-style
49872
49914
  // license that can be found on https://github.com/clappr/hlsjs-playback/blob/main/LICENSE
@@ -49876,7 +49918,6 @@ const DEFAULT_RECOVER_ATTEMPTS = 16;
49876
49918
  Events$1.register('PLAYBACK_FRAGMENT_PARSING_METADATA');
49877
49919
  const T$7 = 'playback.hls';
49878
49920
  class HlsPlayback extends BasePlayback {
49879
- _ccTracksUpdated = false;
49880
49921
  _currentFragment = null;
49881
49922
  _currentLevel = null;
49882
49923
  _durationExcludesAfterLiveSyncPoint = false;
@@ -49901,7 +49942,8 @@ class HlsPlayback extends BasePlayback {
49901
49942
  _timeUpdateTimer = null;
49902
49943
  oncueenter = null;
49903
49944
  oncueexit = null;
49904
- cues = []; // TODO check the list size and use BST if needed
49945
+ cues = null;
49946
+ cuesByTrack = {};
49905
49947
  currentCueId = null;
49906
49948
  /**
49907
49949
  * @internal
@@ -50098,7 +50140,6 @@ class HlsPlayback extends BasePlayback {
50098
50140
  }
50099
50141
  this._manifestParsed = false;
50100
50142
  // this._ccIsSetup = false
50101
- this._ccTracksUpdated = false;
50102
50143
  this._setInitialState();
50103
50144
  this._hls.destroy();
50104
50145
  this._hls = null;
@@ -50152,12 +50193,20 @@ class HlsPlayback extends BasePlayback {
50152
50193
  this._hls.on(Events.AUDIO_TRACK_SWITCHED, (evt, data) => this._onAudioTrackSwitched(evt, data));
50153
50194
  this._hls.on(Events.CUES_PARSED, (evt, data) => {
50154
50195
  data.cues?.forEach((cue) => {
50155
- this.cues.push({
50196
+ if (!this.cues) {
50197
+ const trackId = this._hls.subtitleTrack;
50198
+ if (!this.cuesByTrack[trackId]) {
50199
+ this.cuesByTrack[trackId] = new RangesList();
50200
+ }
50201
+ this.cues = this.cuesByTrack[trackId];
50202
+ }
50203
+ const cueInfo = {
50156
50204
  id: cue.id,
50157
50205
  start: cue.startTime,
50158
50206
  end: cue.endTime,
50159
50207
  text: cue.text,
50160
- });
50208
+ };
50209
+ this.cues.insert(cue.startTime, cue.endTime, cueInfo);
50161
50210
  });
50162
50211
  });
50163
50212
  this.bindCustomListeners();
@@ -50384,7 +50433,7 @@ class HlsPlayback extends BasePlayback {
50384
50433
  }
50385
50434
  }
50386
50435
  reload() {
50387
- this.cues = [];
50436
+ this.cues = null;
50388
50437
  this.currentCueId = null;
50389
50438
  this._hls?.startLoad(-1);
50390
50439
  }
@@ -50449,9 +50498,7 @@ class HlsPlayback extends BasePlayback {
50449
50498
  }
50450
50499
  triggerCues() {
50451
50500
  const currentTime = this.getCurrentTime();
50452
- // const cues = Object.values(this.cues)
50453
- // TODO build a search tree
50454
- const cue = this.cues.find((cue) => currentTime >= cue.start && currentTime <= cue.end);
50501
+ const cue = this.cues?.find(currentTime);
50455
50502
  if (cue) {
50456
50503
  this.currentCueId = cue.id;
50457
50504
  this.oncueenter?.(cue);
@@ -50494,20 +50541,14 @@ class HlsPlayback extends BasePlayback {
50494
50541
  destroy() {
50495
50542
  this._stopTimeUpdateTimer();
50496
50543
  this._destroyHLSInstance();
50544
+ this.cues = null;
50545
+ this.cuesByTrack = {};
50497
50546
  return super.destroy();
50498
50547
  }
50499
50548
  _updatePlaybackType(evt, data) {
50500
50549
  const prevPlaybackType = this._playbackType;
50501
50550
  this._playbackType = (data.details.live ? Playback.LIVE : Playback.VOD);
50502
50551
  this._onLevelUpdated(evt, data);
50503
- // Live stream subtitle tracks detection hack (may not immediately available)
50504
- // if (
50505
- // this._ccTracksUpdated &&
50506
- // this._playbackType === Playback.LIVE &&
50507
- // this.hasClosedCaptionsTracks
50508
- // ) {
50509
- // this._onSubtitleLoaded()
50510
- // }
50511
50552
  if (prevPlaybackType !== this._playbackType) {
50512
50553
  this._updateSettings();
50513
50554
  }
@@ -50727,7 +50768,10 @@ class HlsPlayback extends BasePlayback {
50727
50768
  return;
50728
50769
  }
50729
50770
  this._hls.subtitleTrack = id;
50730
- this.cues = [];
50771
+ if (!this.cuesByTrack[id]) {
50772
+ this.cuesByTrack[id] = new RangesList();
50773
+ }
50774
+ this.cues = this.cuesByTrack[id];
50731
50775
  }
50732
50776
  /**
50733
50777
  * @override
@@ -50736,7 +50780,7 @@ class HlsPlayback extends BasePlayback {
50736
50780
  return this.getTextTracks();
50737
50781
  }
50738
50782
  getTextTracks() {
50739
- return this._hls?.subtitleTracks.map((t) => ({
50783
+ return (this._hls?.subtitleTracks.map((t) => ({
50740
50784
  id: t.id,
50741
50785
  name: t.name,
50742
50786
  track: {
@@ -50744,7 +50788,7 @@ class HlsPlayback extends BasePlayback {
50744
50788
  label: t.name,
50745
50789
  language: t.lang,
50746
50790
  },
50747
- })) || [];
50791
+ })) || []);
50748
50792
  }
50749
50793
  }
50750
50794
  HlsPlayback.canPlay = function (resource, mimeType) {
@@ -51357,7 +51401,7 @@ function insertStyle(css) {
51357
51401
 
51358
51402
  insertStyle("@import \"https://fonts.googleapis.com/css?family=Roboto\";\n:root {\n --theme-background-color: rgb(0 0 0 / 70%);\n --theme-text-color: rgb(255 255 255 / 100%);\n --theme-foreground-color: rgb(201 201 201 / 100%);\n --theme-hover-color: rgb(255 255 255 / 100%);\n}\n\n.gcore-skin-bg-color {\n background-color: var(--theme-background-color) !important;\n}\n\n.gcore-skin-text-color {\n color: var(--theme-text-color) !important;\n}\n\n.gcore-skin-text-color svg {\n fill: var(--theme-text-color) !important;\n}\n\n.gcore-skin-text-color svg path {\n fill: var(--theme-text-color) !important;\n}\n\n.gcore-skin-border-textarea-color {\n border-color: var(--theme-text-color) !important;\n}\n\n.gcore-skin-button-color {\n color: var(--theme-foreground-color) !important;\n}\n.gcore-skin-button-color svg {\n fill: var(--theme-foreground-color) !important;\n}\n.gcore-skin-button-color svg path {\n fill: var(--theme-foreground-color) !important;\n}\n.gcore-skin-button-color svg path.icon-hover {\n fill: var(--theme-foreground-color) !important;\n}\n.gcore-skin-button-color[data-fullscreen] svg {\n stroke: var(--theme-foreground-color) !important;\n}\n.gcore-skin-button-color[data-fullscreen] svg path {\n stroke: var(--theme-foreground-color) !important;\n}\n\n.gcore-skin-main-color {\n background-color: var(--theme-foreground-color);\n}\n\n.gcore-skin-border-color {\n border-color: var(--theme-foreground-color) !important;\n}\n\n.gcore-skin-button-color:hover {\n color: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-button-color:hover svg {\n fill: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-button-color:hover svg path {\n fill: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-border-color:hover {\n border-color: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-button-with-bg-color:hover svg path.icon-hover {\n fill: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-active {\n color: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-active svg {\n fill: var(--theme-hover-color) !important;\n}\n\n.gcore-skin-active svg path {\n fill: var(--theme-hover-color) !important;\n}\n\n* {\n -webkit-tap-highlight-color: transparent;\n -webkit-touch-callout: none;\n user-select: none;\n}\n\n.player-poster {\n background-size: contain !important;\n}\n\n.spinner-three-bounce > .gcore-skin-main-color {\n box-shadow: 4px 4px 9px 1px rgba(36, 61, 81, 0.51);\n}\n\n.gplayer-lite-btn {\n cursor: pointer;\n border: none;\n margin: 0;\n padding: 0;\n width: auto;\n overflow: visible;\n background: transparent;\n /* inherit font & color from ancestor */\n color: inherit;\n font: inherit;\n /* Normalize `line-height`. Cannot be changed from `normal` in Firefox 4+. */\n line-height: normal;\n /* Corrects font smoothing for webkit */\n -webkit-font-smoothing: inherit;\n -moz-osx-font-smoothing: inherit;\n /* Corrects inability to style clickable `input` types in iOS */\n appearance: none;\n /* Remove excess padding and border in Firefox 4+ */\n}\n.gplayer-lite-btn::-moz-focus-inner {\n border: 0;\n padding: 0;\n}");
51359
51403
 
51360
- const pluginHtml$4 = "<button class='gcore-skin-button-color media-control-dd' id=\"gplayer-audiotracks-button\" aria-haspopup=\"menu\" aria-expanded=\"false\">\n <span class=\"media-control-dd__text\" id=\"gplayer-audiotracks-button-text\"><%= title %></span>\n <span class=\"media-control-dd__arrow\"><%= icon %></span>\n</button>\n<ul class=\"gcore-skin-bg-color menu media-control-dd__popup\" id=\"gplayer-audiotracks-menu\" role=\"menu\">\n <% for (const track of tracks) { %>\n <li>\n <a href=\"#\" class=\"gcore-skin-text-color\" data-item=\"<%= track.id %>\" role=\"menuitemradio\" aria-checked=\"<%= track.id === current %>\">\n <%= track.label %>\n </a>\n </li>\n <% }; %>\n</ul>\n";
51404
+ const pluginHtml$4 = "<button class='gcore-skin-button-color media-control-dd' id=\"gplayer-audiotracks-button\" aria-haspopup=\"menu\" aria-expanded=\"false\">\n <span class=\"media-control-dd__text\" id=\"gplayer-audiotracks-button-text\"><%= title %></span>\n <span class=\"media-control-dd__arrow\"><%= icon %></span>\n</button>\n<ul class=\"gcore-skin-bg-color menu media-control-dd__popup\" id=\"gplayer-audiotracks-menu\" role=\"menu\">\n <% for (const track of tracks) { %>\n <li>\n <a href=\"#\" class=\"gcore-skin-text-color\" data-item=\"<%= track.id %>\" role=\"menuitemradio\" aria-checked=\"<%= track.id === current %>\">\n <%= track.label || track.language %>\n </a>\n </li>\n <% }; %>\n</ul>\n";
51361
51405
 
51362
51406
  const audioArrow = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<svg width=\"9px\" height=\"6px\" viewBox=\"0 0 9 6\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n <!-- Generator: Sketch 49 (51002) - http://www.bohemiancoding.com/sketch -->\n <title>quality-arrow</title>\n <desc>Created with Sketch.</desc>\n <defs></defs>\n <g id=\"quality-arrow\" stroke=\"none\" stroke-width=\"1\" fill=\"none\" fill-rule=\"evenodd\">\n <path\n d=\"M5.07079194,5.78553848 C4.91457318,5.94277844 4.70551573,6.00941824 4.50028717,5.99893557 C4.2950586,6.00941824 4.08676693,5.94277844 3.92978239,5.78553848 L0.221118462,1.2997069 C-0.0737061539,1.00469478 -0.0737061539,0.526236029 0.221118462,0.231972666 C0.515177299,-0.0630394586 1.23500883,0.00734414472 1.64852907,0.00734414472 L7.77475484,0.00734414472 C8.21201421,0.00734414472 8.48539703,-0.0630394586 8.77945587,0.231972666 C9.07351471,0.526236029 9.07351471,1.00469478 8.77945587,1.2997069 L5.07079194,5.78553848 Z\"\n fill=\"#FFFFFE\"></path>\n </g>\n</svg>\n";
51363
51407
 
@@ -53011,7 +53055,6 @@ function mergeElements(a, b) {
53011
53055
  }
53012
53056
 
53013
53057
  const VERSION$6 = '2.22.4';
53014
- // const T = 'plugins.audiotracks'
53015
53058
  /**
53016
53059
  * `PLUGIN` that makes possible to switch audio tracks via the media control UI.
53017
53060
  * @public
@@ -53026,6 +53069,7 @@ class AudioTracks extends UICorePlugin {
53026
53069
  currentTrack = null;
53027
53070
  open = false;
53028
53071
  tracks = [];
53072
+ autoUpdateTimerId = null;
53029
53073
  /**
53030
53074
  * @internal
53031
53075
  */
@@ -53086,19 +53130,18 @@ class AudioTracks extends UICorePlugin {
53086
53130
  onActiveContainerChanged() {
53087
53131
  this.currentTrack = null;
53088
53132
  this.listenTo(this.core.activeContainer, Events$1.CONTAINER_AUDIO_AVAILABLE, (tracks) => {
53133
+ const currentTrackId = this.core.activeContainer.currentAudioTrack?.id ??
53134
+ this.core.activePlayback?.currentAudioTrack?.id;
53089
53135
  this.currentTrack =
53090
- tracks.find((track) => track.kind === 'main') ?? null; // TODO test
53136
+ tracks.find((track) => track.id === currentTrackId) ??
53137
+ tracks.find((track) => track.kind === 'main') ??
53138
+ tracks[0] ??
53139
+ null;
53091
53140
  this.tracks = tracks;
53092
53141
  this.render();
53093
53142
  this.mount();
53094
53143
  });
53095
- this.listenTo(this.core.activeContainer, Events$1.CONTAINER_AUDIO_CHANGED, (track) => {
53096
- this.currentTrack = track;
53097
- this.highlightCurrentTrack();
53098
- this.buttonElement().removeClass('changing');
53099
- this.updateText();
53100
- });
53101
- // TODO test
53144
+ this.bindContainerAudioChanged();
53102
53145
  this.listenTo(this.core.activeContainer, Events$1.CONTAINER_CLICK, () => {
53103
53146
  this.hideMenu();
53104
53147
  });
@@ -53106,6 +53149,21 @@ class AudioTracks extends UICorePlugin {
53106
53149
  this.clickaway(null);
53107
53150
  });
53108
53151
  }
53152
+ bindContainerAudioChanged() {
53153
+ this.listenTo(this.core.activeContainer, Events$1.CONTAINER_AUDIO_CHANGED, (track) => {
53154
+ this.setCurrentTrack(track);
53155
+ });
53156
+ }
53157
+ setCurrentTrack(track) {
53158
+ if (this.autoUpdateTimerId) {
53159
+ clearTimeout(this.autoUpdateTimerId);
53160
+ this.autoUpdateTimerId = null;
53161
+ }
53162
+ this.currentTrack = track;
53163
+ this.highlightCurrentTrack();
53164
+ this.buttonElement().removeClass('changing');
53165
+ this.updateText();
53166
+ }
53109
53167
  shouldRender() {
53110
53168
  // Render is called from the parent class constructor so tracks aren't available
53111
53169
  // Only care if we have at least 2 to choose from
@@ -53138,7 +53196,7 @@ class AudioTracks extends UICorePlugin {
53138
53196
  selectAudioTrack(id) {
53139
53197
  this.startTrackSwitching();
53140
53198
  this.core.activeContainer.switchAudioTrack(id);
53141
- this.updateText();
53199
+ this.autoUpdateSelected(id);
53142
53200
  }
53143
53201
  hideMenu() {
53144
53202
  this.open = false;
@@ -53189,7 +53247,7 @@ class AudioTracks extends UICorePlugin {
53189
53247
  if (!this.currentTrack) {
53190
53248
  return;
53191
53249
  }
53192
- this.buttonElementText().text(this.currentTrack.label);
53250
+ this.buttonElementText().text(this.getTitle());
53193
53251
  }
53194
53252
  highlightCurrentTrack() {
53195
53253
  this.trackElement().removeClass('current');
@@ -53210,6 +53268,15 @@ class AudioTracks extends UICorePlugin {
53210
53268
  this.core.getPlugin('media_control')?.slot('audiotracks', this.$el);
53211
53269
  }
53212
53270
  }
53271
+ autoUpdateSelected(id) {
53272
+ if (this.autoUpdateTimerId) {
53273
+ clearTimeout(this.autoUpdateTimerId);
53274
+ }
53275
+ this.autoUpdateTimerId = setTimeout(() => {
53276
+ const track = this.tracks.find(t => t.id === id) ?? null;
53277
+ this.setCurrentTrack(track);
53278
+ }, 500);
53279
+ }
53213
53280
  clickaway = mediaControlClickaway(() => this.hideMenu());
53214
53281
  }
53215
53282
 
@@ -58849,8 +58916,6 @@ class ClosedCaptions extends UICorePlugin {
58849
58916
  // event.target does not exist for some reason in tests
58850
58917
  const id = Number((event.target ?? event.currentTarget).dataset?.item ??
58851
58918
  '-1');
58852
- // TODO review, make configurable, and emit event in addition
58853
- // localStorage.setItem(LOCAL_STORAGE_CC_ID, id) // TODO store language instead?
58854
58919
  this.userSelectedItemId = id;
58855
58920
  this.selectItem(this.findById(id));
58856
58921
  this.hideMenu();