shaka-player 4.4.3 → 4.5.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 (198) hide show
  1. package/.github/workflows/release-please.yaml +2 -27
  2. package/CHANGELOG.md +64 -45
  3. package/README.md +16 -10
  4. package/demo/asset_card.js +18 -21
  5. package/demo/cast_receiver/index.html +0 -1
  6. package/demo/close_button.js +0 -3
  7. package/demo/common/asset.js +22 -5
  8. package/demo/common/assets.js +132 -49
  9. package/demo/config.js +192 -253
  10. package/demo/custom.js +39 -98
  11. package/demo/front.js +7 -10
  12. package/demo/index.html +19 -22
  13. package/demo/input.js +6 -11
  14. package/demo/input_container.js +8 -9
  15. package/demo/main.js +51 -123
  16. package/demo/search.js +22 -34
  17. package/demo/service_worker.js +0 -3
  18. package/demo/tooltip.js +3 -5
  19. package/demo/visualizer.js +3 -5
  20. package/demo/visualizer_button.js +1 -20
  21. package/dist/demo.compiled.debug.js +152 -178
  22. package/dist/demo.compiled.debug.map +4 -4
  23. package/dist/demo.compiled.js +152 -178
  24. package/dist/demo.compiled.map +4 -4
  25. package/dist/deps.js +27 -24
  26. package/dist/locales.js +31 -31
  27. package/dist/receiver.compiled.debug.js +22 -43
  28. package/dist/receiver.compiled.debug.map +4 -4
  29. package/dist/receiver.compiled.js +22 -43
  30. package/dist/receiver.compiled.map +4 -4
  31. package/dist/shaka-player.compiled.d.ts +507 -365
  32. package/dist/shaka-player.compiled.debug.d.ts +507 -365
  33. package/dist/shaka-player.compiled.debug.externs.js +205 -51
  34. package/dist/shaka-player.compiled.debug.js +541 -450
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +205 -51
  37. package/dist/shaka-player.compiled.js +1120 -1066
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +562 -410
  40. package/dist/shaka-player.ui.debug.d.ts +562 -410
  41. package/dist/shaka-player.ui.debug.externs.js +226 -51
  42. package/dist/shaka-player.ui.debug.js +606 -506
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +226 -51
  45. package/dist/shaka-player.ui.js +1266 -1207
  46. package/dist/shaka-player.ui.map +4 -4
  47. package/docs/design/lcevc-integration.md +14 -14
  48. package/docs/tutorials/faq.md +27 -55
  49. package/docs/tutorials/index.json +2 -1
  50. package/docs/tutorials/lcevc.md +118 -0
  51. package/docs/tutorials/ui-customization.md +4 -0
  52. package/externs/css_style_declaration.js +19 -0
  53. package/externs/lcevc.js +37 -13
  54. package/externs/media_remote.js +68 -0
  55. package/externs/mediatailor.js +193 -0
  56. package/externs/pictureinpicture.js +11 -0
  57. package/externs/shaka/ads.js +27 -0
  58. package/externs/shaka/manifest.js +10 -5
  59. package/externs/shaka/manifest_parser.js +7 -1
  60. package/externs/shaka/offline.js +4 -0
  61. package/externs/shaka/player.js +12 -1
  62. package/karma.conf.js +7 -3
  63. package/lib/abr/simple_abr_manager.js +43 -3
  64. package/lib/ads/ad_manager.js +104 -50
  65. package/lib/ads/media_tailor_ad.js +297 -0
  66. package/lib/ads/media_tailor_ad_manager.js +828 -0
  67. package/lib/cea/ts_cea_parser.js +15 -2
  68. package/lib/config/codec_switching_strategy.js +24 -0
  69. package/lib/dash/content_protection.js +120 -2
  70. package/lib/dash/dash_parser.js +75 -12
  71. package/lib/dash/mpd_utils.js +10 -6
  72. package/lib/dash/segment_base.js +13 -5
  73. package/lib/dash/segment_list.js +13 -5
  74. package/lib/dash/segment_template.js +43 -85
  75. package/lib/dependencies/all.js +8 -7
  76. package/lib/hls/hls_parser.js +44 -16
  77. package/lib/lcevc/lcevc_dec.js +220 -0
  78. package/lib/media/adaptation_set.js +22 -11
  79. package/lib/media/adaptation_set_criteria.js +25 -7
  80. package/lib/media/media_source_engine.js +215 -27
  81. package/lib/media/segment_index.js +1 -1
  82. package/lib/media/segment_reference.js +7 -7
  83. package/lib/media/streaming_engine.js +33 -18
  84. package/lib/mss/mss_parser.js +1 -0
  85. package/lib/net/networking_engine.js +1 -0
  86. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  87. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  88. package/lib/offline/manifest_converter.js +1 -0
  89. package/lib/offline/storage.js +3 -0
  90. package/lib/player.js +142 -72
  91. package/lib/routing/payload.js +5 -1
  92. package/lib/text/cue.js +15 -0
  93. package/lib/text/ttml_text_parser.js +17 -0
  94. package/lib/text/ui_text_displayer.js +4 -0
  95. package/lib/text/vtt_text_parser.js +33 -20
  96. package/lib/transmuxer/h265.js +862 -0
  97. package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
  98. package/lib/transmuxer/ts_transmuxer.js +160 -15
  99. package/lib/util/error.js +28 -9
  100. package/lib/util/exp_golomb.js +30 -2
  101. package/lib/util/fake_event.js +3 -0
  102. package/lib/util/mp4_generator.js +4 -4
  103. package/lib/util/periods.js +2 -0
  104. package/lib/util/platform.js +40 -0
  105. package/lib/util/player_configuration.js +8 -0
  106. package/lib/util/state_history.js +6 -2
  107. package/lib/util/stream_utils.js +133 -217
  108. package/lib/util/ts_parser.js +226 -40
  109. package/maintained-branches.md +3 -2
  110. package/package.json +4 -6
  111. package/roadmap.md +15 -5
  112. package/shaka-player.uncompiled.js +2 -1
  113. package/support.html +0 -1
  114. package/test/cast/cast_receiver_integration.js +47 -0
  115. package/test/codec_switching/codec_switching_integration.js +181 -0
  116. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  117. package/test/dash/dash_parser_integration.js +73 -0
  118. package/test/dash/dash_parser_live_unit.js +2 -0
  119. package/test/dash/dash_parser_manifest_unit.js +42 -0
  120. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  121. package/test/dash/dash_parser_segment_list_unit.js +2 -0
  122. package/test/dash/dash_parser_segment_template_unit.js +2 -0
  123. package/test/demo/demo_unit.js +0 -16
  124. package/test/hls/hls_live_unit.js +2 -0
  125. package/test/hls/hls_parser_unit.js +8 -6
  126. package/test/media/adaptation_set_criteria_unit.js +118 -0
  127. package/test/media/adaptation_set_unit.js +1 -0
  128. package/test/media/media_source_engine_unit.js +165 -1
  129. package/test/media/segment_index_unit.js +4 -4
  130. package/test/media/segment_prefetch_unit.js +1 -1
  131. package/test/media/streaming_engine_unit.js +17 -17
  132. package/test/mss/mss_parser_unit.js +2 -0
  133. package/test/offline/manifest_convert_unit.js +5 -0
  134. package/test/offline/storage_integration.js +1 -4
  135. package/test/player_unit.js +102 -131
  136. package/test/routing/walker_unit.js +1 -0
  137. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  138. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  139. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  140. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  141. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  142. package/test/test/assets/dash-aes-128/dash.mpd +18 -0
  143. package/test/test/assets/dash-aes-128/license +1 -0
  144. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  145. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  146. package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
  147. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  148. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  149. package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
  150. package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
  151. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  152. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  153. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
  154. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
  155. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  156. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  157. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  158. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  159. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  160. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  161. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  162. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  163. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  164. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  165. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
  166. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
  167. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  168. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  169. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  170. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  171. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  172. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  173. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  174. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  175. package/test/test/util/dash_parser_util.js +4 -0
  176. package/test/test/util/fake_ad_manager.js +20 -0
  177. package/test/test/util/fake_media_source_engine.js +8 -2
  178. package/test/test/util/manifest_generator.js +7 -3
  179. package/test/test/util/mss_parser_util.js +4 -0
  180. package/test/test/util/offline_utils.js +1 -0
  181. package/test/test/util/streaming_engine_util.js +7 -4
  182. package/test/text/ttml_text_parser_unit.js +52 -0
  183. package/test/text/vtt_text_parser_unit.js +103 -31
  184. package/test/transmuxer/transmuxer_integration.js +117 -0
  185. package/test/ui/ui_unit.js +3 -10
  186. package/test/util/stream_utils_unit.js +208 -74
  187. package/ui/controls.js +125 -0
  188. package/ui/externs/ui.js +8 -1
  189. package/ui/pip_button.js +22 -120
  190. package/ui/remote_button.js +201 -0
  191. package/ui/ui.js +5 -2
  192. package/demo/common/message_ids.js +0 -309
  193. package/demo/locales/en.json +0 -288
  194. package/demo/locales/source.json +0 -1146
  195. package/externs/mux.js +0 -69
  196. package/lib/lcevc/lcevc_dil.js +0 -152
  197. package/lib/transmuxer/muxjs_transmuxer.js +0 -242
  198. package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
