Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

m3u8-parser

Package Overview
Dependencies
Maintainers
22
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

m3u8-parser - npm Package Compare versions

Comparing version 6.2.0 to 7.0.0

16

CHANGELOG.md

@@ -0,1 +1,17 @@

<a name="7.0.0"></a>
# [7.0.0](https://github.com/videojs/m3u8-parser/compare/v6.2.0...v7.0.0) (2023-07-10)
### Features
* Add PDT to each segment ([#168](https://github.com/videojs/m3u8-parser/issues/168)) ([e7c683f](https://github.com/videojs/m3u8-parser/commit/e7c683f))
* output segment title from EXTINF ([#158](https://github.com/videojs/m3u8-parser/issues/158)) ([4adaa2c](https://github.com/videojs/m3u8-parser/commit/4adaa2c))
### Bug Fixes
* rename daterange to dateRanges ([#166](https://github.com/videojs/m3u8-parser/issues/166)) ([516ab67](https://github.com/videojs/m3u8-parser/commit/516ab67))
### Documentation
* correct `customType` option name ([#147](https://github.com/videojs/m3u8-parser/issues/147)) ([4d3e6ce](https://github.com/videojs/m3u8-parser/commit/4d3e6ce))
<a name="6.2.0"></a>

@@ -2,0 +18,0 @@ # [6.2.0](https://github.com/videojs/m3u8-parser/compare/v6.1.0...v6.2.0) (2023-05-25)

94

dist/m3u8-parser.cjs.js

@@ -1,2 +0,2 @@

/*! @name m3u8-parser @version 6.2.0 @license Apache-2.0 */
/*! @name m3u8-parser @version 7.0.0 @license Apache-2.0 */
'use strict';

@@ -460,3 +460,2 @@

event.dateTimeString = match[1];
event.dateTimeObject = new Date(match[1]);
}

@@ -912,2 +911,3 @@

this.lineStream.pipe(this.parseStream);
this.lastProgramDateTime = null;
/* eslint-disable consistent-this */

@@ -943,2 +943,3 @@

discontinuityStarts: [],
dateRanges: [],
segments: []

@@ -952,3 +953,3 @@ }; // keep track of the last seen segment's byte range end, as segments are not required

let lastPartByterangeEnd = 0;
const daterangeTags = {};
const dateRangeTags = {};
this.on('end', () => {

@@ -1049,2 +1050,6 @@ // only add preloadSegment if we don't yet have a uri for it.

if (entry.title) {
currentUri.title = entry.title;
}
if (entry.duration > 0) {

@@ -1291,13 +1296,17 @@ currentUri.duration = entry.duration;

'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(); // 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);
}
currentUri.dateTimeString = entry.dateTimeString;
currentUri.dateTimeObject = entry.dateTimeObject;
},

@@ -1466,9 +1475,8 @@

'daterange'() {
this.manifest.daterange = this.manifest.daterange || [];
this.manifest.daterange.push(camelCaseKeys(entry.attributes));
const index = this.manifest.daterange.length - 1;
this.manifest.dateRanges.push(camelCaseKeys(entry.attributes));
const index = this.manifest.dateRanges.length - 1;
this.warnOnMissingAttributes_(`#EXT-X-DATERANGE #${index}`, entry.attributes, ['ID', 'START-DATE']);
const daterange = this.manifest.daterange[index];
const dateRange = this.manifest.dateRanges[index];
if (daterange.endDate && daterange.startDate && new Date(daterange.endDate) < new Date(daterange.startDate)) {
if (dateRange.endDate && dateRange.startDate && new Date(dateRange.endDate) < new Date(dateRange.startDate)) {
this.trigger('warn', {

@@ -1479,3 +1487,3 @@ message: 'EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE'

if (daterange.duration && daterange.duration < 0) {
if (dateRange.duration && dateRange.duration < 0) {
this.trigger('warn', {

@@ -1486,3 +1494,3 @@ message: 'EXT-X-DATERANGE DURATION must not be negative'

if (daterange.plannedDuration && daterange.plannedDuration < 0) {
if (dateRange.plannedDuration && dateRange.plannedDuration < 0) {
this.trigger('warn', {

@@ -1493,5 +1501,5 @@ message: 'EXT-X-DATERANGE PLANNED-DURATION must not be negative'

const endOnNextYes = !!daterange.endOnNext;
const endOnNextYes = !!dateRange.endOnNext;
if (endOnNextYes && !daterange.class) {
if (endOnNextYes && !dateRange.class) {
this.trigger('warn', {

@@ -1502,3 +1510,3 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute'

if (endOnNextYes && (daterange.duration || daterange.endDate)) {
if (endOnNextYes && (dateRange.duration || dateRange.endDate)) {
this.trigger('warn', {

@@ -1509,19 +1517,13 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes'

if (daterange.duration && daterange.endDate) {
const startDate = daterange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + daterange.duration);
this.manifest.daterange[index].endDate = new Date(newDateInSeconds);
if (dateRange.duration && dateRange.endDate) {
const startDate = dateRange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + dateRange.duration);
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;
if (!dateRangeTags[dateRange.id]) {
dateRangeTags[dateRange.id] = dateRange;
} else {
for (const attribute in daterangeTags[daterange.id]) {
if (daterangeTags[daterange.id][attribute] !== daterange[attribute]) {
for (const attribute in dateRangeTags[dateRange.id]) {
if (dateRangeTags[dateRange.id][attribute] !== dateRange[attribute]) {
this.trigger('warn', {

@@ -1566,4 +1568,10 @@ message: 'EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes and same attribute values'

lastPartByterangeEnd = 0; // prepare for the next URI
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 = {};

@@ -1624,2 +1632,10 @@ },

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');

@@ -1632,3 +1648,3 @@ }

* @param {RegExp} options.expression a regular expression to match the custom header
* @param {string} options.type the type to register to the output
* @param {string} options.customType the custom type to register to the output
* @param {Function} [options.dataParser] function to parse the line into an object

@@ -1635,0 +1651,0 @@ * @param {boolean} [options.segment] should tag data be attached to the segment object

@@ -1,2 +0,2 @@

/*! @name m3u8-parser @version 6.2.0 @license Apache-2.0 */
/*! @name m3u8-parser @version 7.0.0 @license Apache-2.0 */
import Stream from '@videojs/vhs-utils/es/stream.js';

@@ -450,3 +450,2 @@ import _extends from '@babel/runtime/helpers/extends';

event.dateTimeString = match[1];
event.dateTimeObject = new Date(match[1]);
}

@@ -902,2 +901,3 @@

this.lineStream.pipe(this.parseStream);
this.lastProgramDateTime = null;
/* eslint-disable consistent-this */

@@ -933,2 +933,3 @@

discontinuityStarts: [],
dateRanges: [],
segments: []

@@ -942,3 +943,3 @@ }; // keep track of the last seen segment's byte range end, as segments are not required

let lastPartByterangeEnd = 0;
const daterangeTags = {};
const dateRangeTags = {};
this.on('end', () => {

@@ -1039,2 +1040,6 @@ // only add preloadSegment if we don't yet have a uri for it.

if (entry.title) {
currentUri.title = entry.title;
}
if (entry.duration > 0) {

@@ -1281,13 +1286,17 @@ currentUri.duration = entry.duration;

'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(); // 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);
}
currentUri.dateTimeString = entry.dateTimeString;
currentUri.dateTimeObject = entry.dateTimeObject;
},

@@ -1456,9 +1465,8 @@

'daterange'() {
this.manifest.daterange = this.manifest.daterange || [];
this.manifest.daterange.push(camelCaseKeys(entry.attributes));
const index = this.manifest.daterange.length - 1;
this.manifest.dateRanges.push(camelCaseKeys(entry.attributes));
const index = this.manifest.dateRanges.length - 1;
this.warnOnMissingAttributes_(`#EXT-X-DATERANGE #${index}`, entry.attributes, ['ID', 'START-DATE']);
const daterange = this.manifest.daterange[index];
const dateRange = this.manifest.dateRanges[index];
if (daterange.endDate && daterange.startDate && new Date(daterange.endDate) < new Date(daterange.startDate)) {
if (dateRange.endDate && dateRange.startDate && new Date(dateRange.endDate) < new Date(dateRange.startDate)) {
this.trigger('warn', {

@@ -1469,3 +1477,3 @@ message: 'EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE'

if (daterange.duration && daterange.duration < 0) {
if (dateRange.duration && dateRange.duration < 0) {
this.trigger('warn', {

@@ -1476,3 +1484,3 @@ message: 'EXT-X-DATERANGE DURATION must not be negative'

if (daterange.plannedDuration && daterange.plannedDuration < 0) {
if (dateRange.plannedDuration && dateRange.plannedDuration < 0) {
this.trigger('warn', {

@@ -1483,5 +1491,5 @@ message: 'EXT-X-DATERANGE PLANNED-DURATION must not be negative'

const endOnNextYes = !!daterange.endOnNext;
const endOnNextYes = !!dateRange.endOnNext;
if (endOnNextYes && !daterange.class) {
if (endOnNextYes && !dateRange.class) {
this.trigger('warn', {

@@ -1492,3 +1500,3 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute'

if (endOnNextYes && (daterange.duration || daterange.endDate)) {
if (endOnNextYes && (dateRange.duration || dateRange.endDate)) {
this.trigger('warn', {

@@ -1499,19 +1507,13 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes'

if (daterange.duration && daterange.endDate) {
const startDate = daterange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + daterange.duration);
this.manifest.daterange[index].endDate = new Date(newDateInSeconds);
if (dateRange.duration && dateRange.endDate) {
const startDate = dateRange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + dateRange.duration);
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;
if (!dateRangeTags[dateRange.id]) {
dateRangeTags[dateRange.id] = dateRange;
} else {
for (const attribute in daterangeTags[daterange.id]) {
if (daterangeTags[daterange.id][attribute] !== daterange[attribute]) {
for (const attribute in dateRangeTags[dateRange.id]) {
if (dateRangeTags[dateRange.id][attribute] !== dateRange[attribute]) {
this.trigger('warn', {

@@ -1556,4 +1558,10 @@ message: 'EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes and same attribute values'

lastPartByterangeEnd = 0; // prepare for the next URI
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 = {};

@@ -1614,2 +1622,10 @@ },

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');

@@ -1622,3 +1638,3 @@ }

* @param {RegExp} options.expression a regular expression to match the custom header
* @param {string} options.type the type to register to the output
* @param {string} options.customType the custom type to register to the output
* @param {Function} [options.dataParser] function to parse the line into an object

@@ -1625,0 +1641,0 @@ * @param {boolean} [options.segment] should tag data be attached to the segment object

@@ -1,2 +0,2 @@

/*! @name m3u8-parser @version 6.2.0 @license Apache-2.0 */
/*! @name m3u8-parser @version 7.0.0 @license Apache-2.0 */
(function (global, factory) {

@@ -593,3 +593,2 @@ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :

event.dateTimeString = match[1];
event.dateTimeObject = new Date(match[1]);
}

@@ -1060,2 +1059,3 @@

this.lineStream.pipe(this.parseStream);
this.lastProgramDateTime = null;
/* eslint-disable consistent-this */

@@ -1091,2 +1091,3 @@

discontinuityStarts: [],
dateRanges: [],
segments: []

@@ -1100,3 +1101,3 @@ }; // keep track of the last seen segment's byte range end, as segments are not required

let lastPartByterangeEnd = 0;
const daterangeTags = {};
const dateRangeTags = {};
this.on('end', () => {

@@ -1197,2 +1198,6 @@ // only add preloadSegment if we don't yet have a uri for it.

if (entry.title) {
currentUri.title = entry.title;
}
if (entry.duration > 0) {

@@ -1439,13 +1444,17 @@ currentUri.duration = entry.duration;

'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(); // 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);
}
currentUri.dateTimeString = entry.dateTimeString;
currentUri.dateTimeObject = entry.dateTimeObject;
},

@@ -1614,9 +1623,8 @@

'daterange'() {
this.manifest.daterange = this.manifest.daterange || [];
this.manifest.daterange.push(camelCaseKeys(entry.attributes));
const index = this.manifest.daterange.length - 1;
this.manifest.dateRanges.push(camelCaseKeys(entry.attributes));
const index = this.manifest.dateRanges.length - 1;
this.warnOnMissingAttributes_(`#EXT-X-DATERANGE #${index}`, entry.attributes, ['ID', 'START-DATE']);
const daterange = this.manifest.daterange[index];
const dateRange = this.manifest.dateRanges[index];
if (daterange.endDate && daterange.startDate && new Date(daterange.endDate) < new Date(daterange.startDate)) {
if (dateRange.endDate && dateRange.startDate && new Date(dateRange.endDate) < new Date(dateRange.startDate)) {
this.trigger('warn', {

@@ -1627,3 +1635,3 @@ message: 'EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE'

if (daterange.duration && daterange.duration < 0) {
if (dateRange.duration && dateRange.duration < 0) {
this.trigger('warn', {

@@ -1634,3 +1642,3 @@ message: 'EXT-X-DATERANGE DURATION must not be negative'

if (daterange.plannedDuration && daterange.plannedDuration < 0) {
if (dateRange.plannedDuration && dateRange.plannedDuration < 0) {
this.trigger('warn', {

@@ -1641,5 +1649,5 @@ message: 'EXT-X-DATERANGE PLANNED-DURATION must not be negative'

const endOnNextYes = !!daterange.endOnNext;
const endOnNextYes = !!dateRange.endOnNext;
if (endOnNextYes && !daterange.class) {
if (endOnNextYes && !dateRange.class) {
this.trigger('warn', {

@@ -1650,3 +1658,3 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute'

if (endOnNextYes && (daterange.duration || daterange.endDate)) {
if (endOnNextYes && (dateRange.duration || dateRange.endDate)) {
this.trigger('warn', {

@@ -1657,19 +1665,13 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes'

if (daterange.duration && daterange.endDate) {
const startDate = daterange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + daterange.duration);
this.manifest.daterange[index].endDate = new Date(newDateInSeconds);
if (dateRange.duration && dateRange.endDate) {
const startDate = dateRange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + dateRange.duration);
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;
if (!dateRangeTags[dateRange.id]) {
dateRangeTags[dateRange.id] = dateRange;
} else {
for (const attribute in daterangeTags[daterange.id]) {
if (daterangeTags[daterange.id][attribute] !== daterange[attribute]) {
for (const attribute in dateRangeTags[dateRange.id]) {
if (dateRangeTags[dateRange.id][attribute] !== dateRange[attribute]) {
this.trigger('warn', {

@@ -1714,4 +1716,10 @@ message: 'EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes and same attribute values'

lastPartByterangeEnd = 0; // prepare for the next URI
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 = {};

@@ -1772,2 +1780,10 @@ },

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');

@@ -1780,3 +1796,3 @@ }

* @param {RegExp} options.expression a regular expression to match the custom header
* @param {string} options.type the type to register to the output
* @param {string} options.customType the custom type to register to the output
* @param {Function} [options.dataParser] function to parse the line into an object

@@ -1783,0 +1799,0 @@ * @param {boolean} [options.segment] should tag data be attached to the segment object

@@ -1,2 +0,2 @@

/*! @name m3u8-parser @version 6.2.0 @license Apache-2.0 */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).m3u8Parser={})}(this,(function(t){"use strict";var e=function(){function t(){this.listeners={}}var e=t.prototype;return e.on=function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},e.off=function(t,e){if(!this.listeners[t])return!1;var i=this.listeners[t].indexOf(e);return this.listeners[t]=this.listeners[t].slice(0),this.listeners[t].splice(i,1),i>-1},e.trigger=function(t){var e=this.listeners[t];if(e)if(2===arguments.length)for(var i=e.length,a=0;a<i;++a)e[a].call(this,arguments[1]);else for(var s=Array.prototype.slice.call(arguments,1),r=e.length,n=0;n<r;++n)e[n].apply(this,s)},e.dispose=function(){this.listeners={}},e.pipe=function(t){this.on("data",(function(e){t.push(e)}))},t}();class i extends e{constructor(){super(),this.buffer=""}push(t){let e;for(this.buffer+=t,e=this.buffer.indexOf("\n");e>-1;e=this.buffer.indexOf("\n"))this.trigger("data",this.buffer.substring(0,e)),this.buffer=this.buffer.substring(e+1)}}function a(){return s=a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var a in i)Object.prototype.hasOwnProperty.call(i,a)&&(t[a]=i[a])}return t},a.apply(this,arguments)}var s=a,r=s;const n=String.fromCharCode(9),u=function(t){const e=/([0-9.]*)?@?([0-9.]*)?/.exec(t||""),i={};return e[1]&&(i.length=parseInt(e[1],10)),e[2]&&(i.offset=parseInt(e[2],10)),i},o=function(t){const e={};if(!t)return e;const i=t.split(new RegExp('(?:^|,)((?:[^=]*)=(?:"[^"]*"|[^,]*))'));let a,s=i.length;for(;s--;)""!==i[s]&&(a=/([^=]*)=(.*)/.exec(i[s]).slice(1),a[0]=a[0].replace(/^\s+|\s+$/g,""),a[1]=a[1].replace(/^\s+|\s+$/g,""),a[1]=a[1].replace(/^['"](.*)['"]$/g,"$1"),e[a[0]]=a[1]);return e};class g extends e{constructor(){super(),this.customParsers=[],this.tagMappers=[]}push(t){let e,i;if(0===(t=t.trim()).length)return;if("#"!==t[0])return void this.trigger("data",{type:"uri",uri:t});this.tagMappers.reduce(((e,i)=>{const a=i(t);return a===t?e:e.concat([a])}),[t]).forEach((t=>{for(let e=0;e<this.customParsers.length;e++)if(this.customParsers[e].call(this,t))return;if(0===t.indexOf("#EXT"))if(t=t.replace("\r",""),e=/^#EXTM3U/.exec(t),e)this.trigger("data",{type:"tag",tagType:"m3u"});else{if(e=/^#EXTINF:([0-9\.]*)?,?(.*)?$/.exec(t),e)return i={type:"tag",tagType:"inf"},e[1]&&(i.duration=parseFloat(e[1])),e[2]&&(i.title=e[2]),void this.trigger("data",i);if(e=/^#EXT-X-TARGETDURATION:([0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"targetduration"},e[1]&&(i.duration=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-VERSION:([0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"version"},e[1]&&(i.version=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-MEDIA-SEQUENCE:(\-?[0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"media-sequence"},e[1]&&(i.number=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-DISCONTINUITY-SEQUENCE:(\-?[0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"discontinuity-sequence"},e[1]&&(i.number=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-PLAYLIST-TYPE:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"playlist-type"},e[1]&&(i.playlistType=e[1]),void this.trigger("data",i);if(e=/^#EXT-X-BYTERANGE:(.*)?$/.exec(t),e)return i=r(u(e[1]),{type:"tag",tagType:"byterange"}),void this.trigger("data",i);if(e=/^#EXT-X-ALLOW-CACHE:(YES|NO)?/.exec(t),e)return i={type:"tag",tagType:"allow-cache"},e[1]&&(i.allowed=!/NO/.test(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-MAP:(.*)$/.exec(t),e){if(i={type:"tag",tagType:"map"},e[1]){const t=o(e[1]);t.URI&&(i.uri=t.URI),t.BYTERANGE&&(i.byterange=u(t.BYTERANGE))}this.trigger("data",i)}else if(e=/^#EXT-X-STREAM-INF:(.*)$/.exec(t),e){if(i={type:"tag",tagType:"stream-inf"},e[1]){if(i.attributes=o(e[1]),i.attributes.RESOLUTION){const t=i.attributes.RESOLUTION.split("x"),e={};t[0]&&(e.width=parseInt(t[0],10)),t[1]&&(e.height=parseInt(t[1],10)),i.attributes.RESOLUTION=e}i.attributes.BANDWIDTH&&(i.attributes.BANDWIDTH=parseInt(i.attributes.BANDWIDTH,10)),i.attributes["FRAME-RATE"]&&(i.attributes["FRAME-RATE"]=parseFloat(i.attributes["FRAME-RATE"])),i.attributes["PROGRAM-ID"]&&(i.attributes["PROGRAM-ID"]=parseInt(i.attributes["PROGRAM-ID"],10))}this.trigger("data",i)}else{if(e=/^#EXT-X-MEDIA:(.*)$/.exec(t),e)return i={type:"tag",tagType:"media"},e[1]&&(i.attributes=o(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-ENDLIST/.exec(t),e)this.trigger("data",{type:"tag",tagType:"endlist"});else if(e=/^#EXT-X-DISCONTINUITY/.exec(t),e)this.trigger("data",{type:"tag",tagType:"discontinuity"});else{if(e=/^#EXT-X-PROGRAM-DATE-TIME:(.*)$/.exec(t),e)return i={type:"tag",tagType:"program-date-time"},e[1]&&(i.dateTimeString=e[1],i.dateTimeObject=new Date(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-KEY:(.*)$/.exec(t),e)return i={type:"tag",tagType:"key"},e[1]&&(i.attributes=o(e[1]),i.attributes.IV&&("0x"===i.attributes.IV.substring(0,2).toLowerCase()&&(i.attributes.IV=i.attributes.IV.substring(2)),i.attributes.IV=i.attributes.IV.match(/.{8}/g),i.attributes.IV[0]=parseInt(i.attributes.IV[0],16),i.attributes.IV[1]=parseInt(i.attributes.IV[1],16),i.attributes.IV[2]=parseInt(i.attributes.IV[2],16),i.attributes.IV[3]=parseInt(i.attributes.IV[3],16),i.attributes.IV=new Uint32Array(i.attributes.IV))),void this.trigger("data",i);if(e=/^#EXT-X-START:(.*)$/.exec(t),e)return i={type:"tag",tagType:"start"},e[1]&&(i.attributes=o(e[1]),i.attributes["TIME-OFFSET"]=parseFloat(i.attributes["TIME-OFFSET"]),i.attributes.PRECISE=/YES/.test(i.attributes.PRECISE)),void this.trigger("data",i);if(e=/^#EXT-X-CUE-OUT-CONT:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"cue-out-cont"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-CUE-OUT:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"cue-out"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-CUE-IN:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"cue-in"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-SKIP:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"skip"},i.attributes=o(e[1]),i.attributes.hasOwnProperty("SKIPPED-SEGMENTS")&&(i.attributes["SKIPPED-SEGMENTS"]=parseInt(i.attributes["SKIPPED-SEGMENTS"],10)),i.attributes.hasOwnProperty("RECENTLY-REMOVED-DATERANGES")&&(i.attributes["RECENTLY-REMOVED-DATERANGES"]=i.attributes["RECENTLY-REMOVED-DATERANGES"].split(n)),void this.trigger("data",i);if(e=/^#EXT-X-PART:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"part"},i.attributes=o(e[1]),["DURATION"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),["INDEPENDENT","GAP"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=/YES/.test(i.attributes[t]))})),i.attributes.hasOwnProperty("BYTERANGE")&&(i.attributes.byterange=u(i.attributes.BYTERANGE)),void this.trigger("data",i);if(e=/^#EXT-X-SERVER-CONTROL:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"server-control"},i.attributes=o(e[1]),["CAN-SKIP-UNTIL","PART-HOLD-BACK","HOLD-BACK"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),["CAN-SKIP-DATERANGES","CAN-BLOCK-RELOAD"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=/YES/.test(i.attributes[t]))})),void this.trigger("data",i);if(e=/^#EXT-X-PART-INF:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"part-inf"},i.attributes=o(e[1]),["PART-TARGET"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),void this.trigger("data",i);if(e=/^#EXT-X-PRELOAD-HINT:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"preload-hint"},i.attributes=o(e[1]),["BYTERANGE-START","BYTERANGE-LENGTH"].forEach((function(t){if(i.attributes.hasOwnProperty(t)){i.attributes[t]=parseInt(i.attributes[t],10);const e="BYTERANGE-LENGTH"===t?"length":"offset";i.attributes.byterange=i.attributes.byterange||{},i.attributes.byterange[e]=i.attributes[t],delete i.attributes[t]}})),void this.trigger("data",i);if(e=/^#EXT-X-RENDITION-REPORT:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"rendition-report"},i.attributes=o(e[1]),["LAST-MSN","LAST-PART"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseInt(i.attributes[t],10))})),void this.trigger("data",i);if(e=/^#EXT-X-DATERANGE:(.*)$/.exec(t),e&&e[1]){i={type:"tag",tagType:"daterange"},i.attributes=o(e[1]),["ID","CLASS"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=String(i.attributes[t]))})),["START-DATE","END-DATE"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=new Date(i.attributes[t]))})),["DURATION","PLANNED-DURATION"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),["END-ON-NEXT"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=/YES/i.test(i.attributes[t]))})),["SCTE35-CMD"," SCTE35-OUT","SCTE35-IN"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=i.attributes[t].toString(16))}));const t=/^X-([A-Z]+-)+[A-Z]+$/;for(const e in i.attributes){if(!t.test(e))continue;const a=/[0-9A-Fa-f]{6}/g.test(i.attributes[e]),s=/^\d+(\.\d+)?$/.test(i.attributes[e]);i.attributes[e]=a?i.attributes[e].toString(16):s?parseFloat(i.attributes[e]):String(i.attributes[e])}this.trigger("data",i)}else e=/^#EXT-X-INDEPENDENT-SEGMENTS/.exec(t),e?this.trigger("data",{type:"tag",tagType:"independent-segments"}):this.trigger("data",{type:"tag",data:t.slice(4)})}}}else this.trigger("data",{type:"comment",text:t.slice(1)})}))}addParser({expression:t,customType:e,dataParser:i,segment:a}){"function"!=typeof i&&(i=t=>t),this.customParsers.push((s=>{if(t.exec(s))return this.trigger("data",{type:"custom",data:i(s),customType:e,segment:a}),!0}))}addTagMapper({expression:t,map:e}){this.tagMappers.push((i=>t.test(i)?e(i):i))}}function h(t){for(var e,i=(e=t,window.atob?window.atob(e):Buffer.from(e,"base64").toString("binary")),a=new Uint8Array(i.length),s=0;s<i.length;s++)a[s]=i.charCodeAt(s);return a}const p=function(t){const e={};return Object.keys(t).forEach((function(i){var a;e[(a=i,a.toLowerCase().replace(/-(\w)/g,(t=>t[1].toUpperCase())))]=t[i]})),e},d=function(t){const{serverControl:e,targetDuration:i,partTargetDuration:a}=t;if(!e)return;const s="#EXT-X-SERVER-CONTROL",r="holdBack",n="partHoldBack",u=i&&3*i,o=a&&2*a;i&&!e.hasOwnProperty(r)&&(e[r]=u,this.trigger("info",{message:`${s} defaulting HOLD-BACK to targetDuration * 3 (${u}).`})),u&&e[r]<u&&(this.trigger("warn",{message:`${s} clamping HOLD-BACK (${e[r]}) to targetDuration * 3 (${u})`}),e[r]=u),a&&!e.hasOwnProperty(n)&&(e[n]=3*a,this.trigger("info",{message:`${s} defaulting PART-HOLD-BACK to partTargetDuration * 3 (${e[n]}).`})),a&&e[n]<o&&(this.trigger("warn",{message:`${s} clamping PART-HOLD-BACK (${e[n]}) to partTargetDuration * 2 (${o}).`}),e[n]=o)};t.LineStream=i,t.ParseStream=g,t.Parser=class extends e{constructor(){super(),this.lineStream=new i,this.parseStream=new g,this.lineStream.pipe(this.parseStream);const t=this,e=[];let a,s,n={},u=!1;const o=function(){},f={AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}};let E=0;this.manifest={allowCache:!0,discontinuityStarts:[],segments:[]};let c=0,T=0;const b={};this.on("end",(()=>{n.uri||!n.parts&&!n.preloadHints||(!n.map&&a&&(n.map=a),!n.key&&s&&(n.key=s),n.timeline||"number"!=typeof E||(n.timeline=E),this.manifest.preloadSegment=n)})),this.parseStream.on("data",(function(i){let g,m;({tag(){({version(){i.version&&(this.manifest.version=i.version)},"allow-cache"(){this.manifest.allowCache=i.allowed,"allowed"in i||(this.trigger("info",{message:"defaulting allowCache to YES"}),this.manifest.allowCache=!0)},byterange(){const t={};"length"in i&&(n.byterange=t,t.length=i.length,"offset"in i||(i.offset=c)),"offset"in i&&(n.byterange=t,t.offset=i.offset),c=t.offset+t.length},endlist(){this.manifest.endList=!0},inf(){"mediaSequence"in this.manifest||(this.manifest.mediaSequence=0,this.trigger("info",{message:"defaulting media sequence to zero"})),"discontinuitySequence"in this.manifest||(this.manifest.discontinuitySequence=0,this.trigger("info",{message:"defaulting discontinuity sequence to zero"})),i.duration>0&&(n.duration=i.duration),0===i.duration&&(n.duration=.01,this.trigger("info",{message:"updating zero segment duration to a small value"})),this.manifest.segments=e},key(){if(i.attributes)if("NONE"!==i.attributes.METHOD)if(i.attributes.URI){if("com.apple.streamingkeydelivery"===i.attributes.KEYFORMAT)return this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.apple.fps.1_0"]={attributes:i.attributes});if("com.microsoft.playready"===i.attributes.KEYFORMAT)return this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.microsoft.playready"]={uri:i.attributes.URI});if("urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"===i.attributes.KEYFORMAT){return-1===["SAMPLE-AES","SAMPLE-AES-CTR","SAMPLE-AES-CENC"].indexOf(i.attributes.METHOD)?void this.trigger("warn",{message:"invalid key method provided for Widevine"}):("SAMPLE-AES-CENC"===i.attributes.METHOD&&this.trigger("warn",{message:"SAMPLE-AES-CENC is deprecated, please use SAMPLE-AES-CTR instead"}),"data:text/plain;base64,"!==i.attributes.URI.substring(0,23)?void this.trigger("warn",{message:"invalid key URI provided for Widevine"}):i.attributes.KEYID&&"0x"===i.attributes.KEYID.substring(0,2)?(this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.widevine.alpha"]={attributes:{schemeIdUri:i.attributes.KEYFORMAT,keyId:i.attributes.KEYID.substring(2)},pssh:h(i.attributes.URI.split(",")[1])})):void this.trigger("warn",{message:"invalid key ID provided for Widevine"}))}i.attributes.METHOD||this.trigger("warn",{message:"defaulting key method to AES-128"}),s={method:i.attributes.METHOD||"AES-128",uri:i.attributes.URI},void 0!==i.attributes.IV&&(s.iv=i.attributes.IV)}else this.trigger("warn",{message:"ignoring key declaration without URI"});else s=null;else this.trigger("warn",{message:"ignoring key declaration without attribute list"})},"media-sequence"(){isFinite(i.number)?this.manifest.mediaSequence=i.number:this.trigger("warn",{message:"ignoring invalid media sequence: "+i.number})},"discontinuity-sequence"(){isFinite(i.number)?(this.manifest.discontinuitySequence=i.number,E=i.number):this.trigger("warn",{message:"ignoring invalid discontinuity sequence: "+i.number})},"playlist-type"(){/VOD|EVENT/.test(i.playlistType)?this.manifest.playlistType=i.playlistType:this.trigger("warn",{message:"ignoring unknown playlist type: "+i.playlist})},map(){a={},i.uri&&(a.uri=i.uri),i.byterange&&(a.byterange=i.byterange),s&&(a.key=s)},"stream-inf"(){this.manifest.playlists=e,this.manifest.mediaGroups=this.manifest.mediaGroups||f,i.attributes?(n.attributes||(n.attributes={}),r(n.attributes,i.attributes)):this.trigger("warn",{message:"ignoring empty stream-inf attributes"})},media(){if(this.manifest.mediaGroups=this.manifest.mediaGroups||f,!(i.attributes&&i.attributes.TYPE&&i.attributes["GROUP-ID"]&&i.attributes.NAME))return void this.trigger("warn",{message:"ignoring incomplete or missing media group"});const t=this.manifest.mediaGroups[i.attributes.TYPE];t[i.attributes["GROUP-ID"]]=t[i.attributes["GROUP-ID"]]||{},g=t[i.attributes["GROUP-ID"]],m={default:/yes/i.test(i.attributes.DEFAULT)},m.default?m.autoselect=!0:m.autoselect=/yes/i.test(i.attributes.AUTOSELECT),i.attributes.LANGUAGE&&(m.language=i.attributes.LANGUAGE),i.attributes.URI&&(m.uri=i.attributes.URI),i.attributes["INSTREAM-ID"]&&(m.instreamId=i.attributes["INSTREAM-ID"]),i.attributes.CHARACTERISTICS&&(m.characteristics=i.attributes.CHARACTERISTICS),i.attributes.FORCED&&(m.forced=/yes/i.test(i.attributes.FORCED)),g[i.attributes.NAME]=m},discontinuity(){E+=1,n.discontinuity=!0,this.manifest.discontinuityStarts.push(e.length)},"program-date-time"(){void 0===this.manifest.dateTimeString&&(this.manifest.dateTimeString=i.dateTimeString,this.manifest.dateTimeObject=i.dateTimeObject),n.dateTimeString=i.dateTimeString,n.dateTimeObject=i.dateTimeObject},targetduration(){!isFinite(i.duration)||i.duration<0?this.trigger("warn",{message:"ignoring invalid target duration: "+i.duration}):(this.manifest.targetDuration=i.duration,d.call(this,this.manifest))},start(){i.attributes&&!isNaN(i.attributes["TIME-OFFSET"])?this.manifest.start={timeOffset:i.attributes["TIME-OFFSET"],precise:i.attributes.PRECISE}:this.trigger("warn",{message:"ignoring start declaration without appropriate attribute list"})},"cue-out"(){n.cueOut=i.data},"cue-out-cont"(){n.cueOutCont=i.data},"cue-in"(){n.cueIn=i.data},skip(){this.manifest.skip=p(i.attributes),this.warnOnMissingAttributes_("#EXT-X-SKIP",i.attributes,["SKIPPED-SEGMENTS"])},part(){u=!0;const t=this.manifest.segments.length,e=p(i.attributes);n.parts=n.parts||[],n.parts.push(e),e.byterange&&(e.byterange.hasOwnProperty("offset")||(e.byterange.offset=T),T=e.byterange.offset+e.byterange.length);const a=n.parts.length-1;this.warnOnMissingAttributes_(`#EXT-X-PART #${a} for segment #${t}`,i.attributes,["URI","DURATION"]),this.manifest.renditionReports&&this.manifest.renditionReports.forEach(((t,e)=>{t.hasOwnProperty("lastPart")||this.trigger("warn",{message:`#EXT-X-RENDITION-REPORT #${e} lacks required attribute(s): LAST-PART`})}))},"server-control"(){const t=this.manifest.serverControl=p(i.attributes);t.hasOwnProperty("canBlockReload")||(t.canBlockReload=!1,this.trigger("info",{message:"#EXT-X-SERVER-CONTROL defaulting CAN-BLOCK-RELOAD to false"})),d.call(this,this.manifest),t.canSkipDateranges&&!t.hasOwnProperty("canSkipUntil")&&this.trigger("warn",{message:"#EXT-X-SERVER-CONTROL lacks required attribute CAN-SKIP-UNTIL which is required when CAN-SKIP-DATERANGES is set"})},"preload-hint"(){const t=this.manifest.segments.length,e=p(i.attributes),a=e.type&&"PART"===e.type;n.preloadHints=n.preloadHints||[],n.preloadHints.push(e),e.byterange&&(e.byterange.hasOwnProperty("offset")||(e.byterange.offset=a?T:0,a&&(T=e.byterange.offset+e.byterange.length)));const s=n.preloadHints.length-1;if(this.warnOnMissingAttributes_(`#EXT-X-PRELOAD-HINT #${s} for segment #${t}`,i.attributes,["TYPE","URI"]),e.type)for(let i=0;i<n.preloadHints.length-1;i++){const a=n.preloadHints[i];a.type&&(a.type===e.type&&this.trigger("warn",{message:`#EXT-X-PRELOAD-HINT #${s} for segment #${t} has the same TYPE ${e.type} as preload hint #${i}`}))}},"rendition-report"(){const t=p(i.attributes);this.manifest.renditionReports=this.manifest.renditionReports||[],this.manifest.renditionReports.push(t);const e=this.manifest.renditionReports.length-1,a=["LAST-MSN","URI"];u&&a.push("LAST-PART"),this.warnOnMissingAttributes_(`#EXT-X-RENDITION-REPORT #${e}`,i.attributes,a)},"part-inf"(){this.manifest.partInf=p(i.attributes),this.warnOnMissingAttributes_("#EXT-X-PART-INF",i.attributes,["PART-TARGET"]),this.manifest.partInf.partTarget&&(this.manifest.partTargetDuration=this.manifest.partInf.partTarget),d.call(this,this.manifest)},daterange(){this.manifest.daterange=this.manifest.daterange||[],this.manifest.daterange.push(p(i.attributes));const t=this.manifest.daterange.length-1;this.warnOnMissingAttributes_(`#EXT-X-DATERANGE #${t}`,i.attributes,["ID","START-DATE"]);const e=this.manifest.daterange[t];e.endDate&&e.startDate&&new Date(e.endDate)<new Date(e.startDate)&&this.trigger("warn",{message:"EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE"}),e.duration&&e.duration<0&&this.trigger("warn",{message:"EXT-X-DATERANGE DURATION must not be negative"}),e.plannedDuration&&e.plannedDuration<0&&this.trigger("warn",{message:"EXT-X-DATERANGE PLANNED-DURATION must not be negative"});const a=!!e.endOnNext;if(a&&!e.class&&this.trigger("warn",{message:"EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute"}),a&&(e.duration||e.endDate)&&this.trigger("warn",{message:"EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes"}),e.duration&&e.endDate){const i=e.startDate,a=i.setSeconds(i.getSeconds()+e.duration);this.manifest.daterange[t].endDate=new Date(a)}if(e&&!this.manifest.dateTimeString&&this.trigger("warn",{message:"A playlist with EXT-X-DATERANGE tag must contain atleast one EXT-X-PROGRAM-DATE-TIME tag"}),b[e.id]){for(const t in b[e.id])if(b[e.id][t]!==e[t]){this.trigger("warn",{message:"EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes and same attribute values"});break}}else b[e.id]=e},"independent-segments"(){this.manifest.independentSegments=!0}}[i.tagType]||o).call(t)},uri(){n.uri=i.uri,e.push(n),this.manifest.targetDuration&&!("duration"in n)&&(this.trigger("warn",{message:"defaulting segment duration to the target duration"}),n.duration=this.manifest.targetDuration),s&&(n.key=s),n.timeline=E,a&&(n.map=a),T=0,n={}},comment(){},custom(){i.segment?(n.custom=n.custom||{},n.custom[i.customType]=i.data):(this.manifest.custom=this.manifest.custom||{},this.manifest.custom[i.customType]=i.data)}})[i.type].call(t)}))}warnOnMissingAttributes_(t,e,i){const a=[];i.forEach((function(t){e.hasOwnProperty(t)||a.push(t)})),a.length&&this.trigger("warn",{message:`${t} lacks required attribute(s): ${a.join(", ")}`})}push(t){this.lineStream.push(t)}end(){this.lineStream.push("\n"),this.trigger("end")}addParser(t){this.parseStream.addParser(t)}addTagMapper(t){this.parseStream.addTagMapper(t)}},Object.defineProperty(t,"__esModule",{value:!0})}));
/*! @name m3u8-parser @version 7.0.0 @license Apache-2.0 */
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).m3u8Parser={})}(this,(function(t){"use strict";var e=function(){function t(){this.listeners={}}var e=t.prototype;return e.on=function(t,e){this.listeners[t]||(this.listeners[t]=[]),this.listeners[t].push(e)},e.off=function(t,e){if(!this.listeners[t])return!1;var i=this.listeners[t].indexOf(e);return this.listeners[t]=this.listeners[t].slice(0),this.listeners[t].splice(i,1),i>-1},e.trigger=function(t){var e=this.listeners[t];if(e)if(2===arguments.length)for(var i=e.length,a=0;a<i;++a)e[a].call(this,arguments[1]);else for(var s=Array.prototype.slice.call(arguments,1),r=e.length,n=0;n<r;++n)e[n].apply(this,s)},e.dispose=function(){this.listeners={}},e.pipe=function(t){this.on("data",(function(e){t.push(e)}))},t}();class i extends e{constructor(){super(),this.buffer=""}push(t){let e;for(this.buffer+=t,e=this.buffer.indexOf("\n");e>-1;e=this.buffer.indexOf("\n"))this.trigger("data",this.buffer.substring(0,e)),this.buffer=this.buffer.substring(e+1)}}function a(){return s=a=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var a in i)Object.prototype.hasOwnProperty.call(i,a)&&(t[a]=i[a])}return t},a.apply(this,arguments)}var s=a,r=s;const n=String.fromCharCode(9),o=function(t){const e=/([0-9.]*)?@?([0-9.]*)?/.exec(t||""),i={};return e[1]&&(i.length=parseInt(e[1],10)),e[2]&&(i.offset=parseInt(e[2],10)),i},u=function(t){const e={};if(!t)return e;const i=t.split(new RegExp('(?:^|,)((?:[^=]*)=(?:"[^"]*"|[^,]*))'));let a,s=i.length;for(;s--;)""!==i[s]&&(a=/([^=]*)=(.*)/.exec(i[s]).slice(1),a[0]=a[0].replace(/^\s+|\s+$/g,""),a[1]=a[1].replace(/^\s+|\s+$/g,""),a[1]=a[1].replace(/^['"](.*)['"]$/g,"$1"),e[a[0]]=a[1]);return e};class g extends e{constructor(){super(),this.customParsers=[],this.tagMappers=[]}push(t){let e,i;if(0===(t=t.trim()).length)return;if("#"!==t[0])return void this.trigger("data",{type:"uri",uri:t});this.tagMappers.reduce(((e,i)=>{const a=i(t);return a===t?e:e.concat([a])}),[t]).forEach((t=>{for(let e=0;e<this.customParsers.length;e++)if(this.customParsers[e].call(this,t))return;if(0===t.indexOf("#EXT"))if(t=t.replace("\r",""),e=/^#EXTM3U/.exec(t),e)this.trigger("data",{type:"tag",tagType:"m3u"});else{if(e=/^#EXTINF:([0-9\.]*)?,?(.*)?$/.exec(t),e)return i={type:"tag",tagType:"inf"},e[1]&&(i.duration=parseFloat(e[1])),e[2]&&(i.title=e[2]),void this.trigger("data",i);if(e=/^#EXT-X-TARGETDURATION:([0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"targetduration"},e[1]&&(i.duration=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-VERSION:([0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"version"},e[1]&&(i.version=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-MEDIA-SEQUENCE:(\-?[0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"media-sequence"},e[1]&&(i.number=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-DISCONTINUITY-SEQUENCE:(\-?[0-9.]*)?/.exec(t),e)return i={type:"tag",tagType:"discontinuity-sequence"},e[1]&&(i.number=parseInt(e[1],10)),void this.trigger("data",i);if(e=/^#EXT-X-PLAYLIST-TYPE:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"playlist-type"},e[1]&&(i.playlistType=e[1]),void this.trigger("data",i);if(e=/^#EXT-X-BYTERANGE:(.*)?$/.exec(t),e)return i=r(o(e[1]),{type:"tag",tagType:"byterange"}),void this.trigger("data",i);if(e=/^#EXT-X-ALLOW-CACHE:(YES|NO)?/.exec(t),e)return i={type:"tag",tagType:"allow-cache"},e[1]&&(i.allowed=!/NO/.test(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-MAP:(.*)$/.exec(t),e){if(i={type:"tag",tagType:"map"},e[1]){const t=u(e[1]);t.URI&&(i.uri=t.URI),t.BYTERANGE&&(i.byterange=o(t.BYTERANGE))}this.trigger("data",i)}else if(e=/^#EXT-X-STREAM-INF:(.*)$/.exec(t),e){if(i={type:"tag",tagType:"stream-inf"},e[1]){if(i.attributes=u(e[1]),i.attributes.RESOLUTION){const t=i.attributes.RESOLUTION.split("x"),e={};t[0]&&(e.width=parseInt(t[0],10)),t[1]&&(e.height=parseInt(t[1],10)),i.attributes.RESOLUTION=e}i.attributes.BANDWIDTH&&(i.attributes.BANDWIDTH=parseInt(i.attributes.BANDWIDTH,10)),i.attributes["FRAME-RATE"]&&(i.attributes["FRAME-RATE"]=parseFloat(i.attributes["FRAME-RATE"])),i.attributes["PROGRAM-ID"]&&(i.attributes["PROGRAM-ID"]=parseInt(i.attributes["PROGRAM-ID"],10))}this.trigger("data",i)}else{if(e=/^#EXT-X-MEDIA:(.*)$/.exec(t),e)return i={type:"tag",tagType:"media"},e[1]&&(i.attributes=u(e[1])),void this.trigger("data",i);if(e=/^#EXT-X-ENDLIST/.exec(t),e)this.trigger("data",{type:"tag",tagType:"endlist"});else if(e=/^#EXT-X-DISCONTINUITY/.exec(t),e)this.trigger("data",{type:"tag",tagType:"discontinuity"});else{if(e=/^#EXT-X-PROGRAM-DATE-TIME:(.*)$/.exec(t),e)return i={type:"tag",tagType:"program-date-time"},e[1]&&(i.dateTimeString=e[1]),void this.trigger("data",i);if(e=/^#EXT-X-KEY:(.*)$/.exec(t),e)return i={type:"tag",tagType:"key"},e[1]&&(i.attributes=u(e[1]),i.attributes.IV&&("0x"===i.attributes.IV.substring(0,2).toLowerCase()&&(i.attributes.IV=i.attributes.IV.substring(2)),i.attributes.IV=i.attributes.IV.match(/.{8}/g),i.attributes.IV[0]=parseInt(i.attributes.IV[0],16),i.attributes.IV[1]=parseInt(i.attributes.IV[1],16),i.attributes.IV[2]=parseInt(i.attributes.IV[2],16),i.attributes.IV[3]=parseInt(i.attributes.IV[3],16),i.attributes.IV=new Uint32Array(i.attributes.IV))),void this.trigger("data",i);if(e=/^#EXT-X-START:(.*)$/.exec(t),e)return i={type:"tag",tagType:"start"},e[1]&&(i.attributes=u(e[1]),i.attributes["TIME-OFFSET"]=parseFloat(i.attributes["TIME-OFFSET"]),i.attributes.PRECISE=/YES/.test(i.attributes.PRECISE)),void this.trigger("data",i);if(e=/^#EXT-X-CUE-OUT-CONT:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"cue-out-cont"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-CUE-OUT:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"cue-out"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-CUE-IN:(.*)?$/.exec(t),e)return i={type:"tag",tagType:"cue-in"},e[1]?i.data=e[1]:i.data="",void this.trigger("data",i);if(e=/^#EXT-X-SKIP:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"skip"},i.attributes=u(e[1]),i.attributes.hasOwnProperty("SKIPPED-SEGMENTS")&&(i.attributes["SKIPPED-SEGMENTS"]=parseInt(i.attributes["SKIPPED-SEGMENTS"],10)),i.attributes.hasOwnProperty("RECENTLY-REMOVED-DATERANGES")&&(i.attributes["RECENTLY-REMOVED-DATERANGES"]=i.attributes["RECENTLY-REMOVED-DATERANGES"].split(n)),void this.trigger("data",i);if(e=/^#EXT-X-PART:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"part"},i.attributes=u(e[1]),["DURATION"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),["INDEPENDENT","GAP"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=/YES/.test(i.attributes[t]))})),i.attributes.hasOwnProperty("BYTERANGE")&&(i.attributes.byterange=o(i.attributes.BYTERANGE)),void this.trigger("data",i);if(e=/^#EXT-X-SERVER-CONTROL:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"server-control"},i.attributes=u(e[1]),["CAN-SKIP-UNTIL","PART-HOLD-BACK","HOLD-BACK"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),["CAN-SKIP-DATERANGES","CAN-BLOCK-RELOAD"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=/YES/.test(i.attributes[t]))})),void this.trigger("data",i);if(e=/^#EXT-X-PART-INF:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"part-inf"},i.attributes=u(e[1]),["PART-TARGET"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),void this.trigger("data",i);if(e=/^#EXT-X-PRELOAD-HINT:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"preload-hint"},i.attributes=u(e[1]),["BYTERANGE-START","BYTERANGE-LENGTH"].forEach((function(t){if(i.attributes.hasOwnProperty(t)){i.attributes[t]=parseInt(i.attributes[t],10);const e="BYTERANGE-LENGTH"===t?"length":"offset";i.attributes.byterange=i.attributes.byterange||{},i.attributes.byterange[e]=i.attributes[t],delete i.attributes[t]}})),void this.trigger("data",i);if(e=/^#EXT-X-RENDITION-REPORT:(.*)$/.exec(t),e&&e[1])return i={type:"tag",tagType:"rendition-report"},i.attributes=u(e[1]),["LAST-MSN","LAST-PART"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseInt(i.attributes[t],10))})),void this.trigger("data",i);if(e=/^#EXT-X-DATERANGE:(.*)$/.exec(t),e&&e[1]){i={type:"tag",tagType:"daterange"},i.attributes=u(e[1]),["ID","CLASS"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=String(i.attributes[t]))})),["START-DATE","END-DATE"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=new Date(i.attributes[t]))})),["DURATION","PLANNED-DURATION"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=parseFloat(i.attributes[t]))})),["END-ON-NEXT"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=/YES/i.test(i.attributes[t]))})),["SCTE35-CMD"," SCTE35-OUT","SCTE35-IN"].forEach((function(t){i.attributes.hasOwnProperty(t)&&(i.attributes[t]=i.attributes[t].toString(16))}));const t=/^X-([A-Z]+-)+[A-Z]+$/;for(const e in i.attributes){if(!t.test(e))continue;const a=/[0-9A-Fa-f]{6}/g.test(i.attributes[e]),s=/^\d+(\.\d+)?$/.test(i.attributes[e]);i.attributes[e]=a?i.attributes[e].toString(16):s?parseFloat(i.attributes[e]):String(i.attributes[e])}this.trigger("data",i)}else e=/^#EXT-X-INDEPENDENT-SEGMENTS/.exec(t),e?this.trigger("data",{type:"tag",tagType:"independent-segments"}):this.trigger("data",{type:"tag",data:t.slice(4)})}}}else this.trigger("data",{type:"comment",text:t.slice(1)})}))}addParser({expression:t,customType:e,dataParser:i,segment:a}){"function"!=typeof i&&(i=t=>t),this.customParsers.push((s=>{if(t.exec(s))return this.trigger("data",{type:"custom",data:i(s),customType:e,segment:a}),!0}))}addTagMapper({expression:t,map:e}){this.tagMappers.push((i=>t.test(i)?e(i):i))}}function h(t){for(var e,i=(e=t,window.atob?window.atob(e):Buffer.from(e,"base64").toString("binary")),a=new Uint8Array(i.length),s=0;s<i.length;s++)a[s]=i.charCodeAt(s);return a}const p=function(t){const e={};return Object.keys(t).forEach((function(i){var a;e[(a=i,a.toLowerCase().replace(/-(\w)/g,(t=>t[1].toUpperCase())))]=t[i]})),e},d=function(t){const{serverControl:e,targetDuration:i,partTargetDuration:a}=t;if(!e)return;const s="#EXT-X-SERVER-CONTROL",r="holdBack",n="partHoldBack",o=i&&3*i,u=a&&2*a;i&&!e.hasOwnProperty(r)&&(e[r]=o,this.trigger("info",{message:`${s} defaulting HOLD-BACK to targetDuration * 3 (${o}).`})),o&&e[r]<o&&(this.trigger("warn",{message:`${s} clamping HOLD-BACK (${e[r]}) to targetDuration * 3 (${o})`}),e[r]=o),a&&!e.hasOwnProperty(n)&&(e[n]=3*a,this.trigger("info",{message:`${s} defaulting PART-HOLD-BACK to partTargetDuration * 3 (${e[n]}).`})),a&&e[n]<u&&(this.trigger("warn",{message:`${s} clamping PART-HOLD-BACK (${e[n]}) to partTargetDuration * 2 (${u}).`}),e[n]=u)};t.LineStream=i,t.ParseStream=g,t.Parser=class extends e{constructor(){super(),this.lineStream=new i,this.parseStream=new g,this.lineStream.pipe(this.parseStream),this.lastProgramDateTime=null;const t=this,e=[];let a,s,n={},o=!1;const u=function(){},E={AUDIO:{},VIDEO:{},"CLOSED-CAPTIONS":{},SUBTITLES:{}};let f=0;this.manifest={allowCache:!0,discontinuityStarts:[],dateRanges:[],segments:[]};let c=0,T=0;const l={};this.on("end",(()=>{n.uri||!n.parts&&!n.preloadHints||(!n.map&&a&&(n.map=a),!n.key&&s&&(n.key=s),n.timeline||"number"!=typeof f||(n.timeline=f),this.manifest.preloadSegment=n)})),this.parseStream.on("data",(function(i){let g,m;({tag(){({version(){i.version&&(this.manifest.version=i.version)},"allow-cache"(){this.manifest.allowCache=i.allowed,"allowed"in i||(this.trigger("info",{message:"defaulting allowCache to YES"}),this.manifest.allowCache=!0)},byterange(){const t={};"length"in i&&(n.byterange=t,t.length=i.length,"offset"in i||(i.offset=c)),"offset"in i&&(n.byterange=t,t.offset=i.offset),c=t.offset+t.length},endlist(){this.manifest.endList=!0},inf(){"mediaSequence"in this.manifest||(this.manifest.mediaSequence=0,this.trigger("info",{message:"defaulting media sequence to zero"})),"discontinuitySequence"in this.manifest||(this.manifest.discontinuitySequence=0,this.trigger("info",{message:"defaulting discontinuity sequence to zero"})),i.title&&(n.title=i.title),i.duration>0&&(n.duration=i.duration),0===i.duration&&(n.duration=.01,this.trigger("info",{message:"updating zero segment duration to a small value"})),this.manifest.segments=e},key(){if(i.attributes)if("NONE"!==i.attributes.METHOD)if(i.attributes.URI){if("com.apple.streamingkeydelivery"===i.attributes.KEYFORMAT)return this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.apple.fps.1_0"]={attributes:i.attributes});if("com.microsoft.playready"===i.attributes.KEYFORMAT)return this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.microsoft.playready"]={uri:i.attributes.URI});if("urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed"===i.attributes.KEYFORMAT){return-1===["SAMPLE-AES","SAMPLE-AES-CTR","SAMPLE-AES-CENC"].indexOf(i.attributes.METHOD)?void this.trigger("warn",{message:"invalid key method provided for Widevine"}):("SAMPLE-AES-CENC"===i.attributes.METHOD&&this.trigger("warn",{message:"SAMPLE-AES-CENC is deprecated, please use SAMPLE-AES-CTR instead"}),"data:text/plain;base64,"!==i.attributes.URI.substring(0,23)?void this.trigger("warn",{message:"invalid key URI provided for Widevine"}):i.attributes.KEYID&&"0x"===i.attributes.KEYID.substring(0,2)?(this.manifest.contentProtection=this.manifest.contentProtection||{},void(this.manifest.contentProtection["com.widevine.alpha"]={attributes:{schemeIdUri:i.attributes.KEYFORMAT,keyId:i.attributes.KEYID.substring(2)},pssh:h(i.attributes.URI.split(",")[1])})):void this.trigger("warn",{message:"invalid key ID provided for Widevine"}))}i.attributes.METHOD||this.trigger("warn",{message:"defaulting key method to AES-128"}),s={method:i.attributes.METHOD||"AES-128",uri:i.attributes.URI},void 0!==i.attributes.IV&&(s.iv=i.attributes.IV)}else this.trigger("warn",{message:"ignoring key declaration without URI"});else s=null;else this.trigger("warn",{message:"ignoring key declaration without attribute list"})},"media-sequence"(){isFinite(i.number)?this.manifest.mediaSequence=i.number:this.trigger("warn",{message:"ignoring invalid media sequence: "+i.number})},"discontinuity-sequence"(){isFinite(i.number)?(this.manifest.discontinuitySequence=i.number,f=i.number):this.trigger("warn",{message:"ignoring invalid discontinuity sequence: "+i.number})},"playlist-type"(){/VOD|EVENT/.test(i.playlistType)?this.manifest.playlistType=i.playlistType:this.trigger("warn",{message:"ignoring unknown playlist type: "+i.playlist})},map(){a={},i.uri&&(a.uri=i.uri),i.byterange&&(a.byterange=i.byterange),s&&(a.key=s)},"stream-inf"(){this.manifest.playlists=e,this.manifest.mediaGroups=this.manifest.mediaGroups||E,i.attributes?(n.attributes||(n.attributes={}),r(n.attributes,i.attributes)):this.trigger("warn",{message:"ignoring empty stream-inf attributes"})},media(){if(this.manifest.mediaGroups=this.manifest.mediaGroups||E,!(i.attributes&&i.attributes.TYPE&&i.attributes["GROUP-ID"]&&i.attributes.NAME))return void this.trigger("warn",{message:"ignoring incomplete or missing media group"});const t=this.manifest.mediaGroups[i.attributes.TYPE];t[i.attributes["GROUP-ID"]]=t[i.attributes["GROUP-ID"]]||{},g=t[i.attributes["GROUP-ID"]],m={default:/yes/i.test(i.attributes.DEFAULT)},m.default?m.autoselect=!0:m.autoselect=/yes/i.test(i.attributes.AUTOSELECT),i.attributes.LANGUAGE&&(m.language=i.attributes.LANGUAGE),i.attributes.URI&&(m.uri=i.attributes.URI),i.attributes["INSTREAM-ID"]&&(m.instreamId=i.attributes["INSTREAM-ID"]),i.attributes.CHARACTERISTICS&&(m.characteristics=i.attributes.CHARACTERISTICS),i.attributes.FORCED&&(m.forced=/yes/i.test(i.attributes.FORCED)),g[i.attributes.NAME]=m},discontinuity(){f+=1,n.discontinuity=!0,this.manifest.discontinuityStarts.push(e.length)},"program-date-time"(){const{lastProgramDateTime:t}=this;this.lastProgramDateTime=new Date(i.dateTimeString).getTime(),null===t&&this.manifest.segments.reduceRight(((t,e)=>(e.programDateTime=t-1e3*e.duration,e.programDateTime)),this.lastProgramDateTime)},targetduration(){!isFinite(i.duration)||i.duration<0?this.trigger("warn",{message:"ignoring invalid target duration: "+i.duration}):(this.manifest.targetDuration=i.duration,d.call(this,this.manifest))},start(){i.attributes&&!isNaN(i.attributes["TIME-OFFSET"])?this.manifest.start={timeOffset:i.attributes["TIME-OFFSET"],precise:i.attributes.PRECISE}:this.trigger("warn",{message:"ignoring start declaration without appropriate attribute list"})},"cue-out"(){n.cueOut=i.data},"cue-out-cont"(){n.cueOutCont=i.data},"cue-in"(){n.cueIn=i.data},skip(){this.manifest.skip=p(i.attributes),this.warnOnMissingAttributes_("#EXT-X-SKIP",i.attributes,["SKIPPED-SEGMENTS"])},part(){o=!0;const t=this.manifest.segments.length,e=p(i.attributes);n.parts=n.parts||[],n.parts.push(e),e.byterange&&(e.byterange.hasOwnProperty("offset")||(e.byterange.offset=T),T=e.byterange.offset+e.byterange.length);const a=n.parts.length-1;this.warnOnMissingAttributes_(`#EXT-X-PART #${a} for segment #${t}`,i.attributes,["URI","DURATION"]),this.manifest.renditionReports&&this.manifest.renditionReports.forEach(((t,e)=>{t.hasOwnProperty("lastPart")||this.trigger("warn",{message:`#EXT-X-RENDITION-REPORT #${e} lacks required attribute(s): LAST-PART`})}))},"server-control"(){const t=this.manifest.serverControl=p(i.attributes);t.hasOwnProperty("canBlockReload")||(t.canBlockReload=!1,this.trigger("info",{message:"#EXT-X-SERVER-CONTROL defaulting CAN-BLOCK-RELOAD to false"})),d.call(this,this.manifest),t.canSkipDateranges&&!t.hasOwnProperty("canSkipUntil")&&this.trigger("warn",{message:"#EXT-X-SERVER-CONTROL lacks required attribute CAN-SKIP-UNTIL which is required when CAN-SKIP-DATERANGES is set"})},"preload-hint"(){const t=this.manifest.segments.length,e=p(i.attributes),a=e.type&&"PART"===e.type;n.preloadHints=n.preloadHints||[],n.preloadHints.push(e),e.byterange&&(e.byterange.hasOwnProperty("offset")||(e.byterange.offset=a?T:0,a&&(T=e.byterange.offset+e.byterange.length)));const s=n.preloadHints.length-1;if(this.warnOnMissingAttributes_(`#EXT-X-PRELOAD-HINT #${s} for segment #${t}`,i.attributes,["TYPE","URI"]),e.type)for(let i=0;i<n.preloadHints.length-1;i++){const a=n.preloadHints[i];a.type&&(a.type===e.type&&this.trigger("warn",{message:`#EXT-X-PRELOAD-HINT #${s} for segment #${t} has the same TYPE ${e.type} as preload hint #${i}`}))}},"rendition-report"(){const t=p(i.attributes);this.manifest.renditionReports=this.manifest.renditionReports||[],this.manifest.renditionReports.push(t);const e=this.manifest.renditionReports.length-1,a=["LAST-MSN","URI"];o&&a.push("LAST-PART"),this.warnOnMissingAttributes_(`#EXT-X-RENDITION-REPORT #${e}`,i.attributes,a)},"part-inf"(){this.manifest.partInf=p(i.attributes),this.warnOnMissingAttributes_("#EXT-X-PART-INF",i.attributes,["PART-TARGET"]),this.manifest.partInf.partTarget&&(this.manifest.partTargetDuration=this.manifest.partInf.partTarget),d.call(this,this.manifest)},daterange(){this.manifest.dateRanges.push(p(i.attributes));const t=this.manifest.dateRanges.length-1;this.warnOnMissingAttributes_(`#EXT-X-DATERANGE #${t}`,i.attributes,["ID","START-DATE"]);const e=this.manifest.dateRanges[t];e.endDate&&e.startDate&&new Date(e.endDate)<new Date(e.startDate)&&this.trigger("warn",{message:"EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE"}),e.duration&&e.duration<0&&this.trigger("warn",{message:"EXT-X-DATERANGE DURATION must not be negative"}),e.plannedDuration&&e.plannedDuration<0&&this.trigger("warn",{message:"EXT-X-DATERANGE PLANNED-DURATION must not be negative"});const a=!!e.endOnNext;if(a&&!e.class&&this.trigger("warn",{message:"EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute"}),a&&(e.duration||e.endDate)&&this.trigger("warn",{message:"EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes"}),e.duration&&e.endDate){const i=e.startDate,a=i.setSeconds(i.getSeconds()+e.duration);this.manifest.dateRanges[t].endDate=new Date(a)}if(l[e.id]){for(const t in l[e.id])if(l[e.id][t]!==e[t]){this.trigger("warn",{message:"EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes and same attribute values"});break}}else l[e.id]=e},"independent-segments"(){this.manifest.independentSegments=!0}}[i.tagType]||u).call(t)},uri(){n.uri=i.uri,e.push(n),this.manifest.targetDuration&&!("duration"in n)&&(this.trigger("warn",{message:"defaulting segment duration to the target duration"}),n.duration=this.manifest.targetDuration),s&&(n.key=s),n.timeline=f,a&&(n.map=a),T=0,null!==this.lastProgramDateTime&&(n.programDateTime=this.lastProgramDateTime,this.lastProgramDateTime+=1e3*n.duration),n={}},comment(){},custom(){i.segment?(n.custom=n.custom||{},n.custom[i.customType]=i.data):(this.manifest.custom=this.manifest.custom||{},this.manifest.custom[i.customType]=i.data)}})[i.type].call(t)}))}warnOnMissingAttributes_(t,e,i){const a=[];i.forEach((function(t){e.hasOwnProperty(t)||a.push(t)})),a.length&&this.trigger("warn",{message:`${t} lacks required attribute(s): ${a.join(", ")}`})}push(t){this.lineStream.push(t)}end(){this.lineStream.push("\n"),this.manifest.dateRanges.length&&null===this.lastProgramDateTime&&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")}addParser(t){this.parseStream.addParser(t)}addTagMapper(t){this.parseStream.addTagMapper(t)}},Object.defineProperty(t,"__esModule",{value:!0})}));
{
"name": "m3u8-parser",
"version": "6.2.0",
"version": "7.0.0",
"description": "m3u8 parser",

@@ -5,0 +5,0 @@ "main": "dist/m3u8-parser.cjs.js",

@@ -60,2 +60,3 @@ # m3u8-parser

'1.ts',
'#EXT-X-PROGRAM-DATE-TIME:2019-02-14T02:14:00.106Z'
'#EXTINF:6,',

@@ -83,2 +84,3 @@ '2.ts',

mediaSequence: number,
dateRanges: [],
discontinuitySequence: number,

@@ -111,4 +113,2 @@ playlistType: string,

},
dateTimeString: string,
dateTimeObject: Date,
targetDuration: number,

@@ -119,2 +119,3 @@ totalDuration: number,

{
title: string,
byterange: {

@@ -125,2 +126,3 @@ length: number,

duration: number,
programDateTime: number,
attributes: {},

@@ -127,0 +129,0 @@ discontinuity: number,

@@ -359,3 +359,2 @@ /**

event.dateTimeString = match[1];
event.dateTimeObject = new Date(match[1]);
}

@@ -362,0 +361,0 @@ this.trigger('data', event);

@@ -100,2 +100,4 @@ /**

this.lastProgramDateTime = null;
/* eslint-disable consistent-this */

@@ -128,2 +130,3 @@ const self = this;

discontinuityStarts: [],
dateRanges: [],
segments: []

@@ -137,3 +140,3 @@ };

let lastPartByterangeEnd = 0;
const daterangeTags = {};
const dateRangeTags = {};

@@ -227,2 +230,7 @@ this.on('end', () => {

}
if (entry.title) {
currentUri.title = entry.title;
}
if (entry.duration > 0) {

@@ -458,13 +466,17 @@ currentUri.duration = entry.duration;

'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();
// 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);
}
currentUri.dateTimeString = entry.dateTimeString;
currentUri.dateTimeObject = entry.dateTimeObject;
},

@@ -642,5 +654,4 @@ targetduration() {

'daterange'() {
this.manifest.daterange = this.manifest.daterange || [];
this.manifest.daterange.push(camelCaseKeys(entry.attributes));
const index = this.manifest.daterange.length - 1;
this.manifest.dateRanges.push(camelCaseKeys(entry.attributes));
const index = this.manifest.dateRanges.length - 1;

@@ -652,5 +663,5 @@ this.warnOnMissingAttributes_(

);
const daterange = this.manifest.daterange[index];
const dateRange = this.manifest.dateRanges[index];
if (daterange.endDate && daterange.startDate && new Date(daterange.endDate) < new Date(daterange.startDate)) {
if (dateRange.endDate && dateRange.startDate && new Date(dateRange.endDate) < new Date(dateRange.startDate)) {
this.trigger('warn', {

@@ -660,3 +671,3 @@ message: 'EXT-X-DATERANGE END-DATE must be equal to or later than the value of the START-DATE'

}
if (daterange.duration && daterange.duration < 0) {
if (dateRange.duration && dateRange.duration < 0) {
this.trigger('warn', {

@@ -666,3 +677,3 @@ message: 'EXT-X-DATERANGE DURATION must not be negative'

}
if (daterange.plannedDuration && daterange.plannedDuration < 0) {
if (dateRange.plannedDuration && dateRange.plannedDuration < 0) {
this.trigger('warn', {

@@ -672,5 +683,5 @@ message: 'EXT-X-DATERANGE PLANNED-DURATION must not be negative'

}
const endOnNextYes = !!daterange.endOnNext;
const endOnNextYes = !!dateRange.endOnNext;
if (endOnNextYes && !daterange.class) {
if (endOnNextYes && !dateRange.class) {
this.trigger('warn', {

@@ -680,3 +691,3 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must have a CLASS attribute'

}
if (endOnNextYes && (daterange.duration || daterange.endDate)) {
if (endOnNextYes && (dateRange.duration || dateRange.endDate)) {
this.trigger('warn', {

@@ -686,18 +697,13 @@ message: 'EXT-X-DATERANGE with an END-ON-NEXT=YES attribute must not contain DURATION or END-DATE attributes'

}
if (daterange.duration && daterange.endDate) {
const startDate = daterange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + daterange.duration);
if (dateRange.duration && dateRange.endDate) {
const startDate = dateRange.startDate;
const newDateInSeconds = startDate.setSeconds(startDate.getSeconds() + dateRange.duration);
this.manifest.daterange[index].endDate = new Date(newDateInSeconds);
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;
if (!dateRangeTags[dateRange.id]) {
dateRangeTags[dateRange.id] = dateRange;
} else {
for (const attribute in daterangeTags[daterange.id]) {
if (daterangeTags[daterange.id][attribute] !== daterange[attribute]) {
for (const attribute in dateRangeTags[dateRange.id]) {
if (dateRangeTags[dateRange.id][attribute] !== dateRange[attribute]) {
this.trigger('warn', {

@@ -740,2 +746,8 @@ message: 'EXT-X-DATERANGE tags with the same ID in a playlist must have the same attributes and same attribute values'

// 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

@@ -793,3 +805,9 @@ currentUri = {};

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');

@@ -802,3 +820,3 @@ }

* @param {RegExp} options.expression a regular expression to match the custom header
* @param {string} options.type the type to register to the output
* @param {string} options.customType the custom type to register to the output
* @param {Function} [options.dataParser] function to parse the line into an object

@@ -805,0 +823,0 @@ * @param {boolean} [options.segment] should tag data be attached to the segment object

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',

@@ -5,0 +6,0 @@ segments: [

module.exports = {
allowCache: true,
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',

@@ -5,0 +6,0 @@ segments: [

module.exports = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
mediaGroups: {

@@ -5,0 +6,0 @@ // TYPE

module.exports = {
allowCache: true,
discontinuityStarts: [],
dateRanges: [],
mediaGroups: {

@@ -5,0 +6,0 @@ 'AUDIO': {

module.exports = {
allowCache: true,
dateRanges: [],
playlists: [

@@ -4,0 +5,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

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,

@@ -14,4 +14,3 @@ timeline: 0,

{
dateTimeString: '2016-06-22T09:20:26.166-04:00',
dateTimeObject: new Date('2016-06-22T09:20:26.166-04:00'),
programDateTime: 1466601626166,
duration: 10,

@@ -24,6 +23,4 @@ timeline: 0,

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: []
};

@@ -5,2 +5,3 @@ module.exports = {

discontinuityStarts: [],
dateRanges: [],
mediaSequence: 7794,

@@ -7,0 +8,0 @@ segments: [

module.exports = {
allowCache: false,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ discontinuitySequence: 3,

timeline: 3,
uri: '001.ts'
uri: '001.ts',
title: '0'
},

@@ -15,3 +17,4 @@ {

timeline: 3,
uri: '002.ts'
uri: '002.ts',
title: '0'
},

@@ -22,3 +25,4 @@ {

timeline: 4,
uri: '003.ts'
uri: '003.ts',
title: '0'
},

@@ -28,3 +32,4 @@ {

timeline: 4,
uri: '004.ts'
uri: '004.ts',
title: '0'
}

@@ -31,0 +36,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ discontinuitySequence: 0,

timeline: 0,
uri: '001.ts'
uri: '001.ts',
title: '0'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '002.ts'
uri: '002.ts',
title: '0'
},

@@ -22,3 +25,4 @@ {

timeline: 1,
uri: '003.ts'
uri: '003.ts',
title: '0'
},

@@ -28,3 +32,4 @@ {

timeline: 1,
uri: '004.ts'
uri: '004.ts',
title: '0'
},

@@ -35,3 +40,4 @@ {

timeline: 2,
uri: '005.ts'
uri: '005.ts',
title: '0'
},

@@ -41,3 +47,4 @@ {

timeline: 2,
uri: '006.ts'
uri: '006.ts',
title: '0'
},

@@ -47,3 +54,4 @@ {

timeline: 2,
uri: '007.ts'
uri: '007.ts',
title: '0'
},

@@ -54,3 +62,4 @@ {

timeline: 3,
uri: '008.ts'
uri: '008.ts',
title: '0'
},

@@ -60,3 +69,4 @@ {

timeline: 3,
uri: '009.ts'
uri: '009.ts',
title: '0'
}

@@ -63,0 +73,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
segments: []
};
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},

@@ -21,3 +24,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},

@@ -27,3 +31,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts'
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}

@@ -30,0 +35,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ segments: [

module.exports = {
allowCache: true,
dateRanges: [],
playlists: [

@@ -4,0 +5,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 7794,

@@ -4,0 +5,0 @@ discontinuitySequence: 0,

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'EVENT',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -22,3 +23,4 @@ playlistType: 'VOD',

timeline: 0,
uri: 'hls_450k_video.ts'
uri: 'hls_450k_video.ts',
title: ';asljasdfii11)))00,'
},

@@ -25,0 +27,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 1,

@@ -8,3 +9,4 @@ segments: [

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
}

@@ -11,0 +13,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 1,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],
segments: []
};
module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},

@@ -21,3 +24,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},

@@ -27,3 +31,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts'
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}

@@ -30,0 +35,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ segments: [

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -12,0 +14,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -8,3 +9,4 @@ segments: [

timeline: 0,
uri: '001.ts'
uri: '001.ts',
title: '0'
},

@@ -14,3 +16,4 @@ {

timeline: 0,
uri: '002.ts'
uri: '002.ts',
title: '0'
},

@@ -20,3 +23,4 @@ {

timeline: 0,
uri: '003.ts'
uri: '003.ts',
title: '0'
},

@@ -26,3 +30,4 @@ {

timeline: 0,
uri: '004.ts'
uri: '004.ts',
title: '0'
},

@@ -32,3 +37,4 @@ {

timeline: 0,
uri: '005.ts'
uri: '005.ts',
title: '0'
},

@@ -38,3 +44,4 @@ {

timeline: 0,
uri: '006.ts'
uri: '006.ts',
title: '0'
},

@@ -44,3 +51,4 @@ {

timeline: 0,
uri: '007.ts'
uri: '007.ts',
title: '0'
},

@@ -50,3 +58,4 @@ {

timeline: 0,
uri: '008.ts'
uri: '008.ts',
title: '0'
},

@@ -56,3 +65,4 @@ {

timeline: 0,
uri: '009.ts'
uri: '009.ts',
title: '0'
}

@@ -59,0 +69,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
discontinuitySequence: 0,

@@ -4,0 +5,0 @@ discontinuityStarts: [],

module.exports = {
allowCache: true,
dateRanges: [],
discontinuitySequence: 0,

@@ -4,0 +5,0 @@ discontinuityStarts: [],

module.exports = {
allowCache: true,
dateTimeObject: new Date('2019-02-14T02:13:36.106Z'),
dateTimeString: '2019-02-14T02:13:36.106Z',
dateRanges: [],
discontinuitySequence: 0,

@@ -41,4 +40,3 @@ discontinuityStarts: [],

{
dateTimeObject: new Date('2019-02-14T02:13:36.106Z'),
dateTimeString: '2019-02-14T02:13:36.106Z',
programDateTime: 1550110416106,
duration: 4.00008,

@@ -56,2 +54,3 @@ map: {

},
programDateTime: 1550110420106.08,
timeline: 0,

@@ -65,2 +64,3 @@ uri: 'fileSequence267.mp4'

},
programDateTime: 1550110424106.1602,
timeline: 0,

@@ -74,2 +74,3 @@ uri: 'fileSequence268.mp4'

},
programDateTime: 1550110428106.2402,
timeline: 0,

@@ -83,2 +84,3 @@ uri: 'fileSequence269.mp4'

},
programDateTime: 1550110432106.3203,
timeline: 0,

@@ -92,2 +94,3 @@ uri: 'fileSequence270.mp4'

},
programDateTime: 1550110436106.4004,
timeline: 0,

@@ -149,4 +152,2 @@ uri: 'fileSequence271.mp4',

{
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
dateTimeString: '2019-02-14T02:14:00.106Z',
duration: 4.00008,

@@ -156,2 +157,3 @@ map: {

},
programDateTime: 1550110440106,
timeline: 0,

@@ -158,0 +160,0 @@ uri: 'fileSequence272.mp4',

module.exports = {
allowCache: true,
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
dateTimeString: '2019-02-14T02:14:00.106Z',
dateRanges: [],
discontinuitySequence: 0,

@@ -45,2 +44,3 @@ discontinuityStarts: [],

duration: 4.00008,
programDateTime: 1550110428105.7598,
timeline: 0,

@@ -51,2 +51,3 @@ uri: 'fileSequence269.mp4'

duration: 4.00008,
programDateTime: 1550110432105.8398,
timeline: 0,

@@ -57,2 +58,3 @@ uri: 'fileSequence270.mp4'

duration: 4.00008,
programDateTime: 1550110436105.92,
timeline: 0,

@@ -114,5 +116,4 @@ uri: 'fileSequence271.mp4',

{
dateTimeObject: new Date('2019-02-14T02:14:00.106Z'),
dateTimeString: '2019-02-14T02:14:00.106Z',
duration: 4.00008,
programDateTime: 1550110440106,
timeline: 0,

@@ -119,0 +120,0 @@ uri: 'fileSequence272.mp4',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ segments: [

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ segments: [

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ segments: [

module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],

@@ -4,0 +5,0 @@ mediaGroups: {

module.exports = {
allowCache: true,
dateRanges: [],
playlists: [

@@ -4,0 +5,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},

@@ -21,3 +24,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},

@@ -27,3 +31,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts'
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}

@@ -30,0 +35,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ segments: [

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},

@@ -21,3 +24,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},

@@ -27,3 +31,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts'
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}

@@ -30,0 +35,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -12,0 +14,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],

@@ -4,0 +5,0 @@ mediaGroups: {

module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],

@@ -4,0 +5,0 @@ mediaGroups: {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ targetDuration: 10,

module.exports = {
allowCache: true,
dateRanges: [],
discontinuityStarts: [],

@@ -4,0 +5,0 @@ mediaGroups: {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: -11,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},

@@ -21,3 +24,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},

@@ -27,3 +31,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts'
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}

@@ -30,0 +35,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 17,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
}

@@ -12,0 +14,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
playlists: [

@@ -4,0 +5,0 @@ {

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 11,

@@ -9,3 +10,4 @@ playlistType: 'VOD',

timeline: 0,
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts'
uri: '/test/ts-files/tvy7/8a5e2822668b5370f4eb1438b2564fb7ab12ffe1-hi720.ts',
title: '{}'
},

@@ -15,3 +17,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts'
uri: '/test/ts-files/tvy7/56be1cef869a1c0cc8e38864ad1add17d187f051-hi720.ts',
title: '{}'
},

@@ -21,3 +24,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts'
uri: '/test/ts-files/tvy7/549c8c77f55f049741a06596e5c1e01dacaa46d0-hi720.ts',
title: '{}'
},

@@ -27,3 +31,4 @@ {

timeline: 0,
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts'
uri: '/test/ts-files/tvy7/6cfa378684ffeb1c455a64dae6c103290a1f53d4-hi720.ts',
title: '{}'
}

@@ -30,0 +35,0 @@ ],

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
dateRanges: [],
mediaSequence: 0,

@@ -4,0 +5,0 @@ playlistType: 'VOD',

module.exports = {
allowCache: true,
mediaSequence: 0,
dateRanges: [],
playlistType: 'VOD',

@@ -5,0 +6,0 @@ segments: [

@@ -638,6 +638,2 @@ import {LineStream, ParseStream} from '../src';

);
assert.deepEqual(
element.dateTimeObject, new Date('2016-06-22T09:20:16.166-04:00'),
'dateTimeObject is parsed'
);

@@ -654,6 +650,2 @@ manifest = '#EXT-X-PROGRAM-DATE-TIME:2016-06-22T09:20:16.16389Z\n';

);
assert.deepEqual(
element.dateTimeObject, new Date('2016-06-22T09:20:16.16389Z'),
'dateTimeObject is parsed'
);
}

@@ -660,0 +652,0 @@ );

@@ -848,2 +848,67 @@ import QUnit from 'qunit';

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) {

@@ -1008,3 +1073,3 @@ this.parser.push([

assert.deepEqual(this.parser.manifest.daterange[0].endDate, new Date('2023-04-13T15:16:29.840000Z'));
assert.deepEqual(this.parser.manifest.dateRanges[0].endDate, new Date('2023-04-13T15:16:29.840000Z'));
});

@@ -1058,3 +1123,3 @@

this.parser.end();
assert.equal(this.parser.manifest.daterange.length, 3);
assert.equal(this.parser.manifest.dateRanges.length, 3);
});

@@ -1061,0 +1126,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc