shaka-player 4.5.0 → 4.6.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 (214) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +1 -1
  2. package/AUTHORS +2 -0
  3. package/CHANGELOG.md +98 -0
  4. package/CODE_OF_CONDUCT.md +1 -1
  5. package/CONTRIBUTORS +2 -0
  6. package/README.md +38 -32
  7. package/demo/common/asset.js +11 -17
  8. package/demo/common/assets.js +117 -11
  9. package/demo/config.js +28 -1
  10. package/demo/custom.js +52 -38
  11. package/demo/main.js +11 -3
  12. package/demo/search.js +7 -0
  13. package/dist/controls.css +1 -1
  14. package/dist/controls.css.map +1 -1
  15. package/dist/demo.compiled.debug.js +133 -124
  16. package/dist/demo.compiled.debug.map +3 -3
  17. package/dist/demo.compiled.js +133 -124
  18. package/dist/demo.compiled.map +3 -3
  19. package/dist/deps.js +20 -18
  20. package/dist/locales.js +35 -31
  21. package/dist/receiver.compiled.debug.js +58 -50
  22. package/dist/receiver.compiled.debug.map +3 -3
  23. package/dist/receiver.compiled.js +58 -50
  24. package/dist/receiver.compiled.map +3 -3
  25. package/dist/shaka-player.compiled.d.ts +440 -390
  26. package/dist/shaka-player.compiled.debug.d.ts +440 -390
  27. package/dist/shaka-player.compiled.debug.externs.js +162 -77
  28. package/dist/shaka-player.compiled.debug.js +786 -736
  29. package/dist/shaka-player.compiled.debug.map +4 -4
  30. package/dist/shaka-player.compiled.externs.js +162 -77
  31. package/dist/shaka-player.compiled.js +1154 -1121
  32. package/dist/shaka-player.compiled.map +4 -4
  33. package/dist/shaka-player.ui.d.ts +491 -437
  34. package/dist/shaka-player.ui.debug.d.ts +491 -437
  35. package/dist/shaka-player.ui.debug.externs.js +167 -77
  36. package/dist/shaka-player.ui.debug.js +877 -811
  37. package/dist/shaka-player.ui.debug.map +4 -4
  38. package/dist/shaka-player.ui.externs.js +167 -77
  39. package/dist/shaka-player.ui.js +1362 -1318
  40. package/dist/shaka-player.ui.map +4 -4
  41. package/docs/tutorials/ad_monetization.md +54 -0
  42. package/docs/tutorials/basic-usage.md +2 -1
  43. package/docs/tutorials/errors.md +2 -1
  44. package/docs/tutorials/offline.md +10 -8
  45. package/docs/tutorials/plugins.md +5 -0
  46. package/docs/tutorials/ui-customization.md +13 -0
  47. package/docs/tutorials/ui.md +2 -1
  48. package/docs/tutorials/upgrade.md +3 -0
  49. package/externs/managedmediasource.js +24 -0
  50. package/externs/shaka/abr_manager.js +6 -2
  51. package/externs/shaka/cea.js +7 -0
  52. package/externs/shaka/codecs.js +5 -3
  53. package/externs/shaka/manifest.js +21 -5
  54. package/externs/shaka/manifest_parser.js +17 -0
  55. package/externs/shaka/net.js +2 -2
  56. package/externs/shaka/offline.js +9 -2
  57. package/externs/shaka/player.js +53 -7
  58. package/externs/shaka/text.js +3 -1
  59. package/externs/shaka/transmuxer.js +1 -1
  60. package/lib/abr/simple_abr_manager.js +25 -8
  61. package/lib/ads/media_tailor_ad_manager.js +14 -3
  62. package/lib/cast/cast_receiver.js +1 -1
  63. package/lib/cea/cea_decoder.js +28 -0
  64. package/lib/cea/dummy_caption_decoder.js +5 -0
  65. package/lib/dash/dash_parser.js +249 -83
  66. package/lib/dash/mpd_utils.js +52 -31
  67. package/lib/dash/segment_base.js +4 -5
  68. package/lib/dash/segment_list.js +5 -4
  69. package/lib/dash/segment_template.js +83 -26
  70. package/lib/hls/hls_classes.js +28 -43
  71. package/lib/hls/hls_parser.js +761 -649
  72. package/lib/hls/hls_utils.js +64 -5
  73. package/lib/hls/manifest_text_parser.js +7 -11
  74. package/lib/media/adaptation_set.js +20 -13
  75. package/lib/media/adaptation_set_criteria.js +70 -18
  76. package/lib/media/closed_caption_parser.js +13 -0
  77. package/lib/media/content_workarounds.js +6 -0
  78. package/lib/media/drm_engine.js +8 -13
  79. package/lib/media/manifest_parser.js +8 -113
  80. package/lib/media/media_source_capabilities.js +10 -3
  81. package/lib/media/media_source_engine.js +75 -21
  82. package/lib/media/play_rate_controller.js +8 -38
  83. package/lib/media/presentation_timeline.js +7 -1
  84. package/lib/media/quality_observer.js +1 -1
  85. package/lib/media/segment_index.js +5 -5
  86. package/lib/media/segment_prefetch.js +92 -24
  87. package/lib/media/segment_reference.js +67 -1
  88. package/lib/media/segment_utils.js +343 -0
  89. package/lib/media/stall_detector.js +0 -3
  90. package/lib/media/streaming_engine.js +41 -21
  91. package/lib/mss/mss_parser.js +18 -2
  92. package/lib/net/networking_engine.js +66 -12
  93. package/lib/net/networking_utils.js +95 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +2 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +2 -0
  96. package/lib/offline/manifest_converter.js +2 -0
  97. package/lib/offline/offline_manifest_parser.js +10 -0
  98. package/lib/offline/storage.js +11 -7
  99. package/lib/player.js +993 -1502
  100. package/lib/polyfill/mediasource.js +22 -1
  101. package/lib/text/mp4_ttml_parser.js +2 -2
  102. package/lib/text/srt_text_parser.js +2 -2
  103. package/lib/text/stub_text_displayer.js +51 -0
  104. package/lib/text/text_engine.js +3 -2
  105. package/lib/text/ttml_text_parser.js +28 -5
  106. package/lib/text/ui_text_displayer.js +4 -0
  107. package/lib/text/vtt_text_parser.js +7 -2
  108. package/lib/transmuxer/aac_transmuxer.js +1 -1
  109. package/lib/transmuxer/ac3_transmuxer.js +1 -1
  110. package/lib/transmuxer/ec3_transmuxer.js +1 -1
  111. package/lib/transmuxer/h264.js +5 -4
  112. package/lib/transmuxer/h265.js +5 -4
  113. package/lib/transmuxer/mp3_transmuxer.js +1 -1
  114. package/lib/transmuxer/mpeg_ts_transmuxer.js +1 -1
  115. package/lib/transmuxer/mss_transmuxer.js +1 -1
  116. package/lib/transmuxer/ts_transmuxer.js +33 -13
  117. package/lib/util/buffer_utils.js +26 -4
  118. package/lib/util/content_steering_manager.js +358 -0
  119. package/lib/util/error.js +2 -6
  120. package/lib/util/fairplay_utils.js +1 -1
  121. package/lib/util/fake_event.js +5 -1
  122. package/lib/util/id3_utils.js +50 -1
  123. package/lib/util/manifest_parser_utils.js +12 -8
  124. package/lib/util/mp4_generator.js +2 -4
  125. package/lib/util/mutex.js +59 -0
  126. package/lib/util/object_utils.js +1 -1
  127. package/lib/util/periods.js +154 -179
  128. package/lib/util/platform.js +4 -3
  129. package/lib/util/player_configuration.js +35 -6
  130. package/lib/util/stream_utils.js +105 -98
  131. package/lib/util/ts_parser.js +124 -73
  132. package/lib/util/uint8array_utils.js +5 -1
  133. package/lib/util/xml_utils.js +5 -0
  134. package/maintained-branches.md +2 -2
  135. package/package.json +1 -1
  136. package/roadmap.md +15 -5
  137. package/shaka-player.uncompiled.js +0 -1
  138. package/test/abr/simple_abr_manager_unit.js +33 -33
  139. package/test/ads/ad_manager_unit.js +3 -2
  140. package/test/cast/cast_receiver_integration.js +3 -4
  141. package/test/cast/cast_utils_unit.js +2 -0
  142. package/test/cea/cea_decoder_unit.js +7 -0
  143. package/test/codec_switching/codec_switching_integration.js +2 -1
  144. package/test/dash/dash_parser_integration.js +2 -1
  145. package/test/dash/dash_parser_live_unit.js +0 -19
  146. package/test/dash/dash_parser_manifest_unit.js +494 -2
  147. package/test/dash/mpd_utils_unit.js +61 -30
  148. package/test/hls/hls_live_unit.js +12 -3
  149. package/test/hls/hls_parser_unit.js +377 -27
  150. package/test/hls/manifest_text_parser_unit.js +32 -99
  151. package/test/media/adaptation_set_criteria_unit.js +172 -21
  152. package/test/media/adaptation_set_unit.js +1 -0
  153. package/test/media/content_workarounds_unit.js +1 -1
  154. package/test/media/drm_engine_unit.js +3 -3
  155. package/test/media/media_source_engine_unit.js +1 -1
  156. package/test/media/play_rate_controller_unit.js +0 -48
  157. package/test/media/segment_index_unit.js +2 -1
  158. package/test/mss/mss_player_integration.js +3 -2
  159. package/test/net/networking_engine_unit.js +3 -3
  160. package/test/{media/manifest_parser_unit.js → net/networking_utils_unit.js} +2 -2
  161. package/test/offline/manifest_convert_unit.js +9 -0
  162. package/test/offline/offline_integration.js +2 -1
  163. package/test/offline/storage_integration.js +21 -9
  164. package/test/player_external.js +4 -2
  165. package/test/player_integration.js +15 -4
  166. package/test/player_load_graph_integration.js +47 -151
  167. package/test/player_src_equals_external.js +1 -0
  168. package/test/player_src_equals_integration.js +71 -4
  169. package/test/player_unit.js +80 -27
  170. package/test/test/util/fake_media_source_engine.js +5 -0
  171. package/test/test/util/fake_networking_engine.js +9 -1
  172. package/test/test/util/fake_segment_prefetch.js +3 -0
  173. package/test/test/util/manifest_generator.js +4 -0
  174. package/test/test/util/manifest_parser_util.js +14 -2
  175. package/test/test/util/offline_utils.js +1 -0
  176. package/test/test/util/simple_fakes.js +2 -2
  177. package/test/test/util/streaming_engine_util.js +3 -0
  178. package/test/test/util/test_scheme.js +6 -0
  179. package/test/test/util/ui_utils.js +4 -3
  180. package/test/text/mp4_ttml_parser_unit.js +4 -4
  181. package/test/text/srt_text_parser_unit.js +1 -1
  182. package/test/text/text_displayer_layout_unit.js +1 -1
  183. package/test/text/text_engine_unit.js +6 -0
  184. package/test/text/ttml_text_parser_unit.js +33 -2
  185. package/test/transmuxer/transmuxer_engine_integration.js +9 -0
  186. package/test/transmuxer/transmuxer_integration.js +33 -3
  187. package/test/ui/ad_ui_unit.js +2 -2
  188. package/test/ui/ui_customization_unit.js +17 -16
  189. package/test/ui/ui_integration.js +30 -20
  190. package/test/ui/ui_unit.js +25 -19
  191. package/test/util/buffer_utils_unit.js +1 -1
  192. package/test/util/content_steering_manager_unit.js +427 -0
  193. package/test/util/id3_utils_unit.js +52 -0
  194. package/test/util/stream_utils_unit.js +17 -113
  195. package/test/util/ts_parser_unit.js +3 -3
  196. package/third_party/closure-uri/uri.js +13 -1
  197. package/ui/audio_language_selection.js +9 -2
  198. package/ui/externs/ui.js +17 -2
  199. package/ui/language_utils.js +43 -8
  200. package/ui/less/range_elements.less +33 -0
  201. package/ui/locales/en.json +1 -0
  202. package/ui/locales/es-419.json +1 -0
  203. package/ui/locales/es.json +1 -0
  204. package/ui/locales/source.json +4 -0
  205. package/ui/localization.js +10 -0
  206. package/ui/remote_button.js +3 -1
  207. package/ui/resolution_selection.js +47 -10
  208. package/ui/seek_bar.js +296 -3
  209. package/ui/text_selection.js +2 -1
  210. package/ui/ui.js +6 -2
  211. package/lib/routing/node.js +0 -23
  212. package/lib/routing/payload.js +0 -47
  213. package/lib/routing/walker.js +0 -587
  214. package/test/routing/walker_unit.js +0 -505
