shaka-player 4.4.2 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/.github/workflows/release-please.yaml +2 -27
  2. package/CHANGELOG.md +67 -25
  3. package/README.md +16 -10
  4. package/demo/asset_card.js +18 -21
  5. package/demo/cast_receiver/index.html +0 -1
  6. package/demo/close_button.js +0 -3
  7. package/demo/common/asset.js +27 -5
  8. package/demo/common/assets.js +150 -52
  9. package/demo/config.js +192 -253
  10. package/demo/custom.js +39 -98
  11. package/demo/front.js +7 -10
  12. package/demo/index.html +19 -22
  13. package/demo/input.js +6 -11
  14. package/demo/input_container.js +8 -9
  15. package/demo/main.js +52 -124
  16. package/demo/search.js +23 -35
  17. package/demo/service_worker.js +0 -3
  18. package/demo/tooltip.js +3 -5
  19. package/demo/visualizer.js +3 -5
  20. package/demo/visualizer_button.js +1 -20
  21. package/dist/demo.compiled.debug.js +187 -211
  22. package/dist/demo.compiled.debug.map +4 -4
  23. package/dist/demo.compiled.js +187 -211
  24. package/dist/demo.compiled.map +4 -4
  25. package/dist/deps.js +27 -24
  26. package/dist/locales.js +31 -31
  27. package/dist/receiver.compiled.debug.js +42 -61
  28. package/dist/receiver.compiled.debug.map +4 -4
  29. package/dist/receiver.compiled.js +42 -61
  30. package/dist/receiver.compiled.map +4 -4
  31. package/dist/shaka-player.compiled.d.ts +728 -365
  32. package/dist/shaka-player.compiled.debug.d.ts +728 -365
  33. package/dist/shaka-player.compiled.debug.externs.js +475 -51
  34. package/dist/shaka-player.compiled.debug.js +576 -480
  35. package/dist/shaka-player.compiled.debug.map +4 -4
  36. package/dist/shaka-player.compiled.externs.js +475 -51
  37. package/dist/shaka-player.compiled.js +1117 -1056
  38. package/dist/shaka-player.compiled.map +4 -4
  39. package/dist/shaka-player.ui.d.ts +783 -410
  40. package/dist/shaka-player.ui.debug.d.ts +783 -410
  41. package/dist/shaka-player.ui.debug.externs.js +496 -51
  42. package/dist/shaka-player.ui.debug.js +647 -542
  43. package/dist/shaka-player.ui.debug.map +4 -4
  44. package/dist/shaka-player.ui.externs.js +496 -51
  45. package/dist/shaka-player.ui.js +1260 -1194
  46. package/dist/shaka-player.ui.map +4 -4
  47. package/docs/design/lcevc-integration.md +14 -14
  48. package/docs/tutorials/faq.md +27 -55
  49. package/docs/tutorials/index.json +2 -1
  50. package/docs/tutorials/lcevc.md +118 -0
  51. package/docs/tutorials/offline.md +1 -1
  52. package/docs/tutorials/ui-customization.md +4 -0
  53. package/externs/css_style_declaration.js +19 -0
  54. package/externs/lcevc.js +37 -13
  55. package/externs/media_remote.js +68 -0
  56. package/externs/mediatailor.js +193 -0
  57. package/externs/pictureinpicture.js +11 -0
  58. package/externs/shaka/ads.js +27 -0
  59. package/externs/shaka/manifest.js +10 -5
  60. package/externs/shaka/manifest_parser.js +7 -1
  61. package/externs/shaka/offline.js +4 -0
  62. package/externs/shaka/player.js +12 -1
  63. package/karma.conf.js +7 -3
  64. package/lib/abr/simple_abr_manager.js +43 -3
  65. package/lib/ads/ad_manager.js +104 -50
  66. package/lib/ads/media_tailor_ad.js +297 -0
  67. package/lib/ads/media_tailor_ad_manager.js +828 -0
  68. package/lib/cea/ts_cea_parser.js +15 -2
  69. package/lib/config/codec_switching_strategy.js +24 -0
  70. package/lib/dash/content_protection.js +120 -2
  71. package/lib/dash/dash_parser.js +79 -13
  72. package/lib/dash/mpd_utils.js +10 -6
  73. package/lib/dash/segment_base.js +13 -5
  74. package/lib/dash/segment_list.js +13 -5
  75. package/lib/dash/segment_template.js +43 -85
  76. package/lib/dependencies/all.js +8 -7
  77. package/lib/hls/hls_parser.js +101 -37
  78. package/lib/lcevc/lcevc_dec.js +220 -0
  79. package/lib/media/adaptation_set.js +22 -11
  80. package/lib/media/adaptation_set_criteria.js +25 -7
  81. package/lib/media/media_source_engine.js +215 -27
  82. package/lib/media/segment_index.js +5 -5
  83. package/lib/media/segment_reference.js +10 -5
  84. package/lib/media/streaming_engine.js +44 -39
  85. package/lib/mss/mss_parser.js +1 -0
  86. package/lib/net/networking_engine.js +1 -0
  87. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  88. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  89. package/lib/offline/manifest_converter.js +1 -0
  90. package/lib/offline/storage.js +3 -0
  91. package/lib/player.js +142 -72
  92. package/lib/routing/payload.js +5 -1
  93. package/lib/text/cue.js +62 -47
  94. package/lib/text/ttml_text_parser.js +17 -0
  95. package/lib/text/ui_text_displayer.js +4 -0
  96. package/lib/text/vtt_text_parser.js +35 -22
  97. package/lib/transmuxer/h265.js +862 -0
  98. package/lib/transmuxer/mpeg_ts_transmuxer.js +3 -2
  99. package/lib/transmuxer/ts_transmuxer.js +160 -15
  100. package/lib/util/cmcd_manager.js +6 -1
  101. package/lib/util/error.js +28 -9
  102. package/lib/util/exp_golomb.js +30 -2
  103. package/lib/util/fake_event.js +3 -0
  104. package/lib/util/manifest_parser_utils.js +10 -4
  105. package/lib/util/mp4_generator.js +4 -4
  106. package/lib/util/periods.js +2 -0
  107. package/lib/util/platform.js +54 -0
  108. package/lib/util/player_configuration.js +8 -0
  109. package/lib/util/state_history.js +6 -2
  110. package/lib/util/stream_utils.js +133 -217
  111. package/lib/util/ts_parser.js +229 -43
  112. package/maintained-branches.md +3 -2
  113. package/package.json +4 -6
  114. package/roadmap.md +15 -5
  115. package/shaka-player.uncompiled.js +2 -1
  116. package/support.html +0 -1
  117. package/test/cast/cast_receiver_integration.js +47 -0
  118. package/test/codec_switching/codec_switching_integration.js +181 -0
  119. package/test/dash/dash_parser_content_protection_unit.js +2 -0
  120. package/test/dash/dash_parser_integration.js +73 -0
  121. package/test/dash/dash_parser_live_unit.js +2 -0
  122. package/test/dash/dash_parser_manifest_unit.js +47 -0
  123. package/test/dash/dash_parser_segment_base_unit.js +7 -0
  124. package/test/dash/dash_parser_segment_list_unit.js +23 -17
  125. package/test/dash/dash_parser_segment_template_unit.js +49 -0
  126. package/test/demo/demo_unit.js +0 -16
  127. package/test/hls/hls_live_unit.js +35 -0
  128. package/test/hls/hls_parser_unit.js +8 -61
  129. package/test/media/adaptation_set_criteria_unit.js +118 -0
  130. package/test/media/adaptation_set_unit.js +1 -0
  131. package/test/media/media_source_engine_unit.js +165 -1
  132. package/test/media/segment_index_unit.js +4 -4
  133. package/test/media/segment_prefetch_unit.js +1 -1
  134. package/test/media/streaming_engine_unit.js +17 -17
  135. package/test/mss/mss_parser_unit.js +2 -0
  136. package/test/offline/manifest_convert_unit.js +5 -0
  137. package/test/offline/storage_integration.js +1 -4
  138. package/test/player_unit.js +102 -131
  139. package/test/routing/walker_unit.js +1 -0
  140. package/test/test/assets/dash-aes-128/Fragments(video=0,format=mpd-time-csf) +0 -0
  141. package/test/test/assets/dash-aes-128/Fragments(video=20000000,format=mpd-time-csf) +0 -0
  142. package/test/test/assets/dash-aes-128/Fragments(video=40000000,format=mpd-time-csf) +0 -0
  143. package/test/test/assets/dash-aes-128/Fragments(video=60000000,format=mpd-time-csf) +0 -0
  144. package/test/test/assets/dash-aes-128/Fragments(video=i,format=mpd-time-csf) +0 -0
  145. package/test/test/assets/dash-aes-128/dash.mpd +18 -0
  146. package/test/test/assets/dash-aes-128/license +1 -0
  147. package/test/test/assets/dash-multi-codec/audio_en_2c_128k_aac.mp4 +0 -0
  148. package/test/test/assets/dash-multi-codec/audio_es_2c_64k_opus.webm +0 -0
  149. package/test/test/assets/dash-multi-codec/dash.mpd +32 -0
  150. package/test/test/assets/dash-multi-codec/video_144p_108k_h264.mp4 +0 -0
  151. package/test/test/assets/hls-ts-h265/0.ts +0 -0
  152. package/test/test/assets/hls-ts-h265/hevc.m3u8 +6 -0
  153. package/test/test/assets/hls-ts-h265/index.m3u8 +7 -0
  154. package/test/test/assets/hls-ts-muxed-aac-h265/0.ts +0 -0
  155. package/test/test/assets/hls-ts-muxed-aac-h265/1.ts +0 -0
  156. package/test/test/assets/hls-ts-muxed-aac-h265/media.m3u8 +9 -0
  157. package/test/test/assets/hls-ts-muxed-ac3-h264/media.m3u8 +24 -0
  158. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00000.ts +0 -0
  159. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00001.ts +0 -0
  160. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00002.ts +0 -0
  161. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00003.ts +0 -0
  162. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00004.ts +0 -0
  163. package/test/test/assets/hls-ts-muxed-ac3-h264/s_00005.ts +0 -0
  164. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts +0 -0
  165. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts +0 -0
  166. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts +0 -0
  167. package/test/test/assets/hls-ts-muxed-ec3-h264/ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts +0 -0
  168. package/test/test/assets/hls-ts-muxed-ec3-h264/prog_index.m3u8 +14 -0
  169. package/test/test/assets/hls-ts-muxed-mp3-h264/index.m3u8 +23 -0
  170. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-1-v1-a1.ts +0 -0
  171. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-2-v1-a1.ts +0 -0
  172. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-3-v1-a1.ts +0 -0
  173. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-4-v1-a1.ts +0 -0
  174. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-5-v1-a1.ts +0 -0
  175. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-6-v1-a1.ts +0 -0
  176. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-7-v1-a1.ts +0 -0
  177. package/test/test/assets/hls-ts-muxed-mp3-h264/seg-8-v1-a1.ts +0 -0
  178. package/test/test/util/dash_parser_util.js +20 -7
  179. package/test/test/util/fake_ad_manager.js +20 -0
  180. package/test/test/util/fake_media_source_engine.js +8 -2
  181. package/test/test/util/manifest_generator.js +7 -3
  182. package/test/test/util/mss_parser_util.js +4 -0
  183. package/test/test/util/offline_utils.js +1 -0
  184. package/test/test/util/streaming_engine_util.js +7 -4
  185. package/test/text/ttml_text_parser_unit.js +52 -0
  186. package/test/text/vtt_text_parser_unit.js +105 -48
  187. package/test/transmuxer/transmuxer_integration.js +121 -4
  188. package/test/ui/ui_unit.js +3 -10
  189. package/test/util/stream_utils_unit.js +208 -74
  190. package/test/util/ts_parser_unit.js +1 -1
  191. package/ui/controls.js +125 -0
  192. package/ui/externs/ui.js +8 -1
  193. package/ui/pip_button.js +22 -120
  194. package/ui/remote_button.js +201 -0
  195. package/ui/ui.js +5 -2
  196. package/demo/common/message_ids.js +0 -309
  197. package/demo/locales/en.json +0 -287
  198. package/demo/locales/source.json +0 -1142
  199. package/externs/mux.js +0 -69
  200. package/lib/lcevc/lcevc_dil.js +0 -152
  201. package/lib/transmuxer/muxjs_transmuxer.js +0 -242
  202. package/test/transmuxer/muxjs_transmuxer_integration.js +0 -177
