RockPaperScissors/node_modules/m3u8stream/dist/m3u8-parser.js

111 lines
3.7 KiB
JavaScript
Raw Normal View History

2021-12-02 16:15:29 +00:00
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = require("stream");
/**
* A very simple m3u8 playlist file parser that detects tags and segments.
*/
class m3u8Parser extends stream_1.Writable {
constructor() {
super();
this._lastLine = '';
this._seq = 0;
this._nextItemDuration = null;
this._nextItemRange = null;
this._lastItemRangeEnd = 0;
this.on('finish', () => {
this._parseLine(this._lastLine);
this.emit('end');
});
}
_parseAttrList(value) {
let attrs = {};
let regex = /([A-Z0-9-]+)=(?:"([^"]*?)"|([^,]*?))/g;
let match;
while ((match = regex.exec(value)) !== null) {
attrs[match[1]] = match[2] || match[3];
}
return attrs;
}
_parseRange(value) {
if (!value)
return null;
let svalue = value.split('@');
let start = svalue[1] ? parseInt(svalue[1]) : this._lastItemRangeEnd + 1;
let end = start + parseInt(svalue[0]) - 1;
let range = { start, end };
this._lastItemRangeEnd = range.end;
return range;
}
_parseLine(line) {
let match = line.match(/^#(EXT[A-Z0-9-]+)(?::(.*))?/);
if (match) {
// This is a tag.
const tag = match[1];
const value = match[2] || '';
switch (tag) {
case 'EXT-X-PROGRAM-DATE-TIME':
this.emit('starttime', new Date(value).getTime());
break;
case 'EXT-X-MEDIA-SEQUENCE':
this._seq = parseInt(value);
break;
case 'EXT-X-MAP': {
let attrs = this._parseAttrList(value);
if (!attrs.URI) {
this.destroy(new Error('`EXT-X-MAP` found without required attribute `URI`'));
return;
}
this.emit('item', {
url: attrs.URI,
seq: this._seq,
init: true,
duration: 0,
range: this._parseRange(attrs.BYTERANGE),
});
break;
}
case 'EXT-X-BYTERANGE': {
this._nextItemRange = this._parseRange(value);
break;
}
case 'EXTINF':
this._nextItemDuration =
Math.round(parseFloat(value.split(',')[0]) * 1000);
break;
case 'EXT-X-ENDLIST':
this.emit('endlist');
break;
}
}
else if (!/^#/.test(line) && line.trim()) {
// This is a segment
this.emit('item', {
url: line.trim(),
seq: this._seq++,
duration: this._nextItemDuration,
range: this._nextItemRange,
});
this._nextItemRange = null;
}
}
_write(chunk, encoding, callback) {
let lines = chunk.toString('utf8').split('\n');
if (this._lastLine) {
lines[0] = this._lastLine + lines[0];
}
lines.forEach((line, i) => {
if (this.destroyed)
return;
if (i < lines.length - 1) {
this._parseLine(line);
}
else {
// Save the last line in case it has been broken up.
this._lastLine = line;
}
});
callback();
}
}
exports.default = m3u8Parser;
//# sourceMappingURL=m3u8-parser.js.map