shaka-player 4.4.1 → 4.4.3

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 (84) hide show
  1. package/.github/workflows/deflake.yaml +8 -5
  2. package/.github/workflows/release-please.yaml +47 -7
  3. package/.github/workflows/shaka-bot-commands/command-test.sh +1 -1
  4. package/CHANGELOG.md +43 -0
  5. package/CONTRIBUTORS +1 -0
  6. package/demo/common/asset.js +5 -0
  7. package/demo/common/assets.js +20 -5
  8. package/demo/common/message_ids.js +1 -1
  9. package/demo/custom.js +5 -5
  10. package/demo/locales/en.json +2 -1
  11. package/demo/locales/source.json +5 -1
  12. package/demo/main.js +1 -1
  13. package/demo/search.js +3 -3
  14. package/dist/demo.compiled.debug.js +75 -73
  15. package/dist/demo.compiled.debug.map +3 -3
  16. package/dist/demo.compiled.js +75 -73
  17. package/dist/demo.compiled.map +3 -3
  18. package/dist/deps.js +2 -2
  19. package/dist/locales.js +31 -31
  20. package/dist/receiver.compiled.debug.js +38 -36
  21. package/dist/receiver.compiled.debug.map +3 -3
  22. package/dist/receiver.compiled.js +38 -36
  23. package/dist/receiver.compiled.map +3 -3
  24. package/dist/shaka-player.compiled.d.ts +533 -296
  25. package/dist/shaka-player.compiled.debug.d.ts +533 -296
  26. package/dist/shaka-player.compiled.debug.externs.js +308 -1
  27. package/dist/shaka-player.compiled.debug.js +280 -265
  28. package/dist/shaka-player.compiled.debug.map +3 -3
  29. package/dist/shaka-player.compiled.externs.js +308 -1
  30. package/dist/shaka-player.compiled.js +1037 -1027
  31. package/dist/shaka-player.compiled.map +4 -4
  32. package/dist/shaka-player.ui.d.ts +577 -340
  33. package/dist/shaka-player.ui.debug.d.ts +577 -340
  34. package/dist/shaka-player.ui.debug.externs.js +308 -1
  35. package/dist/shaka-player.ui.debug.js +341 -326
  36. package/dist/shaka-player.ui.debug.map +3 -3
  37. package/dist/shaka-player.ui.externs.js +308 -1
  38. package/dist/shaka-player.ui.js +1149 -1141
  39. package/dist/shaka-player.ui.map +4 -4
  40. package/docs/tutorials/fairplay.md +8 -0
  41. package/docs/tutorials/faq.md +1 -1
  42. package/docs/tutorials/offline.md +1 -1
  43. package/externs/shaka/text.js +7 -0
  44. package/lib/dash/dash_parser.js +4 -1
  45. package/lib/dash/segment_template.js +3 -0
  46. package/lib/hls/hls_parser.js +68 -28
  47. package/lib/media/media_source_engine.js +1 -1
  48. package/lib/media/segment_index.js +4 -4
  49. package/lib/media/segment_reference.js +6 -1
  50. package/lib/media/streaming_engine.js +14 -24
  51. package/lib/player.js +8 -57
  52. package/lib/text/cue.js +47 -47
  53. package/lib/text/lrc_text_parser.js +8 -0
  54. package/lib/text/mp4_ttml_parser.js +8 -0
  55. package/lib/text/mp4_vtt_parser.js +8 -0
  56. package/lib/text/sbv_text_parser.js +8 -0
  57. package/lib/text/srt_text_parser.js +8 -0
  58. package/lib/text/ssa_text_parser.js +8 -0
  59. package/lib/text/text_engine.js +8 -1
  60. package/lib/text/ttml_text_parser.js +10 -1
  61. package/lib/text/ui_text_displayer.js +49 -3
  62. package/lib/text/vtt_text_parser.js +19 -3
  63. package/lib/transmuxer/ts_transmuxer.js +44 -43
  64. package/lib/util/cmcd_manager.js +6 -1
  65. package/lib/util/error.js +16 -10
  66. package/lib/util/manifest_parser_utils.js +10 -4
  67. package/lib/util/platform.js +14 -0
  68. package/lib/util/player_configuration.js +2 -2
  69. package/lib/util/stream_utils.js +13 -11
  70. package/lib/util/ts_parser.js +73 -16
  71. package/package.json +2 -2
  72. package/test/dash/dash_parser_manifest_unit.js +5 -0
  73. package/test/dash/dash_parser_segment_base_unit.js +5 -0
  74. package/test/dash/dash_parser_segment_list_unit.js +21 -17
  75. package/test/dash/dash_parser_segment_template_unit.js +47 -0
  76. package/test/hls/hls_live_unit.js +33 -0
  77. package/test/hls/hls_parser_unit.js +2 -57
  78. package/test/test/util/dash_parser_util.js +16 -7
  79. package/test/text/text_engine_unit.js +4 -2
  80. package/test/text/ttml_text_parser_unit.js +3 -4
  81. package/test/text/web_vtt_layout_integration.js +0 -1
  82. package/test/transmuxer/transmuxer_integration.js +4 -4
  83. package/test/util/ts_parser_unit.js +1 -1
  84. package/ui/language_utils.js +0 -15