@@ -0,0 +1,14 @@
1
+ #EXTM3U
2
+ #EXT-X-VERSION:3
3
+ #EXT-X-TARGETDURATION:6
4
+ #EXT-X-PLAYLIST-TYPE:VOD
5
+ #EXT-X-INDEPENDENT-SEGMENTS
6
+ #EXTINF:6.000,
7
+ ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0000.ts
8
+ #EXTINF:6.000,
9
+ ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0001.ts
10
+ #EXTINF:6.000,
11
+ ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0002.ts
12
+ #EXTINF:6.000,
13
+ ChID_voices_1280x720p_25fps_h264_6ch_256kbps_ddp_sub_0003.ts
14
+ #EXT-X-ENDLIST
@@ -0,0 +1,23 @@
1
+ #EXTM3U
2
+ #EXT-X-TARGETDURATION:6
3
+ #EXT-X-ALLOW-CACHE:YES
4
+ #EXT-X-PLAYLIST-TYPE:VOD
5
+ #EXT-X-VERSION:3
6
+ #EXT-X-MEDIA-SEQUENCE:1
7
+ #EXTINF:2.436,
8
+ seg-1-v1-a1.ts
9
+ #EXTINF:3.337,
10
+ seg-2-v1-a1.ts
11
+ #EXTINF:3.337,
12
+ seg-3-v1-a1.ts
13
+ #EXTINF:5.005,
14
+ seg-4-v1-a1.ts
15
+ #EXTINF:5.005,
16
+ seg-5-v1-a1.ts
17
+ #EXTINF:5.005,
18
+ seg-6-v1-a1.ts
19
+ #EXTINF:5.606,
20
+ seg-7-v1-a1.ts
21
+ #EXTINF:5.005,
22
+ seg-8-v1-a1.ts
23
+ #EXT-X-ENDLIST
@@ -45,12 +45,18 @@ shaka.test.Dash = class {
45
45
  enableLowLatencyMode: () => {},
46
46
  updateDuration: () => {},
47
47
  newDrmInfo: (stream) => {},
48
+ onManifestUpdated: () => {},
49
+ getBandwidthEstimate: () => 1e6,
48
50
  };
