| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- export const chainPromises = <T>(
- lazyPromises: ((p: T) => Promise<T>)[],
- reducer = (lp1: (p: T) => Promise<T>, lp2: (p: T) => Promise<T>) => (p: T) => lp1(p).then(lp2),
- initialValue?: T
- ) => lazyPromises.reduce(reducer, p => Promise.resolve(p))(initialValue);
- const splitBigNumAt = (num: string, at: number) => num.replace(RegExp(String.raw`^([+-]?)(\d+)(\d{${at}})$`), '$1$2,$1$3')
- .replace(/^([^,]*)$/, '0,$1').split(',')
- .map(Number);
- const bigNumPlus = (num1: string, num2: string) => {
- let [high, low] = [splitBigNumAt(num1, 15), splitBigNumAt(num2, 15)]
- .reduce((a, b) => [a[0] + b[0], a[1] + b[1]]);
- const [highSign, lowSign] = [high, low].map(Math.sign);
- if (highSign === 0) return low.toString();
- if (highSign + lowSign === 0) {
- [high, low] = [high - highSign, low - lowSign * 10 ** 15];
- } else {
- [high, low] = [high + Math.trunc(low / 10 ** 15), low % 10 ** 15];
- }
- if (high === 0) return low.toString();
- return `${high}${Math.abs(low).toString().padStart(15, '0')}`;
- };
- const bigNumCompare = (num1: string, num2: string) => Math.sign(Number(bigNumPlus(
- num1,
- num2.replace(/^([+-]?)(\d+)/, (_, $1, $2) => `${$1 === '-' ? '' : '-'}${$2}`)
- )));
- const bigNumMin = (...nums: string[]) => {
- if (!nums || !nums.length) return undefined;
- let min = nums[0];
- for (let i = 1; i < nums.length; i++) {
- if (bigNumCompare(nums[i], min) < 0) min = nums[i];
- }
- return min;
- };
- const bigNumLShift = (num: string, by: number) => {
- if (by < 0) throw Error('cannot perform right shift');
- const at = Math.trunc((52 - by) / 10) * 3;
- const [high, low] = splitBigNumAt(num, at).map(n => n * 2 ** by);
- return bigNumPlus(`${high}${'0'.repeat(at)}`, low.toString());
- };
- const parseBigNum = (str: string) => (/^-?\d+$/.exec(str) || [''])[0].replace(/^(-)?0*/, '$1');
- export const BigNumOps = {
- splitAt: splitBigNumAt,
- plus: bigNumPlus,
- compare: bigNumCompare,
- min: bigNumMin,
- lShift: bigNumLShift,
- parse: parseBigNum,
- };
- const parseStreamlist = (str: string) => {
- const variants: {bandwidth: number, resolution: string, playlistPath: string}[] = [];
- const regex = /#EXT-X-STREAM-INF:.*BANDWIDTH=(.*),RESOLUTION=(.*),.*\n(.*)/g;
- let match: RegExpExecArray;
- while (match = regex.exec(str)) {
- variants.push({bandwidth: Number(match[1]), resolution: match[2], playlistPath: match[3]})
- }
- return variants;
- };
- const parsePlaylist = (str: string) => {
- const segmentRegex = /#EXTINF:(.*),\n(.*)/g;
- const segmentPaths: string[] = [(/#EXT-X-MAP:URI="(.*)"/.exec(str) || [])[1]];
- let match: RegExpExecArray;
- let duration = 0;
- while (match = segmentRegex.exec(str)) {
- duration += Number(match[1]);
- segmentPaths.push(match[2]);
- }
- return {duration, segmentPaths};
- };
- export const M3u8 = {parseStreamlist, parsePlaylist};
|