mirror of
https://github.com/videojs/m3u8-parser.git
synced 2026-06-06 08:22:33 +00:00
Compare commits
12 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a80bba013 |
||
|
|
dc8394fe20 | ||
|
|
42608b7145 | ||
|
|
0f37308b39 | ||
|
|
a57e3d7bef | ||
|
|
12bc3039ab | ||
|
|
c6aa7e62bd | ||
|
|
0aa6179dc3 | ||
|
|
8bdc0d0e30 | ||
|
|
600dff9956 | ||
|
|
95eff0da82 | ||
|
|
3e4ee65efc |
63 changed files with 168 additions and 43 deletions
|
|
@ -57,6 +57,7 @@ var manifest = [
|
|||
'0.ts',
|
||||
'#EXTINF:6,',
|
||||
'1.ts',
|
||||
'#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z'
|
||||
'#EXTINF:6,',
|
||||
'2.ts',
|
||||
'#EXT-X-ENDLIST'
|
||||
|
|
@ -79,6 +80,7 @@ Manifest {
|
|||
allowCache: boolean,
|
||||
endList: boolean,
|
||||
mediaSequence: number,
|
||||
dateRanges: [],
|
||||
discontinuitySequence: number,
|
||||
playlistType: string,
|
||||
custom: {},
|
||||
|
|
@ -106,8 +108,6 @@ Manifest {
|
|||
'CLOSED-CAPTIONS': {},
|
||||
SUBTITLES: {}
|
||||
},
|
||||
dateTimeString: string,
|
||||
dateTimeObject: Date,
|
||||
targetDuration: number,
|
||||
totalDuration: number,
|
||||
discontinuityStarts: [number],
|
||||
|
|
@ -118,6 +118,7 @@ Manifest {
|
|||
offset: number
|
||||
},
|
||||
duration: number,
|
||||
programDateTime: number,
|
||||
attributes: {},
|
||||
discontinuity: number,
|
||||
uri: string,
|
||||
|
|
|
|||
|
|
@ -356,7 +356,6 @@ export default class ParseStream extends Stream {
|
|||
};
|
||||
if (match[1]) {
|
||||
event.dateTimeString = match[1];
|
||||
event.dateTimeObject = new Date(match[1]);
|
||||
}
|
||||
this.trigger('data', event);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ export default class Parser extends Stream {
|
|||
this.parseStream = new ParseStream();
|
||||
this.lineStream.pipe(this.parseStream);
|
||||
|
||||
this.lastProgramDateTime = null;
|
||||
|
||||
/* eslint-disable consistent-this */
|
||||
const self = this;
|
||||
/* eslint-enable consistent-this */
|
||||
|
|
@ -124,6 +126,7 @@ export default class Parser extends Stream {
|
|||
this.manifest = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
dateRanges: [],
|
||||
segments: []
|
||||
};
|
||||
// keep track of the last seen segment's byte range end, as segments are not required
|
||||
|
|
@ -451,17 +454,21 @@ export default class Parser extends Stream {
|
|||
this.manifest.discontinuityStarts.push(uris.length);
|
||||
},
|
||||
'program-date-time'() {
|
||||
if (typeof this.manifest.dateTimeString === 'undefined') {
|
||||
// PROGRAM-DATE-TIME is a media-segment tag, but for backwards
|
||||
// compatibility, we add the first occurence of the PROGRAM-DATE-TIME tag
|
||||
// to the manifest object
|
||||
// TODO: Consider removing this in future major version
|
||||
this.manifest.dateTimeString = entry.dateTimeString;
|
||||
this.manifest.dateTimeObject = entry.dateTimeObject;
|
||||
}
|
||||
const { lastProgramDateTime } = this;
|
||||
|
||||
currentUri.dateTimeString = entry.dateTimeString;
|
||||
currentUri.dateTimeObject = entry.dateTimeObject;
|
||||
this.lastProgramDateTime = new Date(entry.dateTimeString).getTime();
|
||||
|
||||
// We should extrapolate Program Date Time backward only during first program date time occurrence.
|
||||
// Once we have at least one program date time point, we can always extrapolate it forward using lastProgramDateTime reference.
|
||||
if (lastProgramDateTime === null) {
|
||||
// Extrapolate Program Date Time backward
|
||||
// Since it is first program date time occurrence we're assuming that
|
||||
// all this.manifest.segments have no program date time info
|
||||
this.manifest.segments.reduceRight((programDateTime, segment) => {
|
||||
segment.programDateTime = programDateTime - (segment.duration * 1000);
|
||||
return segment.programDateTime;
|
||||
}, this.lastProgramDateTime);
|
||||
}
|
||||
},
|
||||
targetduration() {
|
||||
if (!isFinite(entry.duration) || entry.duration < 0) {
|
||||
|
|
@ -634,7 +641,6 @@ export default class Parser extends Stream {
|
|||
setHoldBack.call(this, this.manifest);
|
||||
},
|
||||
'daterange'() {
|
||||
this.manifest.dateRanges = this.manifest.dateRanges || [];
|
||||
this.manifest.dateRanges.push(camelCaseKeys(entry.attributes));
|
||||
const index = this.manifest.dateRanges.length - 1;
|
||||
|
||||
|
|
@ -678,11 +684,6 @@ export default class Parser extends Stream {
|
|||
|
||||
this.manifest.dateRanges[index].endDate = new Date(newDateInSeconds);
|
||||
}
|
||||
if (dateRange && !this.manifest.dateTimeString) {
|
||||
this.trigger('warn', {
|
||||
message: 'A playlist with EXT-X-DATERANGE tag must contain atleast one EXT-X-PROGRAM-DATE-TIME tag'
|
||||
});
|
||||
}
|
||||
if (!dateRangeTags[dateRange.id]) {
|
||||
dateRangeTags[dateRange.id] = dateRange;
|
||||
} else {
|
||||
|
|
@ -725,6 +726,12 @@ export default class Parser extends Stream {
|
|||
// reset the last byterange end as it needs to be 0 between parts
|
||||
lastPartByterangeEnd = 0;
|
||||
|
||||
// Once we have at least one program date time we can always extrapolate it forward
|
||||
if (this.lastProgramDateTime !== null) {
|
||||
currentUri.programDateTime = this.lastProgramDateTime;
|
||||
this.lastProgramDateTime += currentUri.duration * 1000;
|
||||
}
|
||||
|
||||
// prepare for the next URI
|
||||
currentUri = {};
|
||||
},
|
||||
|
|
@ -777,7 +784,13 @@ export default class Parser extends Stream {
|
|||
end() {
|
||||
// flush any buffered input
|
||||
this.lineStream.push('\n');
|
||||
if (this.manifest.dateRanges.length && this.lastProgramDateTime === null) {
|
||||
this.trigger('warn', {
|
||||
message: 'A playlist with EXT-X-DATERANGE tag must contain atleast one EXT-X-PROGRAM-DATE-TIME tag'
|
||||
});
|
||||
}
|
||||
|
||||
this.lastProgramDateTime = null;
|
||||
this.trigger('end');
|
||||
}
|
||||
/**
|
||||
|
|
|
|||
1
test/fixtures/integration/absoluteUris.js
vendored
1
test/fixtures/integration/absoluteUris.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/allowCache.js
vendored
1
test/fixtures/integration/allowCache.js
vendored
|
|
@ -1,6 +1,7 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
mediaSequence: 0,
|
||||
dateRanges: [],
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
mediaSequence: 0,
|
||||
dateRanges: [],
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
1
test/fixtures/integration/alternateAudio.js
vendored
1
test/fixtures/integration/alternateAudio.js
vendored
|
|
@ -1,6 +1,7 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
dateRanges: [],
|
||||
mediaGroups: {
|
||||
// TYPE
|
||||
'AUDIO': {
|
||||
|
|
|
|||
1
test/fixtures/integration/alternateVideo.js
vendored
1
test/fixtures/integration/alternateVideo.js
vendored
|
|
@ -1,6 +1,7 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
discontinuityStarts: [],
|
||||
dateRanges: [],
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
aac: {
|
||||
|
|
|
|||
1
test/fixtures/integration/brightcove.js
vendored
1
test/fixtures/integration/brightcove.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
|
|
|
|||
1
test/fixtures/integration/byteRange.js
vendored
1
test/fixtures/integration/byteRange.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
9
test/fixtures/integration/dateTime.js
vendored
9
test/fixtures/integration/dateTime.js
vendored
|
|
@ -1,18 +1,17 @@
|
|||
module.exports = {
|
||||
allowCache: false,
|
||||
mediaSequence: 0,
|
||||
dateRanges: [],
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
{
|
||||
dateTimeString: '2016-06-22T09:20:16.166-04:00',
|
||||
dateTimeObject: new Date('2016-06-22T09:20:16.166-04:00'),
|
||||
programDateTime: 1466601616166,
|
||||
duration: 10,
|
||||
timeline: 0,
|
||||
uri: 'hls_450k_video.ts'
|
||||
},
|
||||
{
|
||||
dateTimeString: '2016-06-22T09:20:26.166-04:00',
|
||||
dateTimeObject: new Date('2016-06-22T09:20:26.166-04:00'),
|
||||
programDateTime: 1466601626166,
|
||||
duration: 10,
|
||||
timeline: 0,
|
||||
uri: 'hls_450k_video.ts'
|
||||
|
|
@ -20,8 +19,6 @@ module.exports = {
|
|||
],
|
||||
targetDuration: 10,
|
||||
endList: true,
|
||||
dateTimeString: '2016-06-22T09:20:16.166-04:00',
|
||||
dateTimeObject: new Date('2016-06-22T09:20:16.166-04:00'),
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: []
|
||||
};
|
||||
|
|
|
|||
1
test/fixtures/integration/diff-init-key.js
vendored
1
test/fixtures/integration/diff-init-key.js
vendored
|
|
@ -2,6 +2,7 @@ module.exports = {
|
|||
allowCache: true,
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: [],
|
||||
dateRanges: [],
|
||||
mediaSequence: 7794,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
1
test/fixtures/integration/disallowCache.js
vendored
1
test/fixtures/integration/disallowCache.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: false,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/disc-sequence.js
vendored
1
test/fixtures/integration/disc-sequence.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
discontinuitySequence: 3,
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/discontinuity.js
vendored
1
test/fixtures/integration/discontinuity.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
discontinuitySequence: 0,
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/domainUris.js
vendored
1
test/fixtures/integration/domainUris.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/empty.js
vendored
1
test/fixtures/integration/empty.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuityStarts: [],
|
||||
segments: []
|
||||
};
|
||||
|
|
|
|||
1
test/fixtures/integration/emptyAllowCache.js
vendored
1
test/fixtures/integration/emptyAllowCache.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
|
|
|
|||
1
test/fixtures/integration/encrypted.js
vendored
1
test/fixtures/integration/encrypted.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 7794,
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: [],
|
||||
|
|
|
|||
1
test/fixtures/integration/event.js
vendored
1
test/fixtures/integration/event.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'EVENT',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 1,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
1
test/fixtures/integration/extinf.js
vendored
1
test/fixtures/integration/extinf.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/fmp4.js
vendored
1
test/fixtures/integration/fmp4.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 1,
|
||||
playlistType: 'VOD',
|
||||
targetDuration: 6,
|
||||
|
|
|
|||
1
test/fixtures/integration/headerOnly.js
vendored
1
test/fixtures/integration/headerOnly.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuityStarts: [],
|
||||
segments: []
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: [],
|
||||
mediaSequence: 0,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: [],
|
||||
mediaSequence: 0,
|
||||
|
|
|
|||
14
test/fixtures/integration/llhls.js
vendored
14
test/fixtures/integration/llhls.js
vendored
|
|
@ -1,7 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateTimeObject: new Date('2019-02-14T02:13:36.106Z'),
|
||||
dateTimeString: '2019-02-14T02:13:36.106Z',
|
||||
dateRanges: [],
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: [],
|
||||
mediaSequence: 266,
|
||||
|
|
@ -38,8 +37,7 @@ module.exports = {
|
|||
partTargetDuration: 0.33334,
|
||||
segments: [
|
||||
{
|
||||
dateTimeObject: new Date('2019-02-14T02:13:36.106Z'),
|
||||
dateTimeString: '2019-02-14T02:13:36.106Z',
|
||||
programDateTime: 1550110416106,
|
||||
duration: 4.00008,
|
||||
map: {
|
||||
uri: 'init.mp4'
|
||||
|
|
@ -52,6 +50,7 @@ module.exports = {
|
|||
map: {
|
||||
uri: 'init.mp4'
|
||||
},
|
||||
programDateTime: 1550110420106.08,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence267.mp4'
|
||||
},
|
||||
|
|
@ -60,6 +59,7 @@ module.exports = {
|
|||
map: {
|
||||
uri: 'init.mp4'
|
||||
},
|
||||
programDateTime: 1550110424106.1602,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence268.mp4'
|
||||
},
|
||||
|
|
@ -68,6 +68,7 @@ module.exports = {
|
|||
map: {
|
||||
uri: 'init.mp4'
|
||||
},
|
||||
programDateTime: 1550110428106.2402,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence269.mp4'
|
||||
},
|
||||
|
|
@ -76,6 +77,7 @@ module.exports = {
|
|||
map: {
|
||||
uri: 'init.mp4'
|
||||
},
|
||||
programDateTime: 1550110432106.3203,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence270.mp4'
|
||||
},
|
||||
|
|
@ -84,6 +86,7 @@ module.exports = {
|
|||
map: {
|
||||
uri: 'init.mp4'
|
||||
},
|
||||
programDateTime: 1550110436106.4004,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence271.mp4',
|
||||
parts: [
|
||||
|
|
@ -140,12 +143,11 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
{
|
||||
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
|
||||
dateTimeString: '2019-02-14T02:14:00.106Z',
|
||||
duration: 4.00008,
|
||||
map: {
|
||||
uri: 'init.mp4'
|
||||
},
|
||||
programDateTime: 1550110440106,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence272.mp4',
|
||||
parts: [
|
||||
|
|
|
|||
9
test/fixtures/integration/llhlsDelta.js
vendored
9
test/fixtures/integration/llhlsDelta.js
vendored
|
|
@ -1,7 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
|
||||
dateTimeString: '2019-02-14T02:14:00.106Z',
|
||||
dateRanges: [],
|
||||
discontinuitySequence: 0,
|
||||
discontinuityStarts: [],
|
||||
mediaSequence: 266,
|
||||
|
|
@ -42,16 +41,19 @@ module.exports = {
|
|||
segments: [
|
||||
{
|
||||
duration: 4.00008,
|
||||
programDateTime: 1550110428105.7598,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence269.mp4'
|
||||
},
|
||||
{
|
||||
duration: 4.00008,
|
||||
programDateTime: 1550110432105.8398,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence270.mp4'
|
||||
},
|
||||
{
|
||||
duration: 4.00008,
|
||||
programDateTime: 1550110436105.92,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence271.mp4',
|
||||
parts: [
|
||||
|
|
@ -108,9 +110,8 @@ module.exports = {
|
|||
]
|
||||
},
|
||||
{
|
||||
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
|
||||
dateTimeString: '2019-02-14T02:14:00.106Z',
|
||||
duration: 4.00008,
|
||||
programDateTime: 1550110440106,
|
||||
timeline: 0,
|
||||
uri: 'fileSequence272.mp4',
|
||||
parts: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
1
test/fixtures/integration/master-fmp4.js
vendored
1
test/fixtures/integration/master-fmp4.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuityStarts: [],
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
|
|
|
|||
1
test/fixtures/integration/master.js
vendored
1
test/fixtures/integration/master.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
|
|
|
|||
1
test/fixtures/integration/media.js
vendored
1
test/fixtures/integration/media.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/mediaSequence.js
vendored
1
test/fixtures/integration/mediaSequence.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/missingEndlist.js
vendored
1
test/fixtures/integration/missingEndlist.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
1
test/fixtures/integration/missingExtinf.js
vendored
1
test/fixtures/integration/missingExtinf.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuityStarts: [],
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuityStarts: [],
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
targetDuration: 10,
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/multipleVideo.js
vendored
1
test/fixtures/integration/multipleVideo.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
discontinuityStarts: [],
|
||||
mediaGroups: {
|
||||
'AUDIO': {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: -11,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/playlist.js
vendored
1
test/fixtures/integration/playlist.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 17,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/start.js
vendored
1
test/fixtures/integration/start.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
playlists: [
|
||||
{
|
||||
attributes: {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 11,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/versionInvalid.js
vendored
1
test/fixtures/integration/versionInvalid.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/whiteSpace.js
vendored
1
test/fixtures/integration/whiteSpace.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
dateRanges: [],
|
||||
mediaSequence: 0,
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
|
|
|
|||
1
test/fixtures/integration/zeroDuration.js
vendored
1
test/fixtures/integration/zeroDuration.js
vendored
|
|
@ -1,6 +1,7 @@
|
|||
module.exports = {
|
||||
allowCache: true,
|
||||
mediaSequence: 0,
|
||||
dateRanges: [],
|
||||
playlistType: 'VOD',
|
||||
segments: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -635,10 +635,6 @@ QUnit.test(
|
|||
element.dateTimeString, '2016-06-22T09:20:16.166-04:00',
|
||||
'dateTimeString is parsed'
|
||||
);
|
||||
assert.deepEqual(
|
||||
element.dateTimeObject, new Date('2016-06-22T09:20:16.166-04:00'),
|
||||
'dateTimeObject is parsed'
|
||||
);
|
||||
|
||||
manifest = '#EXT-X-PROGRAM-DATE-TIME:2016-06-22T09:20:16.16389Z\n';
|
||||
this.lineStream.push(manifest);
|
||||
|
|
@ -650,10 +646,6 @@ QUnit.test(
|
|||
element.dateTimeString, '2016-06-22T09:20:16.16389Z',
|
||||
'dateTimeString is parsed'
|
||||
);
|
||||
assert.deepEqual(
|
||||
element.dateTimeObject, new Date('2016-06-22T09:20:16.16389Z'),
|
||||
'dateTimeObject is parsed'
|
||||
);
|
||||
}
|
||||
);
|
||||
QUnit.test('parses #EXT-X-STREAM-INF with common attributes', function(assert) {
|
||||
|
|
|
|||
|
|
@ -845,6 +845,71 @@ QUnit.module('m3u8s', function(hooks) {
|
|||
);
|
||||
});
|
||||
|
||||
QUnit.test('PDT value is assigned to segments with explicit #EXT-X-PROGRAM-DATE-TIME tags', function(assert) {
|
||||
this.parser.push([
|
||||
'#EXTM3U',
|
||||
'#EXT-X-VERSION:6',
|
||||
'#EXT-X-TARGETDURATION:8',
|
||||
'#EXT-X-MEDIA-SEQUENCE:0',
|
||||
'#EXTINF:8.0',
|
||||
'#EXT-X-PROGRAM-DATE-TIME:2017-07-31T20:35:35.053+00:00',
|
||||
'https://example.com/playlist1.m3u8',
|
||||
'#EXTINF:8.0,',
|
||||
'#EXT-X-PROGRAM-DATE-TIME:2017-07-31T22:14:10.053+00:00',
|
||||
'https://example.com/playlist2.m3u8',
|
||||
'#EXT-X-ENDLIST'
|
||||
].join('\n'));
|
||||
this.parser.end();
|
||||
assert.equal(this.parser.manifest.segments[0].programDateTime, new Date('2017-07-31T20:35:35.053+00:00').getTime());
|
||||
assert.equal(this.parser.manifest.segments[1].programDateTime, new Date('2017-07-31T22:14:10.053+00:00').getTime());
|
||||
});
|
||||
|
||||
QUnit.test('backfill PDT values when the first EXT-X-PROGRAM-DATE-TIME tag appears after one or more Media Segment URIs', function(assert) {
|
||||
this.parser.push([
|
||||
'#EXTM3U',
|
||||
'#EXT-X-VERSION:6',
|
||||
'#EXT-X-TARGETDURATION:8',
|
||||
'#EXT-X-MEDIA-SEQUENCE:0',
|
||||
'#EXTINF:8.0',
|
||||
'https://example.com/playlist1.m3u8',
|
||||
'#EXTINF:8.0,',
|
||||
'https://example.com/playlist2.m3u8',
|
||||
'#EXTINF:8.0',
|
||||
'#EXT-X-PROGRAM-DATE-TIME:2017-07-31T20:35:35.053+00:00',
|
||||
'https://example.com/playlist3.m3u8',
|
||||
'#EXT-X-ENDLIST'
|
||||
].join('\n'));
|
||||
this.parser.end();
|
||||
const segments = this.parser.manifest.segments;
|
||||
|
||||
assert.equal(segments[2].programDateTime, new Date('2017-07-31T20:35:35.053+00:00').getTime());
|
||||
assert.equal(segments[1].programDateTime, segments[2].programDateTime - (segments[1].duration * 1000));
|
||||
assert.equal(segments[0].programDateTime, segments[1].programDateTime - (segments[0].duration * 1000));
|
||||
});
|
||||
|
||||
QUnit.test('extrapolates forward when subsequent fragments do not have explicit PDT tags', function(assert) {
|
||||
this.parser.push([
|
||||
'#EXTM3U',
|
||||
'#EXT-X-VERSION:6',
|
||||
'#EXT-X-TARGETDURATION:8',
|
||||
'#EXT-X-MEDIA-SEQUENCE:0',
|
||||
'#EXTINF:8.0',
|
||||
'#EXT-X-PROGRAM-DATE-TIME:2017-07-31T20:35:35.053+00:00',
|
||||
'https://example.com/playlist1.m3u8',
|
||||
'#EXTINF:8.0,',
|
||||
'https://example.com/playlist2.m3u8',
|
||||
'#EXTINF:8.0',
|
||||
'https://example.com/playlist3.m3u8',
|
||||
'#EXT-X-ENDLIST'
|
||||
].join('\n'));
|
||||
this.parser.end();
|
||||
const segments = this.parser.manifest.segments;
|
||||
|
||||
assert.equal(segments[0].programDateTime, new Date('2017-07-31T20:35:35.053+00:00').getTime());
|
||||
assert.equal(segments[1].programDateTime, segments[0].programDateTime + segments[1].duration * 1000);
|
||||
assert.equal(segments[2].programDateTime, segments[1].programDateTime + segments[2].duration * 1000);
|
||||
});
|
||||
|
||||
QUnit.test('warns when #EXT-X-DATERANGE missing attribute', function(assert) {
|
||||
this.parser.push([
|
||||
'#EXT-X-VERSION:3',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue