diff --git a/FAQ.md b/FAQ.md index a4f99246..d4d88e06 100644 --- a/FAQ.md +++ b/FAQ.md @@ -33,10 +33,6 @@ But they support a limited number of peers and can reject connections or even go That is why they can't be used in production environments. Consider running your personal tracker or buy resources from a tracker provider to go stable. -## How to achieve better P2P ratio for live streams & VOD streams? - -Our current default configuration efficiently supports both Live and Video On Demand (VOD) streams. This setup is optimized to provide a robust P2P sharing ratio, enhancing performance without the need for custom settings. - ## What are the requirements to share a stream over P2P? The requirements to share a stream over P2P are: diff --git a/packages/p2p-media-loader-core/package.json b/packages/p2p-media-loader-core/package.json index 37d5dec2..92445fcd 100644 --- a/packages/p2p-media-loader-core/package.json +++ b/packages/p2p-media-loader-core/package.json @@ -53,8 +53,7 @@ "dependencies": { "bittorrent-tracker": "^11.0.2", "debug": "^4.3.4", - "nano-md5": "^1.0.5", - "ts-essentials": "^9.4.1" + "nano-md5": "^1.0.5" }, "devDependencies": { "vite-plugin-node-polyfills": "^0.21.0" diff --git a/packages/p2p-media-loader-core/src/core.ts b/packages/p2p-media-loader-core/src/core.ts index 63c6041a..2f5c26af 100644 --- a/packages/p2p-media-loader-core/src/core.ts +++ b/packages/p2p-media-loader-core/src/core.ts @@ -24,8 +24,7 @@ export class Core { highDemandTimeWindow: 15, httpDownloadTimeWindow: 3000, p2pDownloadTimeWindow: 6000, - cachedSegmentExpiration: 120 * 1000, - cachedSegmentsCount: 1000, + cachedSegmentsCount: 0, webRtcMaxMessageSize: 64 * 1024 - 1, p2pNotReceivingBytesTimeoutMs: 1000, p2pInactiveLoaderDestroyTimeoutMs: 30 * 1000, diff --git a/packages/p2p-media-loader-core/src/hybrid-loader.ts b/packages/p2p-media-loader-core/src/hybrid-loader.ts index d4e58c2d..bdaac2f3 100644 --- a/packages/p2p-media-loader-core/src/hybrid-loader.ts +++ b/packages/p2p-media-loader-core/src/hybrid-loader.ts @@ -185,7 +185,11 @@ export class HybridLoader { this.engineRequest = undefined; } this.requests.remove(request); - void this.segmentStorage.storeSegment(request.segment, request.data); + void this.segmentStorage.storeSegment( + request.segment, + request.data, + this.streamDetails.isLive, + ); break; case "failed": diff --git a/packages/p2p-media-loader-core/src/segments-storage.ts b/packages/p2p-media-loader-core/src/segments-storage.ts index fb76c7a0..88a9cbe4 100644 --- a/packages/p2p-media-loader-core/src/segments-storage.ts +++ b/packages/p2p-media-loader-core/src/segments-storage.ts @@ -23,6 +23,8 @@ type StorageEventHandlers = { [key in `onStorageUpdated-${string}`]: (steam: Stream) => void; }; +const DEFAULT_LIVE_CACHED_SEGMENT_EXPIRATION = 1200; + export class SegmentsMemoryStorage { private cache = new Map(); private _isInitialized = false; @@ -61,7 +63,11 @@ export class SegmentsMemoryStorage { } // eslint-disable-next-line @typescript-eslint/require-await - async storeSegment(segment: SegmentWithStream, data: ArrayBuffer) { + async storeSegment( + segment: SegmentWithStream, + data: ArrayBuffer, + isLiveStream: boolean, + ) { const id = getStorageItemId(segment); this.cache.set(id, { segment, @@ -70,7 +76,7 @@ export class SegmentsMemoryStorage { }); this.logger(`add segment: ${id}`); this.dispatchStorageUpdatedEvent(segment.stream); - void this.clear(); + void this.clear(isLiveStream); } // eslint-disable-next-line @typescript-eslint/require-await @@ -101,7 +107,13 @@ export class SegmentsMemoryStorage { } // eslint-disable-next-line @typescript-eslint/require-await - private async clear(): Promise { + private async clear(isLiveStream: boolean): Promise { + const cacheSegmentExpiration = + (this.storageConfig.cachedSegmentExpiration ?? + (isLiveStream ? DEFAULT_LIVE_CACHED_SEGMENT_EXPIRATION : 0)) * 1000; + + if (cacheSegmentExpiration === 0) return false; + const itemsToDelete: string[] = []; const remainingItems: [string, StorageItem][] = []; const streamsOfChangedItems = new Set(); @@ -112,7 +124,8 @@ export class SegmentsMemoryStorage { for (const entry of this.cache.entries()) { const [itemId, item] = entry; const { lastAccessed, segment } = item; - if (now - lastAccessed > this.storageConfig.cachedSegmentExpiration) { + + if (now - lastAccessed > cacheSegmentExpiration) { if (!this.isSegmentLocked(segment)) { itemsToDelete.push(itemId); streamsOfChangedItems.add(segment.stream); @@ -123,17 +136,19 @@ export class SegmentsMemoryStorage { } // Delete segments over cached count - let countOverhead = - remainingItems.length - this.storageConfig.cachedSegmentsCount; - if (countOverhead > 0) { - remainingItems.sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed); - - for (const [itemId, { segment }] of remainingItems) { - if (!this.isSegmentLocked(segment)) { - itemsToDelete.push(itemId); - streamsOfChangedItems.add(segment.stream); - countOverhead--; - if (countOverhead === 0) break; + if (this.storageConfig.cachedSegmentsCount > 0) { + let countOverhead = + remainingItems.length - this.storageConfig.cachedSegmentsCount; + if (countOverhead > 0) { + remainingItems.sort(([, a], [, b]) => a.lastAccessed - b.lastAccessed); + + for (const [itemId, { segment }] of remainingItems) { + if (!this.isSegmentLocked(segment)) { + itemsToDelete.push(itemId); + streamsOfChangedItems.add(segment.stream); + countOverhead--; + if (countOverhead === 0) break; + } } } } diff --git a/packages/p2p-media-loader-core/src/types.ts b/packages/p2p-media-loader-core/src/types.ts index 9cacf46e..35157acf 100644 --- a/packages/p2p-media-loader-core/src/types.ts +++ b/packages/p2p-media-loader-core/src/types.ts @@ -1,60 +1,36 @@ -/** - * Represents the types of streams available, either primary (main) or secondary. - */ +/** Represents the types of streams available, either primary (main) or secondary. */ export type StreamType = "main" | "secondary"; -/** - * Represents a range of bytes, used for specifying a segment of data to download. - */ +/** Represents a range of bytes, used for specifying a segment of data to download. */ export type ByteRange = { - /** - * The starting byte index of the range. - */ + /** The starting byte index of the range. */ start: number; - /** - * The ending byte index of the range. - */ + /** The ending byte index of the range. */ end: number; }; -/** - * Describes a media segment with its unique identifiers, location, and timing information. - */ +/** Describes a media segment with its unique identifiers, location, and timing information. */ export type Segment = { - /** - * A unique identifier for the segment within the local system. - */ + /** A unique identifier for the segment within the local system. */ readonly localId: string; - /** - * A unique identifier for the segment as recognized by external systems or servers. - */ + /** A unique identifier for the segment as recognized by external systems or servers. */ readonly externalId: number; - /** - * The URL from which the segment can be downloaded. - */ + /** The URL from which the segment can be downloaded. */ readonly url: string; - /** - * An optional property specifying the range of bytes that represent the segment. - */ + /** An optional property specifying the range of bytes that represent the segment. */ readonly byteRange?: ByteRange; - /** - * The start time of the segment in seconds, relative to the beginning of the stream. - */ + /** The start time of the segment in seconds, relative to the beginning of the stream. */ readonly startTime: number; - /** - * The end time of the segment in seconds, relative to the beginning of the stream. - */ + /** The end time of the segment in seconds, relative to the beginning of the stream. */ readonly endTime: number; }; -/** - * Extends a Segment with a reference to its associated stream. - */ +/** Extends a Segment with a reference to its associated stream. */ export type SegmentWithStream = Segment & { readonly stream: StreamWithSegments; }; @@ -67,46 +43,43 @@ export type StreamWithSegments = TStream & { readonly segments: Map>; }; -/** - * Represents a media stream with various defining characteristics. - */ +/** Represents a media stream with various defining characteristics. */ export type Stream = { - /** - * A unique identifier for the stream within the local system. - */ + /** Local ID of the stream: a string that consists of swarm ID, stream type, stream index. */ readonly localId: string; - /** - * The type of stream, either "main" or "secondary". - */ + /** Stream type. */ readonly type: StreamType; - /** - * The index position of the stream within a collection or sequence. - */ + /** Stream index in the manifest. */ readonly index: number; }; -/** - * Defines a subset of CoreConfig for dynamic updates, allowing selective modification of configuration properties. - */ +/** Represents a dynamically modifiable configuration, allowing updates to selected CoreConfig properties at runtime. */ export type DynamicCoreConfig = Partial< Pick< CoreConfig, - | "simultaneousP2PDownloads" - | "simultaneousHttpDownloads" - | "cachedSegmentsCount" + | "highDemandTimeWindow" | "httpDownloadTimeWindow" | "p2pDownloadTimeWindow" + | "simultaneousHttpDownloads" + | "simultaneousP2PDownloads" + | "cachedSegmentExpiration" + | "cachedSegmentsCount" + | "webRtcMaxMessageSize" + | "p2pNotReceivingBytesTimeoutMs" + | "p2pInactiveLoaderDestroyTimeoutMs" + | "httpNotReceivingBytesTimeoutMs" + | "httpErrorRetries" + | "p2pErrorRetries" > >; -/** - * Configuration options for the Core functionality, including network and processing parameters. - */ +/** Configuration options for the Core functionality, including network and processing parameters. */ export type CoreConfig = { /** - * Time window to consider for high demand scenarios, in seconds. + * Defines the duration of the time window, in seconds, during which segments are pre-loaded to ensure smooth playback. + * This window helps prioritize the fetching of media segments that are imminent to playback. * * @default * ```typescript @@ -116,24 +89,30 @@ export type CoreConfig = { highDemandTimeWindow: number; /** - * Time window for HTTP downloads, in seconds. - * Specifies amount of segments to be downloaded in advance through HTTP. + * Defines the time window, in seconds, for HTTP segment downloads. This property specifies the duration + * over which media segments are pre-fetched using HTTP requests. + * + * For a better P2P ratio, it is recommended to set this `httpDownloadTimeWindow` to be lower than `p2pDownloadTimeWindow`. + * + * NOTE: This setting only takes effect if there is at least one peer connection and the connected peer + * does not have the requested segments available to share via P2P. * * @default * ```typescript - * httpDownloadTimeWindowMs: 45 + * httpDownloadTimeWindow: 3000 * ``` */ httpDownloadTimeWindow: number; /** - * Time window for P2P downloads, in seconds. - * Specifies amount of segments to be downloaded in advance through P2P. - * Should be greater than httpDownloadTimeWindow. + * Defines the time window, in seconds, dedicated to pre-fetching media segments via Peer-to-Peer (P2P) downloads. + * This duration determines how much content is downloaded in advance using P2P connections to ensure smooth playback and reduce reliance on HTTP downloads. + * + * For a better P2P ratio, it is recommended to set this time window to be greater than `httpDownloadTimeWindow` to maximize P2P usage. * * @default * ```typescript - * p2pDownloadTimeWindow: 45 + * p2pDownloadTimeWindow: 6000 * ``` */ p2pDownloadTimeWindow: number; @@ -159,22 +138,24 @@ export type CoreConfig = { simultaneousP2PDownloads: number; /** - * Time after which a cached segment expires, in milliseconds. + * Time after which a cached segment expires, in seconds. + * If set to undefined, the cacheSegmentExpiration is disabled for VOD streams, and a default value (20 minutes) is used for live streams. * * @default * ```typescript - * cachedSegmentExpiration: 120 * 1000 + * cachedSegmentExpiration: undefined * ``` */ - cachedSegmentExpiration: number; + cachedSegmentExpiration?: number; /** * Maximum number of segments to store in the cache. * Has to be less then httpDownloadTimeWindow and p2pDownloadTimeWindow. + * If set to 0, the cache is unlimited. * * @default * ```typescript - * cachedSegmentsCount: 50 + * cachedSegmentsCount: 0 * ``` */ cachedSegmentsCount: number; @@ -229,7 +210,8 @@ export type CoreConfig = { */ httpErrorRetries: number; - /** Number of retries allowed after a P2P error. + /** + * Number of retries allowed after a P2P error. * * @default * ```typescript @@ -282,7 +264,8 @@ export type CoreConfig = { */ trackerClientVersionPrefix: string; - /** Optional unique identifier for the swarm, used to isolate peer pools by media stream. + /** + * Optional unique identifier for the swarm, used to isolate peer pools by media stream. * * @default * The master URL of the manifest is used as the swarmId. @@ -322,101 +305,60 @@ export type CoreConfig = { */ export type DownloadSource = "http" | "p2p"; -/** - * Represents details about a segment event. - */ +/** Represents details about a segment event. */ export type SegmentStartDetails = { - /** - * The media segment related to the event. - */ + /** The segment that the event is about. */ segment: Segment; - /** - * The origin of the segment download, such as from a server or a peer. - */ + /** The origin of the segment download. */ downloadSource: DownloadSource; - /** - * The peer ID associated with the segment event, if the segment was downloaded from a peer. Undefined if not applicable. - */ + /** The peer ID, if the segment is downloaded from a peer. */ peerId: string | undefined; }; -/** - * Represents details about a segment error event, providing contextual information about the error during a segment download. - */ +/** Represents details about a segment error event. */ export type SegmentErrorDetails = { - /** - * The error that occurred during the segment download. - */ + /** The error that occurred during the segment download. */ error: RequestError; - /** - * The media segment related to the event. - */ + /** The segment that the event is about. */ segment: Segment; - /** - * The origin of the segment download, such as from a server or a peer. - */ + /** The source of the download. */ downloadSource: DownloadSource; - /** - * The peer ID of the peer that the event is about, if applicable. Undefined if not applicable. - */ + /** The peer ID, if the segment was downloaded from a peer. */ peerId: string | undefined; }; -/** - * Represents details about a segment abort event. This includes information about the segment, the source from where it was being downloaded, and an optional peer ID if the download involved peer-to-peer transfer. - */ +/** Represents details about a segment abort event. */ export type SegmentAbortDetails = { - /** - * The media segment related to the abort event. - */ + /** The segment that the event is about. */ segment: Segment; - /** - * The source of the download, if it was specified; otherwise, undefined. - * This can be from a server or a peer, depending on the scenario. - */ + /** The source of the download. */ downloadSource: DownloadSource | undefined; - /** - * The peer ID of the peer involved in the event, if applicable. Undefined if not relevant or known. - */ + /** The peer ID, if the segment was downloaded from a peer. */ peerId: string | undefined; }; -/** - * Represents the details about a loaded segment in media streaming. - */ +/** Represents the details about a loaded segment. */ export type SegmentLoadDetails = { - /** - * The length of the segment in bytes. - */ + /** The length of the segment in bytes. */ bytesLength: number; - /** - * The source of the download, indicating whether the segment was retrieved over HTTP or from a - * peer-to-peer network. - */ + /** The source of the download. */ downloadSource: DownloadSource; - /** - * The unique identifier of the peer from which this segment was downloaded, if applicable. This field - * is optional and may be undefined if the segment was not sourced from a peer. - */ + /** The peer ID, if the segment was downloaded from a peer. */ peerId: string | undefined; }; -/** - * Represents the details of a peer in a peer-to-peer network. - */ +/** Represents the details of a peer in a peer-to-peer network. */ export type PeerDetails = { - /** - * The unique identifier for a peer in the network. - */ + /** The unique identifier for a peer in the network. */ peerId: string; }; @@ -428,51 +370,51 @@ export type CoreEventMap = { /** * Invoked when a segment is fully downloaded and available for use. * - * @param {SegmentLoadDetails} params - Contains information about the loaded segment. + * @param params - Contains information about the loaded segment. */ onSegmentLoaded: (params: SegmentLoadDetails) => void; /** * Triggered when an error occurs during the download of a segment. * - * @param {SegmentErrorDetails} params - Contains information about the errored segment. + * @param params - Contains information about the errored segment. */ onSegmentError: (params: SegmentErrorDetails) => void; /** * Called if the download of a segment is aborted before completion. * - * @param {SegmentAbortDetails} params - Contains information about the aborted segment. + * @param params - Contains information about the aborted segment. */ onSegmentAbort: (params: SegmentAbortDetails) => void; /** * Fired at the beginning of a segment download process. * - * @param {SegmentStartDetails} params - Provides details about the segment being downloaded. + * @param params - Provides details about the segment being downloaded. */ onSegmentStart: (params: SegmentStartDetails) => void; /** * Occurs when a new peer-to-peer connection is established. * - * @param {string} peerId - The unique identifier of the peer that has just connected. + * @param peerId - The unique identifier of the peer that has just connected. */ onPeerConnect: (params: PeerDetails) => void; /** * Triggered when an existing peer-to-peer connection is closed. * - * @param {string} peerId - The unique identifier of the peer whose connection has been closed. + * @param peerId - The unique identifier of the peer whose connection has been closed. */ onPeerClose: (params: PeerDetails) => void; /** * Invoked after a chunk of data from a segment has been successfully downloaded. * - * @param {number} bytesLength - The size of the downloaded chunk in bytes, offering a measure of the download progress. - * @param {DownloadSource} type - The source of the download. - * @param {string} [peerId] - The peer ID of the peer that the event is about, if applicable. + * @param bytesLength - The size of the downloaded chunk in bytes. + * @param type - The source of the download. + * @param peerId - The peer ID of the peer that the event is about, if applicable. */ onChunkDownloaded: ( bytesLength: number, @@ -483,28 +425,22 @@ export type CoreEventMap = { /** * Called when a chunk of data has been successfully uploaded to a peer. * - * @param {number} bytesLength - The length of the segment in bytes. - * @param {string} peerId - The peer ID of the peer that the event is about, if applicable. + * @param bytesLength - The length of the segment in bytes. + * @param peerId - The peer ID, if the segment was downloaded from a peer */ onChunkUploaded: (bytesLength: number, peerId: string) => void; }; -/** - * Defines the types of errors that can occur during a request abortion process. - */ +/** Defines the types of errors that can occur during a request abortion process. */ export type RequestAbortErrorType = "abort" | "bytes-receiving-timeout"; -/** - * Defines the types of errors specific to HTTP requests. - */ +/** Defines the types of errors specific to HTTP requests. */ export type HttpRequestErrorType = | "http-error" | "http-bytes-mismatch" | "http-unexpected-status-code"; -/** - * Defines the types of errors specific to peer-to-peer requests. - */ +/** Defines the types of errors specific to peer-to-peer requests. */ export type PeerRequestErrorType = | "peer-response-bytes-length-mismatch" | "peer-protocol-violation" @@ -512,9 +448,7 @@ export type PeerRequestErrorType = | "peer-closed" | "p2p-segment-validation-failed"; -/** - * Enumerates all possible request error types, including HTTP and peer-related errors. - */ +/** Enumerates all possible request error types, including HTTP and peer-related errors. */ export type RequestErrorType = | RequestAbortErrorType | PeerRequestErrorType @@ -527,6 +461,7 @@ export type RequestErrorType = export class RequestError< T extends RequestErrorType = RequestErrorType, > extends Error { + /** Error timestamp. */ readonly timestamp: number; /** @@ -543,24 +478,16 @@ export class RequestError< } } -/** - * Represents the response from a segment request in media streaming. - */ +/** Represents the response from a segment request, including the data and measured bandwidth. */ export type SegmentResponse = { - /** - * The raw binary data of the media segment. - */ + /** Segment data as an ArrayBuffer. */ data: ArrayBuffer; - /** - * The measured bandwidth during the segment's download. - */ + /** Measured bandwidth for the segment download, in bytes per second. */ bandwidth: number; }; -/** - * Custom error class for errors that occur during core network requests. - */ +/** Custom error class for errors that occur during core network requests. */ export class CoreRequestError extends Error { /** * Constructs a new CoreRequestError. @@ -571,9 +498,7 @@ export class CoreRequestError extends Error { } } -/** - * Callbacks for handling the success or failure of an engine operation. - */ +/** Callbacks for handling the success or failure of an engine operation. */ export type EngineCallbacks = { /** * Called when the operation is successful. diff --git a/packages/p2p-media-loader-core/typedoc.json b/packages/p2p-media-loader-core/typedoc.json index e838eba9..3a79cd64 100644 --- a/packages/p2p-media-loader-core/typedoc.json +++ b/packages/p2p-media-loader-core/typedoc.json @@ -2,5 +2,6 @@ "entryPoints": ["src/index.ts"], "excludeExternals": true, "excludePrivate": true, - "readme": "none" + "readme": "none", + "sort": ["source-order"] } diff --git a/packages/p2p-media-loader-hlsjs/package.json b/packages/p2p-media-loader-hlsjs/package.json index c44ea1c6..17fe2975 100644 --- a/packages/p2p-media-loader-hlsjs/package.json +++ b/packages/p2p-media-loader-hlsjs/package.json @@ -51,7 +51,6 @@ }, "dependencies": { "hls.js": "^1.5.7", - "p2p-media-loader-core": "workspace:*", - "ts-essentials": "^9.4.1" + "p2p-media-loader-core": "workspace:*" } } diff --git a/packages/p2p-media-loader-hlsjs/src/engine.ts b/packages/p2p-media-loader-hlsjs/src/engine.ts index 33f4efce..89e098c0 100644 --- a/packages/p2p-media-loader-hlsjs/src/engine.ts +++ b/packages/p2p-media-loader-hlsjs/src/engine.ts @@ -19,26 +19,23 @@ import { } from "p2p-media-loader-core"; import { injectMixin } from "./engine-static"; -/** - * Represents the complete configuration for HlsJsP2PEngine. - */ +/** Represents the complete configuration for HlsJsP2PEngine. */ export type HlsJsP2PEngineConfig = { + /** Core config */ core: CoreConfig; }; -/** - * Allows for partial configuration of HlsJsP2PEngine, useful for providing overrides or partial updates. - */ +/** Allows for partial configuration of HlsJsP2PEngine, useful for providing overrides or partial updates. */ export type PartialHlsJsP2PEngineConfig = Partial< Omit > & { + /** Partial core config */ core?: Partial; }; -/** - * Type for specifying dynamic configuration options that can be changed at runtime for the P2P engine's core. - */ +/** Type for specifying dynamic configuration options that can be changed at runtime for the P2P engine's core. */ export type DynamicHlsJsP2PEngineConfig = { + /** Dynamic core config */ core?: DynamicCoreConfig; }; @@ -47,6 +44,7 @@ export type DynamicHlsJsP2PEngineConfig = { * @template HlsType The base HLS type that is being extended. */ export type HlsWithP2PInstance = HlsType & { + /** HlsJsP2PEngine instance */ readonly p2pEngine: HlsJsP2PEngine; }; @@ -76,8 +74,7 @@ export type HlsWithP2PConfig unknown> = * core: { * highDemandTimeWindow: 30, // 30 seconds * simultaneousHttpDownloads: 3, - * cachedSegmentsCount: 50, - * webRtcMaxMessageSize: 262144, // 256 KB + * webRtcMaxMessageSize: 64 * 1024, // 64 KB * p2pNotReceivingBytesTimeoutMs: 10000, // 10 seconds * p2pInactiveLoaderDestroyTimeoutMs: 15000, // 15 seconds * httpNotReceivingBytesTimeoutMs: 8000, // 8 seconds @@ -339,9 +336,7 @@ export class HlsJsP2PEngine { private destroyCore = () => this.core.destroy(); - /** - * Clean up and release all resources. Unregisters all event handlers. - */ + /** Clean up and release all resources. Unregister all event handlers. */ destroy = () => { this.destroyCore(); this.updateHlsEventsHandlers("unregister"); diff --git a/packages/p2p-media-loader-hlsjs/typedoc.json b/packages/p2p-media-loader-hlsjs/typedoc.json index e838eba9..3a79cd64 100644 --- a/packages/p2p-media-loader-hlsjs/typedoc.json +++ b/packages/p2p-media-loader-hlsjs/typedoc.json @@ -2,5 +2,6 @@ "entryPoints": ["src/index.ts"], "excludeExternals": true, "excludePrivate": true, - "readme": "none" + "readme": "none", + "sort": ["source-order"] } diff --git a/packages/p2p-media-loader-shaka/package.json b/packages/p2p-media-loader-shaka/package.json index 4e43b390..21ad1a5b 100644 --- a/packages/p2p-media-loader-shaka/package.json +++ b/packages/p2p-media-loader-shaka/package.json @@ -52,7 +52,6 @@ }, "dependencies": { "p2p-media-loader-core": "workspace:*", - "shaka-player": "^4.7.11", - "ts-essentials": "^9.4.1" + "shaka-player": "^4.7.11" } } diff --git a/packages/p2p-media-loader-shaka/src/engine.ts b/packages/p2p-media-loader-shaka/src/engine.ts index 4647c614..aba08f96 100644 --- a/packages/p2p-media-loader-shaka/src/engine.ts +++ b/packages/p2p-media-loader-shaka/src/engine.ts @@ -20,26 +20,23 @@ import { DynamicCoreConfig, } from "p2p-media-loader-core"; -/** - * Type for specifying dynamic configuration options that can be changed at runtime for the P2P engine's core. - */ +/** Type for specifying dynamic configuration options that can be changed at runtime for the P2P engine's core. */ export type DynamicShakaP2PEngineConfig = { + /** Dynamic core config */ core?: DynamicCoreConfig; }; -/** - * Represents the complete configuration for ShakaP2PEngine. - */ +/** Represents the complete configuration for ShakaP2PEngine. */ export type ShakaP2PEngineConfig = { + /** Core config */ core: CoreConfig; }; -/** - * Allows for partial configuration settings for the Shaka P2P Engine. - */ +/** Allows for partial configuration settings for the Shaka P2P Engine. */ export type PartialShakaEngineConfig = Partial< Omit > & { + /** Partial core config */ core?: Partial; }; @@ -60,8 +57,7 @@ const LIVE_EDGE_DELAY = 25; * core: { * highDemandTimeWindow: 30, // 30 seconds * simultaneousHttpDownloads: 3, - * cachedSegmentsCount: 50, - * webRtcMaxMessageSize: 262144, // 256 KB + * webRtcMaxMessageSize: 64 * 1024, // 64 KB * p2pNotReceivingBytesTimeoutMs: 10000, // 10 seconds * p2pInactiveLoaderDestroyTimeoutMs: 15000, // 15 seconds * httpNotReceivingBytesTimeoutMs: 8000, // 8 seconds @@ -272,9 +268,7 @@ export class ShakaP2PEngine { this.core.updatePlayback(media.currentTime, media.playbackRate); }; - /** - * Clean up and release all resources. Unregisters all event handlers. - */ + /** Clean up and release all resources. Unregister all event handlers. */ destroy() { this.destroyCurrentStreamContext(); this.updatePlayerEventHandlers("unregister"); @@ -333,7 +327,7 @@ export class ShakaP2PEngine { * Registers plugins related to P2P functionality into the Shaka Player. * Plugins must be registered before initializing the player to ensure proper integration. * - * @param {Shaka} [shaka=window.shaka] - The Shaka Player library. Defaults to the global Shaka Player instance if not provided. + * @param shaka - The Shaka Player library. Defaults to the global Shaka Player instance if not provided. */ static registerPlugins(shaka = window.shaka) { validateShaka(shaka); @@ -343,9 +337,9 @@ export class ShakaP2PEngine { } /** - * Unregisters plugins related to P2P functionality from the Shaka Player. + * Unregister plugins related to P2P functionality from the Shaka Player. * - * @param {Shaka} [shaka=window.shaka] - The Shaka Player library. Defaults to the global Shaka Player instance if not provided. + * @param shaka - The Shaka Player library. Defaults to the global Shaka Player instance if not provided. */ static unregisterPlugins(shaka = window.shaka) { validateShaka(shaka); diff --git a/packages/p2p-media-loader-shaka/typedoc.json b/packages/p2p-media-loader-shaka/typedoc.json index e838eba9..3a79cd64 100644 --- a/packages/p2p-media-loader-shaka/typedoc.json +++ b/packages/p2p-media-loader-shaka/typedoc.json @@ -2,5 +2,6 @@ "entryPoints": ["src/index.ts"], "excludeExternals": true, "excludePrivate": true, - "readme": "none" + "readme": "none", + "sort": ["source-order"] } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de404e37..f16cdf85 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -103,9 +103,6 @@ importers: nano-md5: specifier: ^1.0.5 version: 1.0.5 - ts-essentials: - specifier: ^9.4.1 - version: 9.4.1(typescript@5.4.2) devDependencies: vite-plugin-node-polyfills: specifier: ^0.21.0 @@ -186,9 +183,6 @@ importers: p2p-media-loader-core: specifier: workspace:* version: link:../p2p-media-loader-core - ts-essentials: - specifier: ^9.4.1 - version: 9.4.1(typescript@5.4.2) packages/p2p-media-loader-shaka: dependencies: @@ -198,9 +192,6 @@ importers: shaka-player: specifier: ^4.7.11 version: 4.7.11 - ts-essentials: - specifier: ^9.4.1 - version: 9.4.1(typescript@5.4.2) packages: @@ -2535,14 +2526,6 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-essentials@9.4.1: - resolution: {integrity: sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==} - peerDependencies: - typescript: '>=4.1.0' - peerDependenciesMeta: - typescript: - optional: true - tty-browserify@0.0.1: resolution: {integrity: sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==} @@ -5464,10 +5447,6 @@ snapshots: dependencies: typescript: 5.4.2 - ts-essentials@9.4.1(typescript@5.4.2): - optionalDependencies: - typescript: 5.4.2 - tty-browserify@0.0.1: {} type-check@0.4.0: