shaka-player 3.1.4 → 3.3.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/.github/ISSUE_TEMPLATE/feature_request.md +1 -1
  3. package/.github/ISSUE_TEMPLATE/question.md +1 -1
  4. package/AUTHORS +6 -5
  5. package/CHANGELOG.md +363 -0
  6. package/CONTRIBUTORS +4 -2
  7. package/README.md +4 -4
  8. package/build/types/core +3 -0
  9. package/build/types/offline +1 -0
  10. package/build/types/polyfill +2 -0
  11. package/build/types/ui +2 -0
  12. package/demo/common/asset.js +9 -7
  13. package/demo/common/assets.js +28 -1
  14. package/demo/common/message_ids.js +15 -2
  15. package/demo/config.js +35 -2
  16. package/demo/index.html +1 -1
  17. package/demo/locales/en.json +14 -1
  18. package/demo/locales/source.json +56 -4
  19. package/demo/main.js +2 -1
  20. package/dist/controls.css +26 -2
  21. package/dist/controls.css.map +1 -1
  22. package/dist/demo.compiled.debug.js +24 -21
  23. package/dist/demo.compiled.debug.map +3 -3
  24. package/dist/demo.compiled.js +24 -21
  25. package/dist/demo.compiled.map +3 -3
  26. package/dist/deps.js +33 -25
  27. package/dist/locales.js +31 -29
  28. package/dist/receiver.compiled.debug.js +14 -12
  29. package/dist/receiver.compiled.debug.map +3 -3
  30. package/dist/receiver.compiled.js +14 -12
  31. package/dist/receiver.compiled.map +3 -3
  32. package/dist/shaka-player.compiled.d.ts +258 -20
  33. package/dist/shaka-player.compiled.debug.d.ts +258 -20
  34. package/dist/shaka-player.compiled.debug.externs.js +1005 -695
  35. package/dist/shaka-player.compiled.debug.js +720 -640
  36. package/dist/shaka-player.compiled.debug.map +4 -4
  37. package/dist/shaka-player.compiled.externs.js +1005 -695
  38. package/dist/shaka-player.compiled.js +850 -817
  39. package/dist/shaka-player.compiled.map +4 -4
  40. package/dist/shaka-player.ui.d.ts +274 -21
  41. package/dist/shaka-player.ui.debug.d.ts +274 -21
  42. package/dist/shaka-player.ui.debug.externs.js +766 -429
  43. package/dist/shaka-player.ui.debug.js +863 -765
  44. package/dist/shaka-player.ui.debug.map +4 -4
  45. package/dist/shaka-player.ui.externs.js +766 -429
  46. package/dist/shaka-player.ui.js +1042 -996
  47. package/dist/shaka-player.ui.map +4 -4
  48. package/docs/design/bg-fetch-after.gv +29 -0
  49. package/docs/design/bg-fetch-after.gv.png +0 -0
  50. package/docs/design/bg-fetch-before.gv +18 -0
  51. package/docs/design/bg-fetch-before.gv.png +0 -0
  52. package/docs/design/bg-fetch.md +134 -0
  53. package/docs/tutorials/blob-url.md +15 -0
  54. package/docs/tutorials/index.json +1 -0
  55. package/docs/tutorials/ui-customization.md +66 -0
  56. package/docs/tutorials/ui.md +5 -5
  57. package/externs/aria.js +6 -0
  58. package/externs/ima.js +3 -0
  59. package/externs/shaka/ads.js +29 -1
  60. package/externs/shaka/manifest.js +18 -2
  61. package/externs/shaka/manifest_parser.js +10 -1
  62. package/externs/shaka/net.js +20 -4
  63. package/externs/shaka/offline.js +36 -2
  64. package/externs/shaka/player.js +182 -13
  65. package/externs/shaka/text.js +24 -10
  66. package/externs/texttrack.js +3 -0
  67. package/externs/webcrypto.js +18 -0
  68. package/lib/abr/ewma.js +14 -0
  69. package/lib/abr/ewma_bandwidth_estimator.js +16 -2
  70. package/lib/abr/simple_abr_manager.js +6 -0
  71. package/lib/ads/ad_manager.js +16 -15
  72. package/lib/ads/client_side_ad.js +8 -0
  73. package/lib/ads/client_side_ad_manager.js +14 -6
  74. package/lib/ads/server_side_ad.js +7 -0
  75. package/lib/ads/server_side_ad_manager.js +19 -2
  76. package/lib/cast/cast_proxy.js +8 -0
  77. package/lib/cast/cast_utils.js +7 -1
  78. package/lib/cea/cea608_data_channel.js +56 -56
  79. package/lib/cea/cea608_memory.js +33 -33
  80. package/lib/cea/cea708_service.js +43 -43
  81. package/lib/cea/cea708_window.js +38 -38
  82. package/lib/cea/cea_decoder.js +13 -14
  83. package/lib/cea/cea_utils.js +23 -23
  84. package/lib/cea/dtvcc_packet_builder.js +7 -7
  85. package/lib/cea/i_caption_decoder.js +2 -3
  86. package/lib/cea/i_cea_parser.js +2 -2
  87. package/lib/cea/mp4_cea_parser.js +6 -6
  88. package/lib/dash/dash_parser.js +53 -14
  89. package/lib/dash/segment_base.js +25 -1
  90. package/lib/dash/segment_list.js +18 -9
  91. package/lib/dash/segment_template.js +23 -10
  92. package/lib/hls/hls_parser.js +210 -30
  93. package/lib/media/closed_caption_parser.js +1 -2
  94. package/lib/media/drm_engine.js +162 -192
  95. package/lib/media/quality_observer.js +291 -0
  96. package/lib/media/segment_index.js +9 -1
  97. package/lib/media/segment_reference.js +37 -5
  98. package/lib/media/streaming_engine.js +48 -10
  99. package/lib/net/http_fetch_plugin.js +31 -11
  100. package/lib/net/http_plugin_utils.js +1 -0
  101. package/lib/net/http_xhr_plugin.js +40 -14
  102. package/lib/net/networking_engine.js +82 -18
  103. package/lib/offline/download_info.js +68 -0
  104. package/lib/offline/download_manager.js +14 -7
  105. package/lib/offline/indexeddb/base_storage_cell.js +35 -0
  106. package/lib/offline/indexeddb/storage_mechanism.js +1 -1
  107. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  108. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  109. package/lib/offline/indexeddb/v5_storage_cell.js +5 -0
  110. package/lib/offline/manifest_converter.js +3 -1
  111. package/lib/offline/storage.js +404 -297
  112. package/lib/offline/stored_content_utils.js +2 -0
  113. package/lib/player.js +622 -153
  114. package/lib/polyfill/aria.js +82 -0
  115. package/lib/polyfill/random_uuid.js +52 -0
  116. package/lib/routing/walker.js +2 -3
  117. package/lib/text/cue.js +12 -0
  118. package/lib/text/srt_text_parser.js +4 -4
  119. package/lib/text/text_engine.js +2 -2
  120. package/lib/text/ttml_text_parser.js +25 -2
  121. package/lib/text/ui_text_displayer.js +2 -2
  122. package/lib/text/vtt_text_parser.js +2 -2
  123. package/lib/text/web_vtt_generator.js +55 -12
  124. package/lib/util/cmcd_manager.js +826 -0
  125. package/lib/util/error.js +12 -0
  126. package/lib/util/language_utils.js +12 -0
  127. package/lib/util/manifest_parser_utils.js +1 -0
  128. package/lib/util/mp4_box_parsers.js +20 -20
  129. package/lib/util/multi_map.js +8 -0
  130. package/lib/util/mutex.js +52 -0
  131. package/lib/util/periods.js +98 -64
  132. package/lib/util/player_configuration.js +31 -1
  133. package/lib/util/stream_utils.js +140 -85
  134. package/lib/util/xml_utils.js +31 -12
  135. package/package.json +1 -1
  136. package/roadmap.md +24 -22
  137. package/shaka-player.uncompiled.js +4 -0
  138. package/test/cast/cast_utils_unit.js +1 -0
  139. package/test/cea/cea608_memory_unit.js +1 -1
  140. package/test/cea/cea708_service_unit.js +8 -8
  141. package/test/cea/cea708_window_unit.js +6 -6
  142. package/test/cea/cea_decoder_unit.js +1 -1
  143. package/test/cea/dtvcc_packet_builder_unit.js +2 -2
  144. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  145. package/test/dash/dash_parser_live_unit.js +101 -1
  146. package/test/dash/dash_parser_manifest_unit.js +78 -2
  147. package/test/dash/dash_parser_segment_base_unit.js +2 -0
  148. package/test/dash/dash_parser_segment_list_unit.js +2 -1
  149. package/test/dash/dash_parser_segment_template_unit.js +2 -1
  150. package/test/hls/hls_live_unit.js +2 -0
  151. package/test/hls/hls_parser_unit.js +252 -0
  152. package/test/media/drm_engine_integration.js +86 -12
  153. package/test/media/drm_engine_unit.js +310 -450
  154. package/test/media/quality_observer_unit.js +139 -0
  155. package/test/media/segment_reference_unit.js +16 -1
  156. package/test/media/streaming_engine_integration.js +2 -1
  157. package/test/media/streaming_engine_unit.js +2 -0
  158. package/test/net/http_plugin_unit.js +20 -15
  159. package/test/offline/manifest_convert_unit.js +2 -0
  160. package/test/offline/storage_integration.js +117 -23
  161. package/test/player_integration.js +151 -0
  162. package/test/player_src_equals_integration.js +52 -0
  163. package/test/player_unit.js +11 -33
  164. package/test/test/assets/chapters.srt +11 -0
  165. package/test/test/assets/chapters.vtt +10 -0
  166. package/test/test/util/cea_utils.js +12 -12
  167. package/test/test/util/dash_parser_util.js +4 -0
  168. package/test/test/util/fake_ad.js +7 -0
  169. package/test/test/util/fake_ad_manager.js +7 -0
  170. package/test/test/util/fake_drm_engine.js +9 -2
  171. package/test/test/util/manifest_generator.js +5 -2
  172. package/test/test/util/manifest_parser_util.js +3 -1
  173. package/test/test/util/test_scheme.js +14 -1
  174. package/test/text/ttml_text_parser_unit.js +47 -0
  175. package/test/text/web_vtt_generator_unit.js +81 -7
  176. package/test/ui/ui_unit.js +250 -0
  177. package/test/util/cmcd_manager_unit.js +277 -0
  178. package/test/util/stream_utils_unit.js +118 -10
  179. package/ui/airplay_button.js +2 -1
  180. package/ui/audio_language_selection.js +9 -5
  181. package/ui/cast_button.js +5 -6
  182. package/ui/constants.js +0 -3
  183. package/ui/context_menu.js +109 -0
  184. package/ui/controls.js +41 -7
  185. package/ui/controls.less +1 -0
  186. package/ui/enums.js +4 -0
  187. package/ui/externs/ui.js +28 -1
  188. package/ui/fast_forward_button.js +16 -8
  189. package/ui/fullscreen_button.js +2 -3
  190. package/ui/language_utils.js +1 -1
  191. package/ui/less/buttons.less +0 -4
  192. package/ui/less/containers.less +74 -0
  193. package/ui/less/overflow_menu.less +0 -10
  194. package/ui/less/tooltip.less +97 -0
  195. package/ui/locales/en.json +1 -0
  196. package/ui/locales/source.json +4 -0
  197. package/ui/loop_button.js +6 -3
  198. package/ui/mute_button.js +3 -4
  199. package/ui/overflow_menu.js +7 -28
  200. package/ui/pip_button.js +10 -7
  201. package/ui/play_button.js +2 -2
  202. package/ui/playback_rate_selection.js +11 -15
  203. package/ui/presentation_time.js +1 -3
  204. package/ui/resolution_selection.js +11 -7
  205. package/ui/rewind_button.js +17 -9
  206. package/ui/seek_bar.js +6 -6
  207. package/ui/settings_menu.js +36 -4
  208. package/ui/small_play_button.js +1 -0
  209. package/ui/spacer.js +1 -1
  210. package/ui/statistics_button.js +253 -0
  211. package/ui/text_selection.js +19 -15
  212. package/ui/ui.js +30 -0
  213. package/ui/ui_utils.js +1 -1
  214. package/ui/volume_bar.js +2 -4
