@gcorevideo/player 2.28.35 → 2.29.0

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 (61) hide show
  1. package/README.md +22 -1
  2. package/assets/{subtitles → cc}/style.scss +5 -0
  3. package/assets/media-control/media-control.scss +8 -6
  4. package/assets/multi-camera/multicamera.ejs +27 -23
  5. package/assets/multi-camera/style.scss +7 -34
  6. package/assets/style/main.scss +2 -2
  7. package/dist/core.js +24 -28
  8. package/dist/index.css +384 -402
  9. package/dist/index.embed.js +54 -84
  10. package/dist/index.js +122 -219
  11. package/docs/api/player.md +22 -9
  12. package/docs/api/player.mediacontrol.setkeepvisible.md +56 -0
  13. package/docs/api/player.multicamera.md +0 -28
  14. package/docs/api/player.multiccamerasourceinfo.md +27 -0
  15. package/docs/api/{player.multicamera.unbindevents.md → player.multisourcesmode.md} +4 -7
  16. package/docs/api/player.sourcecontroller.md +0 -37
  17. package/lib/playback/BasePlayback.d.ts +1 -0
  18. package/lib/playback/BasePlayback.d.ts.map +1 -1
  19. package/lib/playback/BasePlayback.js +3 -0
  20. package/lib/playback/dash-playback/DashPlayback.d.ts +3 -1
  21. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  22. package/lib/playback/dash-playback/DashPlayback.js +9 -22
  23. package/lib/playback/hls-playback/HlsPlayback.d.ts +2 -1
  24. package/lib/playback/hls-playback/HlsPlayback.d.ts.map +1 -1
  25. package/lib/playback/hls-playback/HlsPlayback.js +4 -0
  26. package/lib/playback/types.d.ts +9 -0
  27. package/lib/playback/types.d.ts.map +1 -1
  28. package/lib/playback.types.d.ts +0 -6
  29. package/lib/playback.types.d.ts.map +1 -1
  30. package/lib/plugins/multi-camera/MultiCamera.d.ts +21 -4
  31. package/lib/plugins/multi-camera/MultiCamera.d.ts.map +1 -1
  32. package/lib/plugins/multi-camera/MultiCamera.js +70 -134
  33. package/lib/plugins/source-controller/SourceController.d.ts +0 -39
  34. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  35. package/lib/plugins/source-controller/SourceController.js +0 -39
  36. package/lib/plugins/subtitles/ClosedCaptions.d.ts +1 -1
  37. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  38. package/lib/plugins/subtitles/ClosedCaptions.js +32 -22
  39. package/lib/testUtils.d.ts +1 -0
  40. package/lib/testUtils.d.ts.map +1 -1
  41. package/lib/testUtils.js +3 -0
  42. package/lib/utils/mediaSources.d.ts +4 -0
  43. package/lib/utils/mediaSources.d.ts.map +1 -1
  44. package/lib/utils/mediaSources.js +8 -6
  45. package/package.json +1 -1
  46. package/src/playback/BasePlayback.ts +4 -0
  47. package/src/playback/dash-playback/DashPlayback.ts +11 -29
  48. package/src/playback/hls-playback/HlsPlayback.ts +5 -1
  49. package/src/playback/types.ts +10 -0
  50. package/src/playback.types.ts +0 -6
  51. package/src/plugins/multi-camera/MultiCamera.ts +103 -166
  52. package/src/plugins/source-controller/SourceController.ts +0 -39
  53. package/src/plugins/subtitles/ClosedCaptions.ts +35 -21
  54. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +73 -112
  55. package/src/plugins/subtitles/__tests__/__snapshots__/ClosedCaptions.test.ts.snap +3 -3
  56. package/src/testUtils.ts +3 -0
  57. package/src/utils/mediaSources.ts +10 -6
  58. package/tsconfig.tsbuildinfo +1 -1
  59. package/docs/api/player.multicamera.activebyid.md +0 -67
  60. /package/assets/{subtitles → cc}/combobox.ejs +0 -0
  61. /package/assets/{subtitles → cc}/string.ejs +0 -0
package/dist/index.js CHANGED
@@ -12778,6 +12778,9 @@ var PlayerEvent;
12778
12778
  PlayerEvent["VolumeUpdate"] = "volumeupdate";
12779
12779
  })(PlayerEvent || (PlayerEvent = {}));
12780
12780
 
12781
+ const MIME_TYPES_HLS = ['application/x-mpegurl', 'application/vnd.apple.mpegurl'];
12782
+ const MIME_TYPE_HLS = MIME_TYPES_HLS[0];
12783
+ const MIME_TYPE_DASH = 'application/dash+xml';
12781
12784
  // TODO rewrite using the Playback classes and canPlay static methods