package/demo/main.js CHANGED
@@ -10,7 +10,6 @@ goog.provide('shakaDemo.Main');
10
10
  goog.require('ShakaDemoAssetInfo');
11
11
  goog.require('goog.asserts');
12
12
  goog.require('shakaDemo.CloseButton');
13
- goog.require('shakaDemo.MessageIds');
14
13
  goog.require('shakaDemo.Utils');
15
14
  goog.require('shakaDemo.Visualizer');
16
15
  goog.require('shakaDemo.VisualizerButton');
@@ -122,9 +121,8 @@ shakaDemo.Main = class {
122
121
  * This does not dispatch the shaka-main-loaded event, so it will not cause
123
122
  * the nav bar buttons to be set up.
124
123
  * @param {!shaka.ui.Overlay.FailReasonCode} reasonCode
125
- * @return {!Promise}
126
124
  */
127
- async initFailed(reasonCode) {
125
+ initFailed(reasonCode) {
128
126
  this.initCommon_();
129
127
 
130
128
  // Set up version links, so the user can switch to compiled mode if
@@ -155,25 +153,19 @@ shakaDemo.Main = class {
155
153
  element.classList.add('disabled-by-fail');
156
154
  }
157
155
 
158
- // Because the UI did not load, this will need to set up a localization
159
- // object manually.
160
- this.localization_ = new shaka.ui.Localization(/* fallbackLocale= */ 'en');
161
- this.localization_.changeLocale(navigator.languages || []);
162
- await this.setupLocalization_();
163
-
164
156
  // Process a synthetic error about lack of browser support.
165
157
  const severity = shaka.util.Error.Severity.CRITICAL;
166
158
  let href = '';
167
159
  let message = '';
168
160
  switch (reasonCode) {
169
161
  case shaka.ui.Overlay.FailReasonCode.NO_BROWSER_SUPPORT:
170
- message = this.getLocalizedString(
171
- shakaDemo.MessageIds.FAILURE_NO_BROWSER_SUPPORT);
162
+ message = 'Your browser is not supported!';
172
163
  href = 'https://github.com/shaka-project/shaka-player#' +
173
164
  'platform-and-browser-support-matrix';
174
165
  break;
175
166
  case shaka.ui.Overlay.FailReasonCode.PLAYER_FAILED_TO_LOAD:
176
- message = this.getLocalizedString(shakaDemo.MessageIds.FAILURE_MISC);
167
+ message = 'Shaka Player failed to load! If you are using an adblocker' +
168
+ ', try switching to compiled mode at the bottom of the page.';
177
169
  break;
178
170
  }
179
171
  this.handleError_(severity, message, href);
@@ -205,7 +197,7 @@ shakaDemo.Main = class {
205
197
  // Optionally enter noinput mode. This has to happen before setting up the
206
198
  // player.
207
199
  this.noInput_ = 'noinput' in this.getParams_();
208
- await this.setupPlayer_();
200
+ this.setupPlayer_();
209
201
  this.readHash_();
210
202
  window.addEventListener('hashchange', () => this.hashChanged_());
211
203
 
@@ -392,11 +384,8 @@ shakaDemo.Main = class {
392
384
  ui.configure(uiConfig);
393
385
  }
394
386
 
395
- /**
396
- * @return {!Promise}
397
- * @private
398
- */
399
- async setupPlayer_() {
387
+ /** @private */
388
+ setupPlayer_() {
400
389
  const video = /** @type {!HTMLVideoElement} */ (this.video_);
401
390
  const ui = video['ui'];
402
391
  this.player_ = ui.getControls().getPlayer();
@@ -443,7 +432,6 @@ shakaDemo.Main = class {
443
432
  });
444
433
 
445
434
  this.localization_ = this.controls_.getLocalization();
446
- await this.setupLocalization_();
447
435
 
448
436
  const drawerCloseButton = document.getElementById('drawer-close-button');
449
437
  drawerCloseButton.addEventListener('click', () => {
@@ -481,50 +469,6 @@ shakaDemo.Main = class {
481
469
  this.hideElement_(drawerCloseButton);
482
470
  }
483
471
 
484
- /**
485
- * @return {!Promise}
486
- * @private
487
- */
488
- async setupLocalization_() {
489
- // Set up localization lazy-loading.
490
- const applyNewLocaleIfPossible = () => {
491
- this.localizeHTMLElements_();
492
- this.dispatchEventWithName_('shaka-main-locale-changed');
493
- };
494
- const UNKNOWN_LOCALES = shaka.ui.Localization.UNKNOWN_LOCALES;
495
- this.localization_.addEventListener(UNKNOWN_LOCALES, (event) => {
496
- for (const locale of event['locales']) {
497
- // This will leave promise rejections uncaught; this is acceptable, as
498
- // this function is actually expected to fail fairly often, and has
499
- // built-in fallback behavior (from localization events) without needing
500
- // to catch the promise rejection.
501
- this.loadUILocale_(locale).then(() => {
502
- if (locale == this.uiLocale_) {
503
- applyNewLocaleIfPossible();
504
- }
505
- });
506
- }
507
- });
508
- const LOCALE_CHANGED = shaka.ui.Localization.LOCALE_CHANGED;
509
- this.localization_.addEventListener(LOCALE_CHANGED, (event) => {
510
- applyNewLocaleIfPossible();
511
- });
512
- const initialLocaleLoads = [];
513
- initialLocaleLoads.push(this.loadUILocale_(this.uiLocale_));
514
- if (this.uiLocale_.includes('-')) {
515
- // Also try to load the 'base' localization.
516
- // This is so that, for example, the uiLocale_ is set to 'en-US', it will
517
- // try to load 'en'.
518
- initialLocaleLoads.push(this.loadUILocale_(this.uiLocale_.split('-')[0]));
519
- }
520
- if (!this.uiLocale_.startsWith('en')) {
521
- // Load 'en' as a fallback option, if not already loaded.
522
- initialLocaleLoads.push(this.loadUILocale_('en'));
523
- }
524
- await Promise.all(initialLocaleLoads);
525
- this.localizeHTMLElements_();
526
- }
527
-
528
472
  /** @return {boolean} */
529
473
  getIsDrawerOpen() {
530
474
  const drawer = document.querySelector('.mdl-layout__drawer');
@@ -719,13 +663,13 @@ shakaDemo.Main = class {
719
663
  *
720
664
  * @param {!ShakaDemoAssetInfo} asset
721
665
  * @param {boolean} needOffline True if offline support is required.
722
- * @return {?shakaDemo.MessageIds} unsupportedReason
666
+ * @return {?string} unsupportedReason
723
667
  * Null if asset is supported.
724
668
  */
725
669
  getAssetUnsupportedReason(asset, needOffline) {
726
670
  if (needOffline &&
727
671
  (!shaka.offline.Storage.support() || !this.initialStoredList_)) {
728
- return shakaDemo.MessageIds.UNSUPPORTED_NO_OFFLINE;
672
+ return 'Your browser does not support offline storage.';
729
673
  }
730
674
 
731
675
  if (asset.source == shakaAssets.Source.CUSTOM) {
@@ -736,11 +680,11 @@ shakaDemo.Main = class {
736
680
 
737
681
  // Is the asset disabled?
738
682
  if (asset.disabled) {
739
- return shakaDemo.MessageIds.UNSUPPORTED_DISABLED;
683
+ return 'This asset is disabled.';
740
684
  }
741
685
 
742
686
  if (needOffline && !asset.features.includes(shakaAssets.Feature.OFFLINE)) {
743
- return shakaDemo.MessageIds.UNSUPPORTED_NO_DOWNLOAD;
687
+ return 'This asset cannot be downloaded.';
744
688
  }
745
689
 
746
690
  if (!asset.isClear() && !asset.isAes128()) {
@@ -748,7 +692,7 @@ shakaDemo.Main = class {
748
692
  return this.support_.drm[shakaAssets.identifierForKeySystem(drm)];
749
693
  });
750
694
  if (!hasSupportedDRM) {
751
- return shakaDemo.MessageIds.UNSUPPORTED_NO_KEY_SUPPORT;
695
+ return 'Your browser does not support the required key systems.';
752
696
  }
753
697
  if (needOffline) {
754
698
  const hasSupportedOfflineDRM = asset.drm.some((drm) => {
@@ -757,7 +701,8 @@ shakaDemo.Main = class {
757
701
  this.support_.drm[identifier].persistentState;
758
702
  });
759
703
  if (!hasSupportedOfflineDRM) {
760
- return shakaDemo.MessageIds.UNSUPPORTED_NO_LICENSE_SUPPORT;
704
+ return 'Your browser does not support offline licenses for the ' +
705
+ 'required key systems.';
761
706
  }
762
707
  }
763
708
  }
@@ -765,15 +710,15 @@ shakaDemo.Main = class {
765
710
  // Does the browser support the asset's manifest type?
766
711
  if (asset.features.includes(shakaAssets.Feature.DASH) &&
767
712
  !this.support_.manifest['mpd']) {
768
- return shakaDemo.MessageIds.UNSUPPORTED_NO_DASH_SUPPORT;
713
+ return 'Your browser does not support MPEG-DASH manifests.';
769
714
  }
770
715
  if (asset.features.includes(shakaAssets.Feature.HLS) &&
771
716
  !this.support_.manifest['m3u8']) {
772
- return shakaDemo.MessageIds.UNSUPPORTED_NO_HLS_SUPPORT;
717
+ return 'Your browser does not support HLS manifests.';
773
718
  }
774
719
  if (asset.features.includes(shakaAssets.Feature.MSS) &&
775
720
  !this.support_.manifest['ism']) {
776
- return shakaDemo.MessageIds.UNSUPPORTED_NO_MSS_SUPPORT;
721
+ return 'Your browser does not support MSS manifests.';
777
722
  }
778
723
 
779
724
  // Does the asset contain a playable mime type?
@@ -794,7 +739,7 @@ shakaDemo.Main = class {
794
739
  return this.support_.media[type];
795
740
  });
796
741
  if (!hasSupportedMimeType) {
797
- return shakaDemo.MessageIds.UNSUPPORTED_NO_FORMAT_SUPPORT;
742
+ return 'Your browser does not support the required video format.';
798
743
  }
799
744
 
800
745
  return null;
@@ -841,55 +786,6 @@ shakaDemo.Main = class {
841
786
  return this.nativeControlsEnabled_;
842
787
  }
843
788
 
844
- /**
845
- * Look through all elements in the DOM, and look for things tagged as having
846
- * a localized string. Then, localize them.
847
- *
848
- * @private
849
- */
850
- localizeHTMLElements_() {
851
- for (const element of document.querySelectorAll('[localized-string]')) {
852
- const key = element.getAttribute('localized-string');
853
- const value = shakaDemo.MessageIds[key];
854
- if (value) {
855
- element.textContent = this.getLocalizedString(value);
856
- }
857
- }
858
- }
859
-
860
- /**
861
- * @param {!shakaDemo.MessageIds} string
862
- * @return {string}
863
- */
864
- getLocalizedString(string) {
865
- return this.localization_.resolve(string);
866
- }
867
-
868
- /**
869
- * @param {string} locale
870
- * @return {!Promise}
871
- * @private
872
- */
873
- async loadUILocale_(locale) {
874
- if (!locale) {
875
- return;
876
- }
877
-
878
- const load = async (urlBase) => {
879
- const url = urlBase + '/locales/' + locale + '.json';
880
-
881
- try {
882
- const text = await this.loadText_(url);
883
- const obj = /** @type {!Object.<string, string>} */(JSON.parse(text));
884
- const map = new Map(Object.entries(obj));
885
- this.localization_.insert(locale, map);
886
- } catch (error) {
887
- console.warn('Unable to load locale', locale, 'for url', url);
888
- }
889
- };
890
- await Promise.all([load('../ui'), load('../demo')]);
891
- }
892
-
893
789
  /** @param {string} locale */
894
790
  setUILocale(locale) {
895
791
  this.uiLocale_ = locale;
@@ -1349,6 +1245,11 @@ shakaDemo.Main = class {
1349
1245
  if (asset.imaAssetKey || (asset.imaContentSrcId && asset.imaVideoId)) {
1350
1246
  manifestUri = await this.getManifestUriFromAdManager_(asset);
1351
1247
  }
1248
+ // If it's a MediaTailor asset, request ad-containing manifest
1249
+ // from the ad manager.
1250
+ if (asset.mediaTailorUrl) {
1251
+ manifestUri = await this.getManifestUriFromMediaTailorAdManager_(asset);
1252
+ }
1352
1253
  await this.player_.load(
1353
1254
  manifestUri,
1354
1255
  /* startTime= */ null,
@@ -1636,6 +1537,34 @@ shakaDemo.Main = class {
1636
1537
  }
1637
1538
  }
1638
1539
 
1540
+ /**
1541
+ * @param {ShakaDemoAssetInfo} asset
1542
+ * @return {!Promise.<string>}
1543
+ * @private
1544
+ */
1545
+ async getManifestUriFromMediaTailorAdManager_(asset) {
1546
+ const adManager = this.player_.getAdManager();
1547
+ const container = this.controls_.getServerSideAdContainer();
1548
+ try {
1549
+ goog.asserts.assert(this.video_ != null, 'Video should not be null!');
1550
+ goog.asserts.assert(asset.mediaTailorUrl != null,
1551
+ 'Media Tailor info not be null!');
1552
+ const netEngine = this.player_.getNetworkingEngine();
1553
+ goog.asserts.assert(netEngine, 'There should be a net engine.');
1554
+ adManager.initMediaTailor(container, netEngine, this.video_);
1555
+ const uri = await adManager.requestMediaTailorStream(
1556
+ asset.mediaTailorUrl, asset.mediaTailorAdsParams,
1557
+ /* backupUri= */ asset.manifestUri);
1558
+ return uri;
1559
+ } catch (error) {
1560
+ console.log(error);
1561
+ console.warn('Ads code has been prevented from running ' +
1562
+ 'or returned an error. Proceeding without ads.');
1563
+
1564
+ return asset.manifestUri;
1565
+ }
1566
+ }
1567
+
1639
1568
  /**
1640
1569
  * Sets up a nav button, and an associated tab.
1641
1570
  * This method is meant to be called by the various tabs, as part of their
@@ -1810,7 +1739,6 @@ shakaDemo.Main = class {
1810
1739
  // Always show the new error if:
1811
1740
  // 1. there is no error showing currently
1812
1741
  // 2. the new error is more severe than the old one
1813
- // Sadly, we do not (yet?) have localizations for error messages.
1814
1742
  if (this.currentErrorSeverity_ == null ||
1815
1743
  severity > this.currentErrorSeverity_) {
1816
1744
  this.errorDisplayLink_.href = href;
package/demo/search.js CHANGED
@@ -11,7 +11,6 @@ goog.provide('shakaDemo.Search');
11
11
  goog.require('shakaDemo.AssetCard');
12
12
  goog.require('shakaDemo.BoolInput');
13
13
  goog.require('shakaDemo.InputContainer');
14
- goog.require('shakaDemo.MessageIds');
15
14
  goog.require('shakaDemo.SelectInput');
16
15
  goog.requireType('ShakaDemoAssetInfo');
17
16
 
@@ -60,12 +59,6 @@ shakaDemo.Search = class {
60
59
  document.addEventListener('shaka-main-offline-progress', () => {
61
60
  this.updateOfflineProgress_();
62
61
  });
63
- document.addEventListener('shaka-main-locale-changed', () => {
64
- this.remakeSearchDiv_(container);
65
- this.remakeResultsDiv_();
66
- // Update the componentHandler, to account for any new MDL elements added.
67
- componentHandler.upgradeDom();
68
- });
69
62
  document.addEventListener('shaka-main-page-changed', () => {
70
63
  if (!this.resultsDiv_.childNodes.length &&
71
64
  !container.classList.contains('hidden')) {
@@ -153,7 +146,7 @@ shakaDemo.Search = class {
153
146
  if (unsupportedReason) {
154
147
  c.markAsUnsupported(unsupportedReason);
155
148
  } else {
156
- c.addButton(shakaDemo.MessageIds.PLAY, () => {
149
+ c.addButton('Play', () => {
157
150
  shakaDemoMain.loadAsset(asset);
158
151
  this.updateSelected_();
159
152
  });
@@ -270,7 +263,7 @@ shakaDemo.Search = class {
270
263
  * The term this represents.
271
264
  * @param {shakaDemo.Search.TermType} type
272
265
  * The type of term that this term is.
273
- * @param {?shakaDemo.MessageIds} tooltip
266
+ * @param {?string} tooltip
274
267
  * @private
275
268
  */
276
269
  makeBooleanInput_(searchContainer, choice, type, tooltip) {
@@ -298,7 +291,7 @@ shakaDemo.Search = class {
298
291
  * Creates an input for a group of related but mutually-exclusive search
299
292
  * terms.
300
293
  * @param {!shakaDemo.InputContainer} searchContainer
301
- * @param {!shakaDemo.MessageIds} name
294
+ * @param {string} name
302
295
  * @param {!Array.<!shakaDemo.Search.SearchTerm>} choices
303
296
  * An array of the terms in this term group.
304
297
  * @param {shakaDemo.Search.TermType} type
@@ -311,7 +304,7 @@ shakaDemo.Search = class {
311
304
  const nullOption = '---';
312
305
  const valuesObject = {};
313
306
  for (const term of choices) {
314
- valuesObject[term] = shakaDemoMain.getLocalizedString(term);
307
+ valuesObject[term] = term;
315
308
  }
316
309
  valuesObject[nullOption] = nullOption;
317
310
  let lastValue = nullOption;
@@ -357,23 +350,18 @@ shakaDemo.Search = class {
357
350
  const coreContainer = new shakaDemo.InputContainer(
358
351
  container, /* headerText= */ null, shakaDemo.InputContainer.Style.FLEX,
359
352
  /* docLink= */ null);
360
- this.makeSelectInput_(coreContainer,
361
- shakaDemo.MessageIds.MANIFEST_SEARCH,
353
+ this.makeSelectInput_(coreContainer, 'Manifest',
362
354
  [Feature.DASH, Feature.HLS, Feature.MSS], FEATURE);
363
- this.makeSelectInput_(coreContainer,
364
- shakaDemo.MessageIds.CONTAINER_SEARCH,
355
+ this.makeSelectInput_(coreContainer, 'Container',
365
356
  [Feature.MP4, Feature.MP2TS, Feature.WEBM, Feature.CONTAINERLESS],
366
357
  FEATURE);
367
- this.makeSelectInput_(coreContainer,
368
- shakaDemo.MessageIds.DRM_SEARCH,
358
+ this.makeSelectInput_(coreContainer, 'DRM',
369
359
  Object.values(shakaAssets.KeySystem), DRM);
370
- this.makeSelectInput_(coreContainer,
371
- shakaDemo.MessageIds.SOURCE_SEARCH,
360
+ this.makeSelectInput_(coreContainer, 'Source',
372
361
  Object.values(shakaAssets.Source).filter((term) => {
373
362
  return term != shakaAssets.Source.CUSTOM;
374
363
  }), SOURCE);
375
- this.makeSelectInput_(coreContainer,
376
- shakaDemo.MessageIds.LIVE_SEARCH,
364
+ this.makeSelectInput_(coreContainer, 'Live',
377
365
  [Feature.LOW_LATENCY, Feature.LIVE, Feature.VOD], FEATURE);
378
366
 
379
367
  // Special terms.
@@ -382,29 +370,29 @@ shakaDemo.Search = class {
382
370
  container, /* headerText= */ null, containerStyle,
383
371
  /* docLink= */ null);
384
372
  this.makeBooleanInput_(specialContainer, Feature.HIGH_DEFINITION, FEATURE,
385
- shakaDemo.MessageIds.HIGH_DEFINITION_SEARCH);
373
+ 'Filters for assets with at least one high-definition video stream.');
386
374
  this.makeBooleanInput_(specialContainer, Feature.XLINK, FEATURE,
387
- shakaDemo.MessageIds.XLINK_SEARCH);
375
+ 'Filters for assets that have XLINK tags in their manifests, so that ' +
376
+ 'they can be broken into multiple files.');
388
377
  this.makeBooleanInput_(specialContainer, Feature.SUBTITLES, FEATURE,
389
- shakaDemo.MessageIds.SUBTITLES_SEARCH);
378
+ 'Filters for assets with caption tracks, or embedded captions.');
390
379
  this.makeBooleanInput_(specialContainer, Feature.TRICK_MODE, FEATURE,
391
- shakaDemo.MessageIds.TRICK_MODE_SEARCH);
380
+ 'Filters for assets that have special video tracks to be used in ' +
381
+ 'trick mode playback (aka fast-forward).');
392
382
  this.makeBooleanInput_(specialContainer, Feature.SURROUND, FEATURE,
393
- shakaDemo.MessageIds.SURROUND_SEARCH);
383
+ 'Filters for assets with at least one surround sound audio track.');
394
384
  this.makeBooleanInput_(specialContainer, Feature.OFFLINE, FEATURE,
395
- shakaDemo.MessageIds.OFFLINE_SEARCH);
385
+ 'Filters for assets that can be stored offline.');
396
386
  this.makeBooleanInput_(specialContainer, Feature.STORED, FEATURE,
397
- shakaDemo.MessageIds.STORED_SEARCH);
387
+ 'Filters for assets that have been stored offline.');
398
388
  this.makeBooleanInput_(specialContainer, Feature.ADS, FEATURE,
399
- shakaDemo.MessageIds.AD_SEARCH);
389
+ 'Filters for assets that have advertisements.');
400
390
  this.makeBooleanInput_(specialContainer, Feature.AUDIO_ONLY, FEATURE,
401
- shakaDemo.MessageIds.AUDIO_ONLY_SEARCH);
391
+ 'Filters for assets that do not have video streams.');
402
392
  this.makeBooleanInput_(specialContainer, Feature.THUMBNAILS, FEATURE,
403
- shakaDemo.MessageIds.THUMBNAILS);
393
+ 'Filters for assets that have a thumbnail track.');
404
394
  this.makeBooleanInput_(specialContainer, Feature.LCEVC, FEATURE,
405
- shakaDemo.MessageIds.LCEVC);
406
- this.makeBooleanInput_(specialContainer, Feature.LOW_LATENCY,
407
- FEATURE, shakaDemo.MessageIds.LOW_LATENCY);
395
+ 'Filters for assets that have an LCEVC enhancement layer.');
408
396
 
409
397
  container.appendChild(this.resultsDiv_);
410
398
  }
@@ -92,9 +92,6 @@ const OPTIONAL_RESOURCES = [
92
92
  'https://shaka-player-demo.appspot.com/assets/poster.jpg',
93
93
  'https://shaka-player-demo.appspot.com/assets/audioOnly.gif',
94
94
 
95
- // The mux.js transmuxing library for MPEG-2 TS and CEA support.
96
- '../node_modules/mux.js/dist/mux.min.js',
97
-
98
95
  // The codem-isoboxer library for MSS support.
99
96
  '../node_modules/codem-isoboxer/dist/iso_boxer.min.js',
100
97
 
package/demo/tooltip.js CHANGED
@@ -7,19 +7,17 @@
7
7
 
8
8
  goog.provide('shakaDemo.Tooltips');
9
9
 
10
- goog.requireType('shakaDemo.MessageIds');
11
-
12
10
  /**
13
11
  * Creates and contains a tooltip.
14
12
  */
15
13
  shakaDemo.Tooltips = class {
16
14
  /**
17
15
  * @param {!Element} labeledElement
18
- * @param {shakaDemo.MessageIds} message
16
+ * @param {string} content
19
17
  */
20
- static make(labeledElement, message) {
18
+ static make(labeledElement, content) {
21
19
  tippy(labeledElement, {
22
- content: shakaDemoMain.getLocalizedString(message),
20
+ content,
23
21
  placement: 'bottom',
24
22
  arrow: true,
25
23
  animation: 'scale',
@@ -84,8 +84,7 @@ shakaDemo.Visualizer = class {
84
84
  inputContainer.addRow(null, null);
85
85
  this.screenshotButton_ = document.createElement('button');
86
86
  inputContainer.latestElementContainer.appendChild(this.screenshotButton_);
87
- this.screenshotButton_.textContent = shakaDemoMain.getLocalizedString(
88
- shakaDemo.MessageIds.VISUALIZER_SCREENSHOT_BUTTON);
87
+ this.screenshotButton_.textContent = 'Take Screenshot';
89
88
  this.screenshotButton_.classList.add('mdl-button');
90
89
  this.screenshotButton_.classList.add('mdl-button--colored');
91
90
  this.screenshotButton_.classList.add('mdl-js-button');
@@ -94,11 +93,10 @@ shakaDemo.Visualizer = class {
94
93
  this.takeScreenshot_();
95
94
  });
96
95
 
97
- inputContainer.addRow(
98
- shakaDemo.MessageIds.VISUALIZER_AUTO_SCREENSHOT_TOGGLE, null);
96
+ inputContainer.addRow('Take Screenshot On Stall', null);
99
97
  /** @private {!shakaDemo.BoolInput} */
100
98
  this.autoScreenshotToggle_ = new shakaDemo.BoolInput(
101
- inputContainer, shakaDemo.MessageIds.VISUALIZER_AUTO_SCREENSHOT_TOGGLE,
99
+ inputContainer, 'Take Screenshot On Stall',
102
100
  (input) => {
103
101
  this.takeAutoScreenshots_ = input.checked;
104
102
  });
@@ -7,8 +7,6 @@
7
7
 
8
8
  goog.provide('shakaDemo.VisualizerButton');
9
9
 
10
- goog.require('shakaDemo.MessageIds');
11
-
12
10
  /**
13
11
  * A custom UI overflow button, to allow users to show the visualizer.
14
12
  * This cannot actually extend shaka.ui.Element, as that class does not exist
@@ -41,6 +39,7 @@ shakaDemo.VisualizerButton = class extends shaka.ui.Element {
41
39
  label.classList.add('shaka-overflow-menu-only');
42
40
  this.nameSpan_ = document.createElement('span');
43
41
  label.appendChild(this.nameSpan_);
42
+ this.nameSpan_.textContent = 'Buffer Visualizer';
44
43
 
45
44
  /** @private {!HTMLElement} */
46
45
  this.currentPipState_ = /** @type {!HTMLElement} */ (
@@ -57,24 +56,6 @@ shakaDemo.VisualizerButton = class extends shaka.ui.Element {
57
56
  !shakaDemoMain.getIsVisualizerActive());
58
57
  this.setIcon_();
59
58
  });
60
-
61
- this.eventManager.listen(
62
- this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
63
- this.updateLocalizedStrings_();
64
- });
65
-
66
- this.eventManager.listen(
67
- this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
68
- this.updateLocalizedStrings_();
69
- });
70
- }
71
-
72
- /** @private */
73
- updateLocalizedStrings_() {
74
- this.nameSpan_.textContent = shakaDemoMain.getLocalizedString(
75
- shakaDemo.MessageIds.VISUALIZER_BUTTON);
76
- // TODO: Make sure that the screenreader description of this control is
77
- // localized!
78
59
  }
79
60
 
80
61
  /** @private */