shaka-player 3.3.4 → 4.0.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 (184) hide show
  1. package/.github/workflows/build-and-test.yaml +0 -1
  2. package/.github/workflows/demo-version-index.yaml +8 -0
  3. package/.github/workflows/release-please.yaml +23 -2
  4. package/.github/workflows/selenium-lab-tests.yaml +0 -1
  5. package/.github/workflows/sync-labels.yaml +33 -0
  6. package/.github/workflows/update-issues.yaml +29 -0
  7. package/.github/workflows/validate-pr-title.yaml +35 -0
  8. package/AUTHORS +1 -0
  9. package/CHANGELOG.md +198 -32
  10. package/CONTRIBUTORS +1 -0
  11. package/README.md +10 -7
  12. package/app-engine/demo-version-index/README.md +3 -3
  13. package/app-engine/demo-version-index/app.yaml +27 -1
  14. package/app-engine/demo-version-index/generate.py +164 -0
  15. package/app-engine/demo-version-index/main.py +4 -155
  16. package/app-engine/demo-version-index/requirements.txt +0 -1
  17. package/build/README.md +2 -2
  18. package/build/compiler.py +1 -1
  19. package/build/generateTsDefs.py +0 -2
  20. package/build/shaka-lab.yaml +0 -2
  21. package/build/test.py +7 -1
  22. package/build/types/core +0 -1
  23. package/build/types/polyfill +0 -3
  24. package/demo/common/asset.js +17 -1
  25. package/demo/common/assets.js +29 -0
  26. package/demo/common/message_ids.js +6 -3
  27. package/demo/config.js +10 -11
  28. package/demo/custom.js +39 -0
  29. package/demo/demo_utils.js +0 -1
  30. package/demo/locales/en.json +6 -3
  31. package/demo/locales/source.json +22 -10
  32. package/demo/main.js +9 -6
  33. package/demo/search.js +2 -1
  34. package/dist/controls.css +1 -1
  35. package/dist/demo.compiled.debug.js +71 -64
  36. package/dist/demo.compiled.debug.map +3 -3
  37. package/dist/demo.compiled.js +71 -64
  38. package/dist/demo.compiled.map +3 -3
  39. package/dist/demo.css +1 -1
  40. package/dist/demo.css.map +1 -1
  41. package/dist/deps.js +16 -20
  42. package/dist/locales.js +31 -29
  43. package/dist/receiver.compiled.debug.js +32 -28
  44. package/dist/receiver.compiled.debug.map +3 -3
  45. package/dist/receiver.compiled.js +32 -28
  46. package/dist/receiver.compiled.map +3 -3
  47. package/dist/shaka-player.compiled.d.ts +78 -83
  48. package/dist/shaka-player.compiled.debug.d.ts +78 -83
  49. package/dist/shaka-player.compiled.debug.externs.js +126 -126
  50. package/dist/shaka-player.compiled.debug.js +426 -483
  51. package/dist/shaka-player.compiled.debug.map +4 -4
  52. package/dist/shaka-player.compiled.externs.js +126 -126
  53. package/dist/shaka-player.compiled.js +838 -856
  54. package/dist/shaka-player.compiled.map +4 -4
  55. package/dist/shaka-player.ui.d.ts +80 -83
  56. package/dist/shaka-player.ui.debug.d.ts +80 -83
  57. package/dist/shaka-player.ui.debug.externs.js +134 -126
  58. package/dist/shaka-player.ui.debug.js +488 -543
  59. package/dist/shaka-player.ui.debug.map +4 -4
  60. package/dist/shaka-player.ui.externs.js +134 -126
  61. package/dist/shaka-player.ui.js +980 -994
  62. package/dist/shaka-player.ui.map +4 -4
  63. package/docs/tutorials/config.md +0 -2
  64. package/docs/tutorials/drm-config.md +5 -0
  65. package/docs/tutorials/fairplay.md +7 -22
  66. package/docs/tutorials/faq.md +0 -11
  67. package/docs/tutorials/index.json +2 -8
  68. package/docs/tutorials/plugins.md +1 -3
  69. package/docs/tutorials/upgrade.md +83 -11
  70. package/externs/polyfill.js +15 -0
  71. package/externs/shaka/manifest.js +5 -1
  72. package/externs/shaka/net.js +12 -0
  73. package/externs/shaka/offline.js +5 -1
  74. package/externs/shaka/player.js +39 -32
  75. package/externs/shaka/text.js +12 -12
  76. package/externs/sourcebuffer.js +15 -0
  77. package/lib/ads/client_side_ad.js +13 -2
  78. package/lib/ads/client_side_ad_manager.js +22 -4
  79. package/lib/cast/cast_utils.js +0 -1
  80. package/lib/dash/content_protection.js +85 -5
  81. package/lib/dash/dash_parser.js +1 -1
  82. package/lib/hls/hls_parser.js +378 -743
  83. package/lib/hls/manifest_text_parser.js +2 -3
  84. package/lib/media/drm_engine.js +102 -53
  85. package/lib/media/gap_jumping_controller.js +10 -45
  86. package/lib/media/media_source_engine.js +87 -15
  87. package/lib/media/playhead.js +2 -5
  88. package/lib/media/presentation_timeline.js +1 -2
  89. package/lib/media/segment_index.js +13 -46
  90. package/lib/media/segment_reference.js +47 -1
  91. package/lib/media/streaming_engine.js +29 -11
  92. package/lib/media/time_ranges_utils.js +4 -9
  93. package/lib/net/networking_engine.js +3 -0
  94. package/lib/offline/indexeddb/v1_storage_cell.js +1 -0
  95. package/lib/offline/indexeddb/v2_storage_cell.js +1 -0
  96. package/lib/offline/manifest_converter.js +1 -0
  97. package/lib/offline/storage.js +100 -132
  98. package/lib/player.js +17 -201
  99. package/lib/polyfill/media_capabilities.js +12 -6
  100. package/lib/polyfill/mediasource.js +0 -28
  101. package/lib/polyfill/patchedmediakeys_nop.js +2 -0
  102. package/lib/polyfill/patchedmediakeys_webkit.js +2 -0
  103. package/lib/text/cue.js +0 -6
  104. package/lib/text/lrc_text_parser.js +8 -0
  105. package/lib/text/mp4_ttml_parser.js +8 -0
  106. package/lib/text/mp4_vtt_parser.js +8 -0
  107. package/lib/text/sbv_text_parser.js +8 -0
  108. package/lib/text/simple_text_displayer.js +1 -7
  109. package/lib/text/srt_text_parser.js +8 -0
  110. package/lib/text/ssa_text_parser.js +8 -0
  111. package/lib/text/text_engine.js +19 -3
  112. package/lib/text/ttml_text_parser.js +8 -0
  113. package/lib/text/ui_text_displayer.js +1 -7
  114. package/lib/text/vtt_text_parser.js +24 -2
  115. package/lib/text/web_vtt_generator.js +1 -7
  116. package/lib/util/error.js +9 -13
  117. package/lib/util/fairplay_utils.js +109 -0
  118. package/lib/util/functional.js +0 -42
  119. package/lib/util/mime_utils.js +2 -0
  120. package/lib/util/platform.js +45 -0
  121. package/lib/util/player_configuration.js +12 -6
  122. package/lib/util/pssh.js +23 -4
  123. package/lib/util/stream_utils.js +92 -22
  124. package/lib/util/uint8array_utils.js +0 -16
  125. package/lib/util/xml_utils.js +1 -1
  126. package/package.json +1 -1
  127. package/roadmap.md +19 -19
  128. package/shaka-player.uncompiled.js +0 -3
  129. package/test/cast/cast_utils_unit.js +1 -0
  130. package/test/dash/dash_parser_content_protection_unit.js +44 -0
  131. package/test/dash/dash_parser_manifest_unit.js +0 -24
  132. package/test/dash/dash_parser_segment_template_unit.js +3 -4
  133. package/test/demo/demo_unit.js +2 -1
  134. package/test/hls/hls_live_unit.js +99 -220
  135. package/test/hls/hls_parser_unit.js +515 -432
  136. package/test/media/drm_engine_unit.js +86 -120
  137. package/test/media/media_source_engine_integration.js +26 -3
  138. package/test/media/media_source_engine_unit.js +7 -6
  139. package/test/media/playhead_unit.js +27 -191
  140. package/test/media/segment_index_unit.js +15 -25
  141. package/test/media/streaming_engine_integration.js +4 -39
  142. package/test/media/streaming_engine_unit.js +3 -2
  143. package/test/media/time_ranges_utils_unit.js +0 -5
  144. package/test/offline/manifest_convert_unit.js +34 -4
  145. package/test/offline/offline_manifest_parser_unit.js +1 -0
  146. package/test/offline/storage_integration.js +5 -4
  147. package/test/player_external.js +0 -6
  148. package/test/player_integration.js +16 -0
  149. package/test/player_unit.js +26 -0
  150. package/test/test/util/fake_media_source_engine.js +11 -4
  151. package/test/test/util/manifest_generator.js +3 -1
  152. package/test/test/util/manifest_parser_util.js +4 -1
  153. package/test/test/util/offline_utils.js +1 -0
  154. package/test/test/util/streaming_engine_util.js +1 -0
  155. package/test/test/util/test_scheme.js +24 -1
  156. package/test/test/util/util.js +4 -4
  157. package/test/text/cue_integration.js +2 -2
  158. package/test/text/lrc_text_parser_unit.js +6 -7
  159. package/test/text/mp4_ttml_parser_unit.js +6 -4
  160. package/test/text/mp4_vtt_parser_unit.js +6 -5
  161. package/test/text/sbv_text_parser_unit.js +5 -6
  162. package/test/text/srt_text_parser_unit.js +5 -6
  163. package/test/text/ssa_text_parser_unit.js +17 -29
  164. package/test/text/text_engine_unit.js +45 -5
  165. package/test/text/ttml_text_parser_unit.js +77 -77
  166. package/test/text/vtt_text_parser_unit.js +55 -57
  167. package/test/ui/ui_integration.js +0 -16
  168. package/test/ui/ui_unit.js +27 -0
  169. package/test/util/cmcd_manager_unit.js +3 -0
  170. package/test/util/stream_utils_unit.js +23 -7
  171. package/ui/controls.js +65 -40
  172. package/ui/fullscreen_button.js +26 -6
  173. package/ui/less/containers.less +3 -3
  174. package/ui/locales/en.json +1 -0
  175. package/ui/locales/source.json +5 -0
  176. package/ui/resolution_selection.js +31 -33
  177. package/ui/ui.js +0 -17
  178. package/docs/tutorials/upgrade-v2-5.md +0 -441
  179. package/docs/tutorials/upgrade-v3.md +0 -38
  180. package/lib/polyfill/mathround.js +0 -49
  181. package/lib/polyfill/patchedmediakeys_apple.js +0 -744
  182. package/lib/polyfill/patchedmediakeys_ms.js +0 -698
  183. package/lib/util/mutex.js +0 -52
  184. package/test/util/functional_unit.js +0 -82
