shaka-player 3.1.0 → 3.1.4

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 (181) hide show
  1. package/AUTHORS +8 -2
  2. package/CHANGELOG.md +209 -0
  3. package/CONTRIBUTORS +10 -3
  4. package/README.md +3 -0
  5. package/build/apps.py +2 -2
  6. package/build/check.py +2 -2
  7. package/build/conformance.textproto +0 -9
  8. package/build/generateExterns.js +1 -1
  9. package/build/misspellings.txt +1 -0
  10. package/build/shakaBuildHelpers.py +6 -5
  11. package/build/subprocessWindowsPatch.py +103 -0
  12. package/demo/common/asset.js +11 -0
  13. package/demo/common/assets.js +1 -1
  14. package/demo/common/message_ids.js +5 -0
  15. package/demo/config.js +2 -1
  16. package/demo/custom.js +84 -3
  17. package/demo/demo.less +13 -1
  18. package/demo/demo_utils.js +1 -0
  19. package/demo/input.js +31 -12
  20. package/demo/input_container.js +24 -1
  21. package/demo/locales/en.json +6 -1
  22. package/demo/locales/source.json +20 -0
  23. package/demo/main.js +5 -1
  24. package/dist/controls.css +2 -2
  25. package/dist/controls.css.map +1 -1
  26. package/dist/demo.compiled.debug.js +99 -91
  27. package/dist/demo.compiled.debug.map +3 -3
  28. package/dist/demo.compiled.js +99 -91
  29. package/dist/demo.compiled.map +3 -3
  30. package/dist/demo.css +1 -1
  31. package/dist/demo.css.map +1 -1
  32. package/dist/deps.js +9 -9
  33. package/dist/locales.js +36 -34
  34. package/dist/receiver.compiled.debug.js +74 -70
  35. package/dist/receiver.compiled.debug.map +3 -3
  36. package/dist/receiver.compiled.js +74 -70
  37. package/dist/receiver.compiled.map +3 -3
  38. package/dist/shaka-player.compiled.d.ts +165 -9
  39. package/dist/shaka-player.compiled.debug.d.ts +165 -9
  40. package/dist/shaka-player.compiled.debug.externs.js +179 -11
  41. package/dist/shaka-player.compiled.debug.js +367 -339
  42. package/dist/shaka-player.compiled.debug.map +4 -4
  43. package/dist/shaka-player.compiled.externs.js +179 -11
  44. package/dist/shaka-player.compiled.js +818 -807
  45. package/dist/shaka-player.compiled.map +4 -4
  46. package/dist/shaka-player.ui.d.ts +165 -9
  47. package/dist/shaka-player.ui.debug.d.ts +165 -9
  48. package/dist/shaka-player.ui.debug.externs.js +181 -13
  49. package/dist/shaka-player.ui.debug.js +459 -429
  50. package/dist/shaka-player.ui.debug.map +4 -4
  51. package/dist/shaka-player.ui.externs.js +181 -13
  52. package/dist/shaka-player.ui.js +973 -961
  53. package/dist/shaka-player.ui.map +4 -4
  54. package/docs/tutorials/fairplay.md +1 -1
  55. package/docs/tutorials/faq.md +25 -0
  56. package/docs/tutorials/index.json +2 -2
  57. package/docs/tutorials/upgrade-v3.md +38 -0
  58. package/docs/tutorials/upgrade.md +3 -3
  59. package/externs/ima.js +4 -0
  60. package/externs/media_capabilities.js +16 -0
  61. package/externs/shaka/ads.js +2 -0
  62. package/externs/shaka/net.js +2 -2
  63. package/externs/shaka/player.js +6 -0
  64. package/karma.conf.js +1 -0
  65. package/lib/abr/simple_abr_manager.js +1 -1
  66. package/lib/ads/ad_manager.js +29 -11
  67. package/lib/ads/client_side_ad_manager.js +76 -86
  68. package/lib/ads/server_side_ad_manager.js +26 -11
  69. package/lib/cast/cast_proxy.js +3 -2
  70. package/lib/cast/cast_receiver.js +2 -1
  71. package/lib/cast/cast_sender.js +2 -2
  72. package/lib/cea/sei_processor.js +24 -17
  73. package/lib/dash/dash_parser.js +107 -4
  74. package/lib/dash/segment_list.js +1 -1
  75. package/lib/dash/segment_template.js +45 -15
  76. package/lib/dependencies/all.js +15 -15
  77. package/lib/hls/hls_parser.js +46 -18
  78. package/lib/media/closed_caption_parser.js +3 -1
  79. package/lib/media/content_workarounds.js +18 -0
  80. package/lib/media/drm_engine.js +20 -1
  81. package/lib/media/gap_jumping_controller.js +8 -4
  82. package/lib/media/media_source_engine.js +1 -2
  83. package/lib/media/playhead.js +1 -1
  84. package/lib/media/presentation_timeline.js +3 -1
  85. package/lib/media/segment_index.js +38 -12
  86. package/lib/media/segment_reference.js +8 -0
  87. package/lib/media/streaming_engine.js +30 -21
  88. package/lib/net/http_fetch_plugin.js +2 -2
  89. package/lib/net/networking_engine.js +3 -2
  90. package/lib/offline/storage.js +4 -0
  91. package/lib/player.js +113 -56
  92. package/lib/polyfill/encryption_scheme.js +2 -0
  93. package/lib/polyfill/fullscreen.js +2 -0
  94. package/lib/polyfill/mathround.js +2 -0
  95. package/lib/polyfill/media_capabilities.js +62 -23
  96. package/lib/polyfill/mediasource.js +8 -0
  97. package/lib/polyfill/orientation.js +3 -1
  98. package/lib/polyfill/patchedmediakeys_apple.js +6 -4
  99. package/lib/polyfill/patchedmediakeys_ms.js +6 -4
  100. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  101. package/lib/polyfill/patchedmediakeys_webkit.js +6 -4
  102. package/lib/polyfill/pip_webkit.js +2 -0
  103. package/lib/polyfill/storage_estimate.js +2 -0
  104. package/lib/polyfill/video_play_promise.js +2 -0
  105. package/lib/polyfill/videoplaybackquality.js +2 -0
  106. package/lib/polyfill/vttcue.js +2 -0
  107. package/lib/text/cue.js +11 -0
  108. package/lib/text/mp4_ttml_parser.js +3 -0
  109. package/lib/text/text_engine.js +14 -2
  110. package/lib/text/ttml_text_parser.js +52 -30
  111. package/lib/text/ui_text_displayer.js +255 -82
  112. package/lib/text/vtt_text_parser.js +4 -2
  113. package/lib/util/error.js +1 -4
  114. package/lib/util/fake_event.js +53 -7
  115. package/lib/util/mime_utils.js +33 -0
  116. package/lib/util/mp4_box_parsers.js +1 -1
  117. package/lib/util/mp4_parser.js +14 -0
  118. package/lib/util/networking.js +1 -1
  119. package/lib/util/periods.js +132 -37
  120. package/lib/util/platform.js +13 -1
  121. package/lib/util/stream_utils.js +46 -7
  122. package/package.json +3 -3
  123. package/test/cast/cast_proxy_unit.js +12 -6
  124. package/test/cast/cast_receiver_integration.js +1 -1
  125. package/test/cast/cast_utils_unit.js +1 -1
  126. package/test/cea/mp4_cea_parser_unit.js +26 -0
  127. package/test/dash/dash_parser_live_unit.js +1 -0
  128. package/test/dash/dash_parser_manifest_unit.js +187 -1
  129. package/test/dash/dash_parser_segment_template_unit.js +3 -3
  130. package/test/demo/demo_unit.js +0 -1
  131. package/test/hls/hls_parser_unit.js +45 -1
  132. package/test/media/closed_caption_parser_unit.js +20 -0
  133. package/test/media/drm_engine_unit.js +59 -3
  134. package/test/media/playhead_unit.js +27 -1
  135. package/test/media/presentation_timeline_unit.js +19 -0
  136. package/test/media/segment_index_unit.js +76 -3
  137. package/test/media/streaming_engine_unit.js +3 -3
  138. package/test/player_integration.js +38 -0
  139. package/test/player_unit.js +125 -6
  140. package/test/test/assets/3675/chunk-stream0-00001.m4s +0 -0
  141. package/test/test/assets/3675/chunk-stream0-00002.m4s +0 -0
  142. package/test/test/assets/3675/chunk-stream0-00003.m4s +0 -0
  143. package/test/test/assets/3675/chunk-stream0-00004.m4s +0 -0
  144. package/test/test/assets/3675/chunk-stream0-00005.m4s +0 -0
  145. package/test/test/assets/3675/chunk-stream0-00006.m4s +0 -0
  146. package/test/test/assets/3675/chunk-stream0-00007.m4s +0 -0
  147. package/test/test/assets/3675/dash_0.mpd +30 -0
  148. package/test/test/assets/3675/dash_1.mpd +30 -0
  149. package/test/test/assets/3675/dash_2.mpd +30 -0
  150. package/test/test/assets/3675/dash_3.mpd +30 -0
  151. package/test/test/assets/3675/dash_4.mpd +30 -0
  152. package/test/test/assets/3675/dash_5.mpd +26 -0
  153. package/test/test/assets/3675/init-stream0.m4s +0 -0
  154. package/test/test/assets/empty_caption_video_init.mp4 +0 -0
  155. package/test/test/assets/empty_caption_video_segment.mp4 +0 -0
  156. package/test/test/util/fake_ad_manager.js +4 -1
  157. package/test/test/util/simple_fakes.js +5 -3
  158. package/test/test/util/waiter.js +36 -2
  159. package/test/text/ttml_text_parser_unit.js +55 -0
  160. package/test/text/ui_text_displayer_unit.js +95 -18
  161. package/test/text/vtt_text_parser_unit.js +17 -1
  162. package/test/ui/localization_unit.js +15 -14
  163. package/test/ui/text_displayer_layout_unit.js +52 -1
  164. package/test/ui/ui_unit.js +4 -0
  165. package/test/util/mp4_box_parsers_unit.js +28 -0
  166. package/test/util/periods_unit.js +190 -2
  167. package/test/util/stream_utils_unit.js +56 -5
  168. package/ui/airplay_button.js +5 -0
  169. package/ui/big_play_button.js +10 -0
  170. package/ui/cast_button.js +2 -3
  171. package/ui/controls.js +9 -7
  172. package/ui/less/containers.less +10 -5
  173. package/ui/locales/en.json +1 -0
  174. package/ui/locales/ru.json +6 -6
  175. package/ui/locales/source.json +4 -0
  176. package/ui/localization.js +28 -51
  177. package/ui/pip_button.js +2 -3
  178. package/ui/play_button.js +10 -10
  179. package/ui/small_play_button.js +12 -0
  180. package/ui/ui.js +1 -1
  181. package/docs/tutorials/upgrade-v2-4.md +0 -481
@@ -12,10 +12,12 @@ goog.require('shaka.polyfill');
12
12
  /**
13
13
  * @summary A polyfill to provide PiP support in Safari.
14
14
  * Note that Safari only supports PiP on video elements, not audio.
15
+ * @export
15
16
  */
16
17
  shaka.polyfill.PiPWebkit = class {
17
18
  /**
18
19
  * Install the polyfill if needed.
20
+ * @export
19
21
  */
20
22
  static install() {
21
23
  if (!window.HTMLVideoElement) {
@@ -13,10 +13,12 @@ goog.require('shaka.polyfill');
13
13
  * @summary A polyfill to provide navigator.storage.estimate in old
14
14
  * webkit browsers.
15
15
  * See: https://developers.google.com/web/updates/2017/08/estimating-available-storage-space#the-present
16
+ * @export
16
17
  */
17
18
  shaka.polyfill.StorageEstimate = class {
18
19
  /**
19
20
  * Install the polyfill if needed.
21
+ * @export
20
22
  */
21
23
  static install() {
22
24
  if (navigator.storage && navigator.storage.estimate) {
@@ -12,10 +12,12 @@ goog.require('shaka.polyfill');
12
12
 
13
13
  /**
14
14
  * @summary A polyfill to silence the play() Promise in HTML5 video.
15
+ * @export
15
16
  */
16
17
  shaka.polyfill.VideoPlayPromise = class {
17
18
  /**
18
19
  * Install the polyfill if needed.
20
+ * @export
19
21
  */
20
22
  static install() {
21
23
  shaka.log.debug('VideoPlayPromise.install');
@@ -13,10 +13,12 @@ goog.require('shaka.polyfill');
13
13
  * @summary A polyfill to provide MSE VideoPlaybackQuality metrics.
14
14
  * Many browsers do not yet provide this API, and Chrome currently provides
15
15
  * similar data through individual prefixed attributes on HTMLVideoElement.
16
+ * @export
16
17
  */
17
18
  shaka.polyfill.VideoPlaybackQuality = class {
18
19
  /**
19
20
  * Install the polyfill if needed.
21
+ * @export
20
22
  */
21
23
  static install() {
22
24
  if (!window.HTMLVideoElement) {
@@ -12,10 +12,12 @@ goog.require('shaka.polyfill');
12
12
 
13
13
  /**
14
14
  * @summary A polyfill to provide VTTCue.
15
+ * @export
15
16
  */
16
17
  shaka.polyfill.VTTCue = class {
17
18
  /**
18
19
  * Install the polyfill if needed.
20
+ * @export
19
21
  */
20
22
  static install() {
21
23
  if (window.VTTCue) {
package/lib/text/cue.js CHANGED
@@ -232,6 +232,17 @@ shaka.text.Cue = class {
232
232
  };
233
233
  }
234
234
 
235
+ /**
236
+ * @param {number} start
237
+ * @param {number} end
238
+ * @return {!shaka.text.Cue}
239
+ */
240
+ static lineBreak(start, end) {
241
+ const cue = new shaka.text.Cue(start, end, '');
242
+ cue.lineBreak = true;
243
+ return cue;
244
+ }
245
+
235
246
  /**
236
247
  * Create a copy of the cue with the same properties.
237
248
  * @return {!shaka.text.Cue}
@@ -88,6 +88,9 @@ shaka.text.Mp4TtmlParser = class {
88
88
 
89
89
  shaka.text.TextEngine.registerParser(
90
90
  'application/mp4; codecs="stpp"', () => new shaka.text.Mp4TtmlParser());
91
+ shaka.text.TextEngine.registerParser(
92
+ 'application/mp4; codecs="stpp.ttml"',
93
+ () => new shaka.text.Mp4TtmlParser());
91
94
  shaka.text.TextEngine.registerParser(
92
95
  'application/mp4; codecs="stpp.ttml.im1t"',
93
96
  () => new shaka.text.Mp4TtmlParser());
@@ -345,6 +345,19 @@ shaka.text.TextEngine = class {
345
345
  return cues;
346
346
  }
347
347
 
348
+ /**
349
+ * @param {!shaka.text.Cue} cue the cue to apply the timestamp to recursively
350
+ * @param {number} videoTimestampOffset the timestamp offset of the video
351
+ * @private
352
+ */
353
+ applyVideoTimestampOffsetRecursive_(cue, videoTimestampOffset) {
354
+ cue.startTime += videoTimestampOffset;
355
+ cue.endTime += videoTimestampOffset;
356
+ for (const nested of cue.nestedCues) {
357
+ this.applyVideoTimestampOffsetRecursive_(nested, videoTimestampOffset);
358
+ }
359
+ }
360
+
348
361
  /**
349
362
  * Store the closed captions in the text engine, and append the cues to the
350
363
  * text displayer. This is a side-channel used for embedded text only.
@@ -373,8 +386,7 @@ shaka.text.TextEngine = class {
373
386
 
374
387
  // Adjust CEA captions with respect to the timestamp offset of the video
375
388
  // stream in which they were embedded.
376
- cue.startTime += videoTimestampOffset;
377
- cue.endTime += videoTimestampOffset;
389
+ this.applyVideoTimestampOffsetRecursive_(cue, videoTimestampOffset);
378
390
 
379
391
  const keepThisCue =
380
392
  cue.startTime >= this.appendWindowStart_ &&
@@ -199,6 +199,11 @@ shaka.text.TtmlTextParser = class {
199
199
  /** @type {Element} */
200
200
  let parentElement = /** @type {Element} */(cueNode.parentNode);
201
201
 
202
+ if (cueNode.nodeType == Node.COMMENT_NODE) {
203
+ // The comments do not contain information that interests us here.
204
+ return null;
205
+ }
206
+
202
207
  if (cueNode.nodeType == Node.TEXT_NODE) {
203
208
  // This should generate an "anonymous span" according to the TTML spec.
204
209
  // So pretend the element was a <span>. parentElement was set above, so
@@ -219,6 +224,36 @@ shaka.text.TtmlTextParser = class {
219
224
 
220
225
  const localWhitespaceTrim = spaceStyle == 'default';
221
226
 
227
+ // Parse any nested cues first.
228
+ const isTextNode = (node) => {
229
+ return node.nodeType == Node.TEXT_NODE;
230
+ };
231
+ const isLeafNode = Array.from(cueElement.childNodes).every(isTextNode);
232
+ const nestedCues = [];
233
+ if (!isLeafNode) {
234
+ // Otherwise, recurse into the children. Text nodes will convert into
235
+ // anonymous spans, which will then be leaf nodes.
236
+ for (const childNode of cueElement.childNodes) {
237
+ const nestedCue = shaka.text.TtmlTextParser.parseCue_(
238
+ childNode,
239
+ offset,
240
+ rateInfo,
241
+ metadataElements,
242
+ styles,
243
+ regionElements,
244
+ cueRegions,
245
+ localWhitespaceTrim,
246
+ /* isNested= */ true,
247
+ cellResolution,
248
+ );
249
+
250
+ // This node may or may not generate a nested cue.
251
+ if (nestedCue) {
252
+ nestedCues.push(nestedCue);
253
+ }
254
+ }
255
+ }
256
+
222
257
  // In this regex, "\S" means "non-whitespace character".
223
258
  const hasTextContent = /\S/.test(cueElement.textContent);
224
259
  const hasTimeAttributes =
@@ -226,7 +261,8 @@ shaka.text.TtmlTextParser = class {
226
261
  cueElement.hasAttribute('end') ||
227
262
  cueElement.hasAttribute('dur');
228
263
 
229
- if (!hasTimeAttributes && !hasTextContent && cueElement.tagName != 'br') {
264
+ if (!hasTimeAttributes && !hasTextContent && cueElement.tagName != 'br' &&
265
+ nestedCues.length == 0) {
230
266
  if (!isNested) {
231
267
  // Disregards empty <p> elements without time attributes nor content.
232
268
  // <p begin="..." smpte:backgroundImage="..." /> will go through,
@@ -263,6 +299,20 @@ shaka.text.TtmlTextParser = class {
263
299
  end += offset;
264
300
  }
265
301
 
302
+ if (!hasTimeAttributes && nestedCues.length > 0) {
303
+ // If no time is defined for this cue, base the timing information on
304
+ // the time of the nested cues. In the case of multiple nested cues with
305
+ // different start times, it is the text displayer's responsibility to
306
+ // make sure that only the appropriate nested cue is drawn at any given
307
+ // time.
308
+ start = Infinity;
309
+ end = 0;
310
+ for (const cue of nestedCues) {
311
+ start = Math.min(start, cue.startTime);
312
+ end = Math.max(end, cue.endTime);
313
+ }
314
+ }
315
+
266
316
  if (cueElement.tagName == 'br') {
267
317
  const cue = new shaka.text.Cue(start, end, '');
268
318
  cue.lineBreak = true;
@@ -270,13 +320,7 @@ shaka.text.TtmlTextParser = class {
270
320
  }
271
321
 
272
322
  let payload = '';
273
- const nestedCues = [];
274
-
275
- const isTextNode = (node) => {
276
- return node.nodeType == Node.TEXT_NODE;
277
- };
278
-
279
- if (Array.from(cueElement.childNodes).every(isTextNode)) {
323
+ if (isLeafNode) {
280
324
  // If the childNodes are all text, this is a leaf node. Get the payload.
281
325
  payload = cueElement.textContent;
282
326
  if (localWhitespaceTrim) {
@@ -285,28 +329,6 @@ shaka.text.TtmlTextParser = class {
285
329
  // Collapse multiple spaces into one.
286
330
  payload = payload.replace(/\s+/g, ' ');
287
331
  }
288
- } else {
289
- // Otherwise, recurse into the children. Text nodes will convert into
290
- // anonymous spans, which will then be leaf nodes.
291
- for (const childNode of cueElement.childNodes) {
292
- const nestedCue = shaka.text.TtmlTextParser.parseCue_(
293
- childNode,
294
- offset,
295
- rateInfo,
296
- metadataElements,
297
- styles,
298
- regionElements,
299
- cueRegions,
300
- localWhitespaceTrim,
301
- /* isNested= */ true,
302
- cellResolution,
303
- );
304
-
305
- // This node may or may not generate a nested cue.
306
- if (nestedCue) {
307
- nestedCues.push(nestedCue);
308
- }
309
- }
310
332
  }
311
333
 
312
334
  const cue = new shaka.text.Cue(start, end, payload);