shaka-player 4.9.13 → 4.10.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 (91) hide show
  1. package/README.md +4 -0
  2. package/dist/controls.css +2 -2
  3. package/dist/controls.css.map +1 -1
  4. package/dist/deps.js +24 -19
  5. package/dist/locales.js +46 -35
  6. package/dist/shaka-player.compiled.d.ts +291 -12
  7. package/dist/shaka-player.compiled.debug.d.ts +291 -12
  8. package/dist/shaka-player.compiled.debug.externs.js +443 -6
  9. package/dist/shaka-player.compiled.debug.js +651 -556
  10. package/dist/shaka-player.compiled.debug.map +4 -4
  11. package/dist/shaka-player.compiled.externs.js +443 -6
  12. package/dist/shaka-player.compiled.js +1325 -1270
  13. package/dist/shaka-player.compiled.map +4 -4
  14. package/dist/shaka-player.ui.d.ts +306 -13
  15. package/dist/shaka-player.ui.debug.d.ts +306 -13
  16. package/dist/shaka-player.ui.debug.externs.js +477 -18
  17. package/dist/shaka-player.ui.debug.js +799 -681
  18. package/dist/shaka-player.ui.debug.map +4 -4
  19. package/dist/shaka-player.ui.externs.js +477 -18
  20. package/dist/shaka-player.ui.js +1600 -1533
  21. package/dist/shaka-player.ui.map +4 -4
  22. package/externs/shaka/ads.js +21 -1
  23. package/externs/shaka/manifest.js +20 -1
  24. package/externs/shaka/manifest_parser.js +18 -1
  25. package/externs/shaka/player.js +164 -50
  26. package/lib/ads/ad_manager.js +225 -10
  27. package/lib/ads/ad_utils.js +323 -0
  28. package/lib/ads/ads_stats.js +24 -0
  29. package/lib/ads/client_side_ad_manager.js +42 -34
  30. package/lib/ads/interstitial_ad.js +292 -0
  31. package/lib/ads/interstitial_ad_manager.js +772 -0
  32. package/lib/ads/media_tailor_ad_manager.js +19 -22
  33. package/lib/ads/server_side_ad_manager.js +12 -15
  34. package/lib/cast/cast_utils.js +1 -0
  35. package/lib/cea/cea_utils.js +12 -0
  36. package/lib/cea/mp4_cea_parser.js +17 -0
  37. package/lib/dash/dash_parser.js +81 -28
  38. package/lib/dash/segment_base.js +3 -0
  39. package/lib/hls/hls_parser.js +429 -121
  40. package/lib/hls/manifest_text_parser.js +1 -0
  41. package/lib/media/adaptation_set_criteria.js +31 -1
  42. package/lib/media/drm_engine.js +16 -2
  43. package/lib/media/manifest_filterer.js +7 -5
  44. package/lib/media/preload_manager.js +8 -10
  45. package/lib/media/presentation_timeline.js +37 -5
  46. package/lib/media/quality_observer.js +68 -2
  47. package/lib/media/segment_reference.js +1 -1
  48. package/lib/media/segment_utils.js +33 -1
  49. package/lib/media/streaming_engine.js +120 -43
  50. package/lib/mss/mss_parser.js +13 -2
  51. package/lib/net/networking_engine.js +1 -0
  52. package/lib/offline/manifest_converter.js +3 -0
  53. package/lib/offline/offline_manifest_parser.js +5 -0
  54. package/lib/offline/storage.js +2 -0
  55. package/lib/player.js +498 -165
  56. package/lib/util/fake_event.js +1 -0
  57. package/lib/util/manifest_parser_utils.js +9 -2
  58. package/lib/util/mp4_box_parsers.js +32 -0
  59. package/lib/util/player_configuration.js +21 -9
  60. package/lib/util/stats.js +43 -0
  61. package/package.json +1 -1
  62. package/shaka-player.uncompiled.js +2 -0
  63. package/ui/ad_counter.js +3 -3
  64. package/ui/ad_position.js +3 -3
  65. package/ui/ad_statistics_button.js +237 -0
  66. package/ui/audio_language_selection.js +8 -4
  67. package/ui/controls.js +6 -3
  68. package/ui/element.js +3 -3
  69. package/ui/enums.js +1 -0
  70. package/ui/externs/ui.js +3 -0
  71. package/ui/language_utils.js +48 -3
  72. package/ui/less/containers.less +32 -0
  73. package/ui/less/thumbnails.less +13 -0
  74. package/ui/locales/en.json +2 -0
  75. package/ui/locales/es-419.json +2 -0
  76. package/ui/locales/es.json +3 -0
  77. package/ui/locales/fr.json +1 -0
  78. package/ui/locales/pl.json +1 -0
  79. package/ui/locales/pt-BR.json +1 -0
  80. package/ui/locales/pt-PT.json +1 -0
  81. package/ui/locales/source.json +8 -0
  82. package/ui/mute_button.js +4 -4
  83. package/ui/overflow_menu.js +3 -3
  84. package/ui/play_button.js +5 -7
  85. package/ui/presentation_time.js +3 -3
  86. package/ui/save_video_frame_button.js +196 -0
  87. package/ui/seek_bar.js +75 -20
  88. package/ui/skip_ad_button.js +4 -4
  89. package/ui/statistics_button.js +14 -2
  90. package/ui/ui.js +15 -0
  91. package/ui/volume_bar.js +4 -4
