@gcorevideo/player 2.28.30 → 2.28.36

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 (37) hide show
  1. package/README.md +22 -1
  2. package/assets/{subtitles → cc}/style.scss +5 -0
  3. package/dist/core.js +17 -23
  4. package/dist/index.css +241 -237
  5. package/dist/index.embed.js +79 -59
  6. package/dist/index.js +137 -119
  7. package/docs/api/player.closedcaptionspluginsettings.md +1 -0
  8. package/docs/api/player.md +9 -0
  9. package/docs/api/player.mediacontrol.md +16 -0
  10. package/docs/api/player.thumbnails.md +1 -1
  11. package/lib/Player.d.ts.map +1 -1
  12. package/lib/playback/BasePlayback.d.ts +1 -0
  13. package/lib/playback/BasePlayback.d.ts.map +1 -1
  14. package/lib/playback/BasePlayback.js +3 -0
  15. package/lib/playback/dash-playback/DashPlayback.d.ts +1 -0
  16. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  17. package/lib/playback/dash-playback/DashPlayback.js +9 -22
  18. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  19. package/lib/playback/hls-playback/HlsPlayback.js +4 -0
  20. package/lib/plugins/subtitles/ClosedCaptions.d.ts +7 -3
  21. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  22. package/lib/plugins/subtitles/ClosedCaptions.js +66 -42
  23. package/lib/testUtils.d.ts +1 -0
  24. package/lib/testUtils.d.ts.map +1 -1
  25. package/lib/testUtils.js +3 -0
  26. package/package.json +4 -1
  27. package/src/Player.ts +12 -12
  28. package/src/playback/BasePlayback.ts +4 -0
  29. package/src/playback/dash-playback/DashPlayback.ts +10 -27
  30. package/src/playback/hls-playback/HlsPlayback.ts +4 -0
  31. package/src/plugins/subtitles/ClosedCaptions.ts +75 -47
  32. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +277 -29
  33. package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +3 -3
  34. package/src/testUtils.ts +3 -0
  35. package/tsconfig.tsbuildinfo +1 -1
  36. /package/assets/{subtitles → cc}/combobox.ejs +0 -0
  37. /package/assets/{subtitles → cc}/string.ejs +0 -0
@@ -12674,6 +12674,9 @@ class BasePlayback extends HTML5Video$1 {
12674
12674
  super._onPlaying();
12675
12675
  this.trigger(Events$1.PLAYBACK_MEDIACONTROL_ENABLE);
12676
12676
  }
12677
+ setTextTrack(id) {
12678
+ // noop
12679
+ }
12677
12680
  }
12678
12681
 
12679
12682
  var PlaybackEvents;
@@ -12696,6 +12699,7 @@ const T$8 = 'playback.dash';
12696
12699
  class DashPlayback extends BasePlayback {
12697
12700
  _levels = [];
12698
12701
  _currentLevel = AUTO$1;
12702
+ _currentTextTrackId = -1;
12699
12703
  // true when the actual duration is longer than hlsjs's live sync point
12700
12704
  // when this is false playableRegionDuration will be the actual duration
12701
12705
  // when this is true playableRegionDuration will exclude the time after the sync point
@@ -12828,7 +12832,11 @@ class DashPlayback extends BasePlayback {
12828
12832
  streaming: {
12829
12833
  text: {
12830
12834
  defaultEnabled: false,
12831
- dispatchForManualRendering: true,
12835
+ // NOTE: dispatchForManualRendering is not correctly implemented in DASH.js;
12836
+ // it does not work when there are multiple text tracks.
12837
+ // CUE_ENTER and CUE_EXIT events might be dispatched additionally
12838
+ // for a track, other than the currently active one.
12839
+ // dispatchForManualRendering: true, // TODO only when useNativeSubtitles is not true?
12832
12840
  },
12833
12841
  },
12834
12842
  }, this.options.dash);
@@ -12872,24 +12880,6 @@ class DashPlayback extends BasePlayback {
12872
12880
  this._dash.on(_.events.PLAYBACK_RATE_CHANGED, (e) => {
12873
12881
  this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate);
12874
12882
  });
