1
0
mirror of https://github.com/musix-org/musix-oss synced 2025-06-17 01:16:00 +00:00
This commit is contained in:
MatteZ02
2020-03-03 22:30:50 +02:00
parent edfcc6f474
commit 30022c7634
11800 changed files with 1984416 additions and 1 deletions

21
node_modules/m3u8stream/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (C) 2017 by fent
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

69
node_modules/m3u8stream/README.md generated vendored Normal file
View File

@ -0,0 +1,69 @@
# node-m3u8stream
Reads segments from a [m3u8 playlist][1] or [DASH MPD file][2] into a consumable stream.
[1]: https://tools.ietf.org/html/draft-pantos-http-live-streaming-20
[2]: https://dashif.org/docs/DASH-IF-IOP-v4.2-clean.pdf
[![Dependency Status](https://david-dm.org/fent/node-m3u8stream.svg)](https://david-dm.org/fent/node-m3u8stream)
[![codecov](https://codecov.io/gh/fent/node-m3u8stream/branch/master/graph/badge.svg)](https://codecov.io/gh/fent/node-m3u8stream)
# Usage
```js
const fs = require('fs');
const m3u8stream = require('m3u8stream')
m3u8stream('http://somesite.com/link/to/the/playlist.m3u8')
.pipe(fs.createWriteStream('videofile.mp4'));
```
# API
### m3u8stream(url, [options])
Creates a readable stream of binary media data. `options` can have the following
* `begin` - Where to begin playing the video. Accepts an absolute unix timestamp or date, and a relative time in the formats `1:23:45.123` and `1m2s`.
* `liveBuffer` - How much buffer in milliseconds to have for live streams. Default is `20000`.
* `chunkReadahead` - How many chunks to preload ahead. Default is `3`.
* `highWaterMark` - How much of the download to buffer into the stream. See [node's docs](https://nodejs.org/api/stream.html#stream_constructor_new_stream_writable_options) for more. Note that the actual amount buffered can be higher since each chunk request maintains its own buffer.
* `requestOptions` - Any options you want to pass to [miniget](https://github.com/fent/node-miniget), such as `headers`.
* `parser` - Either "m3u8" or "dash-mpd". Defaults to guessing based on the playlist url ending in `.m3u8` or `.mpd`.
* `id` - For playlist containing multiple media options. If not given, the first representation will be picked.
### Stream#end()
If called, stops requesting segments, and refreshing the playlist.
#### Event: progress
* `Object` - Current segment with the following fields,
- `number` - number
- `number` - size
- `number` - duration
- `string` - url
* `number` - Total number of segments.
* `number` - Bytes downloaded up to this point.
For static non-live playlists, emitted each time a segment has finished downloading. Since total download size is unknown until all segment endpoints are hit, progress is calculated based on how many segments are available.
### Limitations
Currently, it does not support [encrypted media segments](https://tools.ietf.org/html/draft-pantos-http-live-streaming-20#section-4.3.2.4). This is because the sites where this was tested on and intended for, YouTube and Twitch, don't use it.
This does not parse master playlists, only media playlists. If you want to parse a master playlist to get links to media playlists, you can try the [m3u8 module](https://github.com/tedconf/node-m3u8).
# Install
npm install m3u8stream
# Tests
Tests are written with [mocha](https://mochajs.org)
```bash
npm test
```

11
node_modules/m3u8stream/dist/dash-mpd-parser.d.ts generated vendored Normal file
View File

@ -0,0 +1,11 @@
/// <reference types="node" />
import { Writable } from 'stream';
import { Parser } from './parser';
/**
* A wrapper around sax that emits segments.
*/
export default class DashMPDParser extends Writable implements Parser {
private _parser;
constructor(targetID?: string);
_write(chunk: Buffer, encoding: string, callback: () => void): void;
}

175
node_modules/m3u8stream/dist/dash-mpd-parser.js generated vendored Normal file
View File

@ -0,0 +1,175 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const stream_1 = require("stream");
const sax_1 = __importDefault(require("sax"));
const parse_time_1 = require("./parse-time");
/**
* A wrapper around sax that emits segments.
*/
class DashMPDParser extends stream_1.Writable {
constructor(targetID) {
super();
this._parser = sax_1.default.createStream(false, { lowercase: true });
this._parser.on('error', this.emit.bind(this, 'error'));
let lastTag;
let currtime = 0;
let seq = 0;
let segmentTemplate;
let timescale, offset, duration, baseURL;
let timeline = [];
let getSegments = false;
let isStatic;
let treeLevel;
let periodStart;
const tmpl = (str) => {
const context = {
RepresentationID: targetID,
Number: seq,
Time: currtime,
};
return str.replace(/\$(\w+)\$/g, (m, p1) => context[p1] + '');
};
this._parser.on('opentag', (node) => {
switch (node.name) {
case 'mpd':
currtime =
new Date(node.attributes.availabilitystarttime).getTime();
isStatic = node.attributes.type !== 'dynamic';
break;
case 'period':
// Reset everything on <Period> tag.
seq = 0;
timescale = 1000;
duration = 0;
offset = 0;
baseURL = [];
treeLevel = 0;
periodStart = parse_time_1.durationStr(node.attributes.start) || 0;
break;
case 'segmentlist':
seq = parseInt(node.attributes.startnumber) || seq;
timescale = parseInt(node.attributes.timescale) || timescale;
duration = parseInt(node.attributes.duration) || duration;
offset = parseInt(node.attributes.presentationtimeoffset) || offset;
break;
case 'segmenttemplate':
segmentTemplate = node.attributes;
seq = parseInt(node.attributes.startnumber) || seq;
timescale = parseInt(node.attributes.timescale) || timescale;
break;
case 'segmenttimeline':
case 'baseurl':
lastTag = node.name;
break;
case 's':
timeline.push([
parseInt(node.attributes.d),
parseInt(node.attributes.r)
]);
break;
case 'adaptationset':
case 'representation':
treeLevel++;
if (targetID == null) {
targetID = node.attributes.id;
}
getSegments = node.attributes.id === targetID + '';
if (getSegments) {
if (periodStart) {
currtime += periodStart;
}
if (offset) {
currtime -= offset / timescale * 1000;
}
this.emit('starttime', currtime);
}
if (getSegments && segmentTemplate && timeline.length) {
if (segmentTemplate.initialization) {
this.emit('item', {
url: baseURL.filter(s => !!s).join('') +
tmpl(segmentTemplate.initialization),
seq: seq - 1,
duration: 0,
});
}
for (let [duration, repeat] of timeline) {
duration = duration / timescale * 1000;
repeat = repeat || 1;
for (let i = 0; i < repeat; i++) {
this.emit('item', {
url: baseURL.filter(s => !!s).join('') +
tmpl(segmentTemplate.media),
seq: seq++,
duration,
});
currtime += duration;
}
}
}
break;
case 'initialization':
if (getSegments) {
this.emit('item', {
url: baseURL.filter(s => !!s).join('') + node.attributes.sourceurl,
seq: seq++,
duration: 0,
});
}
break;
case 'segmenturl':
if (getSegments) {
let tl = timeline.shift();
let segmentDuration = (tl && tl[0] || duration) / timescale * 1000;
this.emit('item', {
url: baseURL.filter(s => !!s).join('') + node.attributes.media,
seq: seq++,
duration: segmentDuration,
});
currtime += segmentDuration;
}
break;
}
});
const onEnd = () => {
if (isStatic) {
this.emit('endlist');
}
if (!getSegments) {
this.emit('error', Error(`Representation '${targetID}' not found`));
}
this.emit('end');
};
this._parser.on('closetag', (tagName) => {
switch (tagName) {
case 'adaptationset':
case 'representation':
treeLevel--;
break;
case 'segmentlist':
if (getSegments) {
this.emit('endearly');
onEnd();
this._parser.removeAllListeners();
}
break;
}
});
this._parser.on('text', (text) => {
if (lastTag === 'baseurl') {
baseURL[treeLevel] = text;
lastTag = null;
}
});
this.on('finish', onEnd);
}
_write(chunk, encoding, callback) {
this._parser.write(chunk, encoding);
callback();
}
}
exports.default = DashMPDParser;
;
//# sourceMappingURL=dash-mpd-parser.js.map

1
node_modules/m3u8stream/dist/dash-mpd-parser.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

27
node_modules/m3u8stream/dist/index.d.ts generated vendored Normal file
View File

@ -0,0 +1,27 @@
/// <reference types="node" />
import { PassThrough } from 'stream';
import miniget from 'miniget';
declare namespace m3u8stream {
interface Options {
begin?: number | string;
liveBuffer?: number;
chunkReadahead?: number;
highWaterMark?: number;
requestOptions?: miniget.Options;
parser?: 'm3u8' | 'dash-mpd';
id?: string;
}
interface Progress {
num: number;
size: number;
duration: number;
url: string;
}
interface Stream extends PassThrough {
end: () => void;
on(event: 'progress', progress: Progress, totalSegments: number, downloadedBytes: number): this;
on(event: string | symbol, listener: (...args: any) => void): this;
}
}
declare let m3u8stream: (playlistURL: string, options?: m3u8stream.Options) => m3u8stream.Stream;
export = m3u8stream;

176
node_modules/m3u8stream/dist/index.js generated vendored Normal file
View File

@ -0,0 +1,176 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
const stream_1 = require("stream");
const url_1 = require("url");
const miniget_1 = __importDefault(require("miniget"));
const m3u8_parser_1 = __importDefault(require("./m3u8-parser"));
const dash_mpd_parser_1 = __importDefault(require("./dash-mpd-parser"));
const queue_1 = __importDefault(require("./queue"));
const parse_time_1 = require("./parse-time");
const supportedParsers = {
'm3u8': m3u8_parser_1.default,
'dash-mpd': dash_mpd_parser_1.default,
};
let m3u8stream = (playlistURL, options = {}) => {
const stream = new stream_1.PassThrough();
const chunkReadahead = options.chunkReadahead || 3;
const liveBuffer = options.liveBuffer || 20000; // 20 seconds
const requestOptions = options.requestOptions;
const Parser = supportedParsers[options.parser || (/\.mpd$/.test(playlistURL) ? 'dash-mpd' : 'm3u8')];
if (!Parser) {
throw TypeError(`parser '${options.parser}' not supported`);
}
let begin = 0;
if (typeof options.begin !== 'undefined') {
begin = typeof options.begin === 'string' ?
parse_time_1.humanStr(options.begin) :
Math.max(options.begin - liveBuffer, 0);
}
let liveBegin = Date.now() - liveBuffer;
let currSegment;
const streamQueue = new queue_1.default((req, callback) => {
currSegment = req;
// Count the size manually, since the `content-length` header is not
// always there.
let size = 0;
req.on('data', (chunk) => size += chunk.length);
req.pipe(stream, { end: false });
req.on('end', () => callback(undefined, size));
}, { concurrency: 1 });
let segmentNumber = 0;
let downloaded = 0;
const requestQueue = new queue_1.default((segment, callback) => {
let req = miniget_1.default(url_1.resolve(playlistURL, segment.url), requestOptions);
req.on('error', callback);
streamQueue.push(req, (err, size) => {
downloaded += +size;
stream.emit('progress', {
num: ++segmentNumber,
size: size,
duration: segment.duration,
url: segment.url,
}, requestQueue.total, downloaded);
callback();
});
}, { concurrency: chunkReadahead });
const onError = (err) => {
if (ended) {
return;
}
stream.emit('error', err);
// Stop on any error.
stream.end();
};
// When to look for items again.
let refreshThreshold;
let minRefreshTime;
let refreshTimeout;
let fetchingPlaylist = true;
let ended = false;
let isStatic = false;
let lastRefresh;
const onQueuedEnd = (err) => {
currSegment = null;
if (err) {
onError(err);
}
else if (!fetchingPlaylist && !ended && !isStatic &&
requestQueue.tasks.length + requestQueue.active <= refreshThreshold) {
let ms = Math.max(0, minRefreshTime - (Date.now() - lastRefresh));
fetchingPlaylist = true;
refreshTimeout = setTimeout(refreshPlaylist, ms);
}
else if ((ended || isStatic) &&
!requestQueue.tasks.length && !requestQueue.active) {
stream.end();
}
};
let currPlaylist;
let lastSeq;
let starttime = 0;
const refreshPlaylist = () => {
lastRefresh = Date.now();
currPlaylist = miniget_1.default(playlistURL, requestOptions);
currPlaylist.on('error', onError);
const parser = currPlaylist.pipe(new Parser(options.id));
parser.on('starttime', (a) => {
if (starttime) {
return;
}
starttime = a;
if (typeof options.begin === 'string' && begin >= 0) {
begin += starttime;
}
});
parser.on('endlist', () => { isStatic = true; });
parser.on('endearly', currPlaylist.unpipe.bind(currPlaylist, parser));
let addedItems = [];
let liveAddedItems = [];
const addItem = (item, isLive) => {
if (item.seq <= lastSeq) {
return;
}
lastSeq = item.seq;
begin = item.time;
requestQueue.push(item, onQueuedEnd);
addedItems.push(item);
if (isLive) {
liveAddedItems.push(item);
}
};
let tailedItems = [], tailedItemsDuration = 0;
parser.on('item', (item) => {
let timedItem = Object.assign({ time: starttime }, item);
let isLive = liveBegin <= timedItem.time;
if (begin <= timedItem.time) {
addItem(timedItem, isLive);
}
else {
tailedItems.push(timedItem);
tailedItemsDuration += timedItem.duration;
// Only keep the last `liveBuffer` of items.
while (tailedItems.length > 1 &&
tailedItemsDuration - tailedItems[0].duration > liveBuffer) {
tailedItemsDuration -= tailedItems.shift().duration;
}
}
starttime += timedItem.duration;
});
parser.on('end', () => {
currPlaylist = null;
// If we are too ahead of the stream, make sure to get the
// latest available items with a small buffer.
if (!addedItems.length && tailedItems.length) {
tailedItems.forEach((item) => { addItem(item, true); });
}
// Refresh the playlist when remaining segments get low.
refreshThreshold = Math.max(1, Math.ceil(addedItems.length * 0.01));
// Throttle refreshing the playlist by looking at the duration
// of live items added on this refresh.
minRefreshTime =
addedItems.reduce(((total, item) => item.duration + total), 0);
fetchingPlaylist = false;
});
};
refreshPlaylist();
stream.end = () => {
ended = true;
streamQueue.die();
requestQueue.die();
clearTimeout(refreshTimeout);
if (currPlaylist) {
currPlaylist.unpipe();
currPlaylist.abort();
}
if (currSegment) {
currSegment.unpipe();
currSegment.abort();
}
stream_1.PassThrough.prototype.end.call(stream, null);
};
return stream;
};
module.exports = m3u8stream;
//# sourceMappingURL=index.js.map

1
node_modules/m3u8stream/dist/index.js.map generated vendored Normal file

File diff suppressed because one or more lines are too long

14
node_modules/m3u8stream/dist/m3u8-parser.d.ts generated vendored Normal file
View File

@ -0,0 +1,14 @@
/// <reference types="node" />
import { Writable } from 'stream';
import { Parser } from './parser';
/**
* A very simple m3u8 playlist file parser that detects tags and segments.
*/
export default class m3u8Parser extends Writable implements Parser {
private _lastLine;
private _seq;
private _nextItemDuration;
constructor();
_parseLine(line: string): void;
_write(chunk: Buffer, encoding: string, callback: () => void): void;
}

67
node_modules/m3u8stream/dist/m3u8-parser.js generated vendored Normal file
View File

@ -0,0 +1,67 @@
"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.on('finish', () => {
this._parseLine(this._lastLine);
this.emit('end');
});
}
_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 '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,
});
}
}
_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 (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

1
node_modules/m3u8stream/dist/m3u8-parser.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"m3u8-parser.js","sourceRoot":"","sources":["../src/m3u8-parser.ts"],"names":[],"mappings":";;AAAA,mCAAkC;AAIlC;;GAEG;AACH,MAAqB,UAAW,SAAQ,iBAAQ;IAK9C;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QACpB,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YACrB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAChC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,IAAY;QACrB,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACtD,IAAI,KAAK,EAAE;YACT,iBAAiB;YACjB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7B,QAAQ,GAAG,EAAE;gBACX,KAAK,yBAAyB;oBAC5B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;oBAClD,MAAM;gBACR,KAAK,sBAAsB;oBACzB,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;oBAC5B,MAAM;gBACR,KAAK,QAAQ;oBACX,IAAI,CAAC,iBAAiB;wBACpB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;oBACrD,MAAM;gBACR,KAAK,eAAe;oBAClB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACrB,MAAM;aACT;SAEF;aAAM,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE;YAC1C,oBAAoB;YACpB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;gBAChB,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE;gBAChB,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE;gBAChB,QAAQ,EAAE,IAAI,CAAC,iBAAiB;aACjC,CAAC,CAAC;SACJ;IACH,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,QAAgB,EAAE,QAAoB;QAC1D,IAAI,KAAK,GAAa,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,IAAI,CAAC,SAAS,EAAE;YAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;SAAE;QAC7D,KAAK,CAAC,OAAO,CAAC,CAAC,IAAY,EAAE,CAAS,EAAE,EAAE;YACxC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;gBACxB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;aACvB;iBAAM;gBACL,oDAAoD;gBACpD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;aACvB;QACH,CAAC,CAAC,CAAC;QACH,QAAQ,EAAE,CAAC;IACb,CAAC;CACF;AA7DD,6BA6DC"}

5
node_modules/m3u8stream/dist/parse-time.d.ts generated vendored Normal file
View File

@ -0,0 +1,5 @@
export declare const humanStr: (time: string | number) => number;
/**
* Parses a duration string in the form of "123.456S", returns milliseconds.
*/
export declare const durationStr: (time: string) => number;

52
node_modules/m3u8stream/dist/parse-time.js generated vendored Normal file
View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**
* Converts human friendly time to milliseconds. Supports the format
* 00:00:00.000 for hours, minutes, seconds, and milliseconds respectively.
* And 0ms, 0s, 0m, 0h, and together 1m1s.
*/
const numberFormat = /^\d+$/;
const timeFormat = /^(?:(?:(\d+):)?(\d{1,2}):)?(\d{1,2})(?:\.(\d{3}))?$/;
const timeUnits = {
ms: 1,
s: 1000,
m: 60000,
h: 3600000,
};
exports.humanStr = (time) => {
if (typeof time === 'number') {
return time;
}
if (numberFormat.test(time)) {
return +time;
}
const firstFormat = timeFormat.exec(time);
if (firstFormat) {
return +(firstFormat[1] || 0) * timeUnits.h +
+(firstFormat[2] || 0) * timeUnits.m +
+firstFormat[3] * timeUnits.s +
+(firstFormat[4] || 0);
}
else {
let total = 0;
const r = /(-?\d+)(ms|s|m|h)/g;
let rs;
while ((rs = r.exec(time)) != null) {
total += +rs[1] * timeUnits[rs[2]];
}
return total;
}
};
/**
* Parses a duration string in the form of "123.456S", returns milliseconds.
*/
exports.durationStr = (time) => {
let total = 0;
const r = /(\d+(?:\.\d+)?)(S|M|H)/g;
let rs;
while ((rs = r.exec(time)) != null) {
total += +rs[1] * timeUnits[rs[2].toLowerCase()];
}
return total;
};
//# sourceMappingURL=parse-time.js.map

1
node_modules/m3u8stream/dist/parse-time.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"parse-time.js","sourceRoot":"","sources":["../src/parse-time.ts"],"names":[],"mappings":";;AAAA;;;;GAIG;AACH,MAAM,YAAY,GAAG,OAAO,CAAC;AAC7B,MAAM,UAAU,GAAG,qDAAqD,CAAC;AACzE,MAAM,SAAS,GAA8B;IAC3C,EAAE,EAAE,CAAC;IACL,CAAC,EAAE,IAAI;IACP,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,OAAO;CACX,CAAC;AACW,QAAA,QAAQ,GAAG,CAAC,IAAqB,EAAU,EAAE;IACxD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAAE,OAAO,IAAI,CAAC;KAAE;IAC9C,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC;KAAE;IAC9C,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,WAAW,EAAE;QACf,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;YACzC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;YACpC,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;YAC7B,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;KAC1B;SAAM;QACL,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,oBAAoB,CAAC;QAC/B,IAAI,EAAE,CAAC;QACP,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE;YAClC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;SACpC;QACD,OAAO,KAAK,CAAC;KACd;AACH,CAAC,CAAC;AAEF;;GAEG;AACU,QAAA,WAAW,GAAG,CAAC,IAAY,EAAU,EAAE;IAClD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,CAAC,GAAG,yBAAyB,CAAC;IACpC,IAAI,EAA0B,CAAC;IAC/B,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE;QAClC,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;KAClD;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC"}

14
node_modules/m3u8stream/dist/parser.d.ts generated vendored Normal file
View File

@ -0,0 +1,14 @@
/// <reference types="node" />
import { Writable } from 'stream';
export interface Item {
url: string;
seq: number;
duration: number;
time?: number;
}
export interface Parser extends Writable {
on(event: 'item', listener: (item: Item) => boolean): this;
on(event: string | symbol, listener: (...args: any[]) => any): this;
emit(event: 'item', item: Item): boolean;
emit(event: string, ...args: any[]): boolean;
}

3
node_modules/m3u8stream/dist/parser.js generated vendored Normal file
View File

@ -0,0 +1,3 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=parser.js.map

1
node_modules/m3u8stream/dist/parser.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":""}

31
node_modules/m3u8stream/dist/queue.d.ts generated vendored Normal file
View File

@ -0,0 +1,31 @@
declare type Callback = (err?: Error, result?: any) => void;
interface Task {
item: {};
callback: Callback;
}
export default class Queue {
_worker: (item: any, cb: Callback) => void;
_concurrency: number;
tasks: Task[];
total: number;
active: number;
/**
* A really simple queue with concurrency.
*/
constructor(worker: (item: any, cb: Callback) => void, options?: {
concurrency?: number;
});
/**
* Push a task to the queue.
*/
push(item: any, callback?: Callback): void;
/**
* Process next job in queue.
*/
_next(): void;
/**
* Stops processing queued jobs.
*/
die(): void;
}
export {};

52
node_modules/m3u8stream/dist/queue.js generated vendored Normal file
View File

@ -0,0 +1,52 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class Queue {
/**
* A really simple queue with concurrency.
*/
constructor(worker, options = {}) {
this._worker = worker;
this._concurrency = options.concurrency || 1;
this.tasks = [];
this.total = 0;
this.active = 0;
}
/**
* Push a task to the queue.
*/
push(item, callback) {
this.tasks.push({ item, callback });
this.total++;
this._next();
}
/**
* Process next job in queue.
*/
_next() {
if (this.active >= this._concurrency || !this.tasks.length) {
return;
}
const { item, callback } = this.tasks.shift();
let callbackCalled = false;
this.active++;
this._worker(item, (err, result) => {
if (callbackCalled) {
return;
}
this.active--;
callbackCalled = true;
if (callback) {
callback(err, result);
}
this._next();
});
}
/**
* Stops processing queued jobs.
*/
die() {
this.tasks = [];
}
}
exports.default = Queue;
//# sourceMappingURL=queue.js.map

1
node_modules/m3u8stream/dist/queue.js.map generated vendored Normal file
View File

@ -0,0 +1 @@
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../src/queue.ts"],"names":[],"mappings":";;AAMA,MAAqB,KAAK;IAOxB;;OAEG;IACH,YAAY,MAAyC,EAAE,UAAoC,EAAE;QAC3F,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAClB,CAAC;IAGD;;OAEG;IACH,IAAI,CAAC,IAAS,EAAE,QAAmB;QACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,EAAE,CAAC;QACb,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAGD;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,OAAO;SAAE;QACvE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAU,CAAC;QACtD,IAAI,cAAc,GAAG,KAAK,CAAC;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YACjC,IAAI,cAAc,EAAE;gBAAE,OAAO;aAAE;YAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;YACd,cAAc,GAAG,IAAI,CAAC;YACtB,IAAI,QAAQ,EAAE;gBAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;aAAE;YACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAGD;;OAEG;IACH,GAAG;QACD,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC;IAClB,CAAC;CACF;AArDD,wBAqDC"}

83
node_modules/m3u8stream/package.json generated vendored Normal file
View File

@ -0,0 +1,83 @@
{
"_args": [
[
"m3u8stream@0.6.4",
"C:\\Users\\matia\\Documents\\GitHub\\Musix-V3"
]
],
"_from": "m3u8stream@0.6.4",
"_id": "m3u8stream@0.6.4",
"_inBundle": false,
"_integrity": "sha512-9WLF1VAtbVij03HWJKbVZ8L0orsoZiP53UljR5EwaDrozQFMsTGRDPe3PbzWV73He8a+j5H/hWZNoI2VkUSsiw==",
"_location": "/m3u8stream",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "m3u8stream@0.6.4",
"name": "m3u8stream",
"escapedName": "m3u8stream",
"rawSpec": "0.6.4",
"saveSpec": null,
"fetchSpec": "0.6.4"
},
"_requiredBy": [
"/ytdl-core"
],
"_resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.6.4.tgz",
"_spec": "0.6.4",
"_where": "C:\\Users\\matia\\Documents\\GitHub\\Musix-V3",
"author": {
"name": "fent",
"url": "https://github.com/fent"
},
"bugs": {
"url": "https://github.com/fent/node-m3u8stream/issues"
},
"dependencies": {
"miniget": "^1.6.1",
"sax": "^1.2.4"
},
"description": "Reads segments from a m3u8 or dash playlist into a consumable stream.",
"devDependencies": {
"@types/lolex": "^3.1.1",
"@types/mocha": "^5.2.7",
"@types/node": "^13.1.0",
"@types/sax": "^1.0.1",
"lolex": "^5.0.0",
"mocha": "^6.2.0",
"nock": "^11.1.0",
"nyc": "^15.0.0",
"ts-node": "^8.4.1",
"typescript": "^3.4.2"
},
"engines": {
"node": ">=6"
},
"files": [
"dist"
],
"homepage": "https://github.com/fent/node-m3u8stream#readme",
"keywords": [
"m3u8",
"hls",
"dash",
"live",
"playlist",
"segments",
"stream"
],
"license": "MIT",
"main": "./dist/index.js",
"name": "m3u8stream",
"repository": {
"type": "git",
"url": "git://github.com/fent/node-m3u8stream.git"
},
"scripts": {
"build": "tsc -p tsconfig.build.json",
"test": "nyc --extension .ts --reporter=lcov --reporter=text-summary npm run test:unit",
"test:unit": "mocha -- --require ts-node/register test/*-test.ts"
},
"version": "0.6.4"
}