@amazon/vinyl-hls-parser 1.1.1 → 1.2.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.
- package/dist/hlsTestAssets/types/current/tsconfig.tsbuildinfo +1 -1
- package/dist/index.cjs +8 -1
- package/dist/index.cjs.map +2 -2
- package/dist/index.js +9 -2
- package/dist/index.js.map +3 -3
- package/dist/test/benchmark.es5.js +56 -248
- package/dist/test/benchmark.js +164 -972
- package/dist/test/benchmark.js.map +4 -4
- package/dist/types/current/parse/parseMainPlaylist.d.ts.map +1 -1
- package/dist/types/current/parse/parseMainPlaylist.js +16 -2
- package/dist/types/current/parse/parseMediaPlaylist.d.ts.map +1 -1
- package/dist/types/current/tsconfig.tsbuildinfo +1 -1
- package/package.json +24 -13
- package/dist/test/benchmark.css +0 -71
- package/dist/test/benchmark.html +0 -67
- package/dist/test/favicon.png +0 -0
- package/dist/test/index.html +0 -61
- package/dist/test/integ.es5.js +0 -410
- package/dist/test/integ.js +0 -2127
- package/dist/test/integ.js.map +0 -7
- package/dist/test/jasmine.css +0 -304
- package/dist/test/jasmineHtml.es5.js +0 -670
- package/dist/test/jasmineHtml.js +0 -10851
- package/dist/test/jasmineHtml.js.map +0 -7
- package/dist/test/styles.css +0 -42
- package/dist/unit/types/current/index.d.ts +0 -7
- package/dist/unit/types/current/index.d.ts.map +0 -1
- package/dist/unit/types/current/index.js +0 -6
- package/dist/unit/types/current/parse/parseAttributes.test.d.ts +0 -2
- package/dist/unit/types/current/parse/parseAttributes.test.d.ts.map +0 -1
- package/dist/unit/types/current/parse/parseAttributes.test.js +0 -70
- package/dist/unit/types/current/parse/parseMainPlaylist.test.d.ts +0 -2
- package/dist/unit/types/current/parse/parseMainPlaylist.test.d.ts.map +0 -1
- package/dist/unit/types/current/parse/parseMainPlaylist.test.js +0 -194
- package/dist/unit/types/current/parse/parseMediaPlaylist.test.d.ts +0 -2
- package/dist/unit/types/current/parse/parseMediaPlaylist.test.d.ts.map +0 -1
- package/dist/unit/types/current/parse/parseMediaPlaylist.test.js +0 -401
- package/dist/unit/types/current/parse/parseUtil.test.d.ts +0 -2
- package/dist/unit/types/current/parse/parseUtil.test.d.ts.map +0 -1
- package/dist/unit/types/current/parse/parseUtil.test.js +0 -67
- package/dist/unit/types/current/setup.d.ts +0 -2
- package/dist/unit/types/current/setup.d.ts.map +0 -1
- package/dist/unit/types/current/setup.js +0 -19
- package/dist/unit/types/current/tsconfig.tsbuildinfo +0 -1
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { IllegalArgumentError, StringParseError, substitute, } from '@amazon/vinyl-util';
|
|
6
|
-
import { parseMediaPlaylist, HLS_VARIABLE_PATTERN, } from '@amazon/vinyl-hls-parser';
|
|
7
|
-
describe('parseMediaPlaylist', () => {
|
|
8
|
-
it('throws StringParseError when #EXTM3U is missing', () => {
|
|
9
|
-
expect(() => parseMediaPlaylist('invalid')).toThrowError(StringParseError);
|
|
10
|
-
});
|
|
11
|
-
it('parses segments with uri, duration, and sequenceNumber', () => {
|
|
12
|
-
const manifest = [
|
|
13
|
-
'#EXTM3U',
|
|
14
|
-
'#EXT-X-TARGETDURATION:10',
|
|
15
|
-
'#EXTINF:9.009,',
|
|
16
|
-
'segment0.ts',
|
|
17
|
-
'#EXTINF:9.009,',
|
|
18
|
-
'segment1.ts',
|
|
19
|
-
'#EXTINF:3.003,',
|
|
20
|
-
'segment2.ts',
|
|
21
|
-
].join('\n');
|
|
22
|
-
const result = parseMediaPlaylist(manifest);
|
|
23
|
-
expect(result.segments.length).toBe(3);
|
|
24
|
-
expect(result.segments[0].uri).toBe('segment0.ts');
|
|
25
|
-
expect(result.segments[0].duration).toBe(9.009);
|
|
26
|
-
expect(result.segments[0].sequenceNumber).toBe(0);
|
|
27
|
-
expect(result.segments[1].sequenceNumber).toBe(1);
|
|
28
|
-
expect(result.segments[2].sequenceNumber).toBe(2);
|
|
29
|
-
});
|
|
30
|
-
it('parses target duration', () => {
|
|
31
|
-
const manifest = '#EXTM3U\n#EXT-X-TARGETDURATION:10\n#EXTINF:9,\nseg.ts';
|
|
32
|
-
const result = parseMediaPlaylist(manifest);
|
|
33
|
-
expect(result.targetDuration).toBe(10);
|
|
34
|
-
});
|
|
35
|
-
it('uses media sequence as starting sequence number', () => {
|
|
36
|
-
const manifest = [
|
|
37
|
-
'#EXTM3U',
|
|
38
|
-
'#EXT-X-MEDIA-SEQUENCE:100',
|
|
39
|
-
'#EXTINF:9,',
|
|
40
|
-
'segment0.ts',
|
|
41
|
-
'#EXTINF:9,',
|
|
42
|
-
'segment1.ts',
|
|
43
|
-
].join('\n');
|
|
44
|
-
const result = parseMediaPlaylist(manifest);
|
|
45
|
-
expect(result.mediaSequence).toBe(100);
|
|
46
|
-
expect(result.segments[0].sequenceNumber).toBe(100);
|
|
47
|
-
expect(result.segments[1].sequenceNumber).toBe(101);
|
|
48
|
-
});
|
|
49
|
-
it('sets ended to true when #EXT-X-ENDLIST is present', () => {
|
|
50
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts\n#EXT-X-ENDLIST';
|
|
51
|
-
const result = parseMediaPlaylist(manifest);
|
|
52
|
-
expect(result.ended).toBe(true);
|
|
53
|
-
});
|
|
54
|
-
it('sets ended to false when #EXT-X-ENDLIST is absent', () => {
|
|
55
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts';
|
|
56
|
-
const result = parseMediaPlaylist(manifest);
|
|
57
|
-
expect(result.ended).toBe(false);
|
|
58
|
-
});
|
|
59
|
-
describe('when #EXT-X-PLAYLIST-TYPE is present', () => {
|
|
60
|
-
it('parses VOD type', () => {
|
|
61
|
-
const manifest = '#EXTM3U\n#EXT-X-PLAYLIST-TYPE:VOD\n#EXTINF:9,\nseg.ts';
|
|
62
|
-
const result = parseMediaPlaylist(manifest);
|
|
63
|
-
expect(result.playlistType).toBe('VOD');
|
|
64
|
-
});
|
|
65
|
-
it('parses EVENT type', () => {
|
|
66
|
-
const manifest = '#EXTM3U\n#EXT-X-PLAYLIST-TYPE:EVENT\n#EXTINF:9,\nseg.ts';
|
|
67
|
-
const result = parseMediaPlaylist(manifest);
|
|
68
|
-
expect(result.playlistType).toBe('EVENT');
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
it('defaults playlistType to LIVE when absent', () => {
|
|
72
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts';
|
|
73
|
-
const result = parseMediaPlaylist(manifest);
|
|
74
|
-
expect(result.playlistType).toBe('LIVE');
|
|
75
|
-
});
|
|
76
|
-
it('parses version number', () => {
|
|
77
|
-
const manifest = '#EXTM3U\n#EXT-X-VERSION:3\n#EXTINF:9,\nseg.ts';
|
|
78
|
-
const result = parseMediaPlaylist(manifest);
|
|
79
|
-
expect(result.version).toBe(3);
|
|
80
|
-
});
|
|
81
|
-
it('defaults version to 1 when absent', () => {
|
|
82
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts';
|
|
83
|
-
const result = parseMediaPlaylist(manifest);
|
|
84
|
-
expect(result.version).toBe(1);
|
|
85
|
-
});
|
|
86
|
-
it('parses segments with relative URIs', () => {
|
|
87
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nsegment.ts';
|
|
88
|
-
const result = parseMediaPlaylist(manifest);
|
|
89
|
-
expect(result.segments[0].uri).toBe('segment.ts');
|
|
90
|
-
});
|
|
91
|
-
it('handles EXT-X-PROGRAM-DATE-TIME between EXTINF and URI', () => {
|
|
92
|
-
const manifest = `#EXTM3U
|
|
93
|
-
#EXTINF:10.0,
|
|
94
|
-
#EXT-X-PROGRAM-DATE-TIME:2023-01-01T00:00:00Z
|
|
95
|
-
segment.ts`;
|
|
96
|
-
const result = parseMediaPlaylist(manifest);
|
|
97
|
-
expect(result.segments[0].programDateTime).toBe('2023-01-01T00:00:00Z');
|
|
98
|
-
});
|
|
99
|
-
it('handles EXT-X-DISCONTINUITY between EXTINF and URI', () => {
|
|
100
|
-
const manifest = `#EXTM3U
|
|
101
|
-
#EXTINF:10.0,
|
|
102
|
-
#EXT-X-DISCONTINUITY
|
|
103
|
-
segment.ts`;
|
|
104
|
-
const result = parseMediaPlaylist(manifest);
|
|
105
|
-
expect(result.segments[0].discontinuity).toBe(true);
|
|
106
|
-
});
|
|
107
|
-
it('handles EXT-X-BYTERANGE without offset between EXTINF and URI', () => {
|
|
108
|
-
const manifest = `#EXTM3U
|
|
109
|
-
#EXTINF:10.0,
|
|
110
|
-
#EXT-X-BYTERANGE:1000000
|
|
111
|
-
segment.ts`;
|
|
112
|
-
const result = parseMediaPlaylist(manifest);
|
|
113
|
-
expect(result.segments[0].byteRange?.length).toBe(1000000);
|
|
114
|
-
expect(result.segments[0].byteRange?.offset).toBe(0);
|
|
115
|
-
});
|
|
116
|
-
it('handles EXTINF without URI at end of file', () => {
|
|
117
|
-
const manifest = `#EXTM3U
|
|
118
|
-
#EXTINF:10.0,`;
|
|
119
|
-
const result = parseMediaPlaylist(manifest);
|
|
120
|
-
expect(result.segments.length).toBe(1);
|
|
121
|
-
expect(result.segments[0].uri).toBe('');
|
|
122
|
-
});
|
|
123
|
-
it('handles EXTINF with whitespace before URI', () => {
|
|
124
|
-
const manifest = `#EXTM3U
|
|
125
|
-
#EXTINF:10.0,
|
|
126
|
-
|
|
127
|
-
segment.ts`;
|
|
128
|
-
const result = parseMediaPlaylist(manifest);
|
|
129
|
-
expect(result.segments[0].uri).toBe('segment.ts');
|
|
130
|
-
});
|
|
131
|
-
it('handles unknown tag between EXTINF and URI', () => {
|
|
132
|
-
const manifest = `#EXTM3U
|
|
133
|
-
#EXTINF:10.0,
|
|
134
|
-
#EXT-X-UNKNOWN-TAG:value
|
|
135
|
-
segment.ts`;
|
|
136
|
-
const result = parseMediaPlaylist(manifest);
|
|
137
|
-
expect(result.segments[0].uri).toBe('segment.ts');
|
|
138
|
-
});
|
|
139
|
-
it('handles empty media playlist', () => {
|
|
140
|
-
const manifest = '#EXTM3U';
|
|
141
|
-
const result = parseMediaPlaylist(manifest);
|
|
142
|
-
expect(result.segments.length).toBe(0);
|
|
143
|
-
});
|
|
144
|
-
it('handles line with only whitespace in media playlist', () => {
|
|
145
|
-
const manifest = `#EXTM3U
|
|
146
|
-
#EXT-X-TARGETDURATION:10
|
|
147
|
-
|
|
148
|
-
#EXTINF:10.0,
|
|
149
|
-
segment.ts`;
|
|
150
|
-
const result = parseMediaPlaylist(manifest);
|
|
151
|
-
expect(result.segments.length).toBe(1);
|
|
152
|
-
expect(result.targetDuration).toBe(10);
|
|
153
|
-
});
|
|
154
|
-
it('handles EXT-X-BYTERANGE with offset in existing test', () => {
|
|
155
|
-
// This test already exists in the integration tests, but let's ensure
|
|
156
|
-
// we test the parts.length > 1 branch explicitly
|
|
157
|
-
const manifest = `#EXTM3U
|
|
158
|
-
#EXTINF:10.0,
|
|
159
|
-
#EXT-X-BYTERANGE:1000000@500000
|
|
160
|
-
segment.ts`;
|
|
161
|
-
const result = parseMediaPlaylist(manifest);
|
|
162
|
-
expect(result.segments[0].byteRange?.length).toBe(1000000);
|
|
163
|
-
expect(result.segments[0].byteRange?.offset).toBe(500000);
|
|
164
|
-
});
|
|
165
|
-
it('handles line that becomes empty after trimming in media playlist', () => {
|
|
166
|
-
// Create a line with non-breaking space
|
|
167
|
-
const manifest = '#EXTM3U\n\u00A0\n#EXTINF:10.0,\nsegment.ts';
|
|
168
|
-
const result = parseMediaPlaylist(manifest);
|
|
169
|
-
expect(result.segments.length).toBe(1);
|
|
170
|
-
});
|
|
171
|
-
describe('when #EXT-X-KEY is present', () => {
|
|
172
|
-
it('attaches encryption key to segments', () => {
|
|
173
|
-
const manifest = [
|
|
174
|
-
'#EXTM3U',
|
|
175
|
-
'#EXT-X-KEY:METHOD=AES-128,URI="key.bin",IV=0x00000001,KEYFORMAT="identity",KEYFORMATVERSIONS="1"',
|
|
176
|
-
'#EXTINF:9,',
|
|
177
|
-
'seg0.ts',
|
|
178
|
-
].join('\n');
|
|
179
|
-
const result = parseMediaPlaylist(manifest);
|
|
180
|
-
const key = result.segments[0].key;
|
|
181
|
-
expect(key.method).toBe('AES-128');
|
|
182
|
-
expect(key.uri).toBe('key.bin');
|
|
183
|
-
expect(key.iv).toBe('0x00000001');
|
|
184
|
-
expect(key.keyFormat).toBe('identity');
|
|
185
|
-
expect(key.keyFormatVersions).toBe('1');
|
|
186
|
-
});
|
|
187
|
-
it('supports key rotation across segments', () => {
|
|
188
|
-
const manifest = [
|
|
189
|
-
'#EXTM3U',
|
|
190
|
-
'#EXT-X-KEY:METHOD=AES-128,URI="key1.bin"',
|
|
191
|
-
'#EXTINF:9,',
|
|
192
|
-
'seg0.ts',
|
|
193
|
-
'#EXTINF:9,',
|
|
194
|
-
'seg1.ts',
|
|
195
|
-
'#EXT-X-KEY:METHOD=AES-128,URI="key2.bin"',
|
|
196
|
-
'#EXTINF:9,',
|
|
197
|
-
'seg2.ts',
|
|
198
|
-
].join('\n');
|
|
199
|
-
const result = parseMediaPlaylist(manifest);
|
|
200
|
-
expect(result.segments[0].key.uri).toBe('key1.bin');
|
|
201
|
-
expect(result.segments[1].key.uri).toBe('key1.bin');
|
|
202
|
-
expect(result.segments[2].key.uri).toBe('key2.bin');
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
it('parses byte range with length and offset', () => {
|
|
206
|
-
const manifest = [
|
|
207
|
-
'#EXTM3U',
|
|
208
|
-
'#EXT-X-BYTERANGE:75232@0',
|
|
209
|
-
'#EXTINF:9,',
|
|
210
|
-
'seg.ts',
|
|
211
|
-
].join('\n');
|
|
212
|
-
const result = parseMediaPlaylist(manifest);
|
|
213
|
-
expect(result.segments[0].byteRange.length).toBe(75232);
|
|
214
|
-
expect(result.segments[0].byteRange.offset).toBe(0);
|
|
215
|
-
});
|
|
216
|
-
it('defaults byte range offset to 0 when omitted', () => {
|
|
217
|
-
const manifest = [
|
|
218
|
-
'#EXTM3U',
|
|
219
|
-
'#EXT-X-BYTERANGE:75232',
|
|
220
|
-
'#EXTINF:9,',
|
|
221
|
-
'seg.ts',
|
|
222
|
-
].join('\n');
|
|
223
|
-
const result = parseMediaPlaylist(manifest);
|
|
224
|
-
expect(result.segments[0].byteRange.length).toBe(75232);
|
|
225
|
-
expect(result.segments[0].byteRange.offset).toBe(0);
|
|
226
|
-
});
|
|
227
|
-
it('marks segment with discontinuity', () => {
|
|
228
|
-
const manifest = [
|
|
229
|
-
'#EXTM3U',
|
|
230
|
-
'#EXTINF:9,',
|
|
231
|
-
'seg0.ts',
|
|
232
|
-
'#EXT-X-DISCONTINUITY',
|
|
233
|
-
'#EXTINF:9,',
|
|
234
|
-
'seg1.ts',
|
|
235
|
-
'#EXTINF:9,',
|
|
236
|
-
'seg2.ts',
|
|
237
|
-
].join('\n');
|
|
238
|
-
const result = parseMediaPlaylist(manifest);
|
|
239
|
-
expect(result.segments[0].discontinuity).toBe(false);
|
|
240
|
-
expect(result.segments[1].discontinuity).toBe(true);
|
|
241
|
-
expect(result.segments[2].discontinuity).toBe(false);
|
|
242
|
-
});
|
|
243
|
-
it('parses program date-time', () => {
|
|
244
|
-
const manifest = [
|
|
245
|
-
'#EXTM3U',
|
|
246
|
-
'#EXT-X-PROGRAM-DATE-TIME:2024-01-01T00:00:00.000Z',
|
|
247
|
-
'#EXTINF:9,',
|
|
248
|
-
'seg0.ts',
|
|
249
|
-
'#EXTINF:9,',
|
|
250
|
-
'seg1.ts',
|
|
251
|
-
].join('\n');
|
|
252
|
-
const result = parseMediaPlaylist(manifest);
|
|
253
|
-
expect(result.segments[0].programDateTime).toBe('2024-01-01T00:00:00.000Z');
|
|
254
|
-
expect(result.segments[1].programDateTime).toBeUndefined();
|
|
255
|
-
});
|
|
256
|
-
it('skips blank lines and comments', () => {
|
|
257
|
-
const manifest = [
|
|
258
|
-
'#EXTM3U',
|
|
259
|
-
'',
|
|
260
|
-
'# comment',
|
|
261
|
-
'#EXTINF:9,',
|
|
262
|
-
'seg.ts',
|
|
263
|
-
].join('\n');
|
|
264
|
-
const result = parseMediaPlaylist(manifest);
|
|
265
|
-
expect(result.segments.length).toBe(1);
|
|
266
|
-
});
|
|
267
|
-
it('parses #EXT-X-MAP with URI', () => {
|
|
268
|
-
const manifest = [
|
|
269
|
-
'#EXTM3U',
|
|
270
|
-
'#EXT-X-MAP:URI="init.mp4"',
|
|
271
|
-
'#EXTINF:9,',
|
|
272
|
-
'seg.ts',
|
|
273
|
-
].join('\n');
|
|
274
|
-
const result = parseMediaPlaylist(manifest);
|
|
275
|
-
expect(result.segments.length).toBe(1);
|
|
276
|
-
expect(result.segments[0].map).toEqual({ uri: 'init.mp4' });
|
|
277
|
-
});
|
|
278
|
-
it('parses #EXT-X-MAP with URI and BYTERANGE', () => {
|
|
279
|
-
const manifest = [
|
|
280
|
-
'#EXTM3U',
|
|
281
|
-
'#EXT-X-MAP:URI="main.mp4",BYTERANGE="812@0"',
|
|
282
|
-
'#EXTINF:9,',
|
|
283
|
-
'seg.ts',
|
|
284
|
-
].join('\n');
|
|
285
|
-
const result = parseMediaPlaylist(manifest);
|
|
286
|
-
expect(result.segments[0].map).toEqual({
|
|
287
|
-
uri: 'main.mp4',
|
|
288
|
-
byteRange: { length: 812, offset: 0 },
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
it('#EXT-X-MAP persists across segments', () => {
|
|
292
|
-
const manifest = [
|
|
293
|
-
'#EXTM3U',
|
|
294
|
-
'#EXT-X-MAP:URI="init.mp4"',
|
|
295
|
-
'#EXTINF:9,',
|
|
296
|
-
'seg0.ts',
|
|
297
|
-
'#EXTINF:9,',
|
|
298
|
-
'seg1.ts',
|
|
299
|
-
].join('\n');
|
|
300
|
-
const result = parseMediaPlaylist(manifest);
|
|
301
|
-
expect(result.segments[0].map?.uri).toBe('init.mp4');
|
|
302
|
-
expect(result.segments[1].map?.uri).toBe('init.mp4');
|
|
303
|
-
});
|
|
304
|
-
it('#EXT-X-MAP can be replaced by a later #EXT-X-MAP', () => {
|
|
305
|
-
const manifest = [
|
|
306
|
-
'#EXTM3U',
|
|
307
|
-
'#EXT-X-MAP:URI="init1.mp4"',
|
|
308
|
-
'#EXTINF:9,',
|
|
309
|
-
'seg0.ts',
|
|
310
|
-
'#EXT-X-MAP:URI="init2.mp4"',
|
|
311
|
-
'#EXTINF:9,',
|
|
312
|
-
'seg1.ts',
|
|
313
|
-
].join('\n');
|
|
314
|
-
const result = parseMediaPlaylist(manifest);
|
|
315
|
-
expect(result.segments[0].map?.uri).toBe('init1.mp4');
|
|
316
|
-
expect(result.segments[1].map?.uri).toBe('init2.mp4');
|
|
317
|
-
});
|
|
318
|
-
it('segment has no map when #EXT-X-MAP is absent', () => {
|
|
319
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts';
|
|
320
|
-
const result = parseMediaPlaylist(manifest);
|
|
321
|
-
expect(result.segments[0].map).toBeUndefined();
|
|
322
|
-
});
|
|
323
|
-
it('handles #EXT-X-MAP between EXTINF and URI', () => {
|
|
324
|
-
const manifest = [
|
|
325
|
-
'#EXTM3U',
|
|
326
|
-
'#EXTINF:9,',
|
|
327
|
-
'#EXT-X-MAP:URI="init.mp4",BYTERANGE="812@0"',
|
|
328
|
-
'seg.ts',
|
|
329
|
-
].join('\n');
|
|
330
|
-
const result = parseMediaPlaylist(manifest);
|
|
331
|
-
expect(result.segments[0].map).toEqual({
|
|
332
|
-
uri: 'init.mp4',
|
|
333
|
-
byteRange: { length: 812, offset: 0 },
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
it('handles segment without encryption key', () => {
|
|
337
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts';
|
|
338
|
-
const result = parseMediaPlaylist(manifest);
|
|
339
|
-
expect(result.segments[0].key).toBeUndefined();
|
|
340
|
-
});
|
|
341
|
-
it('handles segment without byte range', () => {
|
|
342
|
-
const manifest = '#EXTM3U\n#EXTINF:9,\nseg.ts';
|
|
343
|
-
const result = parseMediaPlaylist(manifest);
|
|
344
|
-
expect(result.segments[0].byteRange).toBeUndefined();
|
|
345
|
-
});
|
|
346
|
-
it('byte range applies only to the immediately following segment', () => {
|
|
347
|
-
const manifest = [
|
|
348
|
-
'#EXTM3U',
|
|
349
|
-
'#EXT-X-BYTERANGE:75232@0',
|
|
350
|
-
'#EXTINF:9,',
|
|
351
|
-
'seg0.ts',
|
|
352
|
-
'#EXTINF:9,',
|
|
353
|
-
'seg1.ts',
|
|
354
|
-
].join('\n');
|
|
355
|
-
const result = parseMediaPlaylist(manifest);
|
|
356
|
-
expect(result.segments[0].byteRange).toBeDefined();
|
|
357
|
-
expect(result.segments[1].byteRange).toBeUndefined();
|
|
358
|
-
});
|
|
359
|
-
it('program date-time applies only to the immediately following segment', () => {
|
|
360
|
-
const manifest = [
|
|
361
|
-
'#EXTM3U',
|
|
362
|
-
'#EXT-X-PROGRAM-DATE-TIME:2024-01-01T00:00:00.000Z',
|
|
363
|
-
'#EXTINF:9,',
|
|
364
|
-
'seg0.ts',
|
|
365
|
-
'#EXTINF:9,',
|
|
366
|
-
'seg1.ts',
|
|
367
|
-
].join('\n');
|
|
368
|
-
const result = parseMediaPlaylist(manifest);
|
|
369
|
-
expect(result.segments[0].programDateTime).toBeDefined();
|
|
370
|
-
expect(result.segments[1].programDateTime).toBeUndefined();
|
|
371
|
-
});
|
|
372
|
-
it('substitutes variables in segment URIs when provided', () => {
|
|
373
|
-
const manifest = [
|
|
374
|
-
'#EXTM3U',
|
|
375
|
-
'#EXT-X-TARGETDURATION:6',
|
|
376
|
-
'#EXTINF:6.0,',
|
|
377
|
-
'{$prefix}segment0.ts',
|
|
378
|
-
'#EXT-X-ENDLIST',
|
|
379
|
-
].join('\n');
|
|
380
|
-
const result = parseMediaPlaylist(manifest, {
|
|
381
|
-
prefix: 'https://cdn.example.com/',
|
|
382
|
-
});
|
|
383
|
-
expect(result.segments[0].uri).toBe('https://cdn.example.com/segment0.ts');
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
describe('substituteVariables', () => {
|
|
387
|
-
it('replaces variable references', () => {
|
|
388
|
-
expect(substitute('{$host}/path', {
|
|
389
|
-
host: 'https://cdn.example.com',
|
|
390
|
-
}, HLS_VARIABLE_PATTERN)).toBe('https://cdn.example.com/path');
|
|
391
|
-
});
|
|
392
|
-
it('throws IllegalArgumentError for undefined variables', () => {
|
|
393
|
-
expect(() => substitute('{$unknown}/path', {}, HLS_VARIABLE_PATTERN)).toThrowError(IllegalArgumentError);
|
|
394
|
-
});
|
|
395
|
-
it('replaces multiple variables', () => {
|
|
396
|
-
expect(substitute('{$a}/{$b}', { a: 'x', b: 'y' }, HLS_VARIABLE_PATTERN)).toBe('x/y');
|
|
397
|
-
});
|
|
398
|
-
it('returns string unchanged when no variables', () => {
|
|
399
|
-
expect(substitute('no-vars', {}, HLS_VARIABLE_PATTERN)).toBe('no-vars');
|
|
400
|
-
});
|
|
401
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parseUtil.test.d.ts","sourceRoot":"","sources":["../../../../../test/unit/parse/parseUtil.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { StringReader } from '@amazon/vinyl-util';
|
|
6
|
-
import { readLine, skipWhitespaceLine } from '@amazon/vinyl-hls-parser';
|
|
7
|
-
describe('parseUtil', () => {
|
|
8
|
-
describe('readLine', () => {
|
|
9
|
-
it('reads line with LF ending', () => {
|
|
10
|
-
const reader = new StringReader('line1\nline2');
|
|
11
|
-
expect(readLine(reader)).toBe('line1');
|
|
12
|
-
expect(readLine(reader)).toBe('line2');
|
|
13
|
-
});
|
|
14
|
-
it('reads line with CR ending', () => {
|
|
15
|
-
const reader = new StringReader('line1\rline2');
|
|
16
|
-
expect(readLine(reader)).toBe('line1');
|
|
17
|
-
expect(readLine(reader)).toBe('line2');
|
|
18
|
-
});
|
|
19
|
-
it('reads line with CRLF ending', () => {
|
|
20
|
-
const reader = new StringReader('line1\r\nline2');
|
|
21
|
-
expect(readLine(reader)).toBe('line1');
|
|
22
|
-
expect(readLine(reader)).toBe('line2');
|
|
23
|
-
});
|
|
24
|
-
it('reads line with only CR at EOF', () => {
|
|
25
|
-
const reader = new StringReader('line\r');
|
|
26
|
-
expect(readLine(reader)).toBe('line');
|
|
27
|
-
});
|
|
28
|
-
it('reads line with only LF at EOF', () => {
|
|
29
|
-
const reader = new StringReader('line\n');
|
|
30
|
-
expect(readLine(reader)).toBe('line');
|
|
31
|
-
});
|
|
32
|
-
it('reads line without ending at EOF', () => {
|
|
33
|
-
const reader = new StringReader('lastline');
|
|
34
|
-
expect(readLine(reader)).toBe('lastline');
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
describe('skipWhitespaceLine', () => {
|
|
38
|
-
it('skips whitespace-only line with LF', () => {
|
|
39
|
-
const reader = new StringReader(' \t \ntext');
|
|
40
|
-
expect(skipWhitespaceLine(reader)).toBe(true);
|
|
41
|
-
expect(readLine(reader)).toBe('text');
|
|
42
|
-
});
|
|
43
|
-
it('skips whitespace-only line with CR', () => {
|
|
44
|
-
const reader = new StringReader(' \t \rtext');
|
|
45
|
-
expect(skipWhitespaceLine(reader)).toBe(true);
|
|
46
|
-
expect(readLine(reader)).toBe('text');
|
|
47
|
-
});
|
|
48
|
-
it('skips whitespace-only line with CRLF', () => {
|
|
49
|
-
const reader = new StringReader(' \t \r\ntext');
|
|
50
|
-
expect(skipWhitespaceLine(reader)).toBe(true);
|
|
51
|
-
expect(readLine(reader)).toBe('text');
|
|
52
|
-
});
|
|
53
|
-
it('skips whitespace-only line at EOF', () => {
|
|
54
|
-
const reader = new StringReader(' \t ');
|
|
55
|
-
expect(skipWhitespaceLine(reader)).toBe(true);
|
|
56
|
-
});
|
|
57
|
-
it('does not skip non-whitespace line', () => {
|
|
58
|
-
const reader = new StringReader(' text ');
|
|
59
|
-
expect(skipWhitespaceLine(reader)).toBe(false);
|
|
60
|
-
expect(readLine(reader)).toBe(' text ');
|
|
61
|
-
});
|
|
62
|
-
it('handles empty reader', () => {
|
|
63
|
-
const reader = new StringReader('');
|
|
64
|
-
expect(skipWhitespaceLine(reader)).toBe(true);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../../test/unit/setup.ts"],"names":[],"mappings":""}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
*/
|
|
5
|
-
import { addCustomMatchers, ConsoleReporter, flushPromises, } from '@amazon/vinyl-util/browserTestUtil';
|
|
6
|
-
import { RestApiReporter } from '@amazon/vinyl-util/testUtil';
|
|
7
|
-
import { getGlobalRegistry } from '@amazon/vinyl-util';
|
|
8
|
-
addCustomMatchers();
|
|
9
|
-
jasmine.getEnv().configure({
|
|
10
|
-
stopOnSpecFailure: true,
|
|
11
|
-
stopSpecOnExpectationFailure: true,
|
|
12
|
-
failSpecWithNoExpectations: true,
|
|
13
|
-
});
|
|
14
|
-
jasmine.getEnv().addReporter(new ConsoleReporter());
|
|
15
|
-
RestApiReporter.installFromSearchParam();
|
|
16
|
-
afterEach(async () => {
|
|
17
|
-
await flushPromises();
|
|
18
|
-
getGlobalRegistry().reset();
|
|
19
|
-
});
|