shaka-player 3.3.5 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/.github/config.yml +1 -0
  2. package/.github/workflows/demo-version-index.yaml +8 -0
  3. package/.github/workflows/release-please.yaml +18 -2
  4. package/.github/workflows/sync-labels.yaml +33 -0
  5. package/.github/workflows/update-issues.yaml +29 -0
  6. package/.github/workflows/validate-pr-title.yaml +35 -0
  7. package/AUTHORS +1 -0
  8. package/CHANGELOG.md +215 -41
  9. package/CONTRIBUTORS +1 -0
  10. package/README.md +14 -11
  11. package/app-engine/demo-version-index/README.md +3 -3
  12. package/app-engine/demo-version-index/app.yaml +27 -1
  13. package/app-engine/demo-version-index/generate.py +164 -0
  14. package/app-engine/demo-version-index/main.py +4 -155
  15. package/app-engine/demo-version-index/requirements.txt +0 -1
  16. package/build/checkversion.py +1 -1
  17. package/build/compiler.py +1 -1
  18. package/build/misspellings.txt +1 -0
  19. package/build/shaka-lab.yaml +0 -2
  20. package/build/types/polyfill +0 -3
  21. package/demo/common/asset.js +17 -1
  22. package/demo/common/assets.js +29 -0
  23. package/demo/common/message_ids.js +6 -3
  24. package/demo/config.js +10 -11
  25. package/demo/custom.js +39 -0
  26. package/demo/demo.less +0 -1
  27. package/demo/demo_utils.js +0 -1
  28. package/demo/locales/en.json +6 -3
  29. package/demo/locales/source.json +22 -10
  30. package/demo/main.js +9 -6
  31. package/demo/search.js +2 -1
  32. package/dist/controls.css +3 -3
  33. package/dist/controls.css.map +1 -1
  34. package/dist/demo.compiled.debug.js +71 -64
  35. package/dist/demo.compiled.debug.map +3 -3
  36. package/dist/demo.compiled.js +71 -64
  37. package/dist/demo.compiled.map +3 -3
  38. package/dist/demo.css +1 -1
  39. package/dist/demo.css.map +1 -1
  40. package/dist/deps.js +17 -20
  41. package/dist/locales.js +33 -31
  42. package/dist/receiver.compiled.debug.js +32 -28
  43. package/dist/receiver.compiled.debug.map +3 -3
  44. package/dist/receiver.compiled.js +32 -28
  45. package/dist/receiver.compiled.map +3 -3
  46. package/dist/shaka-player.compiled.d.ts +311 -314
  47. package/dist/shaka-player.compiled.debug.d.ts +311 -314
  48. package/dist/shaka-player.compiled.debug.externs.js +126 -126
  49. package/dist/shaka-player.compiled.debug.js +430 -484
  50. package/dist/shaka-player.compiled.debug.map +4 -4
  51. package/dist/shaka-player.compiled.externs.js +126 -126
  52. package/dist/shaka-player.compiled.js +829 -845
  53. package/dist/shaka-player.compiled.map +4 -4
  54. package/dist/shaka-player.ui.d.ts +357 -358
  55. package/dist/shaka-player.ui.debug.d.ts +357 -358
  56. package/dist/shaka-player.ui.debug.externs.js +134 -126
  57. package/dist/shaka-player.ui.debug.js +489 -541
  58. package/dist/shaka-player.ui.debug.map +4 -4
  59. package/dist/shaka-player.ui.externs.js +134 -126
  60. package/dist/shaka-player.ui.js +988 -1000
  61. package/dist/shaka-player.ui.map +4 -4
  62. package/docs/tutorials/config.md +0 -2
  63. package/docs/tutorials/drm-config.md +5 -0
  64. package/docs/tutorials/fairplay.md +7 -22
  65. package/docs/tutorials/faq.md +0 -11
  66. package/docs/tutorials/index.json +2 -8
  67. package/docs/tutorials/plugins.md +1 -3
  68. package/docs/tutorials/upgrade.md +85 -11
  69. package/externs/polyfill.js +15 -0
  70. package/externs/shaka/manifest.js +5 -1
  71. package/externs/shaka/net.js +12 -0
  72. package/externs/shaka/offline.js +5 -1
  73. package/externs/shaka/player.js +39 -21
  74. package/externs/shaka/text.js +12 -12
  75. package/externs/sourcebuffer.js +15 -0
  76. package/lib/abr/simple_abr_manager.js +2 -1
  77. package/lib/ads/client_side_ad.js +13 -2
  78. package/lib/ads/client_side_ad_manager.js +22 -4
  79. package/lib/cast/cast_utils.js +0 -1
  80. package/lib/dash/content_protection.js +85 -5
  81. package/lib/dash/dash_parser.js +1 -0
  82. package/lib/hls/hls_parser.js +390 -747
  83. package/lib/hls/manifest_text_parser.js +2 -3
  84. package/lib/media/drm_engine.js +105 -37
  85. package/lib/media/gap_jumping_controller.js +10 -45
  86. package/lib/media/media_source_engine.js +150 -30
  87. package/lib/media/playhead.js +2 -5
  88. package/lib/media/presentation_timeline.js +1 -2
  89. package/lib/media/segment_index.js +13 -46
  90. package/lib/media/segment_reference.js +47 -1
  91. package/lib/media/streaming_engine.js +28 -11
  92. package/lib/media/time_ranges_utils.js +4 -9
  93. package/lib/net/networking_engine.js +3 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  96. package/lib/offline/manifest_converter.js +1 -0
  97. package/lib/offline/storage.js +8 -41
  98. package/lib/player.js +17 -201
  99. package/lib/polyfill/media_capabilities.js +12 -6
  100. package/lib/polyfill/mediasource.js +0 -28
  101. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  102. package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
  103. package/lib/text/cue.js +0 -6
  104. package/lib/text/lrc_text_parser.js +8 -0
  105. package/lib/text/mp4_ttml_parser.js +8 -0
  106. package/lib/text/mp4_vtt_parser.js +8 -0
  107. package/lib/text/sbv_text_parser.js +8 -0
  108. package/lib/text/simple_text_displayer.js +1 -7
  109. package/lib/text/srt_text_parser.js +8 -0
  110. package/lib/text/ssa_text_parser.js +8 -0
  111. package/lib/text/text_engine.js +19 -3
  112. package/lib/text/ttml_text_parser.js +8 -0
  113. package/lib/text/ui_text_displayer.js +1 -7
  114. package/lib/text/vtt_text_parser.js +27 -5
  115. package/lib/text/web_vtt_generator.js +1 -7
  116. package/lib/util/error.js +9 -13
  117. package/lib/util/fairplay_utils.js +109 -0
  118. package/lib/util/functional.js +0 -42
  119. package/lib/util/mime_utils.js +16 -5
  120. package/lib/util/platform.js +45 -0
  121. package/lib/util/player_configuration.js +17 -6
  122. package/lib/util/pssh.js +23 -4
  123. package/lib/util/stream_utils.js +92 -22
  124. package/lib/util/uint8array_utils.js +0 -16
  125. package/lib/util/xml_utils.js +1 -1
  126. package/package.json +5 -2
  127. package/roadmap.md +19 -19
  128. package/shaka-player.uncompiled.js +0 -3
  129. package/test/dash/dash_parser_content_protection_unit.js +44 -0
  130. package/test/dash/dash_parser_segment_template_unit.js +3 -4
  131. package/test/demo/demo_unit.js +2 -1
  132. package/test/hls/hls_live_unit.js +155 -230
  133. package/test/hls/hls_parser_unit.js +515 -432
  134. package/test/media/drm_engine_unit.js +86 -120
  135. package/test/media/media_source_engine_integration.js +25 -3
  136. package/test/media/media_source_engine_unit.js +3 -2
  137. package/test/media/playhead_unit.js +27 -191
  138. package/test/media/segment_index_unit.js +15 -25
  139. package/test/media/streaming_engine_integration.js +2 -39
  140. package/test/media/streaming_engine_unit.js +3 -2
  141. package/test/media/time_ranges_utils_unit.js +0 -5
  142. package/test/offline/manifest_convert_unit.js +34 -4
  143. package/test/offline/offline_manifest_parser_unit.js +1 -0
  144. package/test/offline/storage_integration.js +5 -4
  145. package/test/player_external.js +0 -6
  146. package/test/player_integration.js +16 -0
  147. package/test/player_unit.js +26 -0
  148. package/test/test/util/fake_media_source_engine.js +11 -4
  149. package/test/test/util/manifest_generator.js +3 -1
  150. package/test/test/util/manifest_parser_util.js +4 -1
  151. package/test/test/util/offline_utils.js +1 -0
  152. package/test/test/util/streaming_engine_util.js +1 -0
  153. package/test/test/util/test_scheme.js +24 -1
  154. package/test/test/util/util.js +4 -4
  155. package/test/text/cue_integration.js +2 -2
  156. package/test/text/lrc_text_parser_unit.js +6 -7
  157. package/test/text/mp4_ttml_parser_unit.js +6 -4
  158. package/test/text/mp4_vtt_parser_unit.js +6 -5
  159. package/test/text/sbv_text_parser_unit.js +5 -6
  160. package/test/text/srt_text_parser_unit.js +5 -6
  161. package/test/text/ssa_text_parser_unit.js +17 -29
  162. package/test/text/text_engine_unit.js +45 -5
  163. package/test/text/ttml_text_parser_unit.js +77 -77
  164. package/test/text/vtt_text_parser_unit.js +116 -59
  165. package/test/ui/ui_integration.js +0 -16
  166. package/test/ui/ui_unit.js +27 -0
  167. package/test/util/cmcd_manager_unit.js +3 -0
  168. package/test/util/stream_utils_unit.js +23 -7
  169. package/ui/controls.js +65 -40
  170. package/ui/fullscreen_button.js +26 -6
  171. package/ui/less/containers.less +4 -4
  172. package/ui/less/general.less +1 -1
  173. package/ui/less/range_elements.less +1 -0
  174. package/ui/locales/en.json +1 -0
  175. package/ui/locales/source.json +5 -0
  176. package/ui/resolution_selection.js +31 -33
  177. package/ui/ui.js +0 -17
  178. package/.github/pull_request_template.md +0 -10
  179. package/docs/tutorials/upgrade-v2-5.md +0 -441
  180. package/docs/tutorials/upgrade-v3.md +0 -38
  181. package/lib/polyfill/mathround.js +0 -49
  182. package/lib/polyfill/patchedmediakeys_apple.js +0 -744
  183. package/lib/polyfill/patchedmediakeys_ms.js +0 -698
  184. package/test/util/functional_unit.js +0 -82