@@ -25,13 +25,13 @@ describe('VttTextParser', () => {
25
25
  it('supports no cues', () => {
26
26
  verifyHelper([],
27
27
  'WEBVTT',
28
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
28
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
29
29
  });
30
30
 
31
31
  it('supports initial comments', () => {
32
32
  verifyHelper([],
33
33
  'WEBVTT - Comments',
34
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
34
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
35
35
  });
36
36
 
37
37
  it('supports comment blocks', () => {
@@ -39,7 +39,7 @@ describe('VttTextParser', () => {
39
39
  'WEBVTT\n\n' +
40
40
  'NOTE\n' +
41
41
  'This is a comment block',
42
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
42
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
43
43
  });
44
44
 
45
45
  it('supports comment blocks with inital comment', () => {
@@ -47,7 +47,7 @@ describe('VttTextParser', () => {
47
47
  'WEBVTT\n\n' +
48
48
  'NOTE - A header comment\n' +
49
49
  'This is a comment block',
50
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
50
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
51
51
  });
52
52
 
53
53
  it('handles a blank line at the end of the file', () => {
@@ -58,7 +58,7 @@ describe('VttTextParser', () => {
58
58
  'WEBVTT\n\n' +
59
59
  '00:00:20.000 --> 00:00:40.000\n' +
60
60
  'Test\n\n',
61
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
61
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
62
62
  });
63
63
 
64
64
  it('handles no blank line at the end of the file', () => {
@@ -69,8 +69,7 @@ describe('VttTextParser', () => {
69
69
  'WEBVTT\n\n' +
70
70
  '00:00:20.000 --> 00:00:40.000\n' +
71
71
  'Test\n',
72
- {periodStart: 0, segmentStart: 0, segmentEnd: 0,
73
- });
72
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
74
73
  });
75
74
 
76
75
  it('handles no newline after the final text payload', () => {
@@ -81,7 +80,7 @@ describe('VttTextParser', () => {
81
80
  'WEBVTT\n\n' +
82
81
  '00:00:20.000 --> 00:00:40.000\n' +
83
82
  'Test',
84
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
83
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
85
84
  });
86
85
 
87
86
  it('supports cues with no settings', () => {
@@ -97,7 +96,7 @@ describe('VttTextParser', () => {
97
96
  '2\n' +
98
97
  '00:00:40.000 --> 00:00:50.000\n' +
99
98
  'Test2',
100
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
99
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
101
100
  });
102
101
 
103
102
  it('supports cues with no ID', () => {
@@ -111,7 +110,7 @@ describe('VttTextParser', () => {
111
110
  'Test\n\n' +
112
111
  '00:00:40.000 --> 00:00:50.000\n' +
113
112
  'Test2',
114
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
113
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
115
114
  });
116
115
 
117
116
  it('supports comments within cues', () => {
@@ -127,7 +126,7 @@ describe('VttTextParser', () => {
127
126
  'This is a note\n\n' +
128
127
  '00:00:40.000 --> 00:00:50.000\n' +
129
128
  'Test2',
130
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
129
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
131
130
  });
132
131
 
133
132
  it('supports non-integer timecodes', () => {
@@ -138,7 +137,7 @@ describe('VttTextParser', () => {
138
137
  'WEBVTT\n\n' +
139
138
  '00:00:20.100 --> 00:00:40.505\n' +
140
139
  'Test',
141
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
140
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
142
141
  });
143
142
 
144
143
  it('supports large timecodes', () => {
@@ -149,50 +148,50 @@ describe('VttTextParser', () => {
149
148
  'WEBVTT\n\n' +
150
149
  '00:00:20.000 --> 30:00:00.000\n' +
151
150
  'Test',
152
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
151
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
153
152
  });
154
153
 
155
154
  it('requires header', () => {
156
155
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_HEADER,
157
156
  '',
158
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
157
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
159
158
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_HEADER,
160
159
  '00:00:00.000 --> 00:00:00.020\nTest',
161
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
160
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
162
161
  });
163
162
 
164
163
  it('rejects invalid time values', () => {
165
164
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
166
165
  'WEBVTT\n\n00.020 --> 0:00.040\nTest',
167
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
166
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
168
167
  anyString);
169
168
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
170
169
  'WEBVTT\n\n0:00.020 --> 0:00.040\nTest',
171
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
170
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
172
171
  anyString);
173
172
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
174
173
  'WEBVTT\n\n00:00.20 --> 0:00.040\nTest',
175
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
174
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
176
175
  anyString);
177
176
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
178
177
  'WEBVTT\n\n00:100.20 --> 0:00.040\nTest',
179
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
178
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
180
179
  anyString);
181
180
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
182
181
  'WEBVTT\n\n00:00.020 --> 0:00.040\nTest',
183
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
182
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
184
183
  anyString);
185
184
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
186
185
  'WEBVTT\n\n00:00:00:00.020 --> 0:00.040\nTest',
187
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
186
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
188
187
  anyString);
189
188
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
190
189
  'WEBVTT\n\n00:61.020 --> 0:00.040\nTest',
191
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
190
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
192
191
  anyString);
193
192
  errorHelper(shaka.util.Error.Code.INVALID_TEXT_CUE,
194
193
  'WEBVTT\n\n61:00.020 --> 0:00.040\nTest',
195
- {periodStart: 0, segmentStart: 0, segmentEnd: 0},
194
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0},
196
195
  anyString);
197
196
  });
198
197
 
@@ -217,7 +216,7 @@ describe('VttTextParser', () => {
217
216
  'Test\n\n' +
218
217
  '00:00:40.000 --> 00:00:50.000 vertical:lr\n' +
219
218
  'Test2',
220
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
219
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
221
220
  });
222
221
 
223
222
  it('supports line setting', () => {
@@ -249,7 +248,7 @@ describe('VttTextParser', () => {
249
248
  'Test3\n\n' +
250
249
  '00:00:55.000 --> 00:01:05.000 line:12.3%\n' +
251
250
  'Test4\n\n',
252
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
251
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
253
252
  });
254
253
 
255
254
  it('supports line setting with optional part', () => {
@@ -271,7 +270,7 @@ describe('VttTextParser', () => {
271
270
  'Test\n\n' +
272
271
  '00:00:40.000 --> 00:00:50.000 line:-1,center\n' +
273
272
  'Test2',
274
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
273
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
275
274
  });
276
275
 
277
276
  it('supports position setting', () => {
@@ -285,7 +284,7 @@ describe('VttTextParser', () => {
285
284
  'Test\n\n' +
286
285
  '00:00:25.000 --> 00:00:45.000 position:12.3%\n' +
287
286
  'Test2\n\n',
288
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
287
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
289
288
  });
290
289
 
291
290
  it('supports position setting with optional part', () => {
@@ -305,7 +304,7 @@ describe('VttTextParser', () => {
305
304
  'Test\n\n' +
306
305
  '00:00:20.000 --> 00:00:40.000 position:45%,start\n' +
307
306
  'Test2',
308
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
307
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
309
308
  });
310
309
 
311
310
  it('supports size setting', () => {
@@ -319,7 +318,7 @@ describe('VttTextParser', () => {
319
318
  'Test\n\n' +
320
319
  '00:00:25.000 --> 00:00:45.000 size:12.3%\n' +
321
320
  'Test2\n\n',
322
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
321
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
323
322
  });
324
323
 
325
324
  it('supports align setting', () => {
@@ -330,7 +329,7 @@ describe('VttTextParser', () => {
330
329
  'WEBVTT\n\n' +
331
330
  '00:00:20.000 --> 00:00:40.000 align:center\n' +
332
331
  'Test',
333
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
332
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
334
333
  });
335
334
 
336
335
  it('supports multiple settings', () => {
@@ -348,7 +347,7 @@ describe('VttTextParser', () => {
348
347
  'WEBVTT\n\n' +
349
348
  '00:00:20.000 --> 00:00:40.000 align:center size:56% vertical:lr\n' +
350
349
  'Test',
351
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
350
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
352
351
  });
353
352
 
354
353
  it('supports timestamps with one-digit hour at start time', () => {
@@ -366,7 +365,7 @@ describe('VttTextParser', () => {
366
365
  'WEBVTT\n\n' +
367
366
  '0:00:20.000 --> 00:00:40.000 align:center size:56% vertical:lr\n' +
368
367
  'Test',
369
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
368
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
370
369
  });
371
370
 
372
371
  it('supports timestamps with one-digit hour at end time', () => {
@@ -384,7 +383,7 @@ describe('VttTextParser', () => {
384
383
  'WEBVTT\n\n' +
385
384
  '00:00:20.000 --> 0:00:40.000 align:center size:56% vertical:lr\n' +
386
385
  'Test',
387
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
386
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
388
387
  });
389
388
 
390
389
  it('supports stamps with one-digit hours at start & end time', () => {
@@ -402,15 +401,15 @@ describe('VttTextParser', () => {
402
401
  'WEBVTT\n\n' +
403
402
  '0:00:20.000 --> 0:00:40.000 align:center size:56% vertical:lr\n' +
404
403
  'Test',
405
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
404
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
406
405
  });
407
406
 
408
- it('uses time offset from periodStart, not segmentStart', () => {
407
+ it('uses time offset from vttOffset, not periodStart or segmentStart', () => {
409
408
  verifyHelper(
410
409
  [
411
410
  {
412
- startTime: 70,
413
- endTime: 80,
411
+ startTime: 50,
412
+ endTime: 60,
414
413
  payload: 'Test',
415
414
  textAlign: 'center',
416
415
  size: 56,
@@ -420,10 +419,9 @@ describe('VttTextParser', () => {
420
419
  'WEBVTT\n\n' +
421
420
  '0:00:10.000 --> 0:00:20.000 align:center size:56% vertical:lr\n' +
422
421
  'Test',
423
- {periodStart: 60, segmentStart: 80, segmentEnd: 100});
422
+ {periodStart: 60, segmentStart: 80, segmentEnd: 100, vttOffset: 40});
424
423
  });
425
424
 
426
-
427
425
  it('parses VTTRegions', () => {
428
426
  verifyHelper(
429
427
  [
@@ -451,7 +449,7 @@ describe('VttTextParser', () => {
451
449
  'viewportanchor=10%,90% scroll=up\n\n' +
452
450
  '0:00:20.000 --> 0:00:40.000 region:reg1\n' +
453
451
  'Test',
454
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
452
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
455
453
  });
456
454
 
457
455
  it('ignores and logs invalid settings', () => {
@@ -464,7 +462,7 @@ describe('VttTextParser', () => {
464
462
  'WEBVTT\n\n' +
465
463
  '00:00:20.000 --> 00:00:40.000 vertical:es\n' +
466
464
  'Test\n\n',
467
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
465
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
468
466
 
469
467
  verifyHelper(
470
468
  [
@@ -473,7 +471,7 @@ describe('VttTextParser', () => {
473
471
  'WEBVTT\n\n' +
474
472
  '00:00:20.000 --> 00:00:40.000 vertical:\n' +
475
473
  'Test\n\n',
476
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
474
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
477
475
 
478
476
  verifyHelper(
479
477
  [
@@ -482,7 +480,7 @@ describe('VttTextParser', () => {
482
480
  'WEBVTT\n\n' +
483
481
  '00:00:20.000 --> 00:00:40.000 vertical\n' +
484
482
  'Test\n\n',
485
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
483
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
486
484
 
487
485
  verifyHelper(
488
486
  [
@@ -491,7 +489,7 @@ describe('VttTextParser', () => {
491
489
  'WEBVTT\n\n' +
492
490
  '00:00:20.000 --> 00:00:40.000 line:-3%\n' +
493
491
  'Test\n\n',
494
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
492
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
495
493
 
496
494
  verifyHelper(
497
495
  [
@@ -500,7 +498,7 @@ describe('VttTextParser', () => {
500
498
  'WEBVTT\n\n' +
501
499
  '00:00:20.000 --> 00:00:40.000 line:45%%\n' +
502
500
  'Test\n\n',
503
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
501
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
504
502
 
505
503
  verifyHelper(
506
504
  [
@@ -509,7 +507,7 @@ describe('VttTextParser', () => {
509
507
  'WEBVTT\n\n' +
510
508
  '00:00:20.000 --> 00:00:40.000 align:10\n' +
511
509
  'Test\n\n',
512
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
510
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
513
511
 
514
512
  verifyHelper(
515
513
  [
@@ -518,7 +516,7 @@ describe('VttTextParser', () => {
518
516
  'WEBVTT\n\n' +
519
517
  '00:00:20.000 --> 00:00:40.000 align:foo\n' +
520
518
  'Test\n\n',
521
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
519
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
522
520
 
523
521
  expect(logWarningSpy).toHaveBeenCalledTimes(7);
524
522
  });
@@ -537,7 +535,7 @@ describe('VttTextParser', () => {
537
535
  'Test\n\n' +
538
536
  '00:00:40.000 --> 00:00:50.000 line:-1\n' +
539
537
  'Test2',
540
- {periodStart: 0, segmentStart: 25, segmentEnd: 65});
538
+ {periodStart: 0, segmentStart: 25, segmentEnd: 65, vttOffset: 0});
541
539
  });
542
540
 
543
541
  it('handles timestamp rollover with X-TIMESTAMP-MAP header', () => {
@@ -553,7 +551,7 @@ describe('VttTextParser', () => {
553
551
  'Test',
554
552
  // Non-null segmentStart takes precedence over X-TIMESTAMP-MAP.
555
553
  // This protects us from rollover in the MPEGTS field.
556
- {periodStart: 0, segmentStart: 95440, segmentEnd: 95550});
554
+ {periodStart: 0, segmentStart: 95440, segmentEnd: 95550, vttOffset: 0});
557
555
 
558
556
  verifyHelper(
559
557
  [
@@ -566,7 +564,7 @@ describe('VttTextParser', () => {
566
564
  'X-TIMESTAMP-MAP=MPEGTS:9745408,LOCAL:00:00:00.000\n\n' +
567
565
  '00:00:00.000 --> 00:00:02.000 line:0\n' +
568
566
  'Test2',
569
- {periodStart: 0, segmentStart: 95550, segmentEnd: 95560});
567
+ {periodStart: 0, segmentStart: 95550, segmentEnd: 95560, vttOffset: 0});
570
568
  });
571
569
 
572
570
  it('supports global style blocks', () => {
@@ -597,7 +595,7 @@ describe('VttTextParser', () => {
597
595
  'Test\n\n' +
598
596
  '00:00:40.000 --> 00:00:50.000\n' +
599
597
  'Test2',
600
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
598
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
601
599
  });
602
600
 
603
601
  it('supports global style blocks without blank lines', () => {
@@ -625,7 +623,7 @@ describe('VttTextParser', () => {
625
623
  'Test\n\n' +
626
624
  '00:00:40.000 --> 00:00:50.000\n' +
627
625
  'Test2',
628
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
626
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
629
627
  });
630
628
 
631
629
  it('supports payload stylized', () => {
@@ -766,7 +764,7 @@ describe('VttTextParser', () => {
766
764
  '<b>Test <i>7</i></b>\n\n' +
767
765
  '00:01:30.000 --> 00:01:40.000\n' +
768
766
  '<b>Test<i>8</b>',
769
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
767
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
770
768
  });
771
769
 
772
770
  it('supports specific style blocks', () => {
@@ -794,7 +792,7 @@ describe('VttTextParser', () => {
794
792
  '<b>Test</b>\n\n' +
795
793
  '00:00:40.000 --> 00:00:50.000\n' +
796
794
  'Test2',
797
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
795
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
798
796
  });
799
797
 
800
798
  it('supports only two digits in the timestamp', () => {
@@ -805,7 +803,7 @@ describe('VttTextParser', () => {
805
803
  'WEBVTT\n\n' +
806
804
  '00:00:20.00 --> 00:00:40.00\n' +
807
805
  'Test',
808
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
806
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
809
807
  });
810
808
 
811
809
  it('supports class with default color', () => {
@@ -947,7 +945,7 @@ describe('VttTextParser', () => {
947
945
  '<c.lime>forward slash 1/2 in text</c>\n\n' +
948
946
  '00:01:50.000 --> 00:02:00.000\n' +
949
947
  '<c.lime>less or more < > in text</c>',
950
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
948
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
951
949
  });
952
950
 
953
951
  it('supports default color overriding', () => {
@@ -973,7 +971,7 @@ describe('VttTextParser', () => {
973
971
  '::cue(bg_blue) { font-size: 10px; background-color: #FF0 }\n\n' +
974
972
  '00:00:10.000 --> 00:00:20.000\n' +
975
973
  '<c.red.bg_blue>Example 1</c>\n\n',
976
- {periodStart: 0, segmentStart: 0, segmentEnd: 0});
974
+ {periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
977
975
  });
978
976
 
979
977
  /**
@@ -454,22 +454,6 @@ describe('UI', () => {
454
454
  expect(isChosen).not.toBe(null);
455
455
  });
456
456
 
457
- it('restores the resolutions menu after audio-only playback', async () => {
458
- /** @type {HTMLElement} */
459
- const resolutionButton = shaka.util.Dom.getElementByClassName(
460
- 'shaka-resolution-button', videoContainer);
461
-
462
- // Load an audio-only clip. The menu should be hidden.
463
- await player.load('test:sintel_audio_only_compiled');
464
- expect(player.isAudioOnly()).toBe(true);
465
- expect(resolutionButton.classList.contains('shaka-hidden')).toBe(true);
466
-
467
- // Load an audio-video clip. The menu should be visible again.
468
- await player.load('test:sintel_multi_lingual_multi_res_compiled');
469
- expect(player.isAudioOnly()).toBe(false);
470
- expect(resolutionButton.classList.contains('shaka-hidden')).toBe(false);
471
- });
472
-
473
457
  /**
474
458
  * @return {Element}
475
459
  */
@@ -642,6 +642,33 @@ describe('UI', () => {
642
642
  expect(getResolutions()).toEqual(['540p']);
643
643
  });
644
644
 
645
+ it('displays audio quality based on current stream', async () => {
646
+ const manifest =
647
+ shaka.test.ManifestGenerator.generate((manifest) => {
648
+ manifest.addVariant(0, (variant) => {
649
+ variant.addAudio(0);
650
+ variant.bandwidth = 100000;
651
+ });
652
+ manifest.addVariant(1, (variant) => {
653
+ variant.addAudio(1);
654
+ variant.bandwidth = 200000;
655
+ });
656
+ });
657
+
658
+ shaka.media.ManifestParser.registerParserByMime(
659
+ fakeMimeType, () => new shaka.test.FakeManifestParser(manifest));
660
+
661
+ await player.load(
662
+ /* uri= */ 'fake', /* startTime= */ 0, fakeMimeType);
663
+
664
+ const qualityButtons = videoContainer.querySelectorAll(
665
+ 'button.explicit-resolution > span');
666
+ const qualityOptions =
667
+ Array.from(qualityButtons).map((btn) => btn.innerText);
668
+
669
+ expect(qualityOptions).toEqual(['200 kbits/s', '100 kbits/s']);
670
+ });
671
+
645
672
  /**
646
673
  * Use internals to update the resolution menu. Our fake manifest can
647
674
  * cause problems with startup where the Player will get stuck using
@@ -120,6 +120,9 @@ describe('CmcdManager', () => {
120
120
  retryParameters: /** @type {shaka.extern.RetryParameters} */({}),
121
121
  licenseRequestType: null,
122
122
  sessionId: null,
123
+ drmInfo: null,
124
+ initData: null,
125
+ initDataType: null,
123
126
  streamDataCallback: null,
124
127
  };
125
128
 
@@ -619,11 +619,20 @@ describe('StreamUtils', () => {
619
619
  stream.mimeType = 'image/png';
620
620
  });
621
621
  manifest.addImageStream(3, (stream) => {
622
- stream.mimeType = 'image/jpeg';
622
+ stream.mimeType = 'image/jpg';
623
623
  });
624
624
  manifest.addImageStream(4, (stream) => {
625
+ stream.mimeType = 'image/jpeg';
626
+ });
627
+ manifest.addImageStream(5, (stream) => {
625
628
  stream.mimeType = 'image/bogus';
626
629
  });
630
+ manifest.addImageStream(6, (stream) => {
631
+ stream.mimeType = 'image/avif';
632
+ });
633
+ manifest.addImageStream(7, (stream) => {
634
+ stream.mimeType = 'image/webp';
635
+ });
627
636
  });
628
637
 
629
638
  const noVariant = null;
@@ -631,12 +640,19 @@ describe('StreamUtils', () => {
631
640
  fakeDrmEngine, noVariant, manifest);
632
641
 
633
642
  // Covers a regression in which we would remove streams with codecs.
634
- // The last two streams should be removed because their full MIME types
635
- // are bogus.
636
- expect(manifest.imageStreams.length).toBe(3);
637
- expect(manifest.imageStreams[0].id).toBe(1);
638
- expect(manifest.imageStreams[1].id).toBe(2);
639
- expect(manifest.imageStreams[2].id).toBe(3);
643
+ // The first 4 streams should be there because they are always supported.
644
+ // The 5th stream should be removed because the MIME type is bogus.
645
+ // The 6th and 7th streams may be there, based on platform support.
646
+ expect(manifest.imageStreams).toContain(
647
+ jasmine.objectContaining({id: 1}));
648
+ expect(manifest.imageStreams).toContain(
649
+ jasmine.objectContaining({id: 2}));
650
+ expect(manifest.imageStreams).toContain(
651
+ jasmine.objectContaining({id: 3}));
652
+ expect(manifest.imageStreams).toContain(
653
+ jasmine.objectContaining({id: 4}));
654
+ expect(manifest.imageStreams).not.toContain(
655
+ jasmine.objectContaining({id: 5}));
640
656
  });
641
657
 
642
658
  it('filters transport streams', async () => {