@@ -0,0 +1,82 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+
7
+ goog.provide('shaka.polyfill.Aria');
8
+
9
+ goog.require('shaka.log');
10
+ goog.require('shaka.polyfill');
11
+
12
+ /**
13
+ * @summary A polyfill to add support for the ARIAMixin interface mixin, for
14
+ * browsers that do not implement it (e.g. Firefox).
15
+ * Note that IE also does not support ARIAMixin, but this polyfill does not work
16
+ * for that platform, as it relies on getters and setters.
17
+ * @see https://w3c.github.io/aria/#ARIAMixin
18
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/Element
19
+ * @export
20
+ */
21
+ shaka.polyfill.Aria = class {
22
+ /**
23
+ * Install the polyfill if needed.
24
+ * @export
25
+ */
26
+ static install() {
27
+ // eslint-disable-next-line no-restricted-syntax
28
+ if (Object.getOwnPropertyDescriptor(Element.prototype, 'ariaHidden')) {
29
+ shaka.log.info('Using native ARIAMixin interface.');
30
+ return;
31
+ }
32
+ shaka.log.info('ARIAMixin interface not detected. Installing polyfill.');
33
+
34
+ // Define a list of all of the ARIAMixin properties that we have externs
35
+ // for.
36
+ const attributes = [
37
+ 'ariaHidden',
38
+ 'ariaLabel',
39
+ 'ariaPressed',
40
+ 'ariaSelected',
41
+ ];
42
+
43
+ // Add each attribute, one by one.
44
+ for (const attribute of attributes) {
45
+ shaka.polyfill.Aria.addARIAMixinAttribute_(attribute);
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Adds an attribute with the given name.
51
+ * @param {string} name The name of the attribute, in camelCase.
52
+ * @private
53
+ */
54
+ static addARIAMixinAttribute_(name) {
55
+ const baseName = name.toLowerCase().replace(/^aria/, '');
56
+ // NOTE: All the attributes listed in the method above begin with "aria".
57
+ // However, to add extra protection against the possibility of XSS attacks
58
+ // through this method, this enforces "aria-" at the beginning of the
59
+ // snake-case name, even if somehow "aria" were missing from the input.
60
+ const snakeCaseName = `aria-${baseName}`;
61
+
62
+ /* eslint-disable no-restricted-syntax */
63
+ Object.defineProperty(Element.prototype, name, {
64
+ get() {
65
+ const element = /** @type {!Element} */ (this);
66
+ return element.getAttribute(snakeCaseName);
67
+ },
68
+ set(value) {
69
+ const element = /** @type {!Element} */ (this);
70
+ if (value == null || value == undefined) {
71
+ element.removeAttribute(snakeCaseName);
72
+ } else {
73
+ element.setAttribute(snakeCaseName, value);
74
+ }
75
+ },
76
+ });
77
+ /* eslint-enable no-restricted-syntax */
78
+ }
79
+ };
80
+
81
+
82
+ shaka.polyfill.register(shaka.polyfill.Aria.install);
@@ -0,0 +1,52 @@
1
+ /*! @license
2
+ * Shaka Player
3
+ * Copyright 2016 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ goog.provide('shaka.polyfill.RandomUUID');
7
+
8
+ goog.require('shaka.log');
9
+ goog.require('shaka.polyfill');
10
+
11
+ /**
12
+ * @summary A polyfill to provide window.crypto.randomUUID in all browsers.
13
+ * @export
14
+ */
15
+ shaka.polyfill.RandomUUID = class {
16
+ /**
17
+ * Install the polyfill if needed.
18
+ * @export
19
+ */
20
+ static install() {
21
+ shaka.log.debug('randomUUID.install');
22
+
23
+ if (!window.crypto) {
24
+ // See: https://caniuse.com/cryptography
25
+ shaka.log.debug(
26
+ 'window.crypto must be available to install randomUUID polyfill.');
27
+ return;
28
+ }
29
+
30
+ if ('randomUUID' in window.crypto) {
31
+ shaka.log.debug(
32
+ 'RandomUUID: Native window.crypto.randomUUID() support found.');
33
+ return;
34
+ }
35
+
36
+ window.crypto.randomUUID = shaka.polyfill.RandomUUID.randomUUID_;
37
+ }
38
+
39
+ /**
40
+ * @return {string}
41
+ * @private
42
+ */
43
+ static randomUUID_() {
44
+ const url = URL.createObjectURL(new Blob());
45
+ const uuid = url.toString();
46
+ URL.revokeObjectURL(url);
47
+ return uuid.substr(uuid.lastIndexOf('/') + 1);
48
+ }
49
+ };
50
+
51
+
52
+ shaka.polyfill.register(shaka.polyfill.RandomUUID.install);
@@ -5,7 +5,6 @@
5
5
  */
6
6
 
7
7
  goog.provide('shaka.routing.Walker');
8
- goog.provide('shaka.routing.Walker.Implementation');
9
8
 
10
9
  goog.require('goog.asserts');
11
10
  goog.require('shaka.routing.Node');
@@ -81,7 +80,7 @@ shaka.routing.Walker = class {
81
80
  * new work is added (and this is not null) it can be resolved. The only
82
81
  * time when this should be non-null is when we are waiting for more work.
83
82
  *
84
- * @private {shaka.util.PublicPromise}
83
+ * @private {?shaka.util.PublicPromise}
85
84
  */
86
85
  this.waitForWork_ = null;
87
86
 
@@ -91,7 +90,7 @@ shaka.routing.Walker = class {
91
90
  /** @private {?shaka.routing.Walker.ActiveRoute_} */
92
91
  this.currentRoute_ = null;
93
92
 
94
- /** @private {shaka.util.AbortableOperation} */
93
+ /** @private {?shaka.util.AbortableOperation} */
95
94
  this.currentStep_ = null;
96
95
 
97
96
  /**
package/lib/text/cue.js CHANGED
@@ -144,6 +144,18 @@ shaka.text.Cue = class {
144
144
  */
145
145
  this.border = '';
146
146
 
147
+ /**
148
+ * @override
149
+ * @exportInterface
150
+ */
151
+ this.textStrokeColor = '';
152
+
153
+ /**
154
+ * @override
155
+ * @exportInterface
156
+ */
157
+ this.textStrokeWidth = '';
158
+
147
159
  /**
148
160
  * @override
149
161
  * @exportInterface
@@ -57,8 +57,8 @@ shaka.text.SrtTextParser = class {
57
57
  /**
58
58
  * Convert a SRT format to WebVTT
59
59
  *
60
- * @param {!string} data
61
- * @return {!string}
60
+ * @param {string} data
61
+ * @return {string}
62
62
  * @export
63
63
  */
64
64
  static srt2webvtt(data) {
@@ -87,8 +87,8 @@ shaka.text.SrtTextParser = class {
87
87
  /**
88
88
  * Convert a SRT cue into WebVTT cue
89
89
  *
90
- * @param {!string} caption
91
- * @return {!string}
90
+ * @param {string} caption
91
+ * @return {string}
92
92
  * @private
93
93
  */
94
94
  static convertSrtCue_(caption) {
@@ -12,7 +12,7 @@ goog.require('shaka.util.BufferUtils');
12
12
  goog.require('shaka.util.Functional');
13
13
  goog.require('shaka.util.IDestroyable');
14
14
  goog.require('shaka.util.MimeUtils');
15
- goog.requireType('shaka.cea.ICaptionDecoder.ClosedCaption');
15
+ goog.requireType('shaka.cea.ICaptionDecoder');
16
16
 
17
17
 
18
18
  // TODO: revisit this when Closure Compiler supports partially-exported classes.
@@ -24,7 +24,7 @@ goog.requireType('shaka.cea.ICaptionDecoder.ClosedCaption');
24
24
  shaka.text.TextEngine = class {
25
25
  /** @param {shaka.extern.TextDisplayer} displayer */
26
26
  constructor(displayer) {
27
- /** @private {shaka.extern.TextParser} */
27
+ /** @private {?shaka.extern.TextParser} */
28
28
  this.parser_ = null;
29
29
 
30
30
  /** @private {shaka.extern.TextDisplayer} */
@@ -531,7 +531,6 @@ shaka.text.TtmlTextParser = class {
531
531
 
532
532
  const color = TtmlTextParser.getStyleAttribute_(
533
533
  cueElement, region, styles, 'color', shouldInheritRegionStyles);
534
-
535
534
  if (color) {
536
535
  cue.color = color;
537
536
  }
@@ -584,7 +583,6 @@ shaka.text.TtmlTextParser = class {
584
583
 
585
584
  const fontSize = TtmlTextParser.getStyleAttribute_(
586
585
  cueElement, region, styles, 'fontSize', shouldInheritRegionStyles);
587
-
588
586
  if (fontSize) {
589
587
  const isValidFontSizeUnit =
590
588
  fontSize.match(TtmlTextParser.unitValues_) ||
@@ -622,6 +620,31 @@ shaka.text.TtmlTextParser = class {
622
620
  }
623
621
  }
624
622
 
623
+ const textOutline = TtmlTextParser.getStyleAttribute_(
624
+ cueElement, region, styles, 'textOutline', shouldInheritRegionStyles);
625
+ if (textOutline) {
626
+ // tts:textOutline isn't natively supported by browsers, but it can be
627
+ // mostly replicated using the non-standard -webkit-text-stroke-width and
628
+ // -webkit-text-stroke-color properties.
629
+ const split = textOutline.split(' ');
630
+ if (split[0].match(TtmlTextParser.unitValues_)) {
631
+ // There is no defined color, so default to the text color.
632
+ cue.textStrokeColor = cue.color;
633
+ } else {
634
+ cue.textStrokeColor = split[0];
635
+ split.shift();
636
+ }
637
+ if (split[0] && split[0].match(TtmlTextParser.unitValues_)) {
638
+ cue.textStrokeWidth = split[0];
639
+ } else {
640
+ // If there is no width, or the width is not a number, don't draw a
641
+ // border.
642
+ cue.textStrokeColor = '';
643
+ }
644
+ // There is an optional blur radius also, but we have no way of
645
+ // replicating that, so ignore it.
646
+ }
647
+
625
648
  const letterSpacing = TtmlTextParser.getStyleAttribute_(
626
649
  cueElement, region, styles, 'letterSpacing', shouldInheritRegionStyles);
627
650
  if (letterSpacing && letterSpacing.match(TtmlTextParser.unitValues_)) {
@@ -403,8 +403,8 @@ shaka.text.UITextDisplayer = class {
403
403
  return nonBreakingSpace.repeat(match.length);
404
404
  });
405
405
 
406
- style.backgroundColor = cue.backgroundColor;
407
- style.border = cue.border;
406
+ style.webkitTextStrokeColor = cue.textStrokeColor;
407
+ style.webkitTextStrokeWidth = cue.textStrokeWidth;
408
408
  style.color = cue.color;
409
409
  style.direction = cue.direction;
410
410
  style.opacity = cue.opacity;
@@ -464,8 +464,8 @@ shaka.text.VttTextParser = class {
464
464
  }
465
465
 
466
466
  /**
467
- * @param {!string} value
468
- * @param {!string} defaultValue
467
+ * @param {string} value
468
+ * @param {string} defaultValue
469
469
  * @private
470
470
  */
471
471
  static getOrDefault_(value, defaultValue) {
@@ -17,9 +17,10 @@ goog.require('shaka.text.Cue');
17
17
  shaka.text.WebVttGenerator = class {
18
18
  /**
19
19
  * @param {!Array.<!shaka.text.Cue>} cues
20
+ * @param {!Array.<!shaka.extern.AdCuePoint>} adCuePoints
20
21
  * @return {string}
21
22
  */
22
- static convert(cues) {
23
+ static convert(cues, adCuePoints) {
23
24
  // Flatten nested cue payloads recursively. If a cue has nested cues,
24
25
  // their contents should be combined and replace the payload of the parent.
25
26
  const flattenPayload = (cue) => {
@@ -64,6 +65,25 @@ shaka.text.WebVttGenerator = class {
64
65
  }
65
66
  };
66
67
 
68
+ const webvttTimeString = (time) => {
69
+ let newTime = time;
70
+ for (const adCuePoint of adCuePoints) {
71
+ if (adCuePoint.end && adCuePoint.start < time) {
72
+ const offset = adCuePoint.end - adCuePoint.start;
73
+ newTime += offset;
74
+ }
75
+ }
76
+ const hours = Math.floor(newTime / 3600);
77
+ const minutes = Math.floor(newTime / 60 % 60);
78
+ const seconds = Math.floor(newTime % 60);
79
+ const milliseconds = Math.floor(newTime * 1000 % 1000);
80
+ return (hours < 10 ? '0' : '') + hours + ':' +
81
+ (minutes < 10 ? '0' : '') + minutes + ':' +
82
+ (seconds < 10 ? '0' : '') + seconds + '.' +
83
+ (milliseconds < 100 ? (milliseconds < 10 ? '00' : '0') : '') +
84
+ milliseconds;
85
+ };
86
+
67
87
  // We don't want to modify the array or objects passed in, since we don't
68
88
  // technically own them. So we build a new array and replace certain items
69
89
  // in it if they need to be flattened.
@@ -80,19 +100,42 @@ shaka.text.WebVttGenerator = class {
80
100
 
81
101
  let webvttString = 'WEBVTT\n\n';
82
102
  for (const cue of flattenedCues) {
83
- const webvttTimeString = (time) => {
84
- const hours = Math.floor(time / 3600);
85
- const minutes = Math.floor(time / 60 % 60);
86
- const seconds = Math.floor(time % 60);
87
- const milliseconds = Math.floor(time * 1000 % 1000);
88
- return (hours < 10 ? '0' : '') + hours + ':' +
89
- (minutes < 10 ? '0' : '') + minutes + ':' +
90
- (seconds < 10 ? '0' : '') + seconds + '.' +
91
- (milliseconds < 100 ? (milliseconds < 10 ? '00' : '0') : '') +
92
- milliseconds;
103
+ const webvttSettings = (cue) => {
104
+ const settings = [];
105
+ const Cue = shaka.text.Cue;
106
+ switch (cue.textAlign) {
107
+ case Cue.textAlign.LEFT:
108
+ settings.push('align:left');
109
+ break;
110
+ case Cue.textAlign.RIGHT:
111
+ settings.push('align:right');
112
+ break;
113
+ case Cue.textAlign.CENTER:
114
+ settings.push('align:middle');
115
+ break;
116
+ case Cue.textAlign.START:
117
+ settings.push('align:start');
118
+ break;
119
+ case Cue.textAlign.END:
120
+ settings.push('align:end');
121
+ break;
122
+ }
123
+ switch (cue.writingMode) {
124
+ case Cue.writingMode.VERTICAL_LEFT_TO_RIGHT:
125
+ settings.push('vertical:lr');
126
+ break;
127
+ case Cue.writingMode.VERTICAL_RIGHT_TO_LEFT:
128
+ settings.push('vertical:rl');
129
+ break;
130
+ }
131
+
132
+ if (settings.length) {
133
+ return ' ' + settings.join(' ');
134
+ }
135
+ return '';
93
136
  };
94
137
  webvttString += webvttTimeString(cue.startTime) + ' --> ' +
95
- webvttTimeString(cue.endTime) + '\n';
138
+ webvttTimeString(cue.endTime) + webvttSettings(cue) + '\n';
96
139
  webvttString += cue.payload + '\n\n';
97
140
  }
98
141
  return webvttString;