package/ui/seek_bar.js CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  goog.provide('shaka.ui.SeekBar');
9
9
 
10
- goog.require('shaka.ads.AdManager');
10
+ goog.require('shaka.ads.Utils');
11
11
  goog.require('shaka.net.NetworkingEngine');
12
12
  goog.require('shaka.ui.Constants');
13
13
  goog.require('shaka.ui.Locales');
@@ -113,6 +113,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
113
113
  this.thumbnailContainer_.appendChild(this.thumbnailTime_);
114
114
  this.container.appendChild(this.thumbnailContainer_);
115
115
 
116
+ this.timeContainer_ = shaka.util.Dom.createHTMLElement('div');
117
+ this.timeContainer_.id = 'shaka-player-ui-time-container';
118
+ this.container.appendChild(this.timeContainer_);
119
+
116
120
  /**
117
121
  * @private {?shaka.extern.Thumbnail}
118
122
  */
@@ -151,21 +155,21 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
151
155
  () => this.updateAriaLabel_());
152
156
 
153
157
  this.eventManager.listen(
154
- this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
158
+ this.adManager, shaka.ads.Utils.AD_STARTED, () => {
155
159
  if (!this.shouldBeDisplayed_()) {
156
160
  shaka.ui.Utils.setDisplay(this.container, false);
157
161
  }
158
162
  });
159
163
 
160
164
  this.eventManager.listen(
161
- this.adManager, shaka.ads.AdManager.AD_STOPPED, () => {
165
+ this.adManager, shaka.ads.Utils.AD_STOPPED, () => {
162
166
  if (this.shouldBeDisplayed_()) {
163
167
  shaka.ui.Utils.setDisplay(this.container, true);
164
168
  }
165
169
  });
166
170
 
167
171
  this.eventManager.listen(
168
- this.adManager, shaka.ads.AdManager.CUEPOINTS_CHANGED, (e) => {
172
+ this.adManager, shaka.ads.Utils.CUEPOINTS_CHANGED, (e) => {
169
173
  this.adCuePoints_ = (e)['cuepoints'];
170
174
  this.onAdCuePointsChanged_();
171
175
  });
@@ -180,13 +184,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
180
184
  }
181
185
  this.lastThumbnail_ = null;
182
186
  this.hideThumbnail_();
187
+ this.hideTime_();
183
188
  });
184
189
 