package/ui/controls.js CHANGED
@@ -9,7 +9,6 @@ goog.provide('shaka.ui.Controls');
9
9
  goog.provide('shaka.ui.ControlsPanel');
10
10
 
11
11
  goog.require('goog.asserts');
12
- goog.require('shaka.Deprecate');
13
12
  goog.require('shaka.ads.AdManager');
14
13
  goog.require('shaka.cast.CastProxy');
15
14
  goog.require('shaka.log');
@@ -556,33 +555,74 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
556
555
  this.hideSettingsMenusTimer_.tickNow();
557
556
  }
558
557
 
558
+ /**
559
+ * @return {boolean}
560
+ * @export
561
+ */
562
+ isFullScreenSupported() {
563
+ if (document.fullscreenEnabled) {
564
+ return true;
565
+ }
566
+ const video = /** @type {HTMLVideoElement} */(this.localVideo_);
567
+ if (video.webkitSupportsFullscreen) {
568
+ return true;
569
+ }
570
+ return false;
571
+ }
572
+
573
+ /**
574
+ * @return {boolean}
575
+ * @export
576
+ */
577
+ isFullScreenEnabled() {
578
+ if (document.fullscreenEnabled) {
579
+ return !!document.fullscreenElement;
580
+ }
581
+ const video = /** @type {HTMLVideoElement} */(this.localVideo_);
582
+ if (video.webkitSupportsFullscreen) {
583
+ return video.webkitDisplayingFullscreen;
584
+ }
585
+ return false;
586
+ }
587
+
559
588
  /** @export */