package/ui/seek_bar.js CHANGED
@@ -8,12 +8,17 @@
8
8
  goog.provide('shaka.ui.SeekBar');
9
9
 
10
10
  goog.require('shaka.ads.AdManager');
11
+ goog.require('shaka.net.NetworkingEngine');
11
12
  goog.require('shaka.ui.Constants');
12
13
  goog.require('shaka.ui.Locales');
13
14
  goog.require('shaka.ui.Localization');
14
15
  goog.require('shaka.ui.RangeElement');
15
16
  goog.require('shaka.ui.Utils');
16
17
  goog.require('shaka.util.Dom');
18
+ goog.require('shaka.util.Error');
19
+ goog.require('shaka.util.EventManager');
20
+ goog.require('shaka.util.Mp4Parser');
21
+ goog.require('shaka.util.Networking');
17
22
  goog.require('shaka.util.Timer');
18
23
  goog.requireType('shaka.ui.Controls');
19
24
 
@@ -79,6 +84,19 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
79
84
  this.markAdBreaks_();
80
85
  });
81
86
 
87
+ /**
88
+ * @private {shaka.util.EventManager}
89
+ */
90
+ this.chaptersEventManager_ = new shaka.util.EventManager();
91
+
92
+
93
+ /** @private {!HTMLElement} */
94
+ this.chaptersContainer_ = shaka.util.Dom.createHTMLElement('div');
95
+ this.chaptersContainer_.id = 'shaka-player-ui-chapters-container';
96
+ this.container.appendChild(this.chaptersContainer_);
97
+
98
+ this.setupChapters_();
99
+
82
100
  /**
83
101
  * When user is scrubbing the seek bar - we should pause the video - see
84
102
  * https://github.com/google/shaka-player/pull/2898#issuecomment-705229215
@@ -108,6 +126,16 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
108
126
  this.thumbnailContainer_.appendChild(this.thumbnailTime_);
109
127
  this.container.appendChild(this.thumbnailContainer_);
110
128
 
129
+ /**
130
+ * @private {?shaka.extern.Thumbnail}
131
+ */
132
+ this.lastThumbnail_ = null;
133
+
134
+ /**
135
+ * @private {?shaka.net.NetworkingEngine.PendingRequest}
136
+ */
137
+ this.lastThumbnailPendingRequest_ = null;
138
+
111
139
  /**
112
140
  * True if the bar is moving due to touchscreen or keyboard events.
113
141
  *
@@ -159,6 +187,12 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
159
187
  this.player, 'unloading', () => {
160
188
  this.adCuePoints_ = [];
161
189
  this.onAdCuePointsChanged_();
190
+ if (this.lastThumbnailPendingRequest_) {
191
+ this.lastThumbnailPendingRequest_.abort();
192
+ this.lastThumbnailPendingRequest_ = null;
193
+ }
194
+ this.lastThumbnail_ = null;
195
+ this.hideThumbnail_();
162
196
  });
163
197
 
164
198
  this.eventManager.listen(this.bar, 'mousemove', (event) => {
@@ -204,6 +238,8 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
204
238
  this.adBreaksTimer_ = null;
205
239
  }
206
240
 
241
+ this.chaptersEventManager_.release();
242
+
207
243
  super.release();
208
244
  }
209
245
 
@@ -504,8 +540,52 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
504
540
  Math.max(0, pixelPosition - (width / 2)));
505
541
  this.thumbnailContainer_.style.left = leftPosition + 'px';
506
542
  this.thumbnailContainer_.style.visibility = 'visible';
507
- const uri = thumbnail.uris[0].split('#xywh=')[0];
508
- if (uri !== this.thumbnailImage_.src) {
543
+ let uri = thumbnail.uris[0].split('#xywh=')[0];
544
+ if (!this.lastThumbnail_ ||
545
+ uri !== this.lastThumbnail_.uris[0].split('#xywh=')[0] ||
546
+ thumbnail.segment.getStartByte() !=
547
+ this.lastThumbnail_.segment.getStartByte() ||
548
+ thumbnail.segment.getEndByte() !=
549
+ this.lastThumbnail_.segment.getEndByte()) {
550
+ this.lastThumbnail_ = thumbnail;
551
+ if (this.lastThumbnailPendingRequest_) {
552
+ this.lastThumbnailPendingRequest_.abort();
553
+ this.lastThumbnailPendingRequest_ = null;
554
+ }
555
+ if (thumbnailTrack.codecs == 'mjpg' || uri.startsWith('offline:')) {
556
+ this.thumbnailImage_.src = shaka.ui.SeekBar.Transparent_Image_;
557
+ try {
558
+ const requestType = shaka.net.NetworkingEngine.RequestType.SEGMENT;
559
+ const type =
560
+ shaka.net.NetworkingEngine.AdvancedRequestType.MEDIA_SEGMENT;
561
+ const request = shaka.util.Networking.createSegmentRequest(
562
+ thumbnail.segment.getUris(),
563
+ thumbnail.segment.getStartByte(),
564
+ thumbnail.segment.getEndByte(),
565
+ this.player.getConfiguration().streaming.retryParameters);
566
+ this.lastThumbnailPendingRequest_ = this.player.getNetworkingEngine()
567
+ .request(requestType, request, {type});
568
+ const response = await this.lastThumbnailPendingRequest_.promise;
569
+ this.lastThumbnailPendingRequest_ = null;
570
+ if (thumbnailTrack.codecs == 'mjpg') {
571
+ const parser = new shaka.util.Mp4Parser()
572
+ .box('mdat', shaka.util.Mp4Parser.allData((data) => {
573
+ const blob = new Blob([data], {type: 'image/jpeg'});
574
+ uri = URL.createObjectURL(blob);
575
+ }));
576
+ parser.parse(response.data, /* partialOkay= */ false);
577
+ } else {
578
+ const mimeType = thumbnailTrack.mimeType || 'image/jpeg';
579
+ const blob = new Blob([response.data], {type: mimeType});
580
+ uri = URL.createObjectURL(blob);
581
+ }
582
+ } catch (error) {
583
+ if (error.code == shaka.util.Error.Code.OPERATION_ABORTED) {
584
+ return;
585
+ }
586
+ throw error;
587
+ }
588
+ }
509
589
  try {
510
590
  this.thumbnailContainer_.removeChild(this.thumbnailImage_);
511
591
  } catch (e) {
@@ -516,6 +596,11 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
516
596
  this.thumbnailImage_.id = 'shaka-player-ui-thumbnail-image';
517
597
  this.thumbnailImage_.draggable = false;
518
598
  this.thumbnailImage_.src = uri;
599
+ this.thumbnailImage_.onload = () => {
600
+ if (uri.startsWith('blob:')) {
601
+ URL.revokeObjectURL(uri);
602
+ }
603
+ };
519
604
  this.thumbnailContainer_.insertBefore(this.thumbnailImage_,
520
605
  this.thumbnailContainer_.firstChild);
521
606
  }