185
190
  this.eventManager.listen(this.bar, 'mousemove', (event) => {
186
- if (!this.player.getImageTracks().length) {
187
- this.hideThumbnail_();
188
- return;
189
- }
190
191
  const rect = this.bar.getBoundingClientRect();
191
192
  const min = parseFloat(this.bar.min);
192
193
  const max = parseFloat(this.bar.max);
@@ -196,11 +197,17 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
196
197
  const scale = (max - min) / rect.width;
197
198
  // Mouse position in units, which may be outside the allowed range.
198
199
  const value = Math.round(min + scale * mousePosition);
199
- // Show Thumbnail
200
+ if (!this.player.getImageTracks().length) {
201
+ this.hideThumbnail_();
202
+ this.showTime_(mousePosition, value);
203
+ return;
204
+ }
205
+ this.hideTime_();
200
206
  this.showThumbnail_(mousePosition, value);
201
207
  });
202
208
 
203
209
  this.eventManager.listen(this.container, 'mouseleave', () => {
210
+ this.hideTime_();
204
211
  this.hideThumbnailTimer_.stop();
205
212
  this.hideThumbnailTimer_.tickAfter(/* seconds= */ 0.25);
206
213
  });
@@ -375,13 +382,14 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
375
382
  markAdBreaks_() {
376
383
  if (!this.adCuePoints_.length) {
377
384
  this.adMarkerContainer_.style.background = 'transparent';
385
+ this.adBreaksTimer_.stop();
378
386
  return;
379
387
  }
380
388
 
381
389
  const seekRange = this.player.seekRange();
382
390
  const seekRangeSize = seekRange.end - seekRange.start;
383
391
  const gradient = ['to right'];
384
- const pointsAsFractions = [];
392
+ let pointsAsFractions = [];
385
393
  const adBreakColor = this.config_.seekBarColors.adBreaks;
386
394
  let postRollAd = false;
387
395
  for (const point of this.adCuePoints_) {
@@ -413,6 +421,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
413
421
  }
414
422
  }
415
423
 