560
589
  async toggleFullScreen() {
561
- if (document.fullscreenElement) {
562
- if (screen.orientation) {
563
- screen.orientation.unlock();
564
- }
565
- await document.exitFullscreen();
566
- } else {
567
- // If we are in PiP mode, leave PiP mode first.
568
- try {
569
- if (document.pictureInPictureElement) {
570
- await document.exitPictureInPicture();
590
+ if (document.fullscreenEnabled) {
591
+ if (document.fullscreenElement) {
592
+ if (screen.orientation) {
593
+ screen.orientation.unlock();
571
594
  }
572
- await this.videoContainer_.requestFullscreen({navigationUI: 'hide'});
573
- if (this.config_.forceLandscapeOnFullscreen && screen.orientation) {
574
- try {
575
- // Locking to 'landscape' should let it be either
576
- // 'landscape-primary' or 'landscape-secondary' as appropriate.
577
- await screen.orientation.lock('landscape');
578
- } catch (error) {
579
- // If screen.orientation.lock does not work on a device, it will
580
- // be rejected with an error. Suppress that error.
595
+ await document.exitFullscreen();
596
+ } else {
597
+ // If we are in PiP mode, leave PiP mode first.
598
+ try {
599
+ if (document.pictureInPictureElement) {
600
+ await document.exitPictureInPicture();
601
+ }
602
+ await this.videoContainer_.requestFullscreen({navigationUI: 'hide'});
603
+ if (this.config_.forceLandscapeOnFullscreen && screen.orientation) {
604
+ try {
605
+ // Locking to 'landscape' should let it be either
606
+ // 'landscape-primary' or 'landscape-secondary' as appropriate.
607
+ await screen.orientation.lock('landscape');
608
+ } catch (error) {
609
+ // If screen.orientation.lock does not work on a device, it will
610
+ // be rejected with an error. Suppress that error.
611
+ }
581
612
  }
613
+ } catch (error) {
614
+ this.dispatchEvent(new shaka.util.FakeEvent(
615
+ 'error', (new Map()).set('detail', error)));
616
+ }
617
+ }
618
+ } else {
619
+ const video = /** @type {HTMLVideoElement} */(this.localVideo_);
620
+ if (video.webkitSupportsFullscreen) {
621
+ if (video.webkitDisplayingFullscreen) {
622
+ video.webkitExitFullscreen();
623
+ } else {
624
+ video.webkitEnterFullscreen();
582
625
  }
583
- } catch (error) {
584
- this.dispatchEvent(new shaka.util.FakeEvent(
585
- 'error', (new Map()).set('detail', error)));
586
626
  }
587
627
  }
588
628
  }
@@ -702,7 +742,8 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
702
742
  });
703
743
 
704
744
  this.eventManager_.listen(this.controlsContainer_, 'dblclick', () => {
705
- if (this.config_.doubleClickForFullscreen && document.fullscreenEnabled) {
745
+ if (this.config_.doubleClickForFullscreen &&
746
+ this.isFullScreenSupported()) {
706
747
  this.toggleFullScreen();
707
748
  }
708
749
  });
@@ -826,22 +867,6 @@ shaka.ui.Controls = class extends shaka.util.FakeEventTarget {
826
867
  const factory =
827
868
  shaka.ui.ControlsPanel.elementNamesToFactories_.get(name);
828
869
  const element = factory.create(this.controlsButtonPanel_, this);
829
-
830
- if (typeof element.release != 'function') {
831
- shaka.Deprecate.deprecateFeature(4,
832
- 'shaka.extern.IUIElement',
833
- 'Please update UI elements to have a release() method.');
834
-
835
- // This cast works around compiler strictness about the IUIElement
836
- // type being "@struct" (as ES6 classes are by default).
837
- const moddableElement = /** @type {Object} */(element);
838
- moddableElement['release'] = () => {
839
- if (moddableElement['destroy']) {
840
- moddableElement['destroy']();
841
- }
842
- };
843
- }
844
-
845
870
  this.elements_.push(element);
846
871
  } else {
847
872
  shaka.log.alwaysWarn('Unrecognized control panel element requested:',
@@ -28,16 +28,16 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
28
28
  constructor(parent, controls) {
29
29
  super(parent, controls);
30
30
 
31
+ /** @private {HTMLMediaElement} */
32
+ this.localVideo_ = this.controls.getLocalVideo();
33
+
31
34
  /** @private {!HTMLButtonElement} */
32
35
  this.button_ = shaka.util.Dom.createButton();
33
36
  this.button_.classList.add('shaka-fullscreen-button');
34
37
  this.button_.classList.add('material-icons-round');
35
38
  this.button_.classList.add('shaka-tooltip');
36
39
 
37
- // Don't show the button if fullscreen is not supported
38
- if (!document.fullscreenEnabled) {
39
- this.button_.classList.add('shaka-hidden');
40
- }
40
+ this.checkSupport_();
41
41
 
42
42
  this.button_.textContent = shaka.ui.Enums.MaterialDesignIcons.FULLSCREEN;
43
43
  this.parent.appendChild(this.button_);
@@ -61,6 +61,26 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
61
61
  this.updateIcon_();
62
62
  this.updateAriaLabel_();
63
63
  });
64
+
65
+ this.eventManager.listen(this.localVideo_, 'loadedmetadata', () => {
66
+ this.checkSupport_();
67
+ });
68
+
69
+ this.eventManager.listen(this.localVideo_, 'loadeddata', () => {
70
+ this.checkSupport_();
71
+ });
72
+ }
73
+
74
+ /**
75
+ * @private
76
+ */
77
+ checkSupport_() {
78
+ // Don't show the button if fullscreen is not supported
79
+ if (!this.controls.isFullScreenSupported()) {
80
+ this.button_.classList.add('shaka-hidden');
81
+ } else {
82
+ this.button_.classList.remove('shaka-hidden');
83
+ }
64
84
  }
65
85
 
66
86
  /**
@@ -68,7 +88,7 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
68
88
  */
69
89
  updateAriaLabel_() {
70
90
  const LocIds = shaka.ui.Locales.Ids;
71
- const label = document.fullscreenElement ?
91
+ const label = this.controls.isFullScreenEnabled() ?
72
92
  LocIds.EXIT_FULL_SCREEN : LocIds.FULL_SCREEN;
73
93
 
74
94
  this.button_.ariaLabel = this.localization.resolve(label);
@@ -79,7 +99,7 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
79
99
  */
80
100
  updateIcon_() {
81
101
  this.button_.textContent =
82
- document.fullscreenElement ?
102
+ this.controls.isFullScreenEnabled() ?
83
103
  shaka.ui.Enums.MaterialDesignIcons.EXIT_FULLSCREEN :
84
104
  shaka.ui.Enums.MaterialDesignIcons.FULLSCREEN;
85
105
  }
@@ -161,7 +161,7 @@
161
161
  /* Consistent margins (external) and padding (internal) between controls. */
162
162
  .bottom-panels-elements-margin();
163
163
 
164
- padding: 0;
164
+ padding: 0 5px;
165
165
 
166
166
  /* Transparent backgrounds, no borders, and a pointer when you mouse over
167
167
  * them. */
@@ -337,8 +337,8 @@
337
337
 
338
338
  .shaka-spinner {
339
339
  /* This uses the same trickery as the big play button define
340
- * the spinner's width and height. See .shaka-play-button
341
- * for the detailed explanation. */
340
+ the spinner's width and height. See .shaka-play-button
341
+ for the detailed explanation. */
342
342
 
343
343
  /* For the padding thing to work, spinner div needs to be an
344
344
  overlay-parent and spinner svg - an overlay child. */
@@ -351,6 +351,6 @@
351
351
  height: 0;
352
352
 
353
353
  /* Add a bit of a white shadow to keep our black spinner visible
354
- * on a black background. */
354
+ on a black background. */
355
355
  filter: drop-shadow(0 0 2px rgba(255 255 255 / 50%));
356
356
  }
@@ -37,7 +37,7 @@
37
37
  }
38
38
 
39
39
  .bottom-panels-elements-margin() {
40
- margin: 1px 6px;
40
+ margin: 1px;
41
41
  }
42
42
 
43
43
  /* For containers which host elements overlaying other things. */
@@ -140,6 +140,7 @@
140
140
 
141
141
  .shaka-volume-bar-container {
142
142
  width: 100px;
143
+ padding: 0;
143
144
  }
144
145
 
145
146
  .shaka-range-element {
@@ -27,6 +27,7 @@
27
27
  "PICTURE_IN_PICTURE": "Picture-in-Picture",
28
28
  "PLAY": "Play",
29
29
  "PLAYBACK_RATE": "Playback speed",
30
+ "QUALITY": "Quality",
30
31
  "REPLAY": "Replay",
31
32
  "RESOLUTION": "Resolution",
32
33
  "REWIND": "Rewind",
@@ -113,6 +113,11 @@
113
113
  "message": "Playback speed",
114
114
  "description": "Label for a button used to navigate to a submenu to choose the playback speed in the video player."
115
115
  },
116
+ "QUALITY": {
117
+ "description": "Label for a button used to open a submenu to choose audio quality in the video player.",
118
+ "meaning": "Audio quality",
119
+ "message": "Quality"
120
+ },
116
121
  "REPLAY": {
117
122
  "description": "Label for a button used to replay the video in a video player.",
118
123
  "message": "Replay"
@@ -61,9 +61,6 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
61
61
  });
62
62
 
63
63
  this.updateResolutionSelection_();
64
-
65
- // Set up all the strings in the user's preferred language.
66
- this.updateLocalizedStrings_();
67
64
  }
68
65
 
69
66
 
@@ -72,27 +69,6 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
72
69
  /** @type {!Array.<shaka.extern.Track>} */
73
70
  let tracks = this.player.getVariantTracks();
74
71
 
75
- // Hide resolution menu and button for audio-only content and src= content
76
- // without resolution information.
77
- // TODO: for audio-only content, this should be a bitrate selection menu
78
- // instead.
79
- if (tracks.length && !tracks[0].height) {
80
- shaka.ui.Utils.setDisplay(this.menu, false);
81
- shaka.ui.Utils.setDisplay(this.button, false);
82
- return;
83
- }
84
- // Otherwise, restore it.
85
- shaka.ui.Utils.setDisplay(this.button, true);
86
-
87
- tracks.sort((t1, t2) => {
88
- // We have already screened for audio-only content, but the compiler
89
- // doesn't know that.
90
- goog.asserts.assert(t1.height != null, 'Null height');
91
- goog.asserts.assert(t2.height != null, 'Null height');
92
-
93
- return t2.height - t1.height;
94
- });
95
-
96
72
  // If there is a selected variant track, then we filter out any tracks in
97
73
  // a different language. Then we use those remaining tracks to display the
98
74
  // available resolutions.
@@ -104,14 +80,31 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
104
80
  track.channelsCount == selectedTrack.channelsCount);
105
81
  }