12782
12785
  function buildMediaSourcesList(sources, priorityTransport = 'dash') {
12783
12786
  const playbacks = Loader.registeredPlaybacks;
@@ -12817,22 +12820,21 @@ function wrapSource(s) {
12817
12820
  }
12818
12821
  function guessMimeType(s) {
12819
12822
  if (s.endsWith('.mpd')) {
12820
- return 'application/dash+xml';
12823
+ return MIME_TYPE_DASH;
12821
12824
  }
12822
12825
  if (s.endsWith('.m3u8')) {
12823
- // return 'application/vnd.apple.mpegurl'
12824
- return 'application/x-mpegurl';
12826
+ return MIME_TYPE_HLS;
12825
12827
  }
12826
12828
  }
12827
12829
  function isDashSource(source, mimeType) {
12828
12830
  if (mimeType) {
12829
- return mimeType === 'application/dash+xml'; // TODO consider video/mp4
12831
+ return mimeType === MIME_TYPE_DASH; // TODO consider video/mp4
12830
12832
  }
12831
12833
  return source.endsWith('.mpd');
12832
12834
  }
12833
12835
  function isHlsSource(source, mimeType) {
12834
12836
  if (mimeType) {
12835
- return ['application/vnd.apple.mpegurl', 'application/x-mpegurl'].includes(mimeType.toLowerCase());
12837
+ return MIME_TYPES_HLS.includes(mimeType.toLowerCase());
12836
12838
  }
12837
12839
  return source.endsWith('.m3u8');
12838
12840
  }
@@ -12899,6 +12901,9 @@ class BasePlayback extends HTML5Video$1 {
12899
12901
  super._onPlaying();
12900
12902
  this.trigger(Events$1.PLAYBACK_MEDIACONTROL_ENABLE);
12901
12903
  }
12904
+ setTextTrack(id) {
12905
+ // noop
12906
+ }
12902
12907
  }
12903
12908
 
12904
12909
  var PlaybackEvents;
@@ -12921,6 +12926,7 @@ const T$e = 'playback.dash';
12921
12926
  class DashPlayback extends BasePlayback {
12922
12927
  _levels = [];
12923
12928
  _currentLevel = AUTO$1;
12929
+ _currentTextTrackId = -1;
12924
12930
  // true when the actual duration is longer than hlsjs's live sync point
12925
12931
  // when this is false playableRegionDuration will be the actual duration
12926
12932
  // when this is true playableRegionDuration will exclude the time after the sync point
@@ -13053,7 +13059,11 @@ class DashPlayback extends BasePlayback {
13053
13059
  streaming: {
13054
13060
  text: {
13055
13061
  defaultEnabled: false,
13056
- dispatchForManualRendering: true,
13062
+ // NOTE: dispatchForManualRendering is not correctly implemented in DASH.js;
13063
+ // it does not work when there are multiple text tracks.
13064
+ // CUE_ENTER and CUE_EXIT events might be dispatched additionally
13065
+ // for a track, other than the currently active one.
13066
+ // dispatchForManualRendering: true, // TODO only when useNativeSubtitles is not true?
13057
13067
  },
13058
13068
  },
13059
13069
  }, this.options.dash);
@@ -13097,24 +13107,6 @@ class DashPlayback extends BasePlayback {
13097
13107
  this._dash.on(_.events.PLAYBACK_RATE_CHANGED, (e) => {
13098
13108
  this.trigger(PlaybackEvents.PLAYBACK_RATE_CHANGED, e.playbackRate);
13099
13109
  });
13100
- this._dash.on(_.events.TRACK_CHANGE_RENDERED, (e) => {
13101
- if (e.mediaType === 'audio') {
13102
- this.trigger(Events$1.PLAYBACK_AUDIO_CHANGED, toClapprTrack$1(e.newMediaInfo));
13103
- }
13104
- });
13105
- this._dash.on(_.events.CUE_ENTER, (e) => {
13106
- this.oncueenter?.({
13107
- end: e.end,
13108
- id: e.id,
13109
- start: e.start,
13110
- text: e.text,
13111
- });
13112
- });
13113
- this._dash.on(_.events.CUE_EXIT, (e) => {
13114
- this.oncueexit?.({
13115
- id: e.id,
13116
- });
13117
- });
13118
13110
  }