package/lib/text/cue.js CHANGED
@@ -26,7 +26,7 @@ shaka.text.Cue = class {
26
26
  * The start time of the cue in seconds, relative to the start of the
27
27
  * presentation.
28
28
  * @type {number}
29
- * @exportDoc
29
+ * @export
30
30
  */
31
31
  this.startTime = startTime;
32
32
 
@@ -34,7 +34,7 @@ shaka.text.Cue = class {
34
34
  * The end time of the cue in seconds, relative to the start of the
35
35
  * presentation.
36
36
  * @type {number}
37
- * @exportDoc
37
+ * @export
38
38
  */
39
39
  this.endTime = endTime;
40
40
 
@@ -42,7 +42,7 @@ shaka.text.Cue = class {
42
42
  * The text payload of the cue. If nestedCues is non-empty, this should be
43
43
  * empty. Top-level block containers should have no payload of their own.
44
44
  * @type {string}
45
- * @exportDoc
45
+ * @export
46
46
  */
47
47
  this.payload = payload;
48
48
 
@@ -50,7 +50,7 @@ shaka.text.Cue = class {
50
50
  * The region to render the cue into. Only supported on top-level cues,
51
51
  * because nested cues are inline elements.
52
52
  * @type {shaka.text.CueRegion}
53
- * @exportDoc
53
+ * @export
54
54
  */
55
55
  this.region = new shaka.text.CueRegion();
56
56
 
@@ -58,42 +58,42 @@ shaka.text.Cue = class {
58
58
  * The indent (in percent) of the cue box in the direction defined by the
59
59
  * writing direction.
60
60
  * @type {?number}
61
- * @exportDoc
61
+ * @export
62
62
  */
63
63
  this.position = null;
64
64
 
65
65
  /**
66
66
  * Position alignment of the cue.
67
67
  * @type {shaka.text.Cue.positionAlign}
68
- * @exportDoc
68
+ * @export
69
69
  */
70
70
  this.positionAlign = Cue.positionAlign.AUTO;
71
71
 
72
72
  /**
73
73
  * Size of the cue box (in percents), where 0 means "auto".
74
74
  * @type {number}
75
- * @exportDoc
75
+ * @export
76
76
  */
77
77
  this.size = 0;
78
78
 
79
79
  /**
80
80
  * Alignment of the text inside the cue box.
81
81
  * @type {shaka.text.Cue.textAlign}
82
- * @exportDoc
82
+ * @export
83
83
  */
84
84
  this.textAlign = Cue.textAlign.CENTER;
85
85
 
86
86
  /**
87
87
  * Text direction of the cue.
88
88
  * @type {shaka.text.Cue.direction}
89
- * @exportDoc
89
+ * @export
90
90
  */
91
91
  this.direction = Cue.direction.HORIZONTAL_LEFT_TO_RIGHT;
92
92
 
93
93
  /**
94
94
  * Text writing mode of the cue.
95
95
  * @type {shaka.text.Cue.writingMode}
96
- * @exportDoc
96
+ * @export
97
97
  */
98
98
  this.writingMode = Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM;
99
99
 
@@ -101,7 +101,7 @@ shaka.text.Cue = class {
101
101
  * The way to interpret line field. (Either as an integer line number or
102
102
  * percentage from the display box).
103
103
  * @type {shaka.text.Cue.lineInterpretation}
104
- * @exportDoc
104
+ * @export
105
105
  */
106
106
  this.lineInterpretation = Cue.lineInterpretation.LINE_NUMBER;
107
107
 
@@ -109,7 +109,7 @@ shaka.text.Cue = class {
109
109
  * The offset from the display box in either number of lines or
110
110
  * percentage depending on the value of lineInterpretation.
111
111
  * @type {?number}
112
- * @exportDoc
112
+ * @export
113
113
  */
114
114
  this.line = null;
115
115
 
@@ -118,7 +118,7 @@ shaka.text.Cue = class {
118
118
  * (e.g. '100px'/'100em'). If not specified, this should be no less than
119
119
  * the largest font size applied to the text in the cue.
120
120
  * @type {string}.
121
- * @exportDoc
121
+ * @export
122
122
  */
123
123
  this.lineHeight = '';
124
124
 
@@ -132,7 +132,7 @@ shaka.text.Cue = class {
132
132
  * (for vertical growing right), or left side (for vertical growing left) is
133
133
  * aligned at the line.
134
134
  * @type {shaka.text.Cue.lineAlign}
135
- * @exportDoc
135
+ * @export
136
136
  */
137
137
  this.lineAlign = Cue.lineAlign.START;
138
138
 
@@ -141,84 +141,84 @@ shaka.text.Cue = class {
141
141
  * 'BEFORE' means displaying the captions at the top of the text display
142
142
  * container box, 'CENTER' means in the middle, 'AFTER' means at the bottom.
143
143
  * @type {shaka.text.Cue.displayAlign}
144
- * @exportDoc
144
+ * @export
145
145
  */
146
146
  this.displayAlign = Cue.displayAlign.AFTER;
147
147
 
148
148
  /**
149
149
  * Text color as a CSS color, e.g. "#FFFFFF" or "white".
150
150
  * @type {string}
151
- * @exportDoc
151
+ * @export
152
152
  */
153
153
  this.color = '';
154
154
 
155
155
  /**
156
156
  * Text background color as a CSS color, e.g. "#FFFFFF" or "white".
157
157
  * @type {string}
158
- * @exportDoc
158
+ * @export
159
159
  */
160
160
  this.backgroundColor = '';
161
161
 
162
162
  /**
163
163
  * The URL of the background image, e.g. "data:[mime type];base64,[data]".
164
164
  * @type {string}
165
- * @exportDoc
165
+ * @export
166
166
  */
167
167
  this.backgroundImage = '';
168
168
 
169
169
  /**
170
170
  * The border around this cue as a CSS border.
171
171
  * @type {string}
172
- * @exportDoc
172
+ * @export
173
173
  */
174
174
  this.border = '';
175
175
 
176
176
  /**
177
177
  * Text font size in px or em (e.g. '100px'/'100em').
178
178
  * @type {string}
179
- * @exportDoc
179
+ * @export
180
180
  */
181
181
  this.fontSize = '';
182
182
 
183
183
  /**
184
184
  * Text font weight. Either normal or bold.
185
185
  * @type {shaka.text.Cue.fontWeight}
186
- * @exportDoc
186
+ * @export
187
187
  */
188
188
  this.fontWeight = Cue.fontWeight.NORMAL;
189
189
 
190
190
  /**
191
191
  * Text font style. Normal, italic or oblique.
192
192
  * @type {shaka.text.Cue.fontStyle}
193
- * @exportDoc
193
+ * @export
194
194
  */
195
195
  this.fontStyle = Cue.fontStyle.NORMAL;
196
196
 
197
197
  /**
198
198
  * Text font family.
199
199
  * @type {string}
200
- * @exportDoc
200
+ * @export
201
201
  */
202
202
  this.fontFamily = '';
203
203
 
204
204
  /**
205
205
  * Text letter spacing as a CSS letter-spacing value.
206
206
  * @type {string}
207
- * @exportDoc
207
+ * @export
208
208
  */
209
209
  this.letterSpacing = '';
210
210
 
211
211
  /**
212
212
  * Text line padding as a CSS line-padding value.
213
213
  * @type {string}
214
- * @exportDoc
214
+ * @export
215
215
  */
216
216
  this.linePadding = '';
217
217
 
218
218
  /**
219
219
  * Opacity of the cue element, from 0-1.
220
220
  * @type {number}
221
- * @exportDoc
221
+ * @export
222
222
  */
223
223
  this.opacity = 1;
224
224
 
@@ -226,42 +226,42 @@ shaka.text.Cue = class {
226
226
  * Text decoration. A combination of underline, overline
227
227
  * and line through. Empty array means no decoration.
228
228
  * @type {!Array.<!shaka.text.Cue.textDecoration>}
229
- * @exportDoc
229
+ * @export
230
230
  */
231
231
  this.textDecoration = [];
232
232
 
233
233
  /**
234
234
  * Text shadow color as a CSS text-shadow value.
235
235
  * @type {string}
236
- * @exportDoc
236
+ * @export
237
237
  */
238
238
  this.textShadow = '';
239
239
 
240
240
  /**
241
241
  * Text stroke color as a CSS color, e.g. "#FFFFFF" or "white".
242
242
  * @type {string}
243
- * @exportDoc
243
+ * @export
244
244
  */
245
245
  this.textStrokeColor = '';
246
246
 
247
247
  /**
248
248
  * Text stroke width as a CSS stroke-width value.
249
249
  * @type {string}
250
- * @exportDoc
250
+ * @export
251
251
  */
252
252
  this.textStrokeWidth = '';
253
253
 
254
254
  /**
255
255
  * Whether or not line wrapping should be applied to the cue.
256
256
  * @type {boolean}
257
- * @exportDoc
257
+ * @export
258
258
  */
259
259
  this.wrapLine = true;
260
260
 
261
261
  /**
262
262
  * Id of the cue.
263
263
  * @type {string}
264
- * @exportDoc
264
+ * @export
265
265
  */
266
266
  this.id = '';
267
267
 
@@ -270,7 +270,7 @@ shaka.text.Cue = class {
270
270
  * Top-level cues are blocks, and nested cues are inline elements.
271
271
  * Cues can be nested arbitrarily deeply.
272
272
  * @type {!Array.<!shaka.text.Cue>}
273
- * @exportDoc
273
+ * @export
274
274
  */
275
275
  this.nestedCues = [];
276
276
 
@@ -280,7 +280,7 @@ shaka.text.Cue = class {
280
280
  * in a TTML file. This controls the flow of the final cues; any nested cues
281
281
  * within an "isContainer" cue will be laid out as separate lines.
282
282
  * @type {boolean}
283
- * @exportDoc
283
+ * @export
284
284
  */
285
285
  this.isContainer = false;
286
286
 
@@ -288,7 +288,7 @@ shaka.text.Cue = class {
288
288
  * Whether or not the cue only acts as a line break between two nested cues.
289
289
  * Should only appear in nested cues.
290
290
  * @type {boolean}
291
- * @exportDoc
291
+ * @export
292
292
  */
293
293
  this.lineBreak = false;
294
294
 
@@ -297,7 +297,7 @@ shaka.text.Cue = class {
297
297
  * Region area is divided.
298
298
  *
299
299
  * @type {{ columns: number, rows: number }}
300
- * @exportDoc
300
+ * @export
301
301
  */
302
302
  this.cellResolution = {
303
303
  columns: 32,
@@ -551,7 +551,7 @@ shaka.text.CueRegion = class {
551
551
  /**
552
552
  * Region identifier.
553
553
  * @type {string}
554
- * @exportDoc
554
+ * @export
555
555
  */
556
556
  this.id = '';
557
557
 
@@ -559,7 +559,7 @@ shaka.text.CueRegion = class {
559
559
  * The X offset to start the rendering area in viewportAnchorUnits of the
560
560
  * video width.
561
561
  * @type {number}
562
- * @exportDoc
562
+ * @export
563
563
  */
564
564
  this.viewportAnchorX = 0;
565
565
 
@@ -567,7 +567,7 @@ shaka.text.CueRegion = class {
567
567
  * The X offset to start the rendering area in viewportAnchorUnits of the
568
568
  * video height.
569
569
  * @type {number}
570
- * @exportDoc
570
+ * @export
571
571
  */
572
572
  this.viewportAnchorY = 0;
573
573
 
@@ -575,7 +575,7 @@ shaka.text.CueRegion = class {
575
575
  * The X offset to start the rendering area in percentage (0-100) of this
576
576
  * region width.
577
577
  * @type {number}
578
- * @exportDoc
578
+ * @export
579
579
  */
580
580
  this.regionAnchorX = 0;
581
581
 
@@ -583,42 +583,42 @@ shaka.text.CueRegion = class {
583
583
  * The Y offset to start the rendering area in percentage (0-100) of the
584
584
  * region height.
585
585
  * @type {number}
586
- * @exportDoc
586
+ * @export
587
587
  */
588
588
  this.regionAnchorY = 0;
589
589
 
590
590
  /**
591
591
  * The width of the rendering area in widthUnits.
592
592
  * @type {number}
593
- * @exportDoc
593
+ * @export
594
594
  */
595
595
  this.width = 100;
596
596
 
597
597
  /**
598
598
  * The width of the rendering area in heightUnits.
599
599
  * @type {number}
600
- * @exportDoc
600
+ * @export
601
601
  */
602
602
  this.height = 100;
603
603
 
604
604
  /**
605
605
  * The units (percentage, pixels or lines) the region height is in.
606
606
  * @type {shaka.text.CueRegion.units}
607
- * @exportDoc
607
+ * @export
608
608
  */
609
609
  this.heightUnits = CueRegion.units.PERCENTAGE;
610
610
 
611
611
  /**
612
612
  * The units (percentage or pixels) the region width is in.
613
613
  * @type {shaka.text.CueRegion.units}
614
- * @exportDoc
614
+ * @export
615
615
  */
616
616
  this.widthUnits = CueRegion.units.PERCENTAGE;
617
617
 
618
618
  /**
619
619
  * The units (percentage or pixels) the region viewportAnchors are in.
620
620
  * @type {shaka.text.CueRegion.units}
621
- * @exportDoc
621
+ * @export
622
622
  */
623
623
  this.viewportAnchorUnits = CueRegion.units.PERCENTAGE;
624
624
 
@@ -628,7 +628,7 @@ shaka.text.CueRegion = class {
628
628
  * region up. Otherwise (scroll=NONE) cues will stay fixed at the location
629
629
  * they were first painted in.
630
630
  * @type {shaka.text.CueRegion.scrollMode}
631
- * @exportDoc
631
+ * @export
632
632
  */
633
633
  this.scroll = CueRegion.scrollMode.NONE;
634
634
  }
@@ -36,6 +36,14 @@ shaka.text.LrcTextParser = class {
36
36
  // Unused.
37
37
  }
38
38
 
39
+ /**
40
+ * @override
41
+ * @export
42
+ */
43
+ setManifestType(manifestType) {
44
+ // Unused.
45
+ }
46
+
39
47
  /**
40
48
  * @override
41
49
  * @export
@@ -63,6 +63,14 @@ shaka.text.Mp4TtmlParser = class {
63
63
  // Unused.
64
64
  }
65
65
 
66
+ /**
67
+ * @override
68
+ * @export
69
+ */
70
+ setManifestType(manifestType) {
71
+ // Unused.
72
+ }
73
+
66
74
  /**
67
75
  * @override
68
76
  * @export
@@ -92,6 +92,14 @@ shaka.text.Mp4VttParser = class {
92
92
  // Unused.
93
93
  }
94
94
 
95
+ /**
96
+ * @override
97
+ * @export
98
+ */
99
+ setManifestType(manifestType) {
100
+ // Unused.
101
+ }
102
+
95
103
  /**
96
104
  * @override
97
105
  * @export
@@ -35,6 +35,14 @@ shaka.text.SbvTextParser = class {
35
35
  // Unused.
36
36
  }
37
37
 
38
+ /**
39
+ * @override
40
+ * @export
41
+ */
42
+ setManifestType(manifestType) {
43
+ // Unused.
44
+ }
45
+
38
46
  /**
39
47
  * @override
40
48
  * @export
@@ -43,6 +43,14 @@ shaka.text.SrtTextParser = class {
43
43
  // Unused.
44
44
  }
45
45
 
46
+ /**
47
+ * @override
48
+ * @export
49
+ */
50
+ setManifestType(manifestType) {
51
+ // Unused.
52
+ }
53
+
46
54
  /**
47
55
  * @override
48
56
  * @export
@@ -36,6 +36,14 @@ shaka.text.SsaTextParser = class {
36
36
  // Unused.
37
37
  }
38
38
 
39
+ /**
40
+ * @override
41
+ * @export
42
+ */
43
+ setManifestType(manifestType) {
44
+ // Unused.
45
+ }
46
+
39
47
  /**
40
48
  * @override
41
49
  * @export
@@ -132,8 +132,9 @@ shaka.text.TextEngine = class {
132
132
  * @param {string} mimeType
133
133
  * @param {boolean} sequenceMode
134
134
  * @param {boolean} segmentRelativeVttTiming
135
+ * @param {string} manifestType
135
136
  */
136
- initParser(mimeType, sequenceMode, segmentRelativeVttTiming) {
137
+ initParser(mimeType, sequenceMode, segmentRelativeVttTiming, manifestType) {
137
138
  // No parser for CEA, which is extracted from video and side-loaded
138
139
  // into TextEngine and TextDisplayer.
139
140
  if (mimeType == shaka.util.MimeUtils.CEA608_CLOSED_CAPTION_MIMETYPE ||
@@ -152,6 +153,12 @@ shaka.text.TextEngine = class {
152
153
  shaka.log.alwaysWarn(
153
154
  'Text parsers should have a "setSequenceMode" method!');
154
155
  }
156
+ if (this.parser_.setManifestType) {
157
+ this.parser_.setManifestType(manifestType);
158
+ } else {
159
+ shaka.log.alwaysWarn(
160
+ 'Text parsers should have a "setManifestType" method!');
161
+ }
155
162
  this.segmentRelativeVttTiming_ = segmentRelativeVttTiming;
156
163
  }
157
164
 
@@ -38,6 +38,14 @@ shaka.text.TtmlTextParser = class {
38
38
  // Unused.
39
39
  }
40
40
 
41
+ /**
42
+ * @override
43
+ * @export
44
+ */
45
+ setManifestType(manifestType) {
46
+ // Unused.
47
+ }
48
+
41
49
  /**
42
50
  * @override
43
51
  * @export
@@ -214,11 +222,12 @@ shaka.text.TtmlTextParser = class {
214
222
  }
215
223
  }
216
224
 
217
- const parentIsContent = isContent;
218
225
  if (cueNode.nodeName == 'p' || imageElement) {
219
226
  isContent = true;
220
227
  }
221
228
 
229
+ const parentIsContent = isContent;
230
+
222
231
  const spaceStyle = cueElement.getAttribute('xml:space') ||
223
232
  (whitespaceTrim ? 'default' : 'preserve');
224
233
 
@@ -481,6 +481,43 @@ shaka.text.UITextDisplayer = class {
481
481
  this.currentCuesMap_.set(cue, {cueElement, wrapper, regionElement});
482
482
  }
483
483
 
484
+ /**
485
+ * Compute cue position alignment
486
+ * See https://www.w3.org/TR/webvtt1/#webvtt-cue-position-alignment
487
+ *
488
+ * @param {!shaka.text.Cue} cue
489
+ * @private
490
+ */
491
+ computeCuePositionAlignment_(cue) {
492
+ const Cue = shaka.text.Cue;
493
+ const {direction, positionAlign, textAlign} = cue;
494
+
495
+ if (positionAlign !== Cue.positionAlign.AUTO) {
496
+ // Position align is not AUTO: use it
497
+ return positionAlign;
498
+ }
499
+
500
+ // Position align is AUTO: use text align to compute its value
501
+
502
+ if (textAlign === Cue.textAlign.LEFT ||
503
+ (textAlign === Cue.textAlign.START &&
504
+ direction === Cue.direction.HORIZONTAL_LEFT_TO_RIGHT) ||
505
+ (textAlign === Cue.textAlign.END &&
506
+ direction === Cue.direction.HORIZONTAL_RIGHT_TO_LEFT)) {
507
+ return Cue.positionAlign.LEFT;
508
+ }
509
+
510
+ if (textAlign === Cue.textAlign.RIGHT ||
511
+ (textAlign === Cue.textAlign.START &&
512
+ direction === Cue.direction.HORIZONTAL_RIGHT_TO_LEFT) ||
513
+ (textAlign === Cue.textAlign.END &&
514
+ direction === Cue.direction.HORIZONTAL_LEFT_TO_RIGHT)) {
515
+ return Cue.positionAlign.RIGHT;
516
+ }
517
+
518
+ return Cue.positionAlign.CENTER;
519
+ }
520
+
484
521
  /**
485
522
  * @param {!HTMLElement} cueElement
486
523
  * @param {!shaka.text.Cue} cue
@@ -617,7 +654,15 @@ shaka.text.UITextDisplayer = class {
617
654
  // TODO: Implement line alignment with line number.
618
655
  // TODO: Implement lineAlignment of 'CENTER'.
619
656
  if (cue.line != null) {
620
- if (cue.lineInterpretation == Cue.lineInterpretation.PERCENTAGE) {
657
+ let lineInterpretation = cue.lineInterpretation;
658
+ // HACK: the current implementation of UITextDisplayer only handled
659
+ // PERCENTAGE, as cue.line=0 is zero, we can interpret it as percentage
660
+ // safely.
661
+ if (cue.line == 0 &&
662
+ lineInterpretation == Cue.lineInterpretation.LINE_NUMBER) {
663
+ lineInterpretation = Cue.lineInterpretation.PERCENTAGE;
664
+ }
665
+ if (lineInterpretation == Cue.lineInterpretation.PERCENTAGE) {
621
666
  style.position = 'absolute';
622
667
  if (cue.writingMode == Cue.writingMode.HORIZONTAL_TOP_TO_BOTTOM) {
623
668
  style.width = '100%';
@@ -658,9 +703,10 @@ shaka.text.UITextDisplayer = class {
658
703
 
659
704
  // The positionAlign attribute is an alignment for the text container in
660
705
  // the dimension of the writing direction.
661
- if (cue.positionAlign == Cue.positionAlign.LEFT) {
706
+ const computedPositionAlign = this.computeCuePositionAlignment_(cue);
707
+ if (computedPositionAlign == Cue.positionAlign.LEFT) {
662
708
  style.cssFloat = 'left';
663
- } else if (cue.positionAlign == Cue.positionAlign.RIGHT) {
709
+ } else if (computedPositionAlign == Cue.positionAlign.RIGHT) {
664
710
  style.cssFloat = 'right';
665
711
  }
666
712
 
@@ -8,6 +8,7 @@ goog.provide('shaka.text.VttTextParser');
8
8
 
9
9
  goog.require('goog.asserts');
10
10
  goog.require('shaka.log');
11
+ goog.require('shaka.media.ManifestParser');
11
12
  goog.require('shaka.text.Cue');
12
13
  goog.require('shaka.text.CueRegion');
13
14
  goog.require('shaka.text.TextEngine');
@@ -26,6 +27,9 @@ shaka.text.VttTextParser = class {
26
27
  constructor() {
27
28
  /** @private {boolean} */
28
29
  this.sequenceMode_ = false;
30
+
31
+ /** @private {string} */
32
+ this.manifestType_ = shaka.media.ManifestParser.UNKNOWN;
29
33
  }
30
34
 
31
35
  /**
@@ -44,6 +48,14 @@ shaka.text.VttTextParser = class {
44
48
  this.sequenceMode_ = sequenceMode;
45
49
  }
46
50
 
51
+ /**
52
+ * @override
53
+ * @export
54
+ */
55
+ setManifestType(manifestType) {
56
+ this.manifestType_ = manifestType;
57
+ }
58
+
47
59
  /**
48
60
  * @override
49
61
  * @export
@@ -72,10 +84,9 @@ shaka.text.VttTextParser = class {
72
84
  // HLS content, which should use X-TIMESTAMP-MAP and periodStart instead.
73
85
  let offset = time.vttOffset;
74
86
 
75
- // Only use 'X-TIMESTAMP-MAP' in sequence mode, as that is currently
76
- // shorthand for HLS. Note that an offset based on the first video
87
+ // Only use 'X-TIMESTAMP-MAP' in sequence mode.
88
+ // Note that an offset based on the first video
77
89
  // timestamp has already been extracted, and appears in periodStart.
78
- // The relative offset from X-TIMESTAMP-MAP will be added to that for HLS.
79
90
  if (blocks[0].includes('X-TIMESTAMP-MAP') && this.sequenceMode_) {
80
91
  // https://bit.ly/2K92l7y
81
92
  // The 'X-TIMESTAMP-MAP' header is used in HLS to align text with
@@ -113,6 +124,11 @@ shaka.text.VttTextParser = class {
113
124
 
114
125
  offset = time.periodStart + mpegTime / mpegTimescale - cueTime;
115
126
  }
127
+ } else if (blocks[0].includes('X-TIMESTAMP-MAP') &&
128
+ this.manifestType_ == shaka.media.ManifestParser.HLS) {
129
+ // In we use HLS segments mode, with the presence of this tag we need
130
+ // calculate the offset from the segment startTime.
131
+ offset = time.segmentStart;
116
132
  }
117
133
 
118
134
  // Parse VTT regions.