@@ -571,7 +656,10 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
571
656
  return bestOptions[0];
572
657
  }
573
658
  }
574
- return imageTracks[0];
659
+ const mjpgTrack = imageTracks.find((track) => {
660
+ return track.mimeType == 'application/mp4' && track.codecs == 'mjpg';
661
+ });
662
+ return mjpgTrack || imageTracks[0];
575
663
  }
576
664
 
577
665
 
@@ -605,9 +693,214 @@ shaka.ui.SeekBar = class extends shaka.ui.RangeElement {
605
693
  return minutes + ':' + seconds;
606
694
  }
607
695
  }
696
+
697
+ /**
698
+ * Sets up the chapter element creator and change handling.
699
+ * @private
700
+ */
701
+ setupChapters_() {
702
+ let language = 'und';
703
+ /** @type {!Array<shaka.extern.Chapter>} */
704
+ let chapters = [];
705
+
706
+ /**
707
+ * Does a value compare on chapters.
708
+ * @param {shaka.extern.Chapter} a
709
+ * @param {shaka.extern.Chapter} b
710
+ * @return {boolean}
711
+ */
712
+ const chaptersEqual = (a, b) => {
713
+ return (!a && !b) || (a.id === b.id && a.title === b.title &&
714
+ a.startTime === b.startTime && a.endTime === b.endTime);
715
+ };
716
+
717
+ /** @type {function(): void} */
718
+ const handleChapterTrackChange = () => {
719
+ let nextLanguage = 'und';
720
+ /** @type {!Array<shaka.extern.Chapter>} */
721
+ let nextChapters = [];
722
+
723
+ const currentLocales = this.localization.getCurrentLocales();
724
+ for (const locale of Array.from(currentLocales)) {
725
+ nextLanguage = locale;
726
+ nextChapters = this.player.getChapters(nextLanguage);
727
+ if (nextChapters.length) {
728
+ break;
729
+ }
730
+ }
731
+ if (!nextChapters.length) {
732
+ nextLanguage = 'und';
733
+ nextChapters = this.player.getChapters(nextLanguage);
734
+ }
735
+
736
+ const languageChanged = nextLanguage !== language;
737
+ const chaptersChanged = chapters.length !== nextChapters.length ||
738
+ !chapters.some((c, idx) => {
739
+ const n = nextChapters.at(idx);
740
+ return chaptersEqual(c, n) ||
741
+ nextChapters.some((n) => chaptersEqual(c, n));
742
+ });
743
+
744
+ language = nextLanguage;
745
+ chapters = nextChapters;
746
+ if (!nextChapters.length) {
747
+ this.deletePreviousChapters_();
748
+ } else if (languageChanged || chaptersChanged) {
749
+ this.createChapterElements_(this.container, chapters);
750
+ }
751
+ };
752
+
753
+ handleChapterTrackChange();
754
+
755
+ this.eventManager.listen(
756
+ this.player, 'unloading', () => {
757
+ this.deletePreviousChapters_();
758
+ language = 'und';
759
+ chapters = [];
760
+ });
761
+
762
+ this.eventManager.listen(
763
+ this.player, 'trackschanged', handleChapterTrackChange);
764
+
765
+ this.eventManager.listen(
766
+ this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
767
+ handleChapterTrackChange();
768
+ });
769
+
770
+ this.eventManager.listen(
771
+ this.localization, shaka.ui.Localization.LOCALE_CHANGED, () => {
772
+ handleChapterTrackChange();
773
+ });
774
+ }
775
+
776
+ /**
777
+ * Builds and inserts ChaptersElement into dom container.
778
+ * @param {!HTMLElement} container
779
+ * @param {!Array<shaka.extern.Chapter>} chapterTracks
780
+ * @private
781
+ */
782
+ createChapterElements_(container, chapterTracks) {
783
+ this.deletePreviousChapters_();
784
+
785
+ const hiddenClass = 'shaka-hidden';
786
+
787
+ /** @type {{start: number, end: number}} */
788
+ const seekRange = this.player.seekRange();
789
+
790
+ /**
791
+ * @type {!Array<{
792
+ * start: number,
793
+ * end: number,
794
+ * size: number,
795
+ * title: string,
796
+ * id: string
797
+ * }>}
798
+ * */
799
+ const chapters = [];
800
+
801
+ for (const c of chapterTracks) {
802
+ if (c.startTime >= seekRange.end) {
803
+ continue;
804
+ }
805
+ const start = c.startTime > seekRange.start ?
806
+ c.startTime : seekRange.start;
807
+ const end = c.endTime < seekRange.end ?
808
+ c.endTime : seekRange.end;
809
+ const size = (end-start);
810
+ chapters.push({start, end, size, title: c.title, id: c.id});
811
+ }
812
+
813
+ if (chapters.length < 2) {
814
+ return;
815
+ }
816
+
817
+ const totalSize = chapters.reduce((t, c) => {
818
+ t += c.size;
819
+ return t;
820
+ }, 0);
821
+
822
+ /**
823
+ * @type {!Array<{
824
+ * start: number,
825
+ * end: number,
826
+ * el: HTMLElement
827
+ * }>}
828
+ * */
829
+ const chapterElMap = [];
830
+
831
+ for (const c of chapters) {
832
+ /** @type {!HTMLElement} */
833
+ const chapterEl = shaka.util.Dom.createHTMLElement('div');
834
+ chapterEl.classList.add('shaka-chapter');
835
+ chapterEl.style.width = `${c.size * 100 / totalSize}%`;
836
+
837
+ this.chaptersContainer_.appendChild(chapterEl);
838
+
839
+ /** @type {!HTMLElement} */
840
+ const chapterMarker = shaka.util.Dom.createHTMLElement('div');
841
+ chapterMarker.style.borderColor =
842
+ this.config_.seekBarColors.chapterMarks;
843
+ chapterEl.appendChild(chapterMarker);
844
+
845
+ /** @type {!HTMLElement} */
846
+ const chapterLabel = shaka.util.Dom.createHTMLElement('p');
847
+ chapterLabel.classList.add('shaka-chapter-label', hiddenClass);
848
+ chapterLabel.style.color =
849
+ this.config_.seekBarColors.chapterLabels;
850
+ chapterLabel.innerText = c.title;
851
+ chapterEl.appendChild(chapterLabel);
852
+
853
+ chapterElMap.push(
854
+ {start: c.start, end: c.end, el: chapterLabel});
855
+ }
856
+
857
+ // Add chapter event listeners
858
+ this.chaptersEventManager_.listen(this.bar, 'pointermove', (e) => {
859
+ if (!e.target) {
860
+ return;
861
+ }
862
+ const target = /** @type {HTMLElement} */(e.target);
863
+
864
+ const screenXDiff = e.offsetX / target.clientWidth;
865
+ const rangeMax = parseInt(target.getAttribute('max'), 10);
866
+ const hoverVal = screenXDiff * rangeMax;
867
+
868
+ for (const c of chapterElMap) {
869
+ const hidden = c.el.classList.contains(hiddenClass);
870
+ const inChapter = c.start <= hoverVal && hoverVal < c.end;
871
+ if (inChapter === hidden) {
872
+ c.el.classList.toggle(hiddenClass);
873
+ }
874
+ }
875
+ }, {passive: true});
876
+
877
+ this.chaptersEventManager_.listen(this.bar, 'pointerout', () => {
878
+ for (const c of chapterElMap) {
879
+ if (!c.el.classList.contains(hiddenClass)) {
880
+ c.el.classList.add(hiddenClass);
881
+ }
882
+ }
883
+ }, {passive: true});
884
+ }
885
+
886
+ /**
887
+ * @private
888
+ */
889
+ deletePreviousChapters_() {
890
+ this.chaptersEventManager_.removeAll();
891
+ shaka.util.Dom.removeAllChildren(this.chaptersContainer_);
892
+ }
608
893
  };