106
82
 
107
- // Remove duplicate entries with the same height. This can happen if
108
- // we have multiple resolutions of audio. Pick an arbitrary one.
83
+ // Remove duplicate entries with the same resolution or quality depending
84
+ // on content type. Pick an arbitrary one.
109
85
  tracks = tracks.filter((track, idx) => {
110
- // Keep the first one with the same height.
111
- const otherIdx = tracks.findIndex((t) => t.height == track.height);
86
+ // Keep the first one with the same height or bandwidth.
87
+ const otherIdx = this.player.isAudioOnly() ?
88
+ tracks.findIndex((t) => t.bandwidth == track.bandwidth) :
89
+ tracks.findIndex((t) => t.height == track.height);
112
90
  return otherIdx == idx;
113
91
  });
114
92
 
93
+ // Sort the tracks by height or bandwidth depending on content type.
94
+ if (this.player.isAudioOnly()) {
95
+ tracks.sort((t1, t2) => {
96
+ goog.asserts.assert(t1.bandwidth != null, 'Null bandwidth');
97
+ goog.asserts.assert(t2.bandwidth != null, 'Null bandwidth');
98
+ return t2.bandwidth - t1.bandwidth;
99
+ });
100
+ } else {
101
+ tracks.sort((t1, t2) => {
102
+ goog.asserts.assert(t1.height != null, 'Null height');
103
+ goog.asserts.assert(t2.height != null, 'Null height');
104
+ return t2.height - t1.height;
105
+ });
106
+ }
107
+
115
108
  // Remove old shaka-resolutions