12875
- this._dash.on(_.events.TRACK_CHANGE_RENDERED, (e) => {
12876
- if (e.mediaType === 'audio') {
12877
- this.trigger(Events$1.PLAYBACK_AUDIO_CHANGED, toClapprTrack$1(e.newMediaInfo));
12878
- }
12879
- });
12880
- this._dash.on(_.events.CUE_ENTER, (e) => {
12881
- this.oncueenter?.({
12882
- end: e.end,
12883
- id: e.id,
12884
- start: e.start,
12885
- text: e.text,
12886
- });
12887
- });
12888
- this._dash.on(_.events.CUE_EXIT, (e) => {
12889
- this.oncueexit?.({
12890
- id: e.id,
12891
- });
12892
- });
12893
12883
  }
12894
12884
  render() {
12895
12885
  this._ready();
@@ -13199,14 +13189,14 @@ class DashPlayback extends BasePlayback {
13199
13189
  this._dash?.setTextTrack(this.closedCaptionsTrackId);
13200
13190
  }
13201
13191
  setTextTrack(id) {
13192
+ this._currentTextTrackId = id;
13202
13193
  this._dash?.setTextTrack(id);
13203
13194
  }
13204
13195
  /**
13205
13196
  * @override
13206
13197
  */
13207
13198
  get closedCaptionsTracks() {
13208
- const tt = this.getTextTracks();
13209
- return tt;
13199
+ return this.getTextTracks();
13210
13200
  }
13211
13201
  getTextTracks() {
13212
13202
  return this._dash?.getTracksFor('text').map((t, index) => ({
@@ -13216,7 +13206,7 @@ class DashPlayback extends BasePlayback {
13216
13206
  id: index,
13217
13207
  label: getTextTrackLabel(t) || "",
13218
13208
  language: t.lang,
13219
- mode: "hidden",
13209
+ mode: this._currentTextTrackId === index ? "showing" : "hidden",
13220
13210
  },
13221
13211
  })) || [];
13222
13212
  }
@@ -50727,7 +50717,11 @@ class HlsPlayback extends BasePlayback {
50727
50717
  this.trigger(Events$1.PLAYBACK_AUDIO_CHANGED, toClapprTrack(track));
50728
50718
  }
50729
50719
  setTextTrack(id) {
50720
+ if (id === this._hls.subtitleTrack) {
50721
+ return;
50722
+ }
50730
50723
  this._hls.subtitleTrack = id;
50724
+ this.cues = [];
50731
50725
  }
50732
50726
  /**
50733
50727
  * @override
@@ -58549,7 +58543,7 @@ class SourceController extends CorePlugin {
58549
58543
  }
58550
58544
  }
58551
58545
 
58552
- insertStyle(".media-control-skin-1 .media-control-cc button.media-control-button {\n display: flex;\n justify-content: center;\n padding: 0;\n align-items: center;\n vertical-align: top;\n}\n.media-control-skin-1 .media-control-cc button.media-control-button:hover {\n color: white;\n}\n.media-control-skin-1 .media-control-cc ul li {\n text-align: center;\n}\n.media-control-skin-1 .media-control-cc ul li a {\n height: 30px;\n padding: 5px 10px;\n color: #fffffe;\n}\n.media-control-skin-1 .media-control-cc ul li a:hover {\n background-color: rgba(0, 0, 0, 0.4);\n}\n.media-control-skin-1 .media-control-cc ul li.current a {\n background-color: rgba(0, 0, 0, 0.4);\n}\n.media-control-skin-1 .media-control-cc ul li:first-child a {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.media-control-skin-1 .media-control-cc ul li:last-child a {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.media-control-skin-1 .media-control-cc {\n position: relative;\n order: 85;\n}\n\n::cue {\n visibility: hidden !important;\n font-size: 0 !important;\n}\n\n.ios-fullscreen::cue {\n visibility: visible !important;\n font-size: 1em !important;\n}\n\n.container .gplayer-cc-line {\n position: absolute;\n bottom: calc(var(--bottom-panel) + 5px);\n width: 100%;\n}\n.container .gplayer-cc-line p {\n width: auto;\n background-color: rgba(0, 0, 0, 0.4);\n color: white;\n display: inline-block;\n}");
58546
+ insertStyle(".media-control-skin-1 .media-control-cc button.media-control-button {\n display: flex;\n justify-content: center;\n padding: 0;\n align-items: center;\n vertical-align: top;\n}\n.media-control-skin-1 .media-control-cc button.media-control-button:hover {\n color: white;\n}\n.media-control-skin-1 .media-control-cc ul li {\n text-align: center;\n}\n.media-control-skin-1 .media-control-cc ul li a {\n height: 30px;\n padding: 5px 10px;\n color: #fffffe;\n}\n.media-control-skin-1 .media-control-cc ul li a:hover {\n background-color: rgba(0, 0, 0, 0.4);\n}\n.media-control-skin-1 .media-control-cc ul li.current a {\n background-color: rgba(0, 0, 0, 0.4);\n}\n.media-control-skin-1 .media-control-cc ul li:first-child a {\n border-bottom-left-radius: 4px;\n border-bottom-right-radius: 4px;\n}\n.media-control-skin-1 .media-control-cc ul li:last-child a {\n border-top-left-radius: 4px;\n border-top-right-radius: 4px;\n}\n.media-control-skin-1 .media-control-cc {\n position: relative;\n order: 85;\n}\n\n::cue {\n visibility: hidden !important;\n font-size: 0 !important;\n}\n\n.ios-fullscreen::cue {\n visibility: visible !important;\n font-size: 1em !important;\n}\n\n.container .gplayer-cc-line {\n position: absolute;\n bottom: calc(var(--bottom-panel) + 5px);\n width: 100%;\n transition: transform 0.3s ease-out;\n}\n.container .gplayer-cc-line.media-control-cc-pulled {\n transform: translateY(var(--bottom-panel));\n}\n.container .gplayer-cc-line p {\n width: auto;\n background-color: rgba(0, 0, 0, 0.4);\n color: white;\n display: inline-block;\n}");
58553
58547
 
58554
58548
  const subtitlesOffIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M16.238 16.1C13.979 16.1 12.578 14.538 12.578 11.997C12.578 9.462 13.973 7.9 16.238 7.9C18.087 7.9 19.5029 9.127 19.6219 10.824H18.032C17.876 9.927 17.168 9.338 16.238 9.338C15.011 9.338 14.249 10.354 14.249 11.997C14.249 13.641 15.011 14.662 16.243 14.662C17.178 14.662 17.881 14.111 18.038 13.251H19.627C19.492 14.938 18.119 16.1 16.238 16.1ZM8.03198 16.1C5.77298 16.1 4.37299 14.538 4.37299 11.997C4.37299 9.462 5.76798 7.9 8.03198 7.9C9.88098 7.9 11.298 9.127 11.416 10.824H9.82697C9.67097 9.927 8.96198 9.338 8.03198 9.338C6.80598 9.338 6.04297 10.354 6.04297 11.997C6.04297 13.641 6.80596 14.662 8.03796 14.662C8.97296 14.662 9.67601 14.111 9.83301 13.251H11.422C11.287 14.938 9.91398 16.1 8.03198 16.1ZM22.5 3H1.5C0.672 3 0 3.671 0 4.5V19.5C0 20.329 0.672 21 1.5 21H22.5C23.329 21 24 20.329 24 19.5V4.5C24 3.671 23.329 3 22.5 3Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
58555
58549
 
@@ -58560,7 +58554,6 @@ const comboboxHTML = "<button\n class='media-control-button media-control-ico
58560
58554
  const stringHTML = "<div class=\"gplayer-cc-line\" id=\"gplayer-cc-line\">\n <p></p>\n</div>\n";
58561
58555
 
58562
58556
  const VERSION = '2.19.14';
58563
- const LOCAL_STORAGE_CC_ID = 'gplayer.plugins.cc.selected';
58564
58557
  /**
58565
58558
  * `PLUGIN` that provides a UI to select the subtitles when available.
58566
58559
  * @public
@@ -58597,9 +58590,10 @@ const LOCAL_STORAGE_CC_ID = 'gplayer.plugins.cc.selected';
58597
58590
  * ```
58598
58591
  */
58599
58592
  class ClosedCaptions extends UICorePlugin {
58600
- isPreselectedApplied = false;
58593
+ isSelectedApplied = false;
58601
58594
  active = false;
58602
58595
  open = false;
58596
+ userSelectedItemId = -1;
58603
58597
  track = null;
58604
58598
  tracks = [];
58605
58599
  $line = null;
@@ -58661,8 +58655,12 @@ class ClosedCaptions extends UICorePlugin {
58661
58655
  const mediaControl = this.core.getPlugin('media_control');
58662
58656
  assert(mediaControl, 'media_control plugin is required');
58663
58657
  this.listenTo(mediaControl, Events$1.MEDIACONTROL_RENDERED, this.mount);
58658
+ this.listenTo(mediaControl, Events$1.MEDIACONTROL_SHOW, () => {
58659
+ this.$line?.removeClass('media-control-cc-pulled');
58660
+ });
58664
58661
  this.listenTo(mediaControl, Events$1.MEDIACONTROL_HIDE, () => {
58665
58662
  this.hideMenu();
58663
+ this.$line?.addClass('media-control-cc-pulled');
58666
58664
  });
58667
58665
  this.listenTo(mediaControl, ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, (from) => {
58668
58666
  if (from !== this.name) {
@@ -58697,7 +58695,7 @@ class ClosedCaptions extends UICorePlugin {
58697
58695
  video.classList.remove('ios-fullscreen');
58698
58696
  }
58699
58697
  });
58700
- this.isPreselectedApplied = false;
58698
+ this.isSelectedApplied = false;
58701
58699
  }
58702
58700
  onPlaybackReady() {
58703
58701
  this.core.activePlayback.oncueenter = (e) => {
@@ -58720,23 +58718,27 @@ class ClosedCaptions extends UICorePlugin {
58720
58718
  this.activateTrack(id);
58721
58719
  }
58722
58720
  activateTrack(id) {
58723
- if (['dash', 'hls'].includes(this.core.activePlayback?.name)) {
58724
- this.core.activePlayback.setTextTrack(id);
58721
+ const isManaged = this.core.activePlayback?.name === 'hls';
58722
+ this.core.activePlayback.setTextTrack(id);
58723
+ if (isManaged) {
58724
+ return;
58725
+ }
58726
+ if (!this.core.activePlayback?.el.textTracks) {
58725
58727
  return;
58726
58728
  }
58727
- for (const track of this.currentTracks) {
58728
- if (track.id === id) {
58729
+ for (const [index, track] of Array.from(this.core.activePlayback?.el.textTracks ?? []).entries()) {
58730
+ if (index === id) {
58729
58731
  if (this.useNativeSubtitles) {
58730
- track.track.mode = 'showing';
58732
+ track.mode = 'showing';
58731
58733
  }
58732
58734
  else {
58733
- track.track.mode = 'hidden';
58735
+ track.mode = 'hidden';
58734
58736
  }
58735
- this.setSubtitleText(this.getSubtitleText(track.track));
58736
- track.track.oncuechange = (e) => {
58737
+ this.setSubtitleText(this.getSubtitleText(track));
58738
+ track.oncuechange = () => {
58737
58739
  try {
58738
- if (track.track.activeCues?.length) {
58739
- const html = track.track.activeCues[0].getCueAsHTML();
58740
+ if (track.activeCues?.length) {
58741
+ const html = track.activeCues[0].getCueAsHTML();
58740
58742
  this.setSubtitleText(html);
58741
58743
  }
58742
58744
  else {
@@ -58748,8 +58750,8 @@ class ClosedCaptions extends UICorePlugin {
58748
58750
  };
58749
58751
  }
58750
58752
  else {
58751
- track.track.oncuechange = () => { };
58752
- track.track.mode = 'disabled';
58753
+ track.oncuechange = () => { };
58754
+ track.mode = 'disabled';
58753
58755
  }
58754
58756
  }
58755
58757
  }
@@ -58757,7 +58759,7 @@ class ClosedCaptions extends UICorePlugin {
58757
58759
  try {
58758
58760
  // TODO ensure to apply only once
58759
58761
  this.currentTracks = this.core.activePlayback.closedCaptionsTracks;
58760
- this.applyPreselectedSubtitles();
58762
+ this.applySelectedSubtitles();
58761
58763
  this.render();
58762
58764
  }
58763
58765
  catch (error) {
@@ -58790,8 +58792,10 @@ class ClosedCaptions extends UICorePlugin {
58790
58792
  this.$el.find('#gplayer-cc-menu').hide();
58791
58793
  this.$el.find('#gplayer-cc-button').attr('aria-expanded', 'false');
58792
58794
  this.$line.hide();
58793
- for (const track of this.currentTracks) {
58794
- track.track.mode = 'hidden';
58795
+ for (const track of this.core.activePlayback.el.textTracks) {
58796
+ if (track.mode === 'showing') {
58797
+ track.mode = 'hidden';
58798
+ }
58795
58799
  }
58796
58800
  }
58797
58801
  /**
@@ -58803,7 +58807,6 @@ class ClosedCaptions extends UICorePlugin {
58803
58807
  if (this.core.activeContainer &&
58804
58808
  isFullscreen(this.core.activeContainer.el) &&
58805
58809
  this.currentTrack &&
58806
- // this.currentTrack.track.mode &&
58807
58810
  (Browser.isiOS || this.useNativeSubtitles)) {
58808
58811
  this.$line.hide();
58809
58812
  this.currentTrack.track.mode = 'showing';
@@ -58845,6 +58848,10 @@ class ClosedCaptions extends UICorePlugin {
58845
58848
  this.resizeFont();
58846
58849
  this.clampPopup();
58847
58850
  this.core.activeContainer.$el.append(this.$line);
58851
+ const mc = this.core.getPlugin('media_control');
58852
+ if (!mc?.isVisible()) {
58853
+ this.$line?.addClass('media-control-cc-pulled');
58854
+ }
58848
58855
  this.updateSelection();
58849
58856
  this.renderIcon();
58850
58857
  return this;
@@ -58862,22 +58869,36 @@ class ClosedCaptions extends UICorePlugin {
58862
58869
  }
58863
58870
  onItemSelect(event) {
58864
58871
  // event.target does not exist for some reason in tests
58865
- const id = (event.target ?? event.currentTarget).dataset?.item ??
58866
- '-1';
58867
- localStorage.setItem(LOCAL_STORAGE_CC_ID, id); // TODO store language instead?
58868
- this.selectItem(this.findById(Number(id)));
58872
+ const id = Number((event.target ?? event.currentTarget).dataset?.item ??
58873
+ '-1');
58874
+ // TODO review, make configurable, and emit event in addition
58875
+ // localStorage.setItem(LOCAL_STORAGE_CC_ID, id) // TODO store language instead?
58876
+ this.userSelectedItemId = id;
58877
+ this.selectItem(this.findById(id));
58869
58878
  this.hideMenu();
58870
58879
  return false;
58871
58880
  }
58872
- applyPreselectedSubtitles() {
58873
- if (!this.isPreselectedApplied) {
58874
- this.isPreselectedApplied = true;
58875
- // if the language is undefined, then let the engine decide
58876
- // to hide the subtitles forcefully, set the language to 'none'
58877
- setTimeout(() => {
58878
- this.selectItem(this.tracks.find((t) => this.isPreselectedLanguage(t.track.language)) ?? null);
58879
- }, 0);
58881
+ applySelectedSubtitles() {
58882
+ if (this.isSelectedApplied) {
58883
+ return;
58880
58884
  }
58885
+ this.isSelectedApplied = true;
58886
+ // If user selected a language, activate that
58887
+ // Otherwise, if there is no configured language, then let the engine decide
58888
+ // To hide the subtitles initially forcefully, set the language to 'none'
58889
+ let matcher;
58890
+ if (this.userSelectedItemId !== -1) {
58891
+ matcher = (track) => track.id === this.userSelectedItemId;
58892
+ }
58893
+ else if (this.preselectedLanguage) {
58894
+ matcher = (track) => this.isPreselectedLanguage(track.track.language);
58895
+ }
58896
+ else {
58897
+ return;
58898
+ }
58899
+ setTimeout(() => {
58900
+ this.selectItem(this.tracks.find(matcher) ?? null);
58901
+ }, 0);
58881
58902
  }
58882
58903
  hideMenu() {
58883
58904
  this.open = false;
@@ -58911,10 +58932,9 @@ class ClosedCaptions extends UICorePlugin {
58911
58932
  return this.$el.find('#gplayer-cc-menu li'); // TODO fix semantically
58912
58933
  }
58913
58934
  selectSubtitles() {
58914
- const trackId = this.currentTrack?.id ?? -1;
58915
- // TODO find out if this is needed
58916
- this.core.activePlayback.closedCaptionsTrackId = trackId;
58917
- // this.core.activePlayback.closedCaptionsTrackId = -1
58935
+ if (this.currentTrack) {
58936
+ this.core.activePlayback.closedCaptionsTrackId = this.currentTrack.id;
58937
+ }
58918
58938
  }
58919
58939
  getSubtitleText(track) {
58920
58940
  const currentTime = this.core.activePlayback?.getCurrentTime() ?? 0;
@@ -58937,7 +58957,7 @@ class ClosedCaptions extends UICorePlugin {
58937
58957
  this.setSubtitleText('');
58938
58958
  }
58939
58959
  updateSelection() {
58940
- if (!this.currentTrack) {
58960
+ if (this.core.activePlayback.closedCaptionsTrackId === -1) {
58941
58961
  this.hide();
58942
58962
  }
58943
58963
  else {