609
894
 
610
895
 
896
+ /**
897
+ * @const {string}
898
+ * @private
899
+ */
900
+ shaka.ui.SeekBar.Transparent_Image_ =
901
+ 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg"/>';
902
+
903
+
611
904
  /**
612
905
  * @implements {shaka.extern.IUISeekBar.Factory}
613
906
  * @export
@@ -135,7 +135,8 @@ shaka.ui.TextSelection = class extends shaka.ui.SettingsMenu {
135
135
  this.player.isTextTrackVisible(),
136
136
  this.currentSelection,
137
137
  this.localization,
138
- this.controls.getConfig().trackLabelFormat);
138
+ this.controls.getConfig().trackLabelFormat,
139
+ this.controls.getConfig().showAudioChannelCountVariants);
139
140
 
140
141
  // Add the Off button
141
142
  const offButton = shaka.util.Dom.createButton();
package/ui/ui.js CHANGED
@@ -229,6 +229,8 @@ shaka.ui.Overlay = class {
229
229
  buffered: 'rgba(255, 255, 255, 0.54)',
230
230
  played: 'rgb(255, 255, 255)',
231
231
  adBreaks: 'rgb(255, 204, 0)',
232
+ chapterMarks: 'rgb(27, 27, 27)',
233
+ chapterLabels: 'rgb(255, 255, 255)',
232
234
  },
233
235
  volumeBarColors: {
234
236
  base: 'rgba(255, 255, 255, 0.54)',
@@ -246,6 +248,7 @@ shaka.ui.Overlay = class {
246
248
  keyboardLargeSeekDistance: 60,
247
249
  fullScreenElement: this.videoContainer_,
248
250
  preferDocumentPictureInPicture: true,
251
+ showAudioChannelCountVariants: true,
249
252
  };
250
253
 
251
254
  // eslint-disable-next-line no-restricted-syntax
@@ -425,8 +428,7 @@ shaka.ui.Overlay = class {
425
428
  */
