Skip to content

Commit

Permalink
Add more types (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
pepoirot authored Apr 6, 2024
1 parent 27ce8b0 commit 12f1e81
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 25 deletions.
39 changes: 22 additions & 17 deletions parse.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import * as utils from './utils';
import {
AllowedCpc,
ExtInfo,
Rendition,
Resolution,
TagParam,
UserAttribute,
Variant,
SessionData,
Key,
Expand Down Expand Up @@ -71,7 +76,7 @@ function getTagCategory(tagName: string): TagCategory {
}
}

function parseEXTINF(param: string) {
function parseEXTINF(param: string): ExtInfo {
const pair = utils.splitAt(param, ',') as [string, string];
return {duration: utils.toNumber(pair[0]), title: decodeURIComponent(escape(pair[1]))};
}
Expand All @@ -81,18 +86,18 @@ function parseBYTERANGE(param: string): Byterange {
return {length: utils.toNumber(pair[0]), offset: pair[1] ? utils.toNumber(pair[1]) : -1};
}

function parseResolution(str: string) {
function parseResolution(str: string): Resolution {
const pair = utils.splitAt(str, 'x') as [string, string];
return {width: utils.toNumber(pair[0]), height: utils.toNumber(pair[1])};
}

function parseAllowedCpc(str: string) {
function parseAllowedCpc(str: string): AllowedCpc[] {
const message = 'ALLOWED-CPC: Each entry must consit of KEYFORMAT and Content Protection Configuration';
const list = str.split(',');
if (list.length === 0) {
utils.INVALIDPLAYLIST(message);
}
const allowedCpcList: {format: string; cpcList: string[]}[] = [];
const allowedCpcList: AllowedCpc[] = [];
for (const item of list) {
const [format, cpcText] = utils.splitAt(item, ':');
if (!format || !cpcText) {
Expand All @@ -112,9 +117,9 @@ function parseIV(str: string): Uint8Array {
return iv;
}

function parseUserAttribute(str: string) {
function parseUserAttribute(str: string): UserAttribute {
if (str.startsWith('"')) {
return unquote(str);
return unquote(str)!;
}
if (str.startsWith('0x') || str.startsWith('0X')) {
return utils.hexToByteSequence(str);
Expand All @@ -131,7 +136,7 @@ function setCompatibleVersionOfKey(params: Record<string, any>, attributes: Reco
}
}

function parseAttributeList(param) {
function parseAttributeList(param): Record<string, any> {
const attributes = {};
for (const item of utils.splitByCommaWithPreservingQuotes(param)) {
const [key, value] = utils.splitAt(item, '=');
Expand Down Expand Up @@ -201,7 +206,7 @@ function parseAttributeList(param) {
return attributes;
}

function parseTagParam(name, param) {
function parseTagParam(name: string, param): TagParam {
switch (name) {
case 'EXTM3U':
case 'EXT-X-DISCONTINUITY':
Expand Down Expand Up @@ -282,7 +287,7 @@ function parseRendition({attributes}: Tag): Rendition {
return rendition;
}

function checkRedundantRendition(renditions, rendition) {
function checkRedundantRendition(renditions, rendition): string {
let defaultFound = false;
for (const item of renditions) {
if (item.name === rendition.name) {
Expand Down Expand Up @@ -322,7 +327,7 @@ function matchTypes(attrs, variant, params) {
}
}

function parseVariant(lines, variantAttrs, uri, iFrameOnly, params) {
function parseVariant(lines, variantAttrs, uri: string, iFrameOnly: boolean, params: Record<string, any>): Variant {
const variant = new Variant({
uri,
bandwidth: variantAttrs['BANDWIDTH'],
Expand Down Expand Up @@ -362,7 +367,7 @@ function parseVariant(lines, variantAttrs, uri, iFrameOnly, params) {
return variant;
}

function sameKey(key1: Key, key2: Key) {
function sameKey(key1: Key, key2: Key): boolean {
if (key1.method !== key2.method) {
return false;
}
Expand Down Expand Up @@ -404,7 +409,7 @@ function parseMasterPlaylist(lines: Line[], params: Record<string, any>): Master
if (typeof uri !== 'string' || uri.startsWith('#EXT')) {
utils.INVALIDPLAYLIST('EXT-X-STREAM-INF must be followed by a URI line');
}
const variant = parseVariant(lines, attributes, uri, false, params);
const variant = parseVariant(lines, attributes, uri as string, false, params);
if (variant) {
if (typeof variant.score === 'number') {
variantIsScored = true;
Expand Down Expand Up @@ -478,7 +483,7 @@ function parseMasterPlaylist(lines: Line[], params: Record<string, any>): Master
return playlist;
}

function parseSegment(lines: Line[], uri: string, start: number, end: number, mediaSequenceNumber: number, discontinuitySequence: number, params: Record<string, any>) {
function parseSegment(lines: Line[], uri: string, start: number, end: number, mediaSequenceNumber: number, discontinuitySequence: number, params: Record<string, any>): Segment {
const segment = new Segment({uri, mediaSequenceNumber, discontinuitySequence});
let mapHint = false;
let partHint = false;
Expand Down Expand Up @@ -605,7 +610,7 @@ function parseSegment(lines: Line[], uri: string, start: number, end: number, me
return segment;
}

function parsePrefetchSegment(lines: Line[], uri: any, start: number, end: number, mediaSequenceNumber: number, discontinuitySequence: number, params: Record<string, any>) {
function parsePrefetchSegment(lines: Line[], uri: any, start: number, end: number, mediaSequenceNumber: number, discontinuitySequence: number, params: Record<string, any>): PrefetchSegment {
const segment = new PrefetchSegment({uri, mediaSequenceNumber, discontinuitySequence});
for (let i = start; i <= end; i++) {
const {name, attributes} = lines[i] as Tag;
Expand All @@ -631,7 +636,7 @@ function parsePrefetchSegment(lines: Line[], uri: any, start: number, end: numbe
return segment;
}

function parseMediaPlaylist(lines: Line[], params: Record<string, any>) {
function parseMediaPlaylist(lines: Line[], params: Record<string, any>): MediaPlaylist {
const playlist = new MediaPlaylist();
let segmentStart = -1;
let mediaSequence = 0;
Expand Down Expand Up @@ -956,7 +961,7 @@ function parseTag(line: string, params: Record<string, any>): Tag | null {

type Line = string | Tag;

function lexicalParse(text: string, params: Record<string, any>) {
function lexicalParse(text: string, params: Record<string, any>): Line[] {
const lines: Line[] = [];
for (const l of text.split('\n')) {
// V8 has garbage collection issues when cleaning up substrings split from strings greater
Expand Down Expand Up @@ -987,7 +992,7 @@ function lexicalParse(text: string, params: Record<string, any>) {
return lines;
}

function semanticParse(lines: Line[], params: Record<string, any>) {
function semanticParse(lines: Line[], params: Record<string, any>): MasterPlaylist | MediaPlaylist {
let playlist;
if (params.isMasterPlaylist) {
playlist = parseMasterPlaylist(lines, params);
Expand Down
2 changes: 1 addition & 1 deletion stringify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ function buildSessionData(sessionData: SessionData) {
return `#EXT-X-SESSION-DATA:${attrs.join(',')}`;
}

function buildKey(key: Key, isSessionKey?: any) {
function buildKey(key: Key, isSessionKey?: boolean) {
const name = isSessionKey ? '#EXT-X-SESSION-KEY' : '#EXT-X-KEY';
const attrs = [`METHOD=${key.method}`];
if (key.uri) {
Expand Down
39 changes: 32 additions & 7 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ class Variant {
averageBandwidth?: number;
score: number;
codecs?: string;
resolution?: { width: number; height: number };
resolution?: Resolution;
frameRate?: number;
hdcpLevel?: string;
allowedCpc: { format: string, cpcList: string[] }[];
allowedCpc: AllowedCpc[];
videoRange: 'SDR' | 'HLG' | 'PQ';
stableVariantId: string;
programId: any;
audio: Rendition[];
video: Rendition[];
subtitles: Rendition[];
closedCaptions: Rendition[];
audio: (Rendition & {type: 'AUDIO'})[];
video: (Rendition & {type: 'VIDEO'})[];
subtitles: (Rendition & {type: 'SUBTITLES'})[];
closedCaptions: (Rendition & {type: 'CLOSED-CAPTIONS'})[];
currentRenditions: { audio: number; video: number; subtitles: number; closedCaptions: number; };

constructor({
Expand Down Expand Up @@ -219,7 +219,7 @@ class SpliceInfo {
type: string;
duration?: number;
tagName?: string;
value?: any;
value?: string;

constructor({
type, // required
Expand Down Expand Up @@ -490,3 +490,28 @@ export {
PrefetchSegment,
RenditionReport
};

export type AllowedCpc = {
format: string;
cpcList: string[];
};

export type ExtInfo = {
duration: number;
title: string;
};

export type Resolution = {
width: number;
height: number;
};

export type TagParam =
| [ null, null ]
| [ number, null ]
| [ null, Record<string, any> ]
| [ ExtInfo, null ]
| [ Byterange, null ]
| [ Date, null ];

export type UserAttribute = number | string | Uint8Array;

0 comments on commit 12f1e81

Please sign in to comment.