shaka-player 4.3.2 → 4.3.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.
- package/.github/workflows/selenium-lab-tests.yaml +22 -0
- package/CHANGELOG.md +37 -0
- package/dist/deps.js +4 -3
- package/dist/locales.js +33 -33
- package/dist/shaka-player.compiled.d.ts +10 -0
- package/dist/shaka-player.compiled.debug.d.ts +10 -0
- package/dist/shaka-player.compiled.debug.externs.js +12 -0
- package/dist/shaka-player.compiled.debug.js +152 -144
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +12 -0
- package/dist/shaka-player.compiled.js +778 -772
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.d.ts +10 -0
- package/dist/shaka-player.ui.debug.d.ts +10 -0
- package/dist/shaka-player.ui.debug.externs.js +12 -0
- package/dist/shaka-player.ui.debug.js +164 -157
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +12 -0
- package/dist/shaka-player.ui.js +851 -846
- package/dist/shaka-player.ui.map +4 -4
- package/lib/dash/segment_template.js +17 -5
- package/lib/hls/hls_parser.js +45 -16
- package/lib/media/media_source_engine.js +34 -4
- package/lib/media/segment_index.js +5 -10
- package/lib/media/segment_reference.js +39 -0
- package/lib/media/streaming_engine.js +15 -3
- package/lib/player.js +7 -1
- package/lib/polyfill/media_capabilities.js +4 -1
- package/lib/text/simple_text_displayer.js +2 -64
- package/lib/text/text_utils.js +88 -0
- package/lib/text/ui_text_displayer.js +24 -9
- package/lib/text/vtt_text_parser.js +224 -97
- package/lib/text/web_vtt_generator.js +2 -52
- package/lib/util/dom_utils.js +3 -1
- package/lib/util/platform.js +8 -0
- package/lib/util/stream_utils.js +6 -0
- package/lib/util/timer.js +17 -0
- package/package.json +1 -1
- package/support.html +1 -0
- package/test/dash/dash_parser_manifest_unit.js +0 -36
- package/test/hls/hls_live_unit.js +8 -30
- package/test/hls/hls_parser_unit.js +30 -0
- package/test/media/segment_index_unit.js +28 -0
- package/test/media/streaming_engine_unit.js +91 -119
- package/test/player_integration.js +27 -0
- package/test/player_unit.js +4 -2
- package/test/test/util/layout_tests.js +433 -0
- package/test/test/util/util.js +0 -120
- package/test/{ui → text}/text_displayer_layout_unit.js +59 -235
- package/test/text/ui_text_displayer_unit.js +72 -4
- package/test/text/vtt_text_parser_unit.js +114 -8
- package/test/text/web_vtt_layout_integration.js +528 -0
|
@@ -852,11 +852,11 @@ describe('VttTextParser', () => {
|
|
|
852
852
|
it('support escaped html payload', () => {
|
|
853
853
|
verifyHelper(
|
|
854
854
|
[
|
|
855
|
-
{startTime: 20.1, endTime: 40.505, payload: '"Test & 1"'},
|
|
855
|
+
{startTime: 20.1, endTime: 40.505, payload: '"Test & 1"\u{a0}'},
|
|
856
856
|
],
|
|
857
857
|
'WEBVTT\n\n' +
|
|
858
858
|
'00:00:20.100 --> 00:00:40.505\n' +
|
|
859
|
-
'"Test & 1"',
|
|
859
|
+
'"Test & 1" ',
|
|
860
860
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
861
861
|
});
|
|
862
862
|
|
|
@@ -997,25 +997,32 @@ describe('VttTextParser', () => {
|
|
|
997
997
|
{
|
|
998
998
|
startTime: 80,
|
|
999
999
|
endTime: 90,
|
|
1000
|
-
payload: '<b><c.lime>Parse fail 1</b></c>',
|
|
1000
|
+
payload: '<b><c.lime>Parse fail 1</b></c.lime>',
|
|
1001
1001
|
nestedCues: [],
|
|
1002
1002
|
},
|
|
1003
1003
|
{
|
|
1004
1004
|
startTime: 90,
|
|
1005
1005
|
endTime: 100,
|
|
1006
|
-
payload: '<c.lime><b>Parse fail 2</c></b>',
|
|
1006
|
+
payload: '<c.lime><b>Parse fail 2</c.lime></b>',
|
|
1007
1007
|
nestedCues: [],
|
|
1008
1008
|
},
|
|
1009
1009
|
{
|
|
1010
1010
|
startTime: 100,
|
|
1011
1011
|
endTime: 110,
|
|
1012
|
-
payload: '
|
|
1013
|
-
nestedCues: [
|
|
1012
|
+
payload: '',
|
|
1013
|
+
nestedCues: [
|
|
1014
|
+
{
|
|
1015
|
+
startTime: 100,
|
|
1016
|
+
endTime: 110,
|
|
1017
|
+
payload: 'forward slash 1/2 in text',
|
|
1018
|
+
color: '#0F0',
|
|
1019
|
+
},
|
|
1020
|
+
],
|
|
1014
1021
|
},
|
|
1015
1022
|
{
|
|
1016
1023
|
startTime: 110,
|
|
1017
1024
|
endTime: 120,
|
|
1018
|
-
payload: '<c.lime>less or more < > in text</c>',
|
|
1025
|
+
payload: '<c.lime>less or more < > in text</c.lime>',
|
|
1019
1026
|
nestedCues: [],
|
|
1020
1027
|
},
|
|
1021
1028
|
],
|
|
@@ -1067,6 +1074,53 @@ describe('VttTextParser', () => {
|
|
|
1067
1074
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1068
1075
|
});
|
|
1069
1076
|
|
|
1077
|
+
it('supports voice style blocks', () => {
|
|
1078
|
+
verifyHelper(
|
|
1079
|
+
[
|
|
1080
|
+
{
|
|
1081
|
+
startTime: 20,
|
|
1082
|
+
endTime: 40,
|
|
1083
|
+
payload: '',
|
|
1084
|
+
nestedCues: [
|
|
1085
|
+
{
|
|
1086
|
+
startTime: 20,
|
|
1087
|
+
endTime: 40,
|
|
1088
|
+
payload: 'Test',
|
|
1089
|
+
color: 'cyan',
|
|
1090
|
+
},
|
|
1091
|
+
],
|
|
1092
|
+
},
|
|
1093
|
+
{
|
|
1094
|
+
startTime: 40,
|
|
1095
|
+
endTime: 50,
|
|
1096
|
+
payload: '',
|
|
1097
|
+
nestedCues: [
|
|
1098
|
+
{
|
|
1099
|
+
startTime: 40,
|
|
1100
|
+
endTime: 50,
|
|
1101
|
+
payload: 'Test',
|
|
1102
|
+
color: 'red',
|
|
1103
|
+
},
|
|
1104
|
+
{
|
|
1105
|
+
startTime: 40,
|
|
1106
|
+
endTime: 50,
|
|
1107
|
+
payload: '2',
|
|
1108
|
+
fontStyle: Cue.fontStyle.ITALIC,
|
|
1109
|
+
},
|
|
1110
|
+
],
|
|
1111
|
+
},
|
|
1112
|
+
],
|
|
1113
|
+
'WEBVTT\n\n' +
|
|
1114
|
+
'STYLE\n' +
|
|
1115
|
+
'::cue(v[voice="Shaka"]) { color: cyan; }\n' +
|
|
1116
|
+
'::cue(v[voice=ShakaBis]) { color: red; }\n\n' +
|
|
1117
|
+
'00:00:20.000 --> 00:00:40.000\n' +
|
|
1118
|
+
'<v Shaka>Test\n\n' +
|
|
1119
|
+
'00:00:40.000 --> 00:00:50.000\n' +
|
|
1120
|
+
'<v ShakaBis>Test</v><i>2</i>',
|
|
1121
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1122
|
+
});
|
|
1123
|
+
|
|
1070
1124
|
it('supports default color overriding', () => {
|
|
1071
1125
|
verifyHelper(
|
|
1072
1126
|
[
|
|
@@ -1087,12 +1141,64 @@ describe('VttTextParser', () => {
|
|
|
1087
1141
|
],
|
|
1088
1142
|
'WEBVTT\n\n' +
|
|
1089
1143
|
'STYLE\n' +
|
|
1090
|
-
'::cue(bg_blue) { font-size: 10px; background-color: #FF0 }\n\n' +
|
|
1144
|
+
'::cue(.bg_blue) { font-size: 10px; background-color: #FF0 }\n\n' +
|
|
1091
1145
|
'00:00:10.000 --> 00:00:20.000\n' +
|
|
1092
1146
|
'<c.red.bg_blue>Example 1</c>\n\n',
|
|
1093
1147
|
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1094
1148
|
});
|
|
1095
1149
|
|
|
1150
|
+
// https://github.com/shaka-project/shaka-player/issues/4479
|
|
1151
|
+
it('keep styles when there are line breaks', () => {
|
|
1152
|
+
verifyHelper(
|
|
1153
|
+
[
|
|
1154
|
+
{
|
|
1155
|
+
startTime: 10, endTime: 20,
|
|
1156
|
+
payload: '',
|
|
1157
|
+
nestedCues: [
|
|
1158
|
+
{
|
|
1159
|
+
startTime: 10,
|
|
1160
|
+
endTime: 20,
|
|
1161
|
+
payload: '1',
|
|
1162
|
+
color: '#F0F',
|
|
1163
|
+
},
|
|
1164
|
+
{
|
|
1165
|
+
startTime: 10,
|
|
1166
|
+
endTime: 20,
|
|
1167
|
+
payload: '',
|
|
1168
|
+
lineBreak: true,
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
startTime: 10,
|
|
1172
|
+
endTime: 20,
|
|
1173
|
+
payload: '2',
|
|
1174
|
+
color: '#F0F',
|
|
1175
|
+
fontStyle: Cue.fontStyle.ITALIC,
|
|
1176
|
+
},
|
|
1177
|
+
],
|
|
1178
|
+
},
|
|
1179
|
+
],
|
|
1180
|
+
'WEBVTT\n\n' +
|
|
1181
|
+
'00:00:10.000 --> 00:00:20.000\n' +
|
|
1182
|
+
'<c.magenta>1</c><br/><c.magenta><i>2</i></c>\n\n',
|
|
1183
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1184
|
+
});
|
|
1185
|
+
|
|
1186
|
+
it('does not fail on REGION blocks', () => {
|
|
1187
|
+
verifyHelper(
|
|
1188
|
+
[
|
|
1189
|
+
{
|
|
1190
|
+
startTime: 10, endTime: 20,
|
|
1191
|
+
payload: 'test',
|
|
1192
|
+
},
|
|
1193
|
+
],
|
|
1194
|
+
'WEBVTT\n\n' +
|
|
1195
|
+
'REGION\n' +
|
|
1196
|
+
'id:1\n\n' +
|
|
1197
|
+
'00:00:10.000 --> 00:00:20.000\n' +
|
|
1198
|
+
'test\n\n',
|
|
1199
|
+
{periodStart: 0, segmentStart: 0, segmentEnd: 0, vttOffset: 0});
|
|
1200
|
+
});
|
|
1201
|
+
|
|
1096
1202
|
/**
|
|
1097
1203
|
* @param {!Array} cues
|
|
1098
1204
|
* @param {string} text
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
/*! @license
|
|
2
|
+
* Shaka Player
|
|
3
|
+
* Copyright 2016 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
filterDescribe('WebVTT layout', shaka.test.TextLayoutTests.supported, () => {
|
|
8
|
+
/** @type {shaka.test.TextLayoutTests} */
|
|
9
|
+
let helper;
|
|
10
|
+
|
|
11
|
+
describe('using UI', () => {
|
|
12
|
+
beforeAll(async () => {
|
|
13
|
+
helper = new shaka.test.DomTextLayoutTests('webvtt-ui');
|
|
14
|
+
|
|
15
|
+
await helper.beforeAll();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
beforeEach(async () => {
|
|
19
|
+
await helper.beforeEach();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
afterEach(async () => {
|
|
23
|
+
await helper.afterEach();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
afterAll(async () => {
|
|
27
|
+
await helper.afterAll();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
defineTests();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('using browser-native rendering', () => {
|
|
34
|
+
beforeAll(async () => {
|
|
35
|
+
helper = new shaka.test.NativeTextLayoutTests('webvtt-native');
|
|
36
|
+
|
|
37
|
+
await helper.beforeAll();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
beforeEach(async () => {
|
|
41
|
+
await helper.beforeEach();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
await helper.afterEach();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
afterAll(async () => {
|
|
49
|
+
await helper.afterAll();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
defineTests();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
function defineTests() {
|
|
56
|
+
// The initial set of tests here were a subset of the official test suite:
|
|
57
|
+
// https://github.com/web-platform-tests/wpt/tree/master/webvtt/rendering/cues-with-video/processing-model
|
|
58
|
+
|
|
59
|
+
it('align center', async () => {
|
|
60
|
+
parseAndDisplay([
|
|
61
|
+
'WEBVTT\n',
|
|
62
|
+
'\n',
|
|
63
|
+
'00:00:00.000 --> 00:00:05.000 align:center\n',
|
|
64
|
+
'This is a test\n',
|
|
65
|
+
].join(''));
|
|
66
|
+
|
|
67
|
+
await helper.checkScreenshot('align-center');
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// FIXME: UI version is slightly wrong: black background should hug text
|
|
71
|
+
it('align center long', async () => {
|
|
72
|
+
parseAndDisplay([
|
|
73
|
+
'WEBVTT\n',
|
|
74
|
+
'\n',
|
|
75
|
+
'00:00:00.000 --> 00:00:05.000 align:center\n',
|
|
76
|
+
'This is a test subtitle that most likely will span over several ',
|
|
77
|
+
'rows since it is a pretty long cue with a lot of text.\n',
|
|
78
|
+
].join(''));
|
|
79
|
+
|
|
80
|
+
await helper.checkScreenshot('align-center-long');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('align center position 50%', async () => {
|
|
84
|
+
parseAndDisplay([
|
|
85
|
+
'WEBVTT\n',
|
|
86
|
+
'\n',
|
|
87
|
+
'00:00:00.000 --> 00:00:05.000 align:center position:50%\n',
|
|
88
|
+
'This is a test\n',
|
|
89
|
+
].join(''));
|
|
90
|
+
|
|
91
|
+
await helper.checkScreenshot('align-center-position-50');
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
// FIXME: UI version is wrong: not positioned on the right
|
|
95
|
+
it('align center position 90%', async () => {
|
|
96
|
+
parseAndDisplay([
|
|
97
|
+
'WEBVTT\n',
|
|
98
|
+
'\n',
|
|
99
|
+
'00:00:00.000 --> 00:00:05.000 align:center position:90%\n',
|
|
100
|
+
'This is a test\n',
|
|
101
|
+
].join(''));
|
|
102
|
+
|
|
103
|
+
await helper.checkScreenshot('align-center-position-90');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// FIXME: UI version is wrong: not positioned on the left
|
|
107
|
+
it('align center position 10%', async () => {
|
|
108
|
+
parseAndDisplay([
|
|
109
|
+
'WEBVTT\n',
|
|
110
|
+
'\n',
|
|
111
|
+
'00:00:00.000 --> 00:00:05.000 align:center position:10%\n',
|
|
112
|
+
'This is a test\n',
|
|
113
|
+
].join(''));
|
|
114
|
+
|
|
115
|
+
await helper.checkScreenshot('align-center-position-10');
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
// FIXME: UI version is wrong: not positioned on the left
|
|
119
|
+
it('align center position 10% size 10%', async () => {
|
|
120
|
+
parseAndDisplay([
|
|
121
|
+
'WEBVTT\n',
|
|
122
|
+
'\n',
|
|
123
|
+
'00:00:00.000 --> 00:00:05.000 align:center position:10% size:10%\n',
|
|
124
|
+
'This is a test\n',
|
|
125
|
+
].join(''));
|
|
126
|
+
|
|
127
|
+
await helper.checkScreenshot('align-center-position-10-size-10');
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// FIXME: UI version is wrong: not positioned on the right
|
|
131
|
+
it('align end', async () => {
|
|
132
|
+
parseAndDisplay([
|
|
133
|
+
'WEBVTT\n',
|
|
134
|
+
'\n',
|
|
135
|
+
'00:00:00.000 --> 00:00:05.000 align:end\n',
|
|
136
|
+
'This is a test\n',
|
|
137
|
+
].join(''));
|
|
138
|
+
|
|
139
|
+
await helper.checkScreenshot('align-end');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
// FIXME: UI version is slightly wrong: black background should hug text
|
|
143
|
+
it('align end long', async () => {
|
|
144
|
+
parseAndDisplay([
|
|
145
|
+
'WEBVTT\n',
|
|
146
|
+
'\n',
|
|
147
|
+
'00:00:00.000 --> 00:00:05.000 align:end\n',
|
|
148
|
+
'This is a test subtitle that most likely will span over several ',
|
|
149
|
+
'rows since it is a pretty long cue with a lot of text.\n',
|
|
150
|
+
].join(''));
|
|
151
|
+
|
|
152
|
+
await helper.checkScreenshot('align-end-long');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// FIXME: UI version is wrong: not positioned on the left
|
|
156
|
+
it('align start', async () => {
|
|
157
|
+
parseAndDisplay([
|
|
158
|
+
'WEBVTT\n',
|
|
159
|
+
'\n',
|
|
160
|
+
'00:00:00.000 --> 00:00:05.000 align:start\n',
|
|
161
|
+
'This is a test\n',
|
|
162
|
+
].join(''));
|
|
163
|
+
|
|
164
|
+
await helper.checkScreenshot('align-start');
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
// FIXME: UI version is slightly wrong: black background should hug text
|
|
168
|
+
it('align start long', async () => {
|
|
169
|
+
parseAndDisplay([
|
|
170
|
+
'WEBVTT\n',
|
|
171
|
+
'\n',
|
|
172
|
+
'00:00:00.000 --> 00:00:05.000 align:start\n',
|
|
173
|
+
'This is a test subtitle that most likely will span over several ',
|
|
174
|
+
'rows since it is a pretty long cue with a lot of text.\n',
|
|
175
|
+
].join(''));
|
|
176
|
+
|
|
177
|
+
await helper.checkScreenshot('align-start-long');
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// FIXME: both versions are wrong, top-left corner should be centered
|
|
181
|
+
it('align with position and line', async () => {
|
|
182
|
+
parseAndDisplay([
|
|
183
|
+
'WEBVTT\n',
|
|
184
|
+
'\n',
|
|
185
|
+
'00:00:00.000 --> 00:00:05.000 ', // continued on next line
|
|
186
|
+
'align:start position:50%,line-left line:50%,start\n',
|
|
187
|
+
'This is a test\n',
|
|
188
|
+
].join(''));
|
|
189
|
+
|
|
190
|
+
await helper.checkScreenshot('align-position-line');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('size 50%', async () => {
|
|
194
|
+
parseAndDisplay([
|
|
195
|
+
'WEBVTT\n',
|
|
196
|
+
'\n',
|
|
197
|
+
'00:00:00.000 --> 00:00:05.000 size:50%\n',
|
|
198
|
+
'This is a test subtitle that should wrap no matter what\n',
|
|
199
|
+
].join(''));
|
|
200
|
+
|
|
201
|
+
await helper.checkScreenshot('size-50');
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// FIXME: UI version is wrong: not positioned by line
|
|
205
|
+
it('line -2', async () => {
|
|
206
|
+
parseAndDisplay([
|
|
207
|
+
'WEBVTT\n',
|
|
208
|
+
'\n',
|
|
209
|
+
'00:00:00.000 --> 00:00:05.000 line:-2\n',
|
|
210
|
+
'This is a test\n',
|
|
211
|
+
].join(''));
|
|
212
|
+
|
|
213
|
+
await helper.checkScreenshot('line-negative-2');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// FIXME: UI version is wrong: not positioned by line
|
|
217
|
+
it('line 0', async () => {
|
|
218
|
+
parseAndDisplay([
|
|
219
|
+
'WEBVTT\n',
|
|
220
|
+
'\n',
|
|
221
|
+
'00:00:00.000 --> 00:00:05.000 line:0\n',
|
|
222
|
+
'This is a test\n',
|
|
223
|
+
].join(''));
|
|
224
|
+
|
|
225
|
+
await helper.checkScreenshot('line-0');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// FIXME: UI version is wrong: not positioned by line
|
|
229
|
+
it('line 1', async () => {
|
|
230
|
+
parseAndDisplay([
|
|
231
|
+
'WEBVTT\n',
|
|
232
|
+
'\n',
|
|
233
|
+
'00:00:00.000 --> 00:00:05.000 line:1\n',
|
|
234
|
+
'This is a test\n',
|
|
235
|
+
].join(''));
|
|
236
|
+
|
|
237
|
+
await helper.checkScreenshot('line-1');
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
it('line 50%', async () => {
|
|
241
|
+
parseAndDisplay([
|
|
242
|
+
'WEBVTT\n',
|
|
243
|
+
'\n',
|
|
244
|
+
'00:00:00.000 --> 00:00:05.000 line:50%\n',
|
|
245
|
+
'This is a test\n',
|
|
246
|
+
].join(''));
|
|
247
|
+
|
|
248
|
+
await helper.checkScreenshot('line-50');
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Regression case for http://b/259121343
|
|
252
|
+
// The top center of the cue box should be 85% from the top and
|
|
253
|
+
// horizontally centered.
|
|
254
|
+
// NOTE: The native version is wrong on Chrome and Edge due to layout bugs
|
|
255
|
+
// in Chrome. https://crbug.com/1411464
|
|
256
|
+
it('align to bottom center with restricted size', async () => {
|
|
257
|
+
parseAndDisplay([
|
|
258
|
+
'WEBVTT\n',
|
|
259
|
+
'\n',
|
|
260
|
+
'00:00:00.000 --> 00:00:05.000 ', // continued on next line
|
|
261
|
+
'line:85% position:50% size:63%\n',
|
|
262
|
+
'This is a test\n',
|
|
263
|
+
].join(''));
|
|
264
|
+
|
|
265
|
+
await helper.checkScreenshot('line-85-position-50-size-63');
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
// FIXME: UI version is slightly wrong: gaps between lines when bold
|
|
269
|
+
it('bold long', async () => {
|
|
270
|
+
parseAndDisplay([
|
|
271
|
+
'WEBVTT\n',
|
|
272
|
+
'\n',
|
|
273
|
+
'00:00:00.000 --> 00:00:05.000 align:start\n',
|
|
274
|
+
'<b>This is a test subtitle that most likely will span over several ',
|
|
275
|
+
'rows since it is a pretty long cue with a lot of text.</b>\n',
|
|
276
|
+
].join(''));
|
|
277
|
+
|
|
278
|
+
await helper.checkScreenshot('bold-long');
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// FIXME: UI version is slightly wrong: gaps between lines when italic
|
|
282
|
+
it('italic long', async () => {
|
|
283
|
+
parseAndDisplay([
|
|
284
|
+
'WEBVTT\n',
|
|
285
|
+
'\n',
|
|
286
|
+
'00:00:00.000 --> 00:00:05.000 align:start\n',
|
|
287
|
+
'<i>This is a test subtitle that most likely will span over several ',
|
|
288
|
+
'rows since it is a pretty long cue with a lot of text.</i>\n',
|
|
289
|
+
].join(''));
|
|
290
|
+
|
|
291
|
+
await helper.checkScreenshot('italic-long');
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
// FIXME: UI version is slightly wrong: gaps between lines when italic
|
|
295
|
+
it('underline long', async () => {
|
|
296
|
+
parseAndDisplay([
|
|
297
|
+
'WEBVTT\n',
|
|
298
|
+
'\n',
|
|
299
|
+
'00:00:00.000 --> 00:00:05.000 align:start\n',
|
|
300
|
+
'<u>This is a test subtitle that most likely will span over several ',
|
|
301
|
+
'rows since it is a pretty long cue with a lot of text.</u>\n',
|
|
302
|
+
].join(''));
|
|
303
|
+
|
|
304
|
+
await helper.checkScreenshot('underline-long');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('escaped entities', async () => {
|
|
308
|
+
parseAndDisplay([
|
|
309
|
+
'WEBVTT\n',
|
|
310
|
+
'\n',
|
|
311
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
312
|
+
'Here are the escaped entities: & < > ‎ ‏ \n',
|
|
313
|
+
].join(''));
|
|
314
|
+
|
|
315
|
+
await helper.checkScreenshot('escaped-entities');
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it('white spaces', async () => {
|
|
319
|
+
parseAndDisplay([
|
|
320
|
+
'WEBVTT\n',
|
|
321
|
+
'\n',
|
|
322
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
323
|
+
// eslint-disable-next-line no-tabs
|
|
324
|
+
'A A A A A A\n',
|
|
325
|
+
].join(''));
|
|
326
|
+
|
|
327
|
+
await helper.checkScreenshot('white-spaces');
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
it('embedded styles', async () => {
|
|
331
|
+
parseAndDisplay([
|
|
332
|
+
'WEBVTT\n',
|
|
333
|
+
'\n',
|
|
334
|
+
'STYLE\n',
|
|
335
|
+
'*|*::cue(b) {\n',
|
|
336
|
+
' background: blue;\n',
|
|
337
|
+
'}\n',
|
|
338
|
+
'|*::cue(i) {\n',
|
|
339
|
+
' color: blue;\n',
|
|
340
|
+
'}\n',
|
|
341
|
+
'::cue(i) {\n',
|
|
342
|
+
' background: white;\n',
|
|
343
|
+
'}\n',
|
|
344
|
+
'*::cue(b) {\n',
|
|
345
|
+
' color: white;\n',
|
|
346
|
+
'}\n',
|
|
347
|
+
'::cue {\n',
|
|
348
|
+
' font-size: 30px;\n',
|
|
349
|
+
'}\n',
|
|
350
|
+
'\n',
|
|
351
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
352
|
+
'This <i>is</i> a <b>test</b> subtitle\n',
|
|
353
|
+
].join(''));
|
|
354
|
+
|
|
355
|
+
await helper.checkScreenshot('embedded-styles');
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
it('voices', async () => {
|
|
359
|
+
parseAndDisplay([
|
|
360
|
+
'WEBVTT\n',
|
|
361
|
+
'\n',
|
|
362
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
363
|
+
'This is a <v foo>test subtitle</v>, <v bar>test subtitle</v>\n',
|
|
364
|
+
].join(''));
|
|
365
|
+
|
|
366
|
+
await helper.checkScreenshot('voices');
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
it('voices with styles', async () => {
|
|
370
|
+
parseAndDisplay([
|
|
371
|
+
'WEBVTT\n',
|
|
372
|
+
'\n',
|
|
373
|
+
'STYLE\n',
|
|
374
|
+
'::cue(v[voice=foo]) {\n',
|
|
375
|
+
' background: blue;\n',
|
|
376
|
+
'}\n',
|
|
377
|
+
'::cue(v[voice=bar]) {\n',
|
|
378
|
+
' background: red;\n',
|
|
379
|
+
'}\n',
|
|
380
|
+
'\n',
|
|
381
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
382
|
+
'This is a <v foo>test subtitle</v>, <v bar>test subtitle</v>\n',
|
|
383
|
+
].join(''));
|
|
384
|
+
|
|
385
|
+
await helper.checkScreenshot('voices-with-styles');
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
it('classes', async () => {
|
|
389
|
+
parseAndDisplay([
|
|
390
|
+
'WEBVTT\n',
|
|
391
|
+
'\n',
|
|
392
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
393
|
+
'This is a <c.foo>test subtitle</c>, <c.bar>test subtitle</c>\n',
|
|
394
|
+
].join(''));
|
|
395
|
+
|
|
396
|
+
await helper.checkScreenshot('classes');
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it('classes with styles', async () => {
|
|
400
|
+
parseAndDisplay([
|
|
401
|
+
'WEBVTT\n',
|
|
402
|
+
'\n',
|
|
403
|
+
'STYLE\n',
|
|
404
|
+
'::cue(.foo) {\n',
|
|
405
|
+
' background: blue;\n',
|
|
406
|
+
'}\n',
|
|
407
|
+
'::cue(.bar) {\n',
|
|
408
|
+
' background: red;\n',
|
|
409
|
+
'}\n',
|
|
410
|
+
'\n',
|
|
411
|
+
'00:00:00.000 --> 00:00:05.000\n',
|
|
412
|
+
'This is a <c.foo>test subtitle</c>, <c.bar>test subtitle</c>\n',
|
|
413
|
+
].join(''));
|
|
414
|
+
|
|
415
|
+
await helper.checkScreenshot('classes-with-styles');
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// FIXME: regions not supported
|
|
419
|
+
it('region without anchors', async () => {
|
|
420
|
+
parseAndDisplay([
|
|
421
|
+
'WEBVTT\n',
|
|
422
|
+
'\n',
|
|
423
|
+
'REGION\n',
|
|
424
|
+
'id:1\n',
|
|
425
|
+
'\n',
|
|
426
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
427
|
+
'This is a test subtitle\n',
|
|
428
|
+
].join(''));
|
|
429
|
+
|
|
430
|
+
await helper.checkScreenshot('region-no-anchors');
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
// FIXME: regions not supported
|
|
434
|
+
it('region anchored at top center', async () => {
|
|
435
|
+
parseAndDisplay([
|
|
436
|
+
'WEBVTT\n',
|
|
437
|
+
'\n',
|
|
438
|
+
'REGION\n',
|
|
439
|
+
'id:1\n',
|
|
440
|
+
'regionanchor:50%,0%\n',
|
|
441
|
+
'viewportanchor:50%,0%\n',
|
|
442
|
+
'width:100%\n',
|
|
443
|
+
'\n',
|
|
444
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
445
|
+
'This is a test subtitle\n',
|
|
446
|
+
].join(''));
|
|
447
|
+
|
|
448
|
+
await helper.checkScreenshot('region-anchor-top-center');
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// FIXME: regions not supported
|
|
452
|
+
it('region anchored at top left', async () => {
|
|
453
|
+
parseAndDisplay([
|
|
454
|
+
'WEBVTT\n',
|
|
455
|
+
'\n',
|
|
456
|
+
'REGION\n',
|
|
457
|
+
'id:1\n',
|
|
458
|
+
'regionanchor:0%,0%\n',
|
|
459
|
+
'viewportanchor:0%,0%\n',
|
|
460
|
+
'width:100%\n',
|
|
461
|
+
'\n',
|
|
462
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
463
|
+
'This is a test subtitle\n',
|
|
464
|
+
].join(''));
|
|
465
|
+
|
|
466
|
+
await helper.checkScreenshot('region-anchor-top-left');
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
// FIXME: regions not supported
|
|
470
|
+
it('region with complex anchors', async () => {
|
|
471
|
+
parseAndDisplay([
|
|
472
|
+
'WEBVTT\n',
|
|
473
|
+
'\n',
|
|
474
|
+
'REGION\n',
|
|
475
|
+
'id:1\n',
|
|
476
|
+
'regionanchor:0%,100%\n',
|
|
477
|
+
'viewportanchor:50%,50%\n',
|
|
478
|
+
'width:30%\n',
|
|
479
|
+
'\n',
|
|
480
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
481
|
+
'This is a test subtitle\n',
|
|
482
|
+
].join(''));
|
|
483
|
+
|
|
484
|
+
await helper.checkScreenshot('region-complex-anchors');
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
// FIXME: regions not supported
|
|
488
|
+
it('region 2 lines scroll up', async () => {
|
|
489
|
+
parseAndDisplay([
|
|
490
|
+
'WEBVTT\n',
|
|
491
|
+
'\n',
|
|
492
|
+
'REGION\n',
|
|
493
|
+
'id:1\n',
|
|
494
|
+
'regionanchor:50%,0%\n',
|
|
495
|
+
'viewportanchor:50%,0%\n',
|
|
496
|
+
'width:100%\n',
|
|
497
|
+
'lines:2\n',
|
|
498
|
+
'scroll:up\n',
|
|
499
|
+
'\n',
|
|
500
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
501
|
+
'This is a first test subtitle\n',
|
|
502
|
+
'\n',
|
|
503
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
504
|
+
'This is a second test subtitle\n',
|
|
505
|
+
'\n',
|
|
506
|
+
'00:00:00.000 --> 00:00:05.000 region:1\n',
|
|
507
|
+
'This is a third test subtitle\n',
|
|
508
|
+
].join(''));
|
|
509
|
+
|
|
510
|
+
await helper.checkScreenshot('region-2-lines-scroll-up');
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
/** @param {string} text */
|
|
515
|
+
function parseAndDisplay(text) {
|
|
516
|
+
const data =
|
|
517
|
+
shaka.util.BufferUtils.toUint8(shaka.util.StringUtils.toUTF8(text));
|
|
518
|
+
const time = {
|
|
519
|
+
periodStart: 0,
|
|
520
|
+
segmentStart: 0,
|
|
521
|
+
segmentEnd: 100,
|
|
522
|
+
vttOffset: 0,
|
|
523
|
+
};
|
|
524
|
+
const textParser = new shaka.text.VttTextParser();
|
|
525
|
+
const cues = textParser.parseMedia(data, time);
|
|
526
|
+
helper.textDisplayer.append(cues);
|
|
527
|
+
}
|
|
528
|
+
});
|