13119
13111
  render() {
13120
13112
  this._ready();
@@ -13424,14 +13416,14 @@ class DashPlayback extends BasePlayback {
13424
13416
  this._dash?.setTextTrack(this.closedCaptionsTrackId);
13425
13417
  }
13426
13418
  setTextTrack(id) {
13419
+ this._currentTextTrackId = id;
13427
13420
  this._dash?.setTextTrack(id);
13428
13421
  }
13429
13422
  /**
13430
13423
  * @override
13431
13424
  */
13432
13425
  get closedCaptionsTracks() {
13433
- const tt = this.getTextTracks();
13434
- return tt;
13426
+ return this.getTextTracks();
13435
13427
  }
13436
13428
  getTextTracks() {
13437
13429
  return this._dash?.getTracksFor('text').map((t, index) => ({
@@ -13441,7 +13433,7 @@ class DashPlayback extends BasePlayback {
13441
13433
  id: index,
13442
13434
  label: getTextTrackLabel(t) || "",
13443
13435
  language: t.lang,
13444
- mode: "hidden",
13436
+ mode: this._currentTextTrackId === index ? "showing" : "hidden",
13445
13437
  },
13446
13438
  })) || [];
13447
13439
  }
@@ -50953,7 +50945,11 @@ class HlsPlayback extends BasePlayback {
50953
50945
  this.trigger(Events$1.PLAYBACK_AUDIO_CHANGED, toClapprTrack(track));
50954
50946
  }
50955
50947
  setTextTrack(id) {
50948
+ if (id === this._hls.subtitleTrack) {
50949
+ return;
50950
+ }
50956
50951
  this._hls.subtitleTrack = id;
50952
+ this.cues = [];
50957
50953
  }
50958
50954
  /**
50959
50955
  * @override
@@ -51573,7 +51569,7 @@ class Player {
51573
51569
  }
51574
51570
  }
51575
51571
 
51576
- var version$1 = "2.28.35";
51572
+ var version$1 = "2.29.0";
51577
51573
 
51578
51574
  var packages = {
51579
51575
  "node_modules/@clappr/core": {
@@ -57964,14 +57960,10 @@ class Logo extends UIContainerPlugin {
57964
57960
  }
57965
57961
  }
57966
57962
 
57967
- const pluginHtml$3 = "<button data-multicamera-button class='gcore-skin-button-color'>\n <span class=\"multicamera-icon\"></span>\n</button>\n\n<ul class=\"gcore-skin-bg-color\">\n <% for (var i = 0; i < streams.length; i++) { %>\n <% if(!streams[i].live && multisources_mode === 'only_live') { %>\n <% continue; %>\n <% } %>\n <li>\n <div class=\"multicamera-item\" data-multicamera-selector-live=\"<%= streams[i].live %>\"\n data-multicamera-selector-select=\"<%= streams[i].id %>\">\n <div class=\"multicamera-screenshot\">\n <% if (streams[i].screenshot) { %>\n <img src=\"<%= streams[i].screenshot %>\" alt=\"<%= streams[i].title %>\"/>\n <% } %>\n </div>\n <div class=\"multicamera-text gcore-skin-text-color\">\n <% if (streams[i].title) { %>\n <div class=\"multicamera-title gcore-skin-text-color\"><%= streams[i].title %></div>\n <% } %>\n <% if (streams[i].description) { %>\n <div class=\"multicamera-description gcore-skin-text-color\"><%= streams[i].description %></div>\n <% } %>\n </div>\n </div>\n </li>\n <% } %>\n</ul>\n";
57963
+ const pluginHtml$3 = "<button data-multicamera-button class='gcore-skin-button-color media-control-button'>\n <span class=\"multicamera-icon\"></span>\n</button>\n\n<ul class=\"gcore-skin-bg-color\">\n <% for (var i=0; i < streams.length; i++) { %>\n <% if(!streams[i].live && multisources_mode==='only_live' ) { %>\n <% continue; %>\n <% } %>\n <li>\n <div class=\"multicamera-item\" data-multicamera-selector-live=\"<%= streams[i].live %>\"\n data-multicamera-selector-select=\"<%= streams[i].id %>\">\n <div class=\"multicamera-screenshot\">\n <% if (streams[i].screenshot) { %>\n <img src=\"<%= streams[i].screenshot %>\" alt=\"<%= streams[i].title %>\" />\n <% } %>\n </div>\n <div class=\"multicamera-text gcore-skin-text-color\">\n <% if (streams[i].title) { %>\n <div class=\"multicamera-title gcore-skin-text-color\">\n <%= streams[i].title %>\n </div>\n <% } %>\n <% if (streams[i].description) { %>\n <div class=\"multicamera-description gcore-skin-text-color\">\n <%= streams[i].description %>\n </div>\n <% } %>\n </div>\n </div>\n </li>\n <% } %>\n</ul>";
57968
57964
 
57969
57965
  const streamsIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"24\" height=\"20\" viewBox=\"0 0 24 20\">\n <path fill=\"#FFF\" fill-rule=\"nonzero\" d=\"M24 1.5v13a1.5 1.5 0 0 1-1.5 1.5h-1a.5.5 0 0 1-.5-.5v-10A2.5 2.5 0 0 0 18.5 3h-14a.5.5 0 0 1-.5-.5v-1A1.5 1.5 0 0 1 5.5 0h17A1.5 1.5 0 0 1 24 1.5M12.724 12.447l-5 2.5a.505.505 0 0 1-.487-.021A.503.503 0 0 1 7 14.5v-5c0-.173.09-.334.237-.426a.505.505 0 0 1 .487-.021l5 2.5a.5.5 0 0 1 0 .894M18.5 4h-17C.673 4 0 4.673 0 5.5v13c0 .827.673 1.5 1.5 1.5h17c.827 0 1.5-.673 1.5-1.5v-13c0-.827-.673-1.5-1.5-1.5\"/>\n</svg>\n";
57970
57966
 
57971
- const streamsMomentoIcon = "<svg id=\"Слой_1\" data-name=\"Слой 1\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 230.73 173.61\"><defs><style>.cls-1{fill:#fff;}</style></defs><path class=\"cls-1\" d=\"M71.82,16.09c11.43,0,22.87-.05,34.31,0,12,.06,19.45,7.45,19.7,19.52.23,11.31.23,11.31,11.81,11.31q24.36,0,48.73,0c12.74,0,20.21,7.3,20.27,19.88q.11,24.12,0,48.23c-.06,12.66-7.12,19.65-19.75,19.77-2,0-4,0-6,0-7.78,0-7.84.05-6,7.79a59.23,59.23,0,0,0,1.95,6.67c1.44,3.95.33,7.18-2.66,9.82-3.28,2.89-6.93,2.88-10.59.76-9.31-5.4-16.95-12.73-23.55-21.11-2.29-2.93-4.66-4.2-8.35-4-5.12.28-10.28.19-15.41,0-10.39-.37-17.64-7.65-18.09-18a62.93,62.93,0,0,0-.09-6.45c-.3-2.07,1.6-5.54-1.49-6-3.62-.48-7.92-2.08-11.07,1.89-6.09,7.7-12.82,14.76-21,20.24a42,42,0,0,1-5.09,3.08,8.16,8.16,0,0,1-9.29-1.12,8.25,8.25,0,0,1-3-8.86c1-4,2-8,3-12,.59-2.51-.34-3.66-3.07-3.59-4.14.12-8.3.14-12.43-.11-9.61-.59-16.86-7.76-17-17.42-.24-17.57-.21-35.14,0-52.71.12-10.07,8-17.46,18.43-17.58C48,16,59.88,16.09,71.82,16.09ZM56.66,120.5c2.53-.3,3.87-1.89,5.38-3.08A99.31,99.31,0,0,0,79.83,98.8a8.72,8.72,0,0,1,8-3.83c6.12.18,12.25.12,18.38,0,7.31-.12,10.6-3.39,10.64-10.72q.11-24.33,0-48.68c0-7-3.5-10.51-10.36-10.53q-35-.11-70,0c-6.34,0-9.92,3.51-9.95,9.83q-.15,25.08,0,50.18c0,6.37,3.42,9.72,9.86,9.89,5.62.14,11.26.1,16.89.06,4.37,0,6.2,2,6.25,6.4C59.55,107.88,58.17,114.1,56.66,120.5ZM167.78,152c-1.93-6.72-3.37-12.44-3.41-18.4,0-6.33,1.17-7.71,7.37-7.77,5-.05,9.94.06,14.9,0,7.6-.13,10.79-3.35,10.81-11q.08-23.85,0-47.69c0-7.61-3.38-11-10.86-11.08-18.88-.07-37.76,0-56.64-.08-3.21,0-4.29.89-4.2,4.21.24,8.27.18,16.56,0,24.83-.13,8.6-4.46,16.11-11.88,17.55-6.73,1.3-7.44,4.81-6.78,10.16.14,1.14,0,2.32,0,3.48.3,6.1,3.53,9.44,9.69,9.63,5.79.18,11.6.34,17.38,0,4.81-.31,7.94,1.3,10.83,5.22A79.08,79.08,0,0,0,167.78,152Z\"/><path class=\"cls-1\" d=\"M73.07,56c-6.4,0-12.15-.06-17.9,0-3.28,0-5.76-1-5.68-4.63s2.66-4.59,5.88-4.45c1.49.06,3-.12,4.47,0,4.79.46,8.51.12,7.44-6.47-.43-2.67,1.82-4.32,4.42-4.26s4.81,1.75,4.35,4.4c-1.18,6.75,2.76,6.72,7.44,6.34a43.43,43.43,0,0,1,6.45.09,4,4,0,0,1,4,4.17c0,2.59-1.46,4.88-4.17,4.48-7-1-7.55,5.72-11.08,8.81-1.54,1.35.36,2.28,1.27,3.06,2.13,1.83,4.38,3.53,6.52,5.36s2.74,4.28.8,6.54c-1.74,2-4,2-6.27.53-.28-.18-.52-.41-.79-.6-3.22-2.29-5.94-6.88-9.46-6.66s-6.61,4-9.91,6.17a19.94,19.94,0,0,1-2.55,1.52c-2.51,1.19-5,1.29-6.46-1.44-1.42-2.57-.6-4.82,1.91-6.34A88.31,88.31,0,0,0,68.17,62.07C69.84,60.52,71.73,59.09,73.07,56Z\"/><path class=\"cls-1\" d=\"M153,104.27a43.76,43.76,0,0,1-4.91,0c-3.27-.4-5.24.75-6.27,4-.9,2.88-2.84,5.23-6.28,3.82-3.66-1.5-3.21-4.49-1.94-7.52,4.68-11.12,9.36-22.22,13.94-33.37,1-2.36,2.28-4.1,5-4.08s3.89,2,4.85,4.25c4.66,11.11,9.4,22.2,14.14,33.28,1.3,3,1.69,6-2,7.46-3.4,1.35-5.49-.73-6.29-3.74C161.49,102,156.3,105.12,153,104.27Zm-.84-20.39a64.73,64.73,0,0,1-2.78,6.37c-2.25,3.89-1.16,4.85,3.14,4.89s4.82-1.35,2.93-4.73C154.36,88.42,154.15,86,152.18,83.88Z\"/></svg>";
57972
-
57973
- 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";
57974
-
57975
57967
  const VERSION$4 = '0.0.1';
57976
57968
  const T$6 = 'plugins.multicamera';
57977
57969
  /**
@@ -58019,6 +58011,8 @@ class MultiCamera extends UICorePlugin {
58019
58011
  // Don't mutate the options, TODO check if some plugin observes the options.multicamera
58020
58012
  this.multicamera = this.options.multisources.map((item) => ({ ...item }));
58021
58013
  this.noActiveStreams = this.multicamera.every((item) => !item.live);
58014
+ // TODO filter out non-live
58015
+ this.core.options.sources = expandMediaSource(this.multicamera[0]);
58022
58016
  }
58023
58017
  bindEvents() {
58024
58018
  this.listenTo(this.core, Events$1.CORE_READY, this.bindPlaybackEvents);
@@ -58027,15 +58021,10 @@ class MultiCamera extends UICorePlugin {
58027
58021
  this.listenTo(this.core.mediaControl, Events$1.MEDIACONTROL_HIDE, this.hideSelectLevelMenu);
58028
58022
  }
58029
58023
  unBindEvents() {
58030
- // @ts-ignore
58031
- this.stopListening(this.core, Events$1.CORE_READY);
58032
- // @ts-ignore
58033
- this.stopListening(this.core.mediaControl, Events$1.MEDIACONTROL_CONTAINERCHANGED);
58034
- // @ts-ignore
58035
- this.stopListening(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED);
58036
- // @ts-ignore
58037
- this.stopListening(this.core.mediaControl, Events$1.MEDIACONTROL_HIDE);
58038
- // @ts-ignore
58024
+ this.stopListening(this.core, Events$1.CORE_READY, this.bindPlaybackEvents);
58025
+ this.stopListening(this.core.mediaControl, Events$1.MEDIACONTROL_CONTAINERCHANGED, this.reload);
58026
+ this.stopListening(this.core.mediaControl, Events$1.MEDIACONTROL_RENDERED, this.render);
58027
+ this.stopListening(this.core.mediaControl, Events$1.MEDIACONTROL_HIDE, this.hideSelectLevelMenu);
58039
58028
  this.stopListening(this.core.activePlayback, Events$1.PLAYBACK_PLAY, this.onPlay);
58040
58029
  }
58041
58030
  onPlay() {
@@ -58051,80 +58040,53 @@ class MultiCamera extends UICorePlugin {
58051
58040
  this.bindPlaybackEvents();
58052
58041
  }
58053
58042
  shouldRender() {
58054
- if (!this.core.activeContainer || this.noActiveStreams) {
58055
- return false;
58056
- }
58057
- if (!this.core.activePlayback) {
58043
+ if (this.noActiveStreams) {
58058
58044
  return false;
58059
58045
  }
58060
58046
  return this.multicamera.length >= 2;
58061
58047
  }
58062
58048
  render() {
58063
- if (this.shouldRender()) {
58064
- let numActiveSources = 0;
58065
- // const currentSource = this.core.options.source
58066
- const currentSource = this.core.activePlayback?.sourceMedia;
58067
- for (const item of this.multicamera) {
58068
- if (item.live) {
58069
- numActiveSources++;
58070
- }
58071
- if (!this.currentCamera && item.source === currentSource) {
58072
- this.currentCamera = item;
58073
- }
58074
- }
58075
- // const mediaControl = this.core.getPlugin('media_control')
58076
- if (this.currentTime &&
58077
- // TODO check the last active playback type instead
58078
- // !mediaControl.$el.hasClass('live') &&
58079
- this.core.getPlaybackType() !== Playback.LIVE) {
58080
- if (this.currentTime < this.core.activePlayback.getDuration()) {
58081
- this.core.activePlayback.seek(this.currentTime);
58082
- }
58083
- this.currentTime = 0;
58084
- // if (mediaControl.$el.hasClass('dvr')) {
58085
- // this.core.activeContainer.dvrInUse = true;
58086
- // }
58087
- }
58088
- // TODO current source
58089
- this.$el.html(this.template({
58090
- streams: this.multicamera,
58091
- multisources_mode: this.options.multisourcesMode,
58092
- }));
58093
- if ((numActiveSources <= 1 &&
58094
- this.options.multisourcesMode !== 'show_all') ||
58095
- this.options.multisourcesMode === 'one_first') {
58096
- this.$el.hide();
58097
- }
58098
- else {
58099
- this.$el.show();
58049
+ if (!this.core.activeContainer || !this.core.activePlayback) {
58050
+ return this;
58051
+ }
58052
+ if (!this.shouldRender()) {
58053
+ return this;
58054
+ }
58055
+ let numActiveSources = 0;
58056
+ const currentSource = this.core.activePlayback?.sourceMedia;
58057
+ for (const item of this.multicamera) {
58058
+ if (item.live) {
58059
+ numActiveSources++;
58100
58060
  }
58101
- if (this.core.mediaControl.$multiCameraSelector &&
58102
- this.core.mediaControl.$multiCameraSelector.length > 0) {
58103
- this.core.mediaControl.$multiCameraSelector.append(this.el);
58061
+ if (!this.currentCamera && item.source === currentSource) {
58062
+ this.currentCamera = item;
58104
58063
  }
58105
- else {
58106
- this.core.mediaControl.$('.media-control-right-panel').append(this.el);
58107
- }
58108
- if (Object.prototype.hasOwnProperty.call(this.core.mediaControl, '$multiCameraSelector') &&
58109
- this.core.mediaControl.$multiCameraSelector.find('span.multicamera-icon').length > 0) {
58110
- if (~window.location.href.indexOf('whitenights.gcdn.co')) {
58111
- this.core.mediaControl.$multiCameraSelector
58112
- .find('span.multicamera-icon')
58113
- .append(streamsWhiteNightsIcon);
58114
- }
58115
- else if (~window.location.href.indexOf('momentosolutions.gcdn.co')) {
58116
- this.core.mediaControl.$multiCameraSelector
58117
- .find('span.multicamera-icon')
58118
- .append(streamsMomentoIcon);
58119
- }
58120
- else {
58121
- this.core.mediaControl.$multiCameraSelector
58122
- .find('span.multicamera-icon')
58123
- .append(streamsIcon);
58124
- }
58064
+ }
58065
+ if (this.currentTime &&
58066
+ this.core.getPlaybackType() !== Playback.LIVE) {
58067
+ if (this.currentTime < this.core.activePlayback.getDuration()) {
58068
+ this.core.activePlayback.seek(this.currentTime);
58125
58069
  }
58126
- this.highlightCurrentLevel();
58070
+ this.currentTime = 0;
58127
58071
  }
58072
+ this.$el.html(this.template({
58073
+ streams: this.multicamera,
58074
+ multisources_mode: this.options.multisourcesMode,
58075
+ }));
58076
+ if ((numActiveSources < 2 &&
58077
+ this.options.multisourcesMode !== 'show_all') ||
58078
+ this.options.multisourcesMode === 'one_first') {
58079
+ this.$el.hide();
58080
+ }
58081
+ else {
58082
+ this.$el.show();
58083
+ }
58084
+ const mediaControl = this.core.getPlugin('media_control');
58085
+ mediaControl.slot('multicamera', this.$el);
58086
+ this.$el
58087
+ .find('span.multicamera-icon')
58088
+ .html(streamsIcon);
58089
+ this.highlightCurrentLevel();
58128
58090
  return this;
58129
58091
  }
58130
58092
  onCameraSelect(event) {
@@ -58137,33 +58099,6 @@ class MultiCamera extends UICorePlugin {
58137
58099
  event.stopPropagation();
58138
58100
  return false;
58139
58101
  }
58140
- activeById(id, active) {
58141
- this.setLiveStatus(id, active);
58142
- if (!this.currentCamera && !this.noActiveStreams) {
58143
- return;
58144
- }
58145
- if (this.noActiveStreams && !active) {
58146
- return;
58147
- }
58148
- if (this.currentCamera) {
58149
- if (this.options.multisourcesMode === 'only_live') {
58150
- this.behaviorLive(id, active);
58151
- }
58152
- if (this.options.multisourcesMode === 'one_first') {
58153
- this.behaviorOne(id, active);
58154
- }
58155
- if (this.options.multisourcesMode === 'show_all') {
58156
- this.behaviorAll(id, active);
58157
- }
58158
- }
58159
- else {
58160
- if (this.noActiveStreams && active) {
58161
- this.changeById(id);
58162
- this.noActiveStreams = false;
58163
- }
58164
- }
58165
- this.render();
58166
- }
58167
58102
  setLiveStatus(id, active) {
58168
58103
  try {
58169
58104
  const index = this.findIndexById(id);
@@ -58226,7 +58161,6 @@ class MultiCamera extends UICorePlugin {
58226
58161
  this.currentCamera = null;
58227
58162
  this.noActiveStreams = true;
58228
58163
  this.core.trigger('core:multicamera:no_active_translation');
58229
- // this.changeById(this.multicamera[nextIndex].id);
58230
58164
  }
58231
58165
  showError() {
58232
58166
  this.core.activePlayback.pause();
@@ -58249,7 +58183,7 @@ class MultiCamera extends UICorePlugin {
58249
58183
  }
58250
58184
  hideError() {
58251
58185
  try {
58252
- this.core.mediaControl.enableControlButton();
58186
+ this.core.getPlugin('media_control')?.enableControlButton();
58253
58187
  }
58254
58188
  catch (error) {
58255
58189
  reportError(error);
@@ -58259,14 +58193,9 @@ class MultiCamera extends UICorePlugin {
58259
58193
  trace(`${T$6} changeById`, { id });
58260
58194
  queueMicrotask(() => {
58261
58195
  const playbackOptions = this.core.options.playback || {};
58262
- // TODO figure out what this does
58196
+ // TODO figure out if it's needed
58263
58197
  playbackOptions.recycleVideo = Browser.isMobile;
58264
- this.currentCamera = this.findElementById(id) ?? null;
58265
- trace(`${T$6} changeById`, {
58266
- id,
58267
- currentCamera: this.currentCamera,
58268
- multicamera: this.multicamera,
58269
- });
58198
+ this.currentCamera = this.findElementById(id);
58270
58199
  if (!this.currentCamera) {
58271
58200
  return;
58272
58201
  }
@@ -58288,26 +58217,16 @@ class MultiCamera extends UICorePlugin {
58288
58217
  this.core.configure({
58289
58218
  playback: playbackOptions,
58290
58219
  source: this.currentCamera.source, // TODO ensure that the preferred transport is used
58291
- video360: {
58292
- // TODO
58293
- projection: this.currentCamera.projection,
58294
- },
58295
58220
  fullscreenDisable,
58296
58221
  autoPlay: this.playing,
58297
58222
  disableCanAutoPlay: true,
58298
58223
  });
58299
- this.core.activeContainer.mediaControlDisabled = false;
58224
+ this.core.activeContainer?.enableMediaControl();
58300
58225
  });
58301
58226
  this.toggleContextMenu();
58302
58227
  }
58303
- getCamerasList() {
58304
- return this.multicamera;
58305
- }
58306
- getCurrentCamera() {
58307
- return this.currentCamera;
58308
- }
58309
58228
  findElementById(id) {
58310
- return this.multicamera.find((element) => element.id === id);
58229
+ return this.multicamera.find((element) => element.id === id) ?? null;
58311
58230
  }
58312
58231
  findIndexById(id) {
58313
58232
  return this.multicamera.findIndex((element) => element.id === id);
@@ -58316,19 +58235,13 @@ class MultiCamera extends UICorePlugin {
58316
58235
  this.toggleContextMenu();
58317
58236
  }
58318
58237
  hideSelectLevelMenu() {
58319
- this.$('.multicamera ul').hide();
58238
+ this.$('ul').hide();
58320
58239
  }
58321
58240
  toggleContextMenu() {
58322
- this.$('.multicamera ul').toggle();
58241
+ this.$('ul').toggle();
58323
58242
  }
58324
- // private buttonElement(): ZeptoResult {
58325
- // return this.$('.multicamera button');
58326
- // }
58327
- // private buttonElementText(): ZeptoResult {
58328
- // return this.$('.multicamera button .quality-text');
58329
- // }
58330
58243
  levelElement(id) {
58331
- return this.$('.multicamera ul li > div' +
58244
+ return this.$('ul .multicamera-item' +
58332
58245
  (id !== undefined
58333
58246
  ? '[data-multicamera-selector-select="' + id + '"]'
58334
58247
  : ''));
@@ -58340,6 +58253,22 @@ class MultiCamera extends UICorePlugin {
58340
58253
  this.levelElement(this.currentCamera.id).addClass('multicamera-active');
58341
58254
  }
58342
58255
  }
58256
+ function expandMediaSource(source) {
58257
+ const result = [{
58258
+ source: source.source,
58259
+ mimeType: guessMimeType(source.source),
58260
+ }];
58261
+ if (source.source_dash) {
58262
+ result.push({
58263
+ source: source.source_dash,
58264
+ mimeType: MIME_TYPE_DASH,
58265
+ });
58266
+ }
58267
+ if (source.hls_mpegts_url) {
58268
+ result.push(source.hls_mpegts_url);
58269
+ }
58270
+ return result;
58271
+ }
58343
58272
 
58344
58273
  const pipIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M21.05 3.00001C21.302 3.00001 21.5435 3.10003 21.7217 3.27833C21.9 3.45646 22 3.69802 22 3.95003V10.6H20.1V4.90003H4.90001V18.2H10.6V20.1H3.95001C3.69802 20.1 3.45647 20 3.27832 19.8217C3.10002 19.6436 3 19.402 3 19.15V3.95001C3 3.69802 3.10002 3.45647 3.27832 3.27832C3.45644 3.10002 3.69801 3 3.95001 3L21.05 3.00001ZM21.05 12.5C21.302 12.5 21.5435 12.6 21.7217 12.7783C21.9 12.9565 22 13.198 22 13.45V19.15C22 19.402 21.9 19.6436 21.7217 19.8217C21.5436 20 21.302 20.1 21.05 20.1H13.45C13.198 20.1 12.9564 20 12.7783 19.8217C12.6 19.6436 12.5 19.402 12.5 19.15V13.45C12.5 13.198 12.6 12.9565 12.7783 12.7783C12.9564 12.6 13.198 12.5 13.45 12.5H21.05ZM7.47178 6.12823L9.60928 8.26572L11.5501 6.32492V11.5499H6.32509L8.26589 9.60911L6.12839 7.47161L7.47178 6.12823Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
58345
58274
 
@@ -59770,45 +59699,6 @@ function noSync(cb) {
59770
59699
  * `PLUGIN` that is managing the automatic failover between media sources.
59771
59700
  * @public
59772
59701
  * @remarks
59773
- * Have a look at the {@link https://miro.com/app/board/uXjVLiN15tY=/?share_link_id=390327585787 | source failover diagram} for the details
59774
- * on how sources ordering and selection works. Below is a simplified diagram:
59775
- *
59776
- * ```markdown
59777
- * sources_list:
59778
- * - a.mpd | +--------------------+
59779
- * - b.m3u8 |--->| init |
59780
- * - ... | |--------------------|
59781
- * | current_source = 0 |
59782
- * +--------------------+
59783
- * |
59784
- * | source = a.mpd
59785
- * | playback = dash.js
59786
- * v
59787
- * +------------------+
59788
- * +-->| load source |
59789
- * | +---------|--------+
59790
- * | v
59791
- * | +------------------+
59792
- * | | play |
59793
- * | +---------|--------+
59794
- * | |
59795
- * | v
59796
- * | +-----------------------+
59797
- * | | on playback_error |
59798
- * | |-----------------------|
59799
- * | | current_source = |
59800
- * | | (current_source + 1) |
59801
- * | | % len sources_list |
59802
- * | | |
59803
- * | | delay 1..3s |
59804
- * | +---------------|-------+
59805
- * | |
59806
- * | source=b.m3u8 |
59807
- * | playback=hls.js |
59808
- * +-------------------+
59809
- *
59810
- * ```
59811
- *
59812
59702
  * @example
59813
59703
  * ```ts
59814
59704
  * import { SourceController } from '@gcorevideo/player'
@@ -60134,8 +60024,12 @@ class ClosedCaptions extends UICorePlugin {
60134
60024
  const mediaControl = this.core.getPlugin('media_control');
60135
60025
  assert(mediaControl, 'media_control plugin is required');
60136
60026
  this.listenTo(mediaControl, Events$1.MEDIACONTROL_RENDERED, this.mount);
60027
+ this.listenTo(mediaControl, Events$1.MEDIACONTROL_SHOW, () => {
60028
+ this.$line?.removeClass('media-control-cc-pulled');
60029
+ });
60137
60030
  this.listenTo(mediaControl, Events$1.MEDIACONTROL_HIDE, () => {
60138
60031
  this.hideMenu();
60032
+ this.$line?.addClass('media-control-cc-pulled');
60139
60033
  });
60140
60034
  this.listenTo(mediaControl, ExtendedEvents.MEDIACONTROL_MENU_COLLAPSE, (from) => {
60141
60035
  if (from !== this.name) {
@@ -60193,23 +60087,27 @@ class ClosedCaptions extends UICorePlugin {
60193
60087
  this.activateTrack(id);
60194
60088
  }
60195
60089
  activateTrack(id) {
60196
- if (this.core.activePlayback && ['dash', 'hls'].includes(this.core.activePlayback.name)) {
60197
- this.core.activePlayback.setTextTrack(id);
60090
+ const isManaged = this.core.activePlayback?.name === 'hls';
60091
+ this.core.activePlayback.setTextTrack(id);
60092
+ if (isManaged) {
60198
60093
  return;
60199
60094
  }
60200
- for (const track of this.currentTracks) {
60201
- if (track.id === id) {
60095
+ if (!this.core.activePlayback?.el.textTracks) {
60096
+ return;
60097
+ }
60098
+ for (const [index, track] of Array.from(this.core.activePlayback?.el.textTracks ?? []).entries()) {
60099
+ if (index === id) {
60202
60100
  if (this.useNativeSubtitles) {
60203
- track.track.mode = 'showing';
60101
+ track.mode = 'showing';
60204
60102
  }
60205
60103
  else {
60206
- track.track.mode = 'hidden';
60104
+ track.mode = 'hidden';
60207
60105
  }
60208
- this.setSubtitleText(this.getSubtitleText(track.track));
60209
- track.track.oncuechange = (e) => {
60106
+ this.setSubtitleText(this.getSubtitleText(track));
60107
+ track.oncuechange = () => {
60210
60108
  try {
60211
- if (track.track.activeCues?.length) {
60212
- const html = track.track.activeCues[0].getCueAsHTML();
60109
+ if (track.activeCues?.length) {
60110
+ const html = track.activeCues[0].getCueAsHTML();
60213
60111
  this.setSubtitleText(html);
60214
60112
  }
60215
60113
  else {
@@ -60222,8 +60120,8 @@ class ClosedCaptions extends UICorePlugin {
60222
60120
  };
60223
60121
  }
60224
60122
  else {
60225
- track.track.oncuechange = () => { };
60226
- track.track.mode = 'disabled';
60123
+ track.oncuechange = () => { };
60124
+ track.mode = 'disabled';
60227
60125
  }
60228
60126
  }
60229
60127
  }
@@ -60266,8 +60164,10 @@ class ClosedCaptions extends UICorePlugin {
60266
60164
  this.$el.find('#gplayer-cc-menu').hide();
60267
60165
  this.$el.find('#gplayer-cc-button').attr('aria-expanded', 'false');
60268
60166
  this.$line.hide();
60269
- for (const track of this.currentTracks) {
60270
- track.track.mode = 'hidden';
60167
+ for (const track of this.core.activePlayback.el.textTracks) {
60168
+ if (track.mode === 'showing') {
60169
+ track.mode = 'hidden';
60170
+ }
60271
60171
  }
60272
60172
  }
60273
60173
  /**
@@ -60279,7 +60179,6 @@ class ClosedCaptions extends UICorePlugin {
60279
60179
  if (this.core.activeContainer &&
60280
60180
  isFullscreen(this.core.activeContainer.el) &&
60281
60181
  this.currentTrack &&
60282
- // this.currentTrack.track.mode &&
60283
60182
  (Browser.isiOS || this.useNativeSubtitles)) {
60284
60183
  this.$line.hide();
60285
60184
  this.currentTrack.track.mode = 'showing';
@@ -60321,6 +60220,10 @@ class ClosedCaptions extends UICorePlugin {
60321
60220
  this.resizeFont();
60322
60221
  this.clampPopup();
60323
60222
  this.core.activeContainer.$el.append(this.$line);
60223
+ const mc = this.core.getPlugin('media_control');
60224
+ if (!mc?.isVisible()) {
60225
+ this.$line?.addClass('media-control-cc-pulled');
60226
+ }
60324
60227
  this.updateSelection();
60325
60228
  this.renderIcon();
60326
60229
  return this;
@@ -60426,7 +60329,7 @@ class ClosedCaptions extends UICorePlugin {
60426
60329
  this.setSubtitleText('');
60427
60330
  }
60428
60331
  updateSelection() {
60429
- if (!this.currentTrack) {
60332
+ if (this.core.activePlayback.closedCaptionsTrackId === -1) {
60430
60333
  this.hide();
60431
60334
  }
60432
60335
  else {
@@ -909,6 +909,28 @@ Identifies a location for mounting custom media control elements.
909
909
 
910
910
 
911
911
 
912
+ </td></tr>
913
+ <tr><td>
914
+
915
+ [MulticCameraSourceInfo](./player.multiccamerasourceinfo.md)
916
+
917
+
918
+ </td><td>
919
+
920
+ **_(BETA)_** Extended media source description
921
+
922
+
923
+ </td></tr>
924
+ <tr><td>
925
+
926
+ [MultisourcesMode](./player.multisourcesmode.md)
927
+
928
+
929
+ </td><td>
930
+
931
+ **_(BETA)_**
932
+
933
+
912
934
  </td></tr>
913
935
  <tr><td>
914
936
 
@@ -1163,15 +1185,6 @@ Preferred streaming media delivery protocol
1163
1185
 
1164
1186
 
1165
1187
 
1166
- </td></tr>
1167
- <tr><td>
1168
-
1169
- [VTTCueInfo](./player.vttcueinfo.md)
1170
-
1171
-
1172
- </td><td>
1173
-
1174
-
1175
1188
  </td></tr>
1176
1189
  <tr><td>
1177
1190