116
109
  // 1. Save the back to menu button
117
110
  const backButton = shaka.ui.Utils.getFirstDescendantWithClassName(
@@ -133,7 +126,8 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
133
126
  () => this.onTrackSelected_(track));
134
127
 
135
128
  const span = shaka.util.Dom.createHTMLElement('span');
136
- span.textContent = track.height + 'p';
129
+ span.textContent = this.player.isAudioOnly() ?
130
+ Math.round(track.bandwidth / 1000) + ' kbits/s' : track.height + 'p';
137
131
  button.appendChild(span);
138
132
 
139
133
  if (!abrEnabled && track == selectedTrack) {
@@ -179,6 +173,8 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
179
173
  shaka.ui.Utils.focusOnTheChosenItem(this.menu);
180
174
  this.controls.dispatchEvent(
181
175
  new shaka.util.FakeEvent('resolutionselectionupdated'));
176
+
177
+ this.updateLocalizedStrings_();
182
178
  }
183
179
 
184
180
 
@@ -200,13 +196,15 @@ shaka.ui.ResolutionSelection = class extends shaka.ui.SettingsMenu {
200
196
  */
201
197
  updateLocalizedStrings_() {
202
198
  const LocIds = shaka.ui.Locales.Ids;
199
+ const locId = this.player.isAudioOnly() ?
200
+ LocIds.QUALITY : LocIds.RESOLUTION;
203
201
 
204
- this.button.ariaLabel = this.localization.resolve(LocIds.RESOLUTION);
205
- this.backButton.ariaLabel = this.localization.resolve(LocIds.RESOLUTION);
202
+ this.button.ariaLabel = this.localization.resolve(locId);
203
+ this.backButton.ariaLabel = this.localization.resolve(locId);
206
204
  this.backSpan.textContent =
207
- this.localization.resolve(LocIds.RESOLUTION);
205
+ this.localization.resolve(locId);
208
206
  this.nameSpan.textContent =
209
- this.localization.resolve(LocIds.RESOLUTION);
207
+ this.localization.resolve(locId);
210
208
  this.abrOnSpan_.textContent =
211
209
  this.localization.resolve(LocIds.AUTO_QUALITY);
212
210
 
package/ui/ui.js CHANGED
@@ -448,14 +448,6 @@ shaka.ui.Overlay.TrackLabelFormat = {
448
448
  'LABEL': 3,
449
449
  };
450
450
 
451
- /*
452
- * "shaka.ui.TrackLabelFormat" is deprecated and will be removed in v4.
453
- *
454
- * @deprecated
455
- * @enum {number}
456
- */
457
- shaka.ui.TrackLabelFormat = shaka.ui.Overlay.TrackLabelFormat;
458
-
459
451
  /**
460
452
  * Describes the possible reasons that the UI might fail to load.
461
453
  *
@@ -468,15 +460,6 @@ shaka.ui.Overlay.FailReasonCode = {
468
460
  };
469
461
 
470
462
 
471
- /**
472
- * "shaka.ui.FailReasonCode" is deprecated and will be removed in v4.
473
- *
474
- * @deprecated
475
- * @enum {number}
476
- */
477
- shaka.ui.FailReasonCode = shaka.ui.Overlay.FailReasonCode;
478
-
479
-
480
463
  if (document.readyState == 'complete') {
481
464
  // Don't fire this event synchronously. In a compiled bundle, the "shaka"
482
465
  // namespace might not be exported to the window until after this point.
@@ -1,10 +0,0 @@
1
- <!--
2
- Please remember to:
3
-
4
- 1. Use Conventional Commits syntax (fix: ..., feat: ..., etc.) in commits and
5
- PR title (https://www.conventionalcommits.org/)
6
- 2. Tag any related or fixed issues ("Issue #123", "Closes #420")
7
- 3. Sign the Google CLA if you haven't (https://cla.developers.google.com)
8
-
9
- You may delete this comment from the PR description.
10
- -->