49
- const manifest = await dashParser.start('dummy://foo', playerInterface);
50
- const stream = manifest.variants[0].video;
51
- await stream.createSegmentIndex();
51
+ try {
52
+ const manifest = await dashParser.start('dummy://foo', playerInterface);
53
+ const stream = manifest.variants[0].video;
54
+ await stream.createSegmentIndex();
52
55
 
53
- shaka.test.ManifestParser.verifySegmentIndex(stream, references);
56
+ shaka.test.ManifestParser.verifySegmentIndex(stream, references);
57
+ } finally {
58
+ dashParser.stop();
59
+ }
54
60
  }
55
61
 
56
62
  /**
@@ -81,10 +87,17 @@ shaka.test.Dash = class {
81
87
  enableLowLatencyMode: () => {},
82
88
  updateDuration: () => {},
83
89
  newDrmInfo: (stream) => {},
90
+ onManifestUpdated: () => {},
91
+ getBandwidthEstimate: () => 1e6,
84
92
  };
85
- const p = dashParser.start('dummy://foo', playerInterface);
86
- await expectAsync(p).toBeRejectedWith(
87
- shaka.test.Util.jasmineError(expectedError));
93
+
94
+ try {
95
+ const p = dashParser.start('dummy://foo', playerInterface);
96
+ await expectAsync(p).toBeRejectedWith(
97
+ shaka.test.Util.jasmineError(expectedError));
98
+ } finally {
99
+ dashParser.stop();
100
+ }
88
101
  }
89
102
 
90
103
  /**
@@ -39,6 +39,14 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
39
39
  /** @override */
