import * as CML from '@svta/common-media-library'; export { CML }; declare class BinaryReader { private _data; private _size; private _position; private _view; constructor(data: BufferSource); data(): Uint8Array; size(): number; available(): number; value(position?: number): number; position(): number; reset(position?: number): void; shrink(available: number): number; next(count?: number): number; read8(): number; read16(): number; read24(): number; read32(): number; read64(): number; readFloat(): number; readDouble(): number; read7Bit(): number; readString(): string; readHex(size: number): string; /** * Read bytes, to convert bytes to string use String.fromCharCode(...reader.read(size)) or Util.stringify * @param {UInt32} size */ read(size?: number): Uint8Array; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * BinaryWriter allows to write data in its binary form */ declare class BinaryWriter { get view(): DataView; get capacity(): number; private _data; private _size; private _view?; private _isConst?; constructor(dataOrSize?: BufferSource | number, offset?: number, length?: number); data(): Uint8Array; size(): number; next(count?: number): BinaryWriter; clear(size?: number): BinaryWriter; /** * Write binary data * @param data */ write(data: ArrayLike | BufferSource | string): BinaryWriter; write8(value: number): BinaryWriter; write16(value: number): BinaryWriter; write24(value: number): BinaryWriter; write32(value: number): BinaryWriter; write64(value: number): BinaryWriter; writeFloat(value: number): BinaryWriter; writeDouble(value: number): BinaryWriter; write7Bit(value: number): BinaryWriter; writeString(value: string): BinaryWriter; writeHex(value: string): BinaryWriter; reserve(size: number): BinaryWriter; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Log levels */ declare enum LogLevel { ERROR = "error", WARN = "warn", INFO = "info", DEBUG = "debug" } /** * Log interface to deal with log everywhere: * - filter log level: filter log level independantly of the browser * - subscribe logs: listen logs to effectuate some specific job related logs * - intercept logs: intercept logs to change the default behavior * - redirect logs: redirect logs to one other logger engine * - redefine logs: change log text like adding a prefix * * You have 4 {@link LogLevel} 'error','warn','info',and 'debug', as commonly managed by browsers. * You can use {@link ILog.level} or {@link ILog.on} to customer log level and behavior. * * @example * // filter log level globally, independantly of the browser * import { log } from '@ceeblue/web-utils'; * log.level = LogLevel.WARN; // displays errors and warns * * // filter log level only for Player compoment * player.log.level = false; // no logs at all for player compoment * * // Intercept and redirect all the logs to the console (default behavior) * import { log } from '@ceeblue/web-utils'; * log.on = (level:LogLevel,args:unknown[]) => { * console[level](...args.splice(0)); // args is empty after this call = final interception * } * * // Intercept the logs from Player compoment and displays only WARN logs * player.log.on = (level:LogLevel,args:unknown[]) => { * if (level !== LogLevel.WARN) { * args.length = 0; // args is empty after this call = final interception * } * } * * // Subscribe and redirect all the logs to a file logger * import { log } from '@ceeblue/web-utils'; * log.on = (level:LogLevel,args:unknown[]) => { * fileLogger[level](...args); // args stays unchanged to let's continue the default behavior * } * * // Redefine the log to add some prefix indication * class Player { * connector = new Connector(); * constructor() { * connector.log = this.log.bind(this,"Connector log:"); * } * } * */ interface ILog { /** * Build a log */ (...args: unknown[]): Log; /** * Intercept,redefine or redirect any log * If you clear args you intercept the log and nothing happen more after this call. * @param level log level * @param args args * @returns */ on: (level: LogLevel, args: unknown[]) => void; /** * Change log level, default log level is {@link LogLevel.INFO}, * Boolean can be user to lets pass all the logs with `true` or disables all the logs with `false`. * @remarks To debug production code without modifying it you can use a special query parameter * called !cb-override-log-level to override this configuration. */ level?: LogLevel | boolean; } /** * Log instance */ declare class Log { get error(): (...args: any[]) => void; get warn(): (...args: any[]) => void; get info(): (...args: any[]) => void; get debug(): (...args: any[]) => void; private _args; private _done?; private _log; constructor(log: ILog, ...args: unknown[]); private _onLog; private _bind; } /** * Inherits from this class to use logs */ declare class Loggable { /** * Start a log * @param args * @returns a Log object with the levels of log to call */ log: ILog; } /** * Global log */ declare const log: ILog; /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * BitReader allows to read binary data bit by bit */ declare class BitReader extends Loggable { private _data; private _size; private _position; private _bit; constructor(data: BufferSource); data(): Uint8Array; size(): number; available(): number; next(count?: number): number; read(count?: number): number; read8(): number; read16(): number; read24(): number; read32(): number; readExpGolomb(): number; } /** * Class to compute a weighted average byte rate over a specified time interval. * * This class continuously tracks data transmission and computes the byte rate * based on a weighted average, considering both the duration and the number of * bytes in each sample. It allows for real-time monitoring of bandwidth usage * and provides mechanisms to dynamically adjust the measurement interval. * * Features: * - Computes the byte rate using a **weighted average** approach. * - Allows setting a custom interval for tracking. * - Supports dynamic clipping to manually shrink the observation window. */ declare class ByteRate { /** * Raised when new bytes are added */ onBytes(bytes: number): void; /** * Returns the interval used for computing the byte rate */ get interval(): number; /** * Sets a new interval for computing the average byte rate */ set interval(value: number); private _interval; private _bytes; private _time; private _samples; private _clip; /** * Constructor initializes the ByteRate object with a specified interval (default: 1000ms). * It sets up necessary variables to track byte rate over time. * * @param interval - Time interval in milliseconds to compute the byte rate. */ constructor(interval?: number); /** * Returns the computed byte rate rounded to the nearest integer */ value(): number; /** * Computes the exact byte rate in bytes per second */ exact(): number; /** * Adds a new byte sample to the tracking system. * Updates the list of samples and recomputes the byte rate * * @param bytes - Number of bytes added in this interval */ addBytes(bytes: number): ByteRate; /** * Clears all recorded byte rate data. */ clear(): ByteRate; /** * Clips the byte rate tracking by marking the last sample as clipped. * If a previous clip exists, removes the clipped sample and all preceding samples. * Allows to shrink the interval manually between two positions. */ clip(): ByteRate; private updateSamples; } /** * Parameters of a key system for encrypted streams (DRM) * * If the key system is a string, it's the URL of the license server. * * If the key system is an object, it's a key system configuration with more parameters. */ type KeySystem = string | { /** * The license server URL */ licenseUrl: string; /** * The certificate URL if needed (for FairPlay) * * Or directly the certificate */ certificate?: string | Uint8Array; /** * The additional HTTP headers to send to the license server */ headers?: Record; /** * Audio robustness level * * A list of robustness levels, prioritized by the order of the array. */ audioRobustness?: string[]; /** * Video robustness level * * A list of robustness levels, prioritized by the order of the array. */ videoRobustness?: string[]; }; /** * Parameters of connections */ type Params = { /** * endPoint to connect. Can be only a host(:port) but accept also a full url of connection, * it can help to force a path or indicate a protocol preference */ endPoint: string; /** * The name of the stream to join. * If `endPoint` is a complete URL and `streamName` is not provided, {@link buildURL} will set this parameter automatically * using the second part of the URL's path (the first part being the protocol name), or the first path if no other part exists. */ streamName?: string; /** * Optional access token to use to join a private stream */ accessToken?: string; /** * iceServer to use while connecting to a WebRTC stream */ iceServer?: RTCIceServer; /** * Map of keys to content protection settings for encrypted streams * The key can be "com.apple.fps" for example for FairPlay */ contentProtection?: Record; /** * Optional media extension (mp4, flv, ts, rts), usefull for protocol like WebRTS which supports different container type. * When not set, it's also an output parameter for {@link defineMediaExt} to indicate what is the media type selected */ mediaExt?: string; /** * Optional query to add into the generated url of connection */ query?: URLSearchParams; }; /** * Type of connection */ declare enum Type { HESP = "HESP", WRTS = "WebRTS", WEBRTC = "WebRTC", DIRECT_STREAMING = "DirectStreaming", META = "Meta", DATA = "Data" } /** * Some connection utility functions */ /** * Defines the {@link Params.mediaExt} based on the type of parameters and its endpoint. * This method always assigns a value to params.mediaExt, defaulting to an empty string if indeterminable, * allowing detection of whether the function has been applied to the parameters. * @param type The type of parameters to define. * @param params The parameters for which the media extension is to be defined */ declare function defineMediaExt(type: Type, params: Params): void; /** * Build an URL from {@link Type | type} and {@link Params | params} * Can assign {@link Params.mediaExt | params.mediaExt} or {@link Params.streamName | params.streamName} * @param type Type of the connection wanted * @param params Connection parameters * @param protocol Optional parameter to choose the prefered protocol to connect * @returns The URL of connection */ declare function buildURL(type: Type, params: Params, protocol?: string): URL; type Connect_KeySystem = KeySystem; type Connect_Params = Params; type Connect_Type = Type; declare const Connect_Type: typeof Type; declare const Connect_buildURL: typeof buildURL; declare const Connect_defineMediaExt: typeof defineMediaExt; declare namespace Connect { export { type Connect_KeySystem as KeySystem, type Connect_Params as Params, Connect_Type as Type, Connect_buildURL as buildURL, Connect_defineMediaExt as defineMediaExt }; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ type FilterOnKey = T extends 'once' | 'on' ? never : T extends `on${infer R}` ? R : never; type CaseVariations = string extends T ? string : Lowercase | Capitalize; /** * Extract all event keys from a class. * @example * class Logger extends EventEmitter { * onLog(log:string) { console.log(log); } * onClick(log:string) { console.log(log); } * } * type LoggerEvents = EventKeys; // "log" | "click" */ type EventKeys = keyof { [K in keyof Keys as CaseVariations>]: never; }; /** * A advanced EventEmitter which allows to declare event as natural function in the inheriting children class, * function must start by `on` prefix to be recognized as an event. * The function can define a behavior by default, and user can choose to redefine this behavior, * or add an additionnal subscription for this event. * In addition you can unsubscribe to multiple events with an `AbortController` * @example * class Logger extends EventEmitter { * onLog(log:string) { console.log(log); } // behavior by default * * test() { * // raise event onLog * this.onLog('test'); * } * } * * const logger = new Logger(); * logger.test(); // displays a log 'test' * * // redefine default behavior to display nothing * logger.onLog = () => {} * logger.test(); // displays nothing * * // add an additionnal subscription * logger.on('log', console.log); * logger.test(); // displays a log 'test' * * // remove the additionnal subscription * logger.off('log', console.log); * logger.test(); // displays nothing * * // add two additionnal subscriptions with a AbortController * const controller = new AbortController(); * logger.on('log', log => console.log(log), controller); * logger.on('log', log => console.error(log), controller); * logger.test(); // displays a log 'test' + an error 'test' * * // Unsubscribe all the subscription with the AbortController * controller.abort(); * logger.test(); // displays nothing */ declare class EventEmitter extends Loggable { private _events; /** * Build our EventEmitter, usually call from children class */ constructor(); /** * Event subscription * @param name Name of event without the `on` prefix (ex: `log` to `onLog` event declared) * @param event Subscriber Function * @param options.signal Optional `AbortSignal` to stop this or multiple subscriptions in same time */ on(name: EventKeys, event: Function, options?: { signal?: AbortSignal; }): void; /** * Event subscription only one time, once time fired it's automatically unsubscribe * @param name Name of event without the `on` prefix (ex: `log` to `onLog` event declared) * @param event Subscriber Function * @param options.signal Optional `AbortSignal` to stop this or multiple subscriptions in same time */ once(name: EventKeys, event: Function, options?: { signal?: AbortSignal; }): void; /** * Event unsubscription * @param name Name of event without the 'on' prefix (ex: 'log' to 'onLog' event declared) * @param event Unsubscriber Function, must be the one passed to {@link on} or {@link once} subscription methods */ off(name: EventKeys, event: Function): boolean; private _event; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Some fix for JS MAP: * - find(key) search an item in the map and returns undefined if not found * - get(key) return the item if exists or otherwise create and returns it * - set(key, value) returns the value of the item (rather the MAP) */ declare class FixMap { private _initValue; [Symbol.iterator](): IterableIterator<[KeyType, ValueType]>; get size(): number; private _map; constructor(_initValue: () => ValueType); get(key: KeyType): ValueType; find(key: KeyType): ValueType | undefined; has(key: KeyType): boolean; clear(): void; delete(key: KeyType): boolean; set(key: KeyType, value: ValueType): ValueType; forEach(callbackfn: (value: ValueType, key: KeyType, map: Map) => void, thisArg?: any): void; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Help class to manipulate and parse a net address. The Address can be only the domain field, * or a URL format with protocol and path part `(http://)domain(:port/path)` * @example * const address = new Address('nl-ams-42.live.ceeblue.tv:80'); * console.log(address.domain) // 'nl-ams-42.live.ceeblue.tv' * console.log(address.port) // '80' * console.log(address) // 'nl-ams-42.live.ceeblue.tv:80' */ declare class NetAddress { /** * Static help function to build an end point from an address `(proto://)domain(:port/path)` * * Mainly it fix the protocol, in addition if: * - the address passed is securized (TLS) and protocol is not => it tries to fix protocol to get its securize version * - the address passed is non securized and protocol is (TLS) => it tries to fix protocol to get its unsecurized version * @param protocol protocol to set in the end point returned * @param address string address to fix with protocol as indicated * @returns the end point built * @example * console.log(NetAddress.fixProtocol('ws','http://domain/path')) // 'ws://domain/path' * console.log(NetAddress.fixProtocol('ws','https://domain/path')) // 'wss://domain/path' * console.log(NetAddress.fixProtocol('wss','http://domain/path')) // 'ws://domain/path' */ static fixProtocol(protocol: string, address: string): string; /** * The host part from address `(http://)domain:port/path)` */ get host(): string; /** * The domain part from address `(http://)domain(:port/path)` */ get domain(): string; /** * The port part from address `(http://)domain(:port/path)`, or defaultPort if passed in NetAddress constructor */ get port(): number | undefined; toString(): string; /** * @returns the string address as passed in the constructor * @override */ valueOf(): string; private _address; private _domain; private _host; private _port?; /** * Build a NetAddress object and parse address * @param address string address to parse, accept an url format with protocol and path `(http://)domain(:port/path)` * @param defaultPort set a default port to use if there is no port in the string address parsed */ constructor(address: string, defaultPort?: number); } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Queue typed similar to a {@link https://en.cppreference.com/w/cpp/container/queue | std::queue} with possibility to limit the capacity like a FIFO * @example * const queue = new Queue(2); * queue.push(1); // [1] * queue.push(2); // [1,2] * queue.push(3); // [2,3] 1 has been removed to respect 2 capacity */ declare class Queue { /** * Number of element in the queue */ get size(): number; /** * Maximum capacity for the queue, if not set queue has unlimited capacity */ get capacity(): number | undefined; /** * Set a maximum capacity for the queue, * if you push new value exceding this capacity the firsts are removed (FIFO) * if set to undefined the queue is unlimited */ set capacity(value: number | undefined); /** * The front element */ get front(): Type; /** * The back element */ get back(): Type; /** * Iterator though queue's elements */ [Symbol.iterator](): IterableIterator; private _capacity?; private _queue; /** * Instanciate a new queue object with the type passed as template * @param capacity if set it limits the size of the queue, any exceding element pops the first element pushed (FIFO) */ constructor(capacity?: number); /** * Push a new element in the queue * @param value value of the element * @returns this */ push(value: Type): Queue; /** * Pop the first element from the queue * @returns The first element removed */ pop(): Type | undefined; /** * Clear all the elements, queue becomes empty * @returns this */ clear(): Queue; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * A collection of number Queue with the following efficient mathematic computation: * - minimum value in the collection * - maximum value in the collection * - average value of the collection */ declare class Numbers extends Queue { /** * minimum value in the collection, or 0 if colleciton is empty */ get minimum(): number; /** * maximum value in the collection, or 0 if colleciton is empty */ get maximum(): number; /** * average value of the collection, or 0 if collection if empty */ get average(): number; private _average?; private _sum; private _min; private _max; /** * Instantiate the collection of the number * @param capacity if set it limits the number of values stored, any exceding number pops the first number pushed (FIFO) */ constructor(capacity?: number); /** * Push a value to the back to the collection * @param value number to add * @returns this */ push(value: number): Numbers; /** * Pop the front number from the collection * @returns the front number removed */ pop(): number | undefined; /** * Clear all the numbers, collection becomes empty * @returns this */ clear(): this; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Toolkit to deal with Session Description Protocol (SDP), * mainly to tranform a SDP string Offer/Answer to a manipulable JS object representation * @example * const peerConnection = new RTCPeerConnection(); * peerConnection.createOffer() * .then( offer => * // Change offer.sdp string to a JS manipulable object * const sdp = SDP.fromString(offer.sdp || ''); * // Change a property of SDP * sdp.v = 2; // change SDP version * // Reserialize to the legal SDP string format * offer.sdp = SDP.toString(sdp); * // Set SDP offer to peerConnection * peerConnection.setLocalDescription(offer); * ) */ declare const SDP: { /** * Unserialize SDP string to a manipulable JS object representation * It's an object with: * - root SDP properties * - media description iterable * @param lines SDP string reprensentation * @returns SDP object representation, iterable through media description * @example * [ * group: "DUNBLE 0 1", * o: "- 1699450751193623 0 IN IP4 0.0.0.0", * s: "-", * t: "0 0", * v: "0", * ice-lite: "", * length: 2, * { * m: "audio 9 UDP/TLS/RTP/SAVPF 111", * c: "IN IP4 0.0.0.0", * rtcp: "9", * sendonly: "", * setup: "passive", * fingerprint: "sha-256 51:36:ED:78:A4:9F:25:8C:39:9A:0E:A0:B4:9B:6E:04:37:FF:AD:96:93:71:43:88:2C:0B:0F:AB:6F:9A:52:B8", * ice-ufrag: "fa37", * ice-pwd: "JncCHryDsbzayy4cBWDxS2", * rtcp-mux: "", * rtcp-rsize: "", * rtpmap: "111 opus/48000/2", * rtcp-fb: "111 nack", * id: "0", * fmtp: "111 minptime=10;useinbandfec=1", * candidate: "1 1 udp 2130706431 89.105.221.108 56643 typ host", * end-of-candidates: "" * }, * { * m: "video 9 UDP/TLS/RTP/SAVPF 106", * c: "IN IP4 0.0.0.0", * rtcp: "9", * sendonly: "", * setup: "passive", * fingerprint: "sha-256 51:36:ED:78:A4:9F:25:8C:39:9A:0E:A0:B4:9B:6E:04:37:FF:AD:96:93:71:43:88:2C:0B:0F:AB:6F:9A:52:B8", * ice-ufrag: "fa37", * ice-pwd: "JncCHryDsbzayy4cBWDxS2", * rtcp-mux: "", * rtcp-rsize: "", * rtpmap: "106 H264/90000", * rtcp-fb: [ * "106 nack", * "106 goog-remb" * ], * mid: "1", * fmtp: "106 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1", * candidate: "1 1 udp 2130706431 89.105.221.108 56643 typ host", * end-of-candidates: "" * } * ] */ fromString(lines: string): any; /** * Serialize SDP JS object to a SDP string legal representation * @param sdp SDP object reprensetation * @returns SDP string reprensentation */ toString(sdp: any): string; /** * While set a property to a SDP object representation is possible directly, * we could prefer add a new property without overload a possible already existing value. * This function allows to add a property to our SDP representation: * - if the key's attribute doesn't exists yet it adds it like a simple JS property sdp[key] = value * - if the key's attribute exists already it morphs the value to a Array and push it inside * @param sdp the SDP object representation on which added the attribute * @param attribute the string attribut in a format "key:value" or just "key" to add an attribute without value * @returns the key part of the attribute added (or if value is empty it returns the same attribute as passed in argument) */ addAttribute(sdp: object, attribute: string): string; /** * While it's possible to delete a attribute manually on the SDP object representation with a delete sdp.key, * we could prefer remove only a value in a sdp.key array containing multiple values. * Like opposite to addAttribute this method allows to remove an unique attribute value. * @param sdp the SDP object representation on which removed the attribute * @param attribute the string attribut in a format "key:value" or just "key" to remove the whole attribute and all its values * @returns the key part of the attribute removed (or if value is empty it returns the same attribute as passed in argument) */ removeAttribute(sdp: object, attribute: string): string; /** * Parse an attribute in a format "key:value" * @param attribute string attribute to parse * @returns the {key, value} result, with value undefined if attribute was a "key" without value */ parseAttribute(attribute: string): { key: string; value: string | undefined; }; }; /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Some basic utility functions */ /** * An empty lambda function, pratical to disable default behavior of function or events which are not expected to be null * @example * console.log = Util.EMPTY_FUNCTION; // disable logs without breaking calls */ declare const EMPTY_FUNCTION: () => void; /** * Returns an efficient timestamp in milliseconds elapsed since performance.timeOrigin, * representing the start of the current JavaScript execution context. * * @see https://developer.mozilla.org/en-US/docs/Web/API/Performance/timeOrigin * * @remarks Each Web Worker runs in a separate JS context, so timestamps * are not directly comparable between different workers. Use {@link unixTime} * for comparable timestamps across different Web Workers. */ declare function time(): number; /** * Returns an efficient Unix timestamp in milliseconds. * * Unix timestamps are universally comparable across different JavaScript * contexts (e.g., Web Workers), as they reference the number of milliseconds * elapsed since January 1, 1970 (UNIX epoch). */ declare function unixTime(): number; /** * Parse query and returns it in an easy-to-use Javascript object form * @param urlOrQueryOrSearch string, url, or searchParams containing query. If not set it uses `location.search` to determinate query. * @returns An javascript object containing each option */ declare function options(urlOrQueryOrSearch?: URL | URLSearchParams | string | object | undefined): any; /** * Returns an easy-to-use Javascript object something iterable, such as a Map, Set, or Array * @param value iterable input * @param params.withType `false`, if set it tries to cast string value to a JS number/boolean/undefined/null type. * @param params.noEmptyString `false`, if set it converts empty string value to a true boolean, usefull to allow a `if(result.key)` check for example * @returns An javascript object */ declare function objectFrom(value: any, params: { withType: boolean; noEmptyString: boolean; }): any; /** * Returns a IterableIterator<[string, any]> from any iterable input like Map, Set, Array, or Object. * * For all other types of values (including `null` or `undefined`) it returns an empty iterator. * * @param value An iterable input * @returns a IterableIterator<[string, any]> */ declare function iterableEntries(value: any): IterableIterator<[string, any]>; /** * Converts various data types, such as objects, strings, exceptions, errors, * or numbers, into a string representation. Since it offers a more comprehensive format, * this function is preferred to `JSON.stringify()`. * * @param obj Any objects, strings, exceptions, errors, or number * @param params.space `''`, allows to configure space in the string representation * @param params.decimal `2`, allows to choose the number of decimal to display in the string representation * @param params.recursion `2`, recursion depth to stringify recursively every object value until this depth, * beware if a value refers to a already parsed value an infinite loop will occur * @param params.noBin `false`, when set skip binary encoding and write inplace a bin-length information * @returns the final string representation */ declare function stringify(obj: any, params?: { space?: string; decimal?: number; recursion?: number; noBin?: boolean; }): string; /** * Encode a string to a binary representation * @param value string value to convert * @returns binary conversion */ declare function toBin(value: string): Uint8Array; /** * Execute a promise in a safe way with a timeout if caller doesn't resolve it in the accurate time */ declare function safePromise(timeout: number, promise: Promise): Promise; /** * Wait in milliseconds, requires a call with await keyword! */ declare function sleep(ms: number): Promise; /** * Test equality between two value whatever their type, object and array included */ declare function equal(a: any, b: any, seen?: WeakMap): boolean; /** * Fetch help method adding an explicit error property when Response is NOK, with the more accurate textual error inside */ declare function fetch(input: RequestInfo | URL, init?: RequestInit): Promise; /** * Fetch help method adding an explicit error property when Response is NOK, with the more accurate textual error inside * Also measure the rtt of fetching and returns it in the property Response.rtt (guaranteed to be ≥ 1), * supports subtracting server processing time using either the Response-Delay or CMSD-rd header when available * * WIP => replace the current implementation to use Resource Timing API */ declare function fetchWithRTT(input: RequestInfo | URL, init?: RequestInit): Promise; /** * Get Extension part from path * @param path path to parse * @returns the extension */ declare function getExtension(path: string): string; /** * Get File part from path * @param path path to parse * @returns the file name */ declare function getFile(path: string): string; /** * Get Base File part from path, without extension * @param path path to parse * @returns the base file name */ declare function getBaseFile(path: string): string; /** * String Trim function with customizable chars * @param value string to trim * @param chars chars to use to trim * @returns string trimmed */ declare function trim(value: string, chars?: string): string; /** * String Trim Start function with customizable chars * @param value string to trim start * @param chars chars to use to trim start * @returns string trimmed */ declare function trimStart(value: string, chars?: string): string; /** * String Trim End function with customizable chars * @param value string to trim end * @param chars chars to use to trim end * @returns string trimmed */ declare function trimEnd(value: string, chars?: string): string; /** * Wraps an object with a Proxy that makes property access case-insensitive. * * Property lookup (e.g. `obj.Foo` or `obj.foo`) will resolve to the same underlying key, regardless of casing. * Only affects string-based property access (not symbols). * * @param obj - The original object. * @returns A proxied object with case-insensitive property access. */ declare function caseInsensitive(obj: any): Record; declare const Util_EMPTY_FUNCTION: typeof EMPTY_FUNCTION; declare const Util_caseInsensitive: typeof caseInsensitive; declare const Util_equal: typeof equal; declare const Util_fetch: typeof fetch; declare const Util_fetchWithRTT: typeof fetchWithRTT; declare const Util_getBaseFile: typeof getBaseFile; declare const Util_getExtension: typeof getExtension; declare const Util_getFile: typeof getFile; declare const Util_iterableEntries: typeof iterableEntries; declare const Util_objectFrom: typeof objectFrom; declare const Util_options: typeof options; declare const Util_safePromise: typeof safePromise; declare const Util_sleep: typeof sleep; declare const Util_stringify: typeof stringify; declare const Util_time: typeof time; declare const Util_toBin: typeof toBin; declare const Util_trim: typeof trim; declare const Util_trimEnd: typeof trimEnd; declare const Util_trimStart: typeof trimStart; declare const Util_unixTime: typeof unixTime; declare namespace Util { export { Util_EMPTY_FUNCTION as EMPTY_FUNCTION, Util_caseInsensitive as caseInsensitive, Util_equal as equal, Util_fetch as fetch, Util_fetchWithRTT as fetchWithRTT, Util_getBaseFile as getBaseFile, Util_getExtension as getExtension, Util_getFile as getFile, Util_iterableEntries as iterableEntries, Util_objectFrom as objectFrom, Util_options as options, Util_safePromise as safePromise, Util_sleep as sleep, Util_stringify as stringify, Util_time as time, Util_toBin as toBin, Util_trim as trim, Util_trimEnd as trimEnd, Util_trimStart as trimStart, Util_unixTime as unixTime }; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ type WebSocketReliableError = /** * Represents a WebSocket disconnection error. */ { type: 'WebSocketReliableError'; name: 'Socket disconnection'; url: string; reason: string; } /** * Represents a server shutdown error. */ | { type: 'WebSocketReliableError'; name: 'Server shutdown'; url: string; } /** * Represents a connection failure error. */ | { type: 'WebSocketReliableError'; name: 'Connection failed'; url: string; reason: string; }; /** * The WebSocketReliable class extends WebSocket to bring up the following improvements: * - Fix all possible unintentional closing ways to get always a related error message, {@link onClose | onClose(error?) event} * - Make possible message sending while connecting. Indeed no need to wait {@link onOpen} before to send message, * you can open the socket and immediately send messages, it will be queue and flushs on connection etablishment * - Make possible a delayed connection, or a reconnection. Indeed you can create an unconnected Websocket instance * without passing any url argument and starts the conneciton more later with {@link WebSocketReliable.open(url) | open(url)} method * - Make possible to control sending/queueing message: send method take an optional queueing=true argument to * queue message rather send it, a futur call to flush will send it. Then queueing getter allows to handle the queue * if need to purge it or remove some queued message. Use it all together can help to prioritize messages or control overload. * @example * const ws = new WebSocketReliable(url); * ws.onClose = (error?:string) => { * if(error) { * console.error(error); * } * // reconnection attempt every seconds * setTimeout(() => ws.open(url), 1000); * } * ws.onMessage = (message:string) => { * console.log(message); * } * ws.send('hello'); // send immediatly a hello message is possible (no need to wait onOpen) */ declare class WebSocketReliable extends EventEmitter { /** * Fired when socket is connected * @event */ onOpen(): void; /** * Fired on message reception * @param message can be binary or string. * If you subscribe to the event with message as string type (and not union), * it means that you know that all your messages are distributed in a string format * @event */ onMessage(message: ArrayBuffer | string): void; /** * Fired on websocket close * @param error error description on an improper closure * @event */ onClose(error?: WebSocketReliableError): void; /** * binaryType, fix binary type to arrayBuffer */ get binaryType(): BinaryType; get recvByteRate(): number; get sendByteRate(): number; /** * url of connection */ get url(): string; /** * extensions negociated by the server */ get extensions(): string; /** * protocol negociated by the server */ get protocol(): string; /** * opened equals true when connection is etablished, in other word when onOpen event is fired */ get opened(): boolean; /** * {@link https://developer.mozilla.org/docs/Web/API/WebSocket/readyState | Official websocket readyState} */ get readyState(): number; /** * True when connection is closed, in other words when {@link onClose} event is fired * or when WebSocketReliable is build without url (disconnected creation) */ get closed(): boolean; /** * The number of bytes of data that were queued during calls to send() but not yet transmitted to the network */ get bufferedAmount(): number; /** * Queued messages from a call to send() waiting to be transmit one time websocket connection opened (or with an explicit call to flush() method) */ get queueing(): Array; private _opened; private _closed; private _queueing; private _queueingBytes; private _ws?; private _recvByteRate; private _sendByteRate; /** * Create a WebSocketReliable object, and open it if an url is passed in argument * @param url URL of the WebSocket endpoint or null to start the connection later */ constructor(url?: string | URL, protocols?: string | string[]); /** * Open a WebSocket connection * @param url url of the websocket endpoint * @returns this */ open(url: URL | string, protocols?: string | string[]): this; /** * Send a message * @param message * @param queueing When set it reports the sending to a more later call to flush * @returns this */ send(message: string | ArrayBuffer | ArrayBufferView, queueing?: boolean): this; /** * Send queueing messages */ flush(): void; /** * Close websocket * @param error the error reason if is not a proper close */ close(error?: WebSocketReliableError): void; private _send; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Decode the timestamp from a video element and compute the latency between the timestamp and the current date. * * @param {HTMLVideoElement} sourceEl the video element to get the image from * @param {HTMLCanvasElement} canvas * @param {CanvasRenderingContext2D} context * @param {Date} now current date, new Date() by default * @param {Number} tolerance percentage of tolerance for the black and white threshold, 0.2 by default * @returns {Number} The latency in millisecond between 'now' and the decoded timestamp, 0 if the timestamp cannot be decoded */ declare function getLatency(sourceEl: HTMLVideoElement, canvas: HTMLCanvasElement, context: CanvasRenderingContext2D, now?: Date, tolerance?: number): number; /** * Decode a previously encoded timestamp from a canvas * * @param {CanvasRenderingContext2D} context * @param {Number} lineWidth width of the line in pixels * @param {Number} tolerance percentage of tolerance for the black and white threshold, 0.2 by default * @returns {Date|null} The Date object representing the timestamp or null if the timestamp cannot be decoded */ declare function decodeTimestamp(context: CanvasRenderingContext2D, lineWidth: number, tolerance?: number): Date | null; /** * Encode the given date (excluding year and month) into a line composed of blocks * of black and white pixels written on the top of the canvas. * * @param {CanvasRenderingContext2D} context * @param {Number} lineWidth width of the line in pixels * @param {Number} blocksPerRow number of blocks in the line, 32 by default * @param {Date} now current date, new Date() by default */ declare function encodeTimestamp(context: CanvasRenderingContext2D, lineWidth: number, blocksPerRow?: number, now?: Date): void; declare const EpochTime_decodeTimestamp: typeof decodeTimestamp; declare const EpochTime_encodeTimestamp: typeof encodeTimestamp; declare const EpochTime_getLatency: typeof getLatency; declare namespace EpochTime { export { EpochTime_decodeTimestamp as decodeTimestamp, EpochTime_encodeTimestamp as encodeTimestamp, EpochTime_getLatency as getLatency }; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * Collects variable names for player statistics metrics across different projects (e.g., wrts, webrtc). * Variables remain undefined if they are not present in the stats for the current project * (for example, 'latency' is undefined for webrtc). * Includes the toCmcd() method to convert stats into a CMCD payload. */ declare class PlayerStats extends Loggable { protocol?: string; currentTime?: number; waitingData?: boolean; bufferAmount?: number; latency?: number; rtt?: number; jitter?: number; skippedVideo?: number; skippedAudio?: number; playbackSpeed?: number; playbackRate?: number; recvByteRate?: number; sendByteRate?: number; videoTrackId?: number; videoTrackBandwidth?: number; audioTrackId?: number; audioTrackBandwidth?: number; videoPerSecond?: number; audioPerSecond?: number; lostPacketCount?: number; nackCount?: number; stallCount?: number; /** * Converts the current {@link PlayerStats} snapshot into a CMCD (Common Media Client Data) payload. * @param url - The full URL of the media object. * @param trackId - The track ID for which to generate the CMCD payload. * @param prevStats - Optional previous {@link PlayerStats} snapshot to calculate deltas for incremental metrics since their last reset. * @returns A {@link CML.Cmcd} object representing the CMCD payload. */ toCmcd(url: URL, trackId: number, prevStats?: PlayerStats): CML.Cmcd; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ /** * An user-interface compoment to vizualize real-time metrics */ declare class UIMetrics { /** * get graph margin in pixels */ get graphMargin(): number; /** * set graph margin in pixels */ set graphMargin(value: number); /** * get text margin in pixels */ get textMargin(): number; /** * set text margin in pixels */ set textMargin(value: number); /** * get metric line height in pixels */ get lineHeight(): number; /** * set metric line height in pixels */ set lineHeight(value: number); /** * get label width in pixels */ get labelWidth(): number; /** * set label width in pixels */ set labelWidth(value: number); /** * get legend font size in pixels */ get legendFontSize(): number; /** * set legend font size in pixels */ set legendFontSize(value: number); /** * get the metric unit-step in pixels */ get stepSize(): number; /** * set the metric unit-step in pixels */ set stepSize(value: number); /** * Return the space width available to display average metric */ get averageDisplayWidth(): number; /** * Return the count of displayable metrics regarding the space available on the screen */ get displayableCount(): number; private _ui; private _html?; private _lineHeight; private _labelWidth; private _graphMargin; private _textMargin; private _legendFontSize; private _stepSize; private _ranges; private _mouseX?; constructor(ui: HTMLElement); /** * Reset metrics stats, essentially rescaling the metrics */ reset(): void; /** * build metric from stats * @param stats Map with stats per entry * @returns */ display(stats: Map>): void; private _drawCircle; } /** * Copyright 2024 Ceeblue B.V. * This file is part of https://github.com/CeeblueTV/web-utils which is released under GNU Affero General Public License. * See file LICENSE or go to https://spdx.org/licenses/AGPL-3.0-or-later.html for full license details. */ declare const VERSION: string; export { BinaryReader, BinaryWriter, BitReader, ByteRate, Connect, EpochTime, EventEmitter, FixMap, type ILog, Log, LogLevel, Loggable, NetAddress, Numbers, PlayerStats, Queue, SDP, UIMetrics, Util, VERSION, WebSocketReliable, type WebSocketReliableError, log };