Skip to content

Commit

Permalink
feat: Add PDT to each segment (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
harisha-swaminathan authored Jul 7, 2023
1 parent 4adaa2c commit e7c683f
Show file tree
Hide file tree
Showing 63 changed files with 168 additions and 43 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand All @@ -79,6 +80,7 @@ Manifest {
allowCache: boolean,
endList: boolean,
mediaSequence: number,
dateRanges: [],
discontinuitySequence: number,
playlistType: string,
custom: {},
Expand Down Expand Up @@ -106,8 +108,6 @@ Manifest {
'CLOSED-CAPTIONS': {},
SUBTITLES: {}
},
dateTimeString: string,
dateTimeObject: Date,
targetDuration: number,
totalDuration: number,
discontinuityStarts: [number],
Expand All @@ -119,6 +119,7 @@ Manifest {
offset: number
},
duration: number,
programDateTime: number,
attributes: {},
discontinuity: number,
uri: string,
Expand Down
1 change: 0 additions & 1 deletion src/parse-stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
45 changes: 29 additions & 16 deletions src/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -456,17 +459,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;

this.lastProgramDateTime = new Date(entry.dateTimeString).getTime();

currentUri.dateTimeString = entry.dateTimeString;
currentUri.dateTimeObject = entry.dateTimeObject;
// 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) {
Expand Down Expand Up @@ -639,7 +646,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;

Expand Down Expand Up @@ -683,11 +689,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 {
Expand Down Expand Up @@ -730,6 +731,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 = {};
},
Expand Down Expand Up @@ -782,7 +789,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');
}
/**
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/absoluteUris.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/allowCache.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
allowCache: true,
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/allowCacheInvalid.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
allowCache: true,
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/alternateAudio.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
mediaGroups: {
// TYPE
'AUDIO': {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/alternateVideo.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module.exports = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
mediaGroups: {
'AUDIO': {
aac: {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/brightcove.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
playlists: [
{
attributes: {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/byteRange.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
9 changes: 3 additions & 6 deletions test/fixtures/integration/dateTime.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
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'
}
],
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 change: 1 addition & 0 deletions test/fixtures/integration/diff-init-key.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module.exports = {
allowCache: true,
discontinuitySequence: 0,
discontinuityStarts: [],
dateRanges: [],
mediaSequence: 7794,
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/disallowCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: false,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/disc-sequence.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
discontinuitySequence: 3,
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/discontinuity.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
discontinuitySequence: 0,
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/domainUris.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/empty.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
segments: []
};
1 change: 1 addition & 0 deletions test/fixtures/integration/emptyAllowCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/emptyMediaSequence.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/emptyPlaylistType.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/emptyTargetDuration.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
playlists: [
{
attributes: {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/encrypted.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 7794,
discontinuitySequence: 0,
discontinuityStarts: [],
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/event.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'EVENT',
segments: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 1,
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/extinf.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/fmp4.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 1,
playlistType: 'VOD',
targetDuration: 6,
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/headerOnly.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
segments: []
};
1 change: 1 addition & 0 deletions test/fixtures/integration/invalidAllowCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/invalidMediaSequence.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/invalidPlaylistType.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/invalidTargetDuration.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/liveMissingSegmentDuration.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
playlistType: 'VOD',
segments: [
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/liveStart30sBefore.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,
segments: [
{
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/llhls-byte-range.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuitySequence: 0,
discontinuityStarts: [],
mediaSequence: 0,
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/integration/llhls-delta-byte-range.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
allowCache: true,
dateRanges: [],
discontinuitySequence: 0,
discontinuityStarts: [],
mediaSequence: 0,
Expand Down
Loading

0 comments on commit e7c683f

Please sign in to comment.