40
40
  updateClientSideAdsRenderingSettings(adsRenderingSettings) {}
41
41
 
42
+ /** @override */
43
+ initMediaTailor(networkingEngine, video) {}
44
+
45
+ /** @override */
46
+ requestMediaTailorStream(url, adsParams, backupUrl) {
47
+ return Promise.resolve('fake:url');
48
+ }
49
+
42
50
  /** @override */
43
51
  initServerSide(adContainer, video) {}
44
52
 
@@ -57,11 +65,23 @@ shaka.test.FakeAdManager = class extends shaka.util.FakeEventTarget {
57
65
  return [];
58
66
  }
59
67
 
68
+ /**
69
+ * @override
70
+ */
71
+ getCuePoints() {
72
+ return [];
73
+ }
74
+
60
75
  /** @override */
61
76
  getStats() {
62
77
  return this.stats_;
63
78
  }
64
79
 
80
+ /**
81
+ * @override
82
+ */
83
+ onManifestUpdated(isLive) {}
84
+
65
85
  /**
66
86
  * @override
67
87
  */
@@ -134,8 +134,8 @@ shaka.test.FakeMediaSourceEngine = class {
134
134
  jasmine.createSpy('setSegmentRelativeVttTiming').and.stub();
135
135
 
136
136
  /** @type {!jasmine.Spy} */
137
- this.updateLcevcDil =
138
- jasmine.createSpy('updateLcevcDil').and.stub();
137
+ this.updateLcevcDec =
138
+ jasmine.createSpy('updateLcevcDec').and.stub();
139
139
 
140
140
  /** @type {!jasmine.Spy} */
141
141
  this.resync=
@@ -341,6 +341,12 @@ shaka.test.FakeMediaSourceEngine = class {
341
341
  return Promise.resolve();
342
342
  }
343
343
 
344
+
345
+ /** @override */
346
+ isResetMediaSourceNecessary() {
347
+ return false;
348
+ }
349
+
344
350
  /**
345
351
  * @param {string} type
346
352
  * @return {!Promise}
@@ -459,9 +459,11 @@ shaka.test.ManifestGenerator.Stream = class {
459
459
  * @param {string=} label
460
460
  */
461
461
  constructor(manifest, isPartial, id, type, lang, label) {
462
- goog.asserts.assert(
463
- !manifest || !manifest.isIdUsed_(id),
464
- 'Streams should have unique ids!');
462
+ // variants can be made up of different combinations of video
463
+ // and audio streams
464
+ // goog.asserts.assert(
465
+ // !manifest || !manifest.isIdUsed_(id),
466
+ // 'Streams should have unique ids!');
465
467
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
466
468
 
467
469
  /** @const {shaka.test.ManifestGenerator.Manifest} */
@@ -499,6 +501,8 @@ shaka.test.ManifestGenerator.Stream = class {
499
501
 
500
502
  /** @type {?string} */
501
503
  this.originalId = null;
504
+ /** @type {?string} */
505
+ this.groupId = null;
502
506
  /** @type {shaka.extern.CreateSegmentIndexFunction} */
503
507
  this.createSegmentIndex = shaka.test.Util.spyFunc(create);
504
508
  /** @type {shaka.media.SegmentIndex} */
@@ -45,6 +45,8 @@ shaka.test.Mss = class {
45
45
  enableLowLatencyMode: () => {},
46
46
  updateDuration: () => {},
47
47
  newDrmInfo: (stream) => {},
48
+ onManifestUpdated: () => {},
49
+ getBandwidthEstimate: () => 1e6,
48
50
  };
49
51
  const manifest = await mssParser.start('dummy://foo', playerInterface);
50
52
  const stream = manifest.variants[0].audio;
@@ -81,6 +83,8 @@ shaka.test.Mss = class {
81
83
  enableLowLatencyMode: () => {},
82
84
  updateDuration: () => {},
83
85
  newDrmInfo: (stream) => {},
86
+ onManifestUpdated: () => {},
87
+ getBandwidthEstimate: () => 1e6,
84
88
  };
85
89
  const p = mssParser.start('dummy://foo', playerInterface);
86
90
  await expectAsync(p).toBeRejectedWith(
@@ -33,6 +33,7 @@ shaka.test.OfflineUtils = class {
33
33
  return {
34
34
  id,
35
35
  originalId: id.toString(),
36
+ groupId: null,
36
37
  primary: false,
37
38
  presentationTimeOffset: 0,
38
39
  type,
@@ -149,13 +149,13 @@ shaka.test.StreamingEngineUtil = class {
149
149
  * ranges for each type of init segment.
150
150
  * @param {!Object.<string,number>=} timestampOffsets The timestamp offset
151
151
  * for each type of segment
152
- * @param {shaka.extern.HlsAes128Key=} hlsAes128Key The AES-128 key to provide
152
+ * @param {shaka.extern.aes128Key=} aes128Key The AES-128 key to provide
153
153
  * to streams, if desired.
154
154
  * @return {shaka.extern.Manifest}
155
155
  */
156
156
  static createManifest(
157
157
  presentationTimeline, periodStartTimes, presentationDuration,
158
- segmentDurations, initSegmentRanges, timestampOffsets, hlsAes128Key) {
158
+ segmentDurations, initSegmentRanges, timestampOffsets, aes128Key) {
159
159
  const Util = shaka.test.Util;
160
160
 
161
161
  /**
@@ -268,9 +268,9 @@ shaka.test.StreamingEngineUtil = class {
268
268
  appendWindowStart,
269
269
  appendWindowEnd);
270
270
  const ContentType = shaka.util.ManifestParserUtils.ContentType;
271
- if (hlsAes128Key &&
271
+ if (aes128Key &&
272
272
  (type == ContentType.AUDIO || type == ContentType.VIDEO)) {
273
- ref.hlsAes128Key = hlsAes128Key;
273
+ ref.aes128Key = aes128Key;
274
274
  }
275
275
  return ref;
276
276
  };
@@ -394,6 +394,7 @@ shaka.test.StreamingEngineUtil = class {
394
394
  return {
395
395
  id: id,
396
396
  originalId: id.toString(),
397
+ groupId: null,
397
398
  createSegmentIndex: Util.spyFunc(jasmine.createSpy('createSegmentIndex')),
398
399
  segmentIndex: null,
399
400
  mimeType: 'audio/mp4',
@@ -433,6 +434,7 @@ shaka.test.StreamingEngineUtil = class {
433
434
  return {
434
435
  id: id,
435
436
  originalId: id.toString(),
437
+ groupId: null,
436
438
  createSegmentIndex: Util.spyFunc(jasmine.createSpy('createSegmentIndex')),
437
439
  segmentIndex: null,
438
440
  mimeType: mimeType,
@@ -473,6 +475,7 @@ shaka.test.StreamingEngineUtil = class {
473
475
  return {
474
476
  id: id,
475
477
  originalId: id.toString(),
478
+ groupId: null,
476
479
  createSegmentIndex: Util.spyFunc(jasmine.createSpy('createSegmentIndex')),
477
480
  segmentIndex: null,
478
481
  mimeType: 'text/vtt',
@@ -1147,6 +1147,31 @@ describe('TtmlTextParser', () => {
1147
1147
  {startTime: 62.05, endTime: 3723.2});
1148
1148
  });
1149
1149
 
1150
+ it('supports textCombine setting', () => {
1151
+ verifyHelper(
1152
+ [
1153
+ {
1154
+ startTime: 62.05,
1155
+ endTime: 3723.2,
1156
+ payload: 'Test',
1157
+ textCombineUpright: 'all',
1158
+ writingMode: Cue.writingMode.VERTICAL_LEFT_TO_RIGHT,
1159
+ },
1160
+ ],
1161
+ '<tt xmlns:tts="http://www.w3.org/ns/ttml#styling">' +
1162
+ '<layout>' +
1163
+ '<region xml:id="subtitleArea" ' +
1164
+ 'tts:writingMode="tb" ' +
1165
+ 'tts:textCombine="all"/>' +
1166
+ '</layout>' +
1167
+ '<body region="subtitleArea"><div>' +
1168
+ '<p begin="01:02.05" end="01:02:03.200">Test</p>' +
1169
+ '</div></body></tt>',
1170
+ {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0},
1171
+ {startTime: 62.05, endTime: 3723.2, region: {id: 'subtitleArea'}},
1172
+ {startTime: 62.05, endTime: 3723.2});
1173
+ });
1174
+
1150
1175
  it('disregards empty divs and ps', () => {
1151
1176
  verifyHelper(
1152
1177
  [
@@ -1286,6 +1311,33 @@ describe('TtmlTextParser', () => {
1286
1311
  {startTime: 62.05, endTime: 3723.2});
1287
1312
  });
1288
1313
 
1314
+ it('supports tts:ruby', () => {
1315
+ verifyHelper(
1316
+ [{
1317
+ startTime: 62.05,
1318
+ endTime: 3723.2,
1319
+ payload: '',
1320
+ nestedCues: [{
1321
+ startTime: 62.05,
1322
+ endTime: 3723.2,
1323
+ payload: 'Line1',
1324
+ }, {
1325
+ startTime: 62.05,
1326
+ endTime: 3723.2,
1327
+ payload: 'Line2',
1328
+ rubyTag: 'rt',
1329
+ }],
1330
+ rubyTag: 'ruby',
1331
+ }],
1332
+ // With anonymous spans
1333
+ '<tt xmlns:tts="http://www.w3.org/ns/ttml#styling"><body><div>' +
1334
+ '<p begin="01:02.05" end="01:02:03.200" tts:ruby="container">' +
1335
+ '<span tts:ruby="base">Line1</span><span tts:ruby="text">Line2' +
1336
+ '</span></p></div></body></tt>',
1337
+ {periodStart: 0, segmentStart: 60, segmentEnd: 3730, vttOffset: 0},
1338
+ {startTime: 62.05, endTime: 3723.2});
1339
+ });
1340
+
1289
1341
  it('inserts line breaks for <br> tags', () => {
1290
1342
  verifyHelper(
1291
1343
  [{
@@ -198,30 +198,15 @@ describe('VttTextParser', () => {
198
198
  {
199
199
  startTime: 40,
200
200
  endTime: 50,
201
- payload: '',
201
+ payload: 'Test2',
202
202
  writingMode: Cue.writingMode.VERTICAL_LEFT_TO_RIGHT,
203
- nestedCues: [
204
- {
205
- startTime: 40,
206
- endTime: 50,
207
- payload: 'Test',
208
- writingMode: Cue.writingMode.VERTICAL_LEFT_TO_RIGHT,
209
- },
210
- {
211
- startTime: 40,
212
- endTime: 50,
213
- payload: '2',
214
- fontWeight: Cue.fontWeight.BOLD,
215
- writingMode: Cue.writingMode.VERTICAL_LEFT_TO_RIGHT,
216
- },
217
- ],
218
203
  },
219
204
  ],
220
205
  'WEBVTT\n\n' +
221
206
  '00:00:20.000 --> 00:00:40.000 vertical:rl\n' +
222
207
  'Test\n\n' +
223
208
  '00:00:40.000 --> 00:00:50.000 vertical:lr\n' +
224
- 'Test<b>2</b>',
209
+ 'Test2',
225
210
  {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
226
211
  });
227
212
 
@@ -661,6 +646,7 @@ describe('VttTextParser', () => {
661
646
  payload: 'Test',
662
647
  color: 'cyan',
663
648
  fontSize: '10px',
649
+ textCombineUpright: 'all',
664
650
  textShadow: textShadow,
665
651
  },
666
652
  {
@@ -669,6 +655,7 @@ describe('VttTextParser', () => {
669
655
  payload: 'Test2',
670
656
  color: 'cyan',
671
657
  fontSize: '10px',
658
+ textCombineUpright: 'all',
672
659
  textShadow: textShadow,
673
660
  },
674
661
  ],
@@ -678,6 +665,7 @@ describe('VttTextParser', () => {
678
665
  'color: cyan;\n'+
679
666
  'font-size: 10px;\n'+
680
667
  `text-shadow: ${textShadow};\n`+
668
+ 'text-combine-upright: all;\n'+
681
669
  '}\n\n' +
682
670
  '00:00:20.000 --> 00:00:40.000\n' +
683
671
  'Test\n\n' +
@@ -776,16 +764,21 @@ describe('VttTextParser', () => {
776
764
  {
777
765
  startTime: 50,
778
766
  endTime: 60,
779
- payload: 'Test',
780
- fontWeight: Cue.fontWeight.BOLD,
781
- fontStyle: Cue.fontStyle.NORMAL,
782
- },
783
- {
784
- startTime: 50,
785
- endTime: 60,
786
- payload: '5',
767
+ payload: '',
787
768
  fontWeight: Cue.fontWeight.BOLD,
788
- fontStyle: Cue.fontStyle.ITALIC,
769
+ nestedCues: [
770
+ {
771
+ startTime: 50,
772
+ endTime: 60,
773
+ payload: 'Test',
774
+ },
775
+ {
776
+ startTime: 50,
777
+ endTime: 60,
778
+ payload: '5',
779
+ fontStyle: Cue.fontStyle.ITALIC,
780
+ },
781
+ ],
789
782
  },
790
783
  ],
791
784
  },
@@ -816,16 +809,21 @@ describe('VttTextParser', () => {
816
809
  {
817
810
  startTime: 80,
818
811
  endTime: 90,
819
- payload: 'Test ',
820
- fontWeight: Cue.fontWeight.BOLD,
821
- fontStyle: Cue.fontStyle.NORMAL,
822
- },
823
- {
824
- startTime: 80,
825
- endTime: 90,
826
- payload: '7',
812
+ payload: '',
827
813
  fontWeight: Cue.fontWeight.BOLD,
828
- fontStyle: Cue.fontStyle.ITALIC,
814
+ nestedCues: [
815
+ {
816
+ startTime: 80,
817
+ endTime: 90,
818
+ payload: 'Test ',
819
+ },
820
+ {
821
+ startTime: 80,
822
+ endTime: 90,
823
+ payload: '7',
824
+ fontStyle: Cue.fontStyle.ITALIC,
825
+ },
826
+ ],
829
827
  },
830
828
  ],
831
829
  },
@@ -918,6 +916,48 @@ describe('VttTextParser', () => {
918
916
  {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
919
917
  });
920
918
 
919
+ it('supports ruby html tags', () => {
920
+ verifyHelper(
921
+ [
922
+ {
923
+ startTime: 20,
924
+ endTime: 40,
925
+ payload: '',
926
+ nestedCues: [
927
+ {
928
+ startTime: 20,
929
+ endTime: 40,
930
+ payload: '',
931
+ rubyTag: 'ruby',
932
+ nestedCues: [
933
+ {
934
+ startTime: 20,
935
+ endTime: 40,
936
+ payload: 'Test',
937
+ },
938
+ {
939
+ startTime: 20,
940
+ endTime: 40,
941
+ payload: '2',
942
+ rubyTag: 'rt',
943
+ },
944
+ {
945
+ startTime: 20,
946
+ endTime: 40,
947
+ payload: '3',
948
+ rubyTag: 'rp',
949
+ },
950
+ ],
951
+ },
952
+ ],
953
+ },
954
+ ],
955
+ 'WEBVTT\n\n' +
956
+ '00:00:20.000 --> 00:00:40.000\n' +
957
+ '<ruby>Test<rt>2</rt><rp>3</rp></ruby>',
958
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
959
+ });
960
+
921
961
  it('supports only two digits in the timestamp', () => {
922
962
  verifyHelper(
923
963
  [
@@ -1013,14 +1053,22 @@ describe('VttTextParser', () => {
1013
1053
  {
1014
1054
  startTime: 70,
1015
1055
  endTime: 80,
1016
- payload: 'Test5.1',
1056
+ payload: '',
1017
1057
  color: 'red',
1018
- },
1019
- {
1020
- startTime: 70,
1021
- endTime: 80,
1022
- payload: 'Test5.2',
1023
- color: 'lime',
1058
+ nestedCues: [
1059
+ {
1060
+ startTime: 70,
1061
+ endTime: 80,
1062
+ payload: 'Test5.1',
1063
+ color: 'red',
1064
+ },
1065
+ {
1066
+ startTime: 70,
1067
+ endTime: 80,
1068
+ payload: 'Test5.2',
1069
+ color: 'lime',
1070
+ },
1071
+ ],
1024
1072
  },
1025
1073
  ],
1026
1074
  },
@@ -1200,9 +1248,17 @@ describe('VttTextParser', () => {
1200
1248
  {
1201
1249
  startTime: 10,
1202
1250
  endTime: 20,
1203
- payload: '2',
1251
+ payload: '',
1204
1252
  color: 'magenta',
1205
- fontStyle: Cue.fontStyle.ITALIC,
1253
+ nestedCues: [
1254
+ {
1255
+ startTime: 10,
1256
+ endTime: 20,
1257
+ payload: '2',
1258
+ color: 'magenta',
1259
+ fontStyle: Cue.fontStyle.ITALIC,
1260
+ },
1261
+ ],
1206
1262
  },
1207
1263
  ],
1208
1264
  },
@@ -1270,13 +1326,14 @@ describe('VttTextParser', () => {
1270
1326
  parser.setSequenceMode(sequenceMode);
1271
1327
  const result = parser.parseMedia(data, time);
1272
1328
 
1273
- const expected = cues.map((cue) => {
1329
+ const checkCue = (cue) => {
1274
1330
  if (cue.nestedCues) {
1275
- cue.nestedCues = cue.nestedCues.map(
1276
- (nestedCue) => jasmine.objectContaining(nestedCue));
1331
+ cue.nestedCues = cue.nestedCues.map((nestedCue) => checkCue(nestedCue));
1277
1332
  }
1278
1333
  return jasmine.objectContaining(cue);
1279
- });
1334
+ };
1335
+
1336
+ const expected = cues.map(checkCue);
1280
1337
  expect(result).toEqual(expected);
1281
1338
  }
1282
1339