424
+ pointsAsFractions = pointsAsFractions.sort((a, b) => {
425
+ return a.start - b.start;
426
+ });
427
+
416
428
  for (const point of pointsAsFractions) {
417
429
  gradient.push(this.makeColor_('transparent', point.start));
418
430
  gradient.push(this.makeColor_(adBreakColor, point.start));
@@ -445,16 +457,24 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
445
457
  */
446
458
  onAdCuePointsChanged_() {
447
459
  this.markAdBreaks_();
448
- const seekRange = this.player.seekRange();
449
- const seekRangeSize = seekRange.end - seekRange.start;
450
- const minSeekBarWindow = shaka.ui.Constants.MIN_SEEK_WINDOW_TO_SHOW_SEEKBAR;
451
- // Seek range keeps changing for live content and some of the known
452
- // ad breaks might not be in the seek range now, but get into
453
- // it later.
454
- // If we have a LIVE seekable content, keep checking for ad breaks
455
- // every second.
456
- if (this.player.isLive() && seekRangeSize > minSeekBarWindow) {
457
- this.adBreaksTimer_.tickEvery(1);
460
+ const action = () => {
461
+ const seekRange = this.player.seekRange();
462
+ const seekRangeSize = seekRange.end - seekRange.start;
463
+ const minSeekBarWindow =
464
+ shaka.ui.Constants.MIN_SEEK_WINDOW_TO_SHOW_SEEKBAR;
465
+ // Seek range keeps changing for live content and some of the known
466
+ // ad breaks might not be in the seek range now, but get into
467
+ // it later.
468
+ // If we have a LIVE seekable content, keep checking for ad breaks
469
+ // every second.
470
+ if (this.player.isLive() && seekRangeSize > minSeekBarWindow) {
471
+ this.adBreaksTimer_.tickEvery(/* seconds= */ 0.25);
472
+ }
473
+ };
474
+ if (this.player.isFullyLoaded()) {
475
+ action();
476
+ } else {
477
+ this.eventManager.listenOnce(this.player, 'loaded', action);
458
478
  }
459
479
  }
460
480
 
@@ -482,6 +502,33 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
482
502
  this.bar.ariaLabel = this.localization.resolve(shaka.ui.Locales.Ids.SEEK);
483
503
  }
484
504
 
505
+ /** @private */
506
+ showTime_(pixelPosition, value) {
507
+ const offsetTop = -10;
508
+ const width = this.timeContainer_.clientWidth;
509
+ const height = 20;
510
+ this.timeContainer_.style.width = 'auto';
511
+ this.timeContainer_.style.height = height + 'px';
512
+ this.timeContainer_.style.top = -(height - offsetTop) + 'px';
513
+ const leftPosition = Math.min(this.bar.offsetWidth - width,
514
+ Math.max(0, pixelPosition - (width / 2)));
515
+ this.timeContainer_.style.left = leftPosition + 'px';
516
+ this.timeContainer_.style.visibility = 'visible';
517
+ if (this.player.isLive()) {
518
+ const seekRange = this.player.seekRange();
519
+ const totalSeconds = seekRange.end - value;
520
+ if (totalSeconds < 1) {
521
+ this.timeContainer_.textContent =
522
+ this.localization.resolve(shaka.ui.Locales.Ids.LIVE);
523
+ } else {
524
+ this.timeContainer_.textContent =
525
+ '-' + this.timeFormatter_(totalSeconds);
526
+ }
527
+ } else {
528
+ this.timeContainer_.textContent = this.timeFormatter_(value);
529
+ }
530
+ }
531
+
485
532
 
486
533
  /**
487
534
  * @private
@@ -657,6 +704,14 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
657
704
  }
658
705
 
659
706
 
707
+ /**
708
+ * @private
709
+ */
710
+ hideTime_() {
711
+ this.timeContainer_.style.visibility = 'hidden';
712
+ }
713
+
714
+
660
715
  /**
661
716
  * @param {number} totalSeconds
662
717
  * @private
@@ -8,7 +8,7 @@
8
8
  goog.provide('shaka.ui.SkipAdButton');
9
9
 
10
10
  goog.require('goog.asserts');
11
- goog.require('shaka.ads.AdManager');
11
+ goog.require('shaka.ads.Utils');
12
12
  goog.require('shaka.ui.Element');
13
13
  goog.require('shaka.ui.Locales');
14
14
  goog.require('shaka.ui.Localization');
@@ -74,17 +74,17 @@ shaka.ui.SkipAdButton = class extends shaka.ui.Element {
74
74
  });
75
75
 
76
76
  this.eventManager.listen(
77
- this.adManager, shaka.ads.AdManager.AD_STARTED, () => {
77
+ this.adManager, shaka.ads.Utils.AD_STARTED, () => {
78
78
  this.onAdStarted_();
79
79
  });
80
80
 
81
81
  this.eventManager.listen(
82
- this.adManager, shaka.ads.AdManager.AD_SKIP_STATE_CHANGED, () => {
82
+ this.adManager, shaka.ads.Utils.AD_SKIP_STATE_CHANGED, () => {
83
83
  this.onSkipStateChanged_();
84
84
  });
85
85
 
86
86
  this.eventManager.listen(
87
- this.adManager, shaka.ads.AdManager.AD_STOPPED, () => {
87
+ this.adManager, shaka.ads.Utils.AD_STOPPED, () => {
88
88
  this.reset_();
89
89
  });
90
90
 
@@ -117,7 +117,15 @@ shaka.ui.StatisticsButton = class extends shaka.ui.Element {
117
117
  return this.currentStats_[name] + ' (stalls)';
118
118
  };
119
119
 
120
- const parseBytesDownloaded = (name) => {
120
+ const parseErrors = (name) => {
121
+ return this.currentStats_[name] + ' (errors)';
122
+ };
123
+
124
+ const parsePeriods = (name) => {
125
+ return this.currentStats_[name] + ' (periods)';
126
+ };
127
+
128
+ const parseBytes = (name) => {
121
129
  const bytes = parseInt(this.currentStats_[name], 10);
122
130
  if (bytes > 1e6) {
123
131
  return (bytes / 1e6).toFixed(2) + 'MB';
@@ -149,7 +157,11 @@ shaka.ui.StatisticsButton = class extends shaka.ui.Element {
149
157
  'droppedFrames': parseFrames,
150
158
  'stallsDetected': parseStalls,
151
159
  'gapsJumped': parseGaps,
152
- 'bytesDownloaded': parseBytesDownloaded,
160
+ 'manifestSizeBytes': parseBytes,
161
+ 'bytesDownloaded': parseBytes,
162
+ 'nonFatalErrorCount': parseErrors,
163
+ 'manifestPeriodCount': parsePeriods,
164
+ 'manifestGapCount': parseGaps,
153
165
  };
154
166
 
155
167
  /** @private {shaka.util.Timer} */
package/ui/ui.js CHANGED
@@ -192,6 +192,7 @@ shaka.ui.Overlay = class {
192
192
  'playback_rate',
193
193
  'recenter_vr',
194
194
  'toggle_stereoscopic',
195
+ 'save_video_frame',
195
196
  ],
196
197
  statisticsList: [
197
198
  'width',
@@ -211,12 +212,26 @@ shaka.ui.Overlay = class {
211
212
  'pauseTime',
212
213
  'playTime',
213
214
  'completionPercent',
215
+ 'manifestSizeBytes',
214
216
  'bytesDownloaded',
217
+ 'nonFatalErrorCount',
218
+ 'manifestPeriodCount',
219
+ 'manifestGapCount',
220
+ ],
221
+ adStatisticsList: [
222
+ 'loadTimes',
223
+ 'averageLoadTime',
224
+ 'started',
225
+ 'playedCompletely',
226
+ 'skipped',
227
+ 'errors',
215
228
  ],
216
229
  contextMenuElements: [
217
230
  'loop',
218
231
  'picture_in_picture',
232
+ 'save_video_frame',
219
233
  'statistics',
234
+ 'ad_statistics',
220
235
  ],
221
236
  playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 1.75, 2],
222
237
  fastForwardRates: [2, 4, 8, 1],
package/ui/volume_bar.js CHANGED
@@ -8,7 +8,7 @@
8
8
  goog.provide('shaka.ui.VolumeBar');
9
9
 
10
10
  goog.require('goog.asserts');
11
- goog.require('shaka.ads.AdManager');
11
+ goog.require('shaka.ads.Utils');
12
12
  goog.require('shaka.ui.Controls');
13
13
  goog.require('shaka.ui.Locales');
14
14
  goog.require('shaka.ui.Localization');
@@ -41,15 +41,15 @@ shaka.ui.VolumeBar = class extends shaka.ui.RangeElement {
41
41
  () => this.onPresentationVolumeChange_());
42
42
 
43
43
  this.eventManager.listen(this.adManager,
44
- shaka.ads.AdManager.AD_VOLUME_CHANGED,
44
+ shaka.ads.Utils.AD_VOLUME_CHANGED,
45
45
  () => this.onAdVolumeChange_());
46
46
 
47
47
  this.eventManager.listen(this.adManager,
48
- shaka.ads.AdManager.AD_MUTED,
48
+ shaka.ads.Utils.AD_MUTED,
49
49
  () => this.onAdVolumeChange_());
50
50
 
51
51
  this.eventManager.listen(this.adManager,
52
- shaka.ads.AdManager.AD_STOPPED,
52
+ shaka.ads.Utils.AD_STOPPED,
53
53
  () => this.onPresentationVolumeChange_());
54
54
 
55
55
  this.eventManager.listen(this.localization,