426
429
  static async setupUIandAutoLoad_(container, video, canvas) {
427
430
  // Create the UI
428
- const player = new shaka.Player(
429
- shaka.util.Dom.asHTMLMediaElement(video));
431
+ const player = new shaka.Player();
430
432
  const ui = new shaka.ui.Overlay(player,
431
433
  shaka.util.Dom.asHTMLElement(container),
432
434
  shaka.util.Dom.asHTMLMediaElement(video));
@@ -489,6 +491,8 @@ shaka.ui.Overlay = class {
489
491
  shaka.log.error('Error auto-loading asset', e);
490
492
  }
491
493
  }
494
+
495
+ await player.attach(shaka.util.Dom.asHTMLMediaElement(video));
492
496
  }
493
497
  };
494
498
 
@@ -1,23 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- goog.provide('shaka.routing.Node');
8
-
9
-
10
- /**
11
- * @typedef {{
12
- * name: string
13
- * }}
14
- *
15
- * @description
16
- * A node is the one of the two fundamental units used to build graphs. It
17
- * represents the position within a graph.
18
- *
19
- * @property {string} name
20
- * A human-readable name for this node. While this should not be used in
21
- * production, the name helps identify nodes when debugging.
22
- */
23
- shaka.routing.Node;
@@ -1,47 +0,0 @@
1
- /*! @license
2
- * Shaka Player
3
- * Copyright 2016 Google LLC
4
- * SPDX-License-Identifier: Apache-2.0
5
- */
6
-
7
- goog.provide('shaka.routing.Payload');
8
-
9
-
10
- /**
11
- * @typedef {{
12
- * mediaElement: HTMLMediaElement,
13
- * mimeType: ?string,
14
- * startTime: ?number,
15
- * startTimeOfLoad: number,
16
- * uri: ?string,
17
- * keepAdManager: boolean
18
- * }}
19
- *
20
- * @description
21
- * The payload is the information to "deliver" to our destination. When
22
- * moving from node-to-node, the payload may be modified.
23
- *
24
- * @property {HTMLMediaElement} mediaElement
25
- * The media element that we are or will be using.
26
- *
27
- * @property {?string} mimeType
28
- * The mime type of the content that we will parse. This will be used when
29
- * picking which parser to use.
30
- *
31
- * @property {?number} startTime
32
- * The time (in seconds) where playback should start. When |null| we will
33
- * use the content's default start time (0 for VOD and live edge for LIVE).
34
- *
35
- * @property {number} startTimeOfLoad
36
- * The time (in seconds) of when a load request is created. This is used to
37
- * track the latency between when the call to |Player.load| and the start
38
- * of playback. When the payload is not for a load request, this should be
39
- * NaN.
40
- *
41
- * @property {?string} uri
42
- * The address of the content that will be loaded.
43
- *
44
- * @property {boolean} keepAdManager
45
- * Indicates if the adManager shouldn't destroyed.
46
- */
47
- shaka.routing.Payload;