UNPKG

@jellyfish-dev/ts-client-sdk

Version:
634 lines 25.5 kB
import { SerializedMediaEvent } from "./mediaEvent"; import TypedEmitter from "typed-emitter"; export type MetadataParser<ParsedMetadata> = (rawMetadata: unknown) => ParsedMetadata; /** * Interface describing Endpoint. */ export interface Endpoint<EndpointMetadata, TrackMetadata> { /** * Endpoint's id. It is assigned by user in custom logic that use backend API. */ id: string; /** * Type of the endpoint, e.g. "webrtc", "hls" or "rtsp". */ type: string; /** * Any information that was provided in {@link WebRTCEndpoint.connect}. */ metadata?: EndpointMetadata; rawMetadata: any; metadataParsingError?: any; /** * List of tracks that are sent by the endpoint. */ tracks: Map<string, TrackContextImpl<EndpointMetadata, TrackMetadata>>; } /** * Type describing Voice Activity Detection statuses. * * - `speech` - voice activity has been detected * - `silence` - lack of voice activity has been detected */ export type VadStatus = "speech" | "silence"; /** * Type describing maximal bandwidth that can be used, in kbps. 0 is interpreted as unlimited bandwidth. */ export type BandwidthLimit = number; /** * Type describing bandwidth limit for simulcast track. * It is a mapping (encoding => BandwidthLimit). * If encoding isn't present in this mapping, it will be assumed that this particular encoding shouldn't have any bandwidth limit */ export type SimulcastBandwidthLimit = Map<TrackEncoding, BandwidthLimit>; /** * Type describing bandwidth limitation of a Track, including simulcast and non-simulcast tracks. * A sum type of `BandwidthLimit` and `SimulcastBandwidthLimit` */ export type TrackBandwidthLimit = BandwidthLimit | SimulcastBandwidthLimit; /** * Type describing possible reasons for currently selected encoding. * - `other` - the exact reason couldn't be determined * - `encodingInactive` - previously selected encoding became inactive * - `lowBandwidth` - there is no longer enough bandwidth to maintain previously selected encoding */ export type EncodingReason = "other" | "encodingInactive" | "lowBandwidth"; /** * Simulcast configuration passed to {@link WebRTCEndpoint.addTrack}. * * At the moment, simulcast track is initialized in three versions - low, medium and high. * High resolution is the original track resolution, while medium and low resolutions * are the original track resolution scaled down by 2 and 4 respectively. */ export interface SimulcastConfig { /** * Whether to simulcast track or not. */ enabled: boolean; /** * List of initially active encodings. * * Encoding that is not present in this list might still be * enabled using {@link WebRTCEndpoint.enableTrackEncoding}. */ activeEncodings: TrackEncoding[]; /** * List of disabled encodings. * * Encoding that is present in this list was * disabled using {@link WebRTCEndpoint.disableTrackEncoding}. */ disabledEncodings: TrackEncoding[]; } /** * Track's context i.e. all data that can be useful when operating on track. */ interface TrackContextFields<EndpointMetadata, TrackMetadata> { readonly track: MediaStreamTrack | null; /** * Stream this track belongs to. */ readonly stream: MediaStream | null; /** * Endpoint this track comes from. */ readonly endpoint: Endpoint<EndpointMetadata, TrackMetadata>; /** * Track id. It is generated by RTC engine and takes form `endpoint_id:<random_uuidv4>`. * It is WebRTC agnostic i.e. it does not contain `mid` or `stream id`. */ readonly trackId: string; /** * Simulcast configuration. * Only present for local tracks. */ readonly simulcastConfig?: SimulcastConfig; /** * Any info that was passed in {@link WebRTCEndpoint.addTrack}. */ readonly metadata?: TrackMetadata; readonly rawMetadata: any; readonly metadataParsingError?: any; readonly maxBandwidth?: TrackBandwidthLimit; readonly vadStatus: VadStatus; /** * Encoding that is currently received. * Only present for remote tracks. */ readonly encoding?: TrackEncoding; /** * The reason of currently selected encoding. * Only present for remote tracks. */ readonly encodingReason?: EncodingReason; } export interface TrackContextEvents<EndpointMetadata, TrackMetadata> { /** * Emitted each time track encoding has changed. * * Track encoding can change in the following cases: * - when user requested a change * - when sender stopped sending some encoding (because of bandwidth change) * - when receiver doesn't have enough bandwidth * * Some of those reasons are indicated in {@link TrackContext.encodingReason}. */ encodingChanged: (context: TrackContext<EndpointMetadata, TrackMetadata>) => void; /** * Emitted every time an update about voice activity is received from the server. */ voiceActivityChanged: (context: TrackContext<EndpointMetadata, TrackMetadata>) => void; } export interface TrackContext<EndpointMetadata, TrackMetadata> extends TrackContextFields<EndpointMetadata, TrackMetadata>, TypedEmitter<Required<TrackContextEvents<EndpointMetadata, TrackMetadata>>> { } type TrackNegotiationStatus = "awaiting" | "offered" | "done"; declare const TrackContextImpl_base: new <EndpointMetadata_1, ParsedMetadata_1>() => TypedEmitter<Required<TrackContextEvents<EndpointMetadata_1, ParsedMetadata_1>>>; declare class TrackContextImpl<EndpointMetadata, ParsedMetadata> extends TrackContextImpl_base<EndpointMetadata, ParsedMetadata> implements TrackContext<EndpointMetadata, ParsedMetadata> { endpoint: Endpoint<EndpointMetadata, ParsedMetadata>; trackId: string; track: MediaStreamTrack | null; stream: MediaStream | null; metadata?: ParsedMetadata; rawMetadata: any; metadataParsingError?: any; simulcastConfig?: SimulcastConfig; maxBandwidth: TrackBandwidthLimit; encoding?: TrackEncoding; encodingReason?: EncodingReason; vadStatus: VadStatus; negotiationStatus: TrackNegotiationStatus; pendingMetadataUpdate: boolean; constructor(endpoint: Endpoint<EndpointMetadata, ParsedMetadata>, trackId: string, metadata: any, simulcastConfig: SimulcastConfig, metadataParser: MetadataParser<ParsedMetadata>); } /** * Type describing possible track encodings. * - `"h"` - original encoding * - `"m"` - original encoding scaled down by 2 * - `"l"` - original encoding scaled down by 4 * * Notice that to make all encodings work, the initial * resolution has to be at least 1280x720. * In other case, browser might not be able to scale * some encodings down. */ export type TrackEncoding = "l" | "m" | "h"; /** * Events emitted by the {@link WebRTCEndpoint} instance. */ export interface WebRTCEndpointEvents<EndpointMetadata, TrackMetadata> { /** * Emitted each time WebRTCEndpoint need to send some data to the server. */ sendMediaEvent: (mediaEvent: SerializedMediaEvent) => void; /** * Emitted when endpoint of this {@link WebRTCEndpoint} instance is ready. Triggered by {@link WebRTCEndpoint.connect} */ connected: (endpointId: string, otherEndpoints: Endpoint<EndpointMetadata, TrackMetadata>[]) => void; /** * Emitted when endpoint of this {@link WebRTCEndpoint} instance was removed. */ disconnected: () => void; /** * Emitted when data in a new track arrives. * * This event is always emitted after {@link trackAdded}. * It informs the user that data related to the given track arrives and can be played or displayed. */ trackReady: (ctx: TrackContext<EndpointMetadata, TrackMetadata>) => void; /** * Emitted each time the endpoint which was already in the room, adds new track. Fields track and stream will be set to null. * These fields will be set to non-null value in {@link trackReady} */ trackAdded: (ctx: TrackContext<EndpointMetadata, TrackMetadata>) => void; /** * Emitted when some track will no longer be sent. * * It will also be emitted before {@link endpointRemoved} for each track of this endpoint. */ trackRemoved: (ctx: TrackContext<EndpointMetadata, TrackMetadata>) => void; /** * Emitted each time endpoint has its track metadata updated. */ trackUpdated: (ctx: TrackContext<EndpointMetadata, TrackMetadata>) => void; /** * Emitted each time new endpoint is added to the room. */ endpointAdded: (endpoint: Endpoint<EndpointMetadata, TrackMetadata>) => void; /** * Emitted each time endpoint is removed, emitted only for other endpoints. */ endpointRemoved: (endpoint: Endpoint<EndpointMetadata, TrackMetadata>) => void; /** * Emitted each time endpoint has its metadata updated. */ endpointUpdated: (endpoint: Endpoint<EndpointMetadata, TrackMetadata>) => void; /** * Emitted in case of errors related to multimedia session e.g. ICE connection. */ connectionError: (message: string) => void; /** * Currently, this event is only emitted when DisplayManager in RTC Engine is * enabled and simulcast is disabled. * * Emitted when priority of video tracks have changed. * @param enabledTracks - list of tracks which will be sent to client from SFU * @param disabledTracks - list of tracks which will not be sent to client from SFU */ tracksPriorityChanged: (enabledTracks: TrackContext<EndpointMetadata, TrackMetadata>[], disabledTracks: TrackContext<EndpointMetadata, TrackMetadata>[]) => void; /** * Emitted every time the server estimates client's bandwidth. * * @param {bigint} estimation - client's available incoming bitrate estimated * by the server. It's measured in bits per second. */ bandwidthEstimationChanged: (estimation: bigint) => void; /** * Emitted each time track encoding has been disabled. */ trackEncodingDisabled: (context: TrackContext<EndpointMetadata, TrackMetadata>, encoding: string) => void; /** * Emitted each time track encoding has been enabled. */ trackEncodingEnabled: (context: TrackContext<EndpointMetadata, TrackMetadata>, encoding: string) => void; targetTrackEncodingRequested: (event: { trackId: string; variant: TrackEncoding; }) => void; disconnectRequested: (event: any) => void; localTrackAdded: (event: { trackId: string; track: MediaStreamTrack; stream: MediaStream; trackMetadata?: TrackMetadata; simulcastConfig: SimulcastConfig; maxBandwidth: TrackBandwidthLimit; }) => void; localTrackRemoved: (event: { trackId: string; }) => void; localTrackReplaced: (event: { trackId: string; track: MediaStreamTrack; metadata?: TrackMetadata; }) => void; localTrackBandwidthSet: (event: { trackId: string; bandwidth: BandwidthLimit; }) => void; localTrackEncodingBandwidthSet: (event: { trackId: string; rid: string; bandwidth: BandwidthLimit; }) => void; localTrackEncodingEnabled: (event: { trackId: string; encoding: TrackEncoding; }) => void; localTrackEncodingDisabled: (event: { trackId: string; encoding: TrackEncoding; }) => void; localEndpointMetadataChanged: (event: { metadata: EndpointMetadata; }) => void; localTrackMetadataChanged: (event: { trackId: string; metadata: TrackMetadata; }) => void; } export type Config<EndpointMetadata, TrackMetadata> = { endpointMetadataParser?: MetadataParser<EndpointMetadata>; trackMetadataParser?: MetadataParser<TrackMetadata>; }; declare const WebRTCEndpoint_base: new <EndpointMetadata_1, TrackMetadata_1>() => TypedEmitter<Required<WebRTCEndpointEvents<EndpointMetadata_1, TrackMetadata_1>>>; /** * Main class that is responsible for connecting to the RTC Engine, sending and receiving media. */ export declare class WebRTCEndpoint<EndpointMetadata = any, TrackMetadata = any> extends WebRTCEndpoint_base<EndpointMetadata, TrackMetadata> { private trackIdToTrack; private connection?; private idToEndpoint; private localEndpoint; private localTrackIdToTrack; private midToTrackId; private disabledTrackEncodings; private rtcConfig; private bandwidthEstimation; /** * Indicates if an ongoing renegotiation is active. * During renegotiation, both parties are expected to actively exchange events: renegotiateTracks, offerData, sdpOffer, sdpAnswer. */ private ongoingRenegotiation; private ongoingTrackReplacement; private commandsQueue; private commandResolutionNotifier; private readonly endpointMetadataParser; private readonly trackMetadataParser; constructor(config?: Config<EndpointMetadata, TrackMetadata>); /** * Tries to connect to the RTC Engine. If user is successfully connected then {@link WebRTCEndpointEvents.connected} * will be emitted. * * @param metadata - Any information that other endpoints will receive in {@link WebRTCEndpointEvents.endpointAdded} * after accepting this endpoint * * @example * ```ts * let webrtc = new WebRTCEndpoint(); * webrtc.connect({displayName: "Bob"}); * ``` */ connect: (metadata: EndpointMetadata) => void; /** * Feeds media event received from RTC Engine to {@link WebRTCEndpoint}. * This function should be called whenever some media event from RTC Engine * was received and can result in {@link WebRTCEndpoint} generating some other * media events. * * @param mediaEvent - String data received over custom signalling layer. * * @example * This example assumes phoenix channels as signalling layer. * As phoenix channels require objects, RTC Engine encapsulates binary data into * map with one field that is converted to object with one field on the TS side. * ```ts * webrtcChannel.on("mediaEvent", (event) => webrtc.receiveMediaEvent(event.data)); * ``` */ receiveMediaEvent: (mediaEvent: SerializedMediaEvent) => void; /** * Retrieves statistics related to the RTCPeerConnection. * These statistics provide insights into the performance and status of the connection. * * @return {Promise<RTCStatsReport>} * * @external RTCPeerConnection#getStats() * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/getStats | MDN Web Docs: RTCPeerConnection.getStats()} */ getStatistics(selector?: MediaStreamTrack | null): Promise<RTCStatsReport>; /** * Returns a snapshot of currently received remote tracks. * * @example * if (webRTCEndpoint.getRemoteTracks()[trackId]?.simulcastConfig?.enabled) { * webRTCEndpoint.setTargetTrackEncoding(trackId, encoding); * } */ getRemoteTracks(): Record<string, TrackContext<EndpointMetadata, TrackMetadata>>; /** * Returns a snapshot of currently received remote endpoints. */ getRemoteEndpoints(): Record<string, Endpoint<EndpointMetadata, TrackMetadata>>; getLocalEndpoint(): Endpoint<EndpointMetadata, TrackMetadata>; getBandwidthEstimation(): bigint; private handleMediaEvent; /** * Adds track that will be sent to the RTC Engine. * @param track - Audio or video track e.g. from your microphone or camera. * @param stream - Stream that this track belongs to. * @param trackMetadata - Any information about this track that other endpoints will * receive in {@link WebRTCEndpointEvents.endpointAdded}. E.g. this can source of the track - whether it's * screensharing, webcam or some other media device. * @param simulcastConfig - Simulcast configuration. By default simulcast is disabled. * For more information refer to {@link SimulcastConfig}. * @param maxBandwidth - maximal bandwidth this track can use. * Defaults to 0 which is unlimited. * This option has no effect for simulcast and audio tracks. * For simulcast tracks use `{@link WebRTCEndpoint.setTrackBandwidth}. * @returns {string} Returns id of added track * @example * ```ts * let localStream: MediaStream = new MediaStream(); * try { * localAudioStream = await navigator.mediaDevices.getUserMedia( * AUDIO_CONSTRAINTS * ); * localAudioStream * .getTracks() * .forEach((track) => localStream.addTrack(track)); * } catch (error) { * console.error("Couldn't get microphone permission:", error); * } * * try { * localVideoStream = await navigator.mediaDevices.getUserMedia( * VIDEO_CONSTRAINTS * ); * localVideoStream * .getTracks() * .forEach((track) => localStream.addTrack(track)); * } catch (error) { * console.error("Couldn't get camera permission:", error); * } * * localStream * .getTracks() * .forEach((track) => webrtc.addTrack(track, localStream)); * ``` */ addTrack(track: MediaStreamTrack, stream: MediaStream, trackMetadata?: TrackMetadata, simulcastConfig?: SimulcastConfig, maxBandwidth?: TrackBandwidthLimit): Promise<string>; private pushCommand; private handleCommand; private processNextCommand; private resolvePreviousCommand; private addTrackHandler; private addTrackToConnection; private createTransceiverConfig; private createAudioTransceiverConfig; private createVideoTransceiverConfig; private applyBandwidthLimitation; private splitBandwidth; /** * Replaces a track that is being sent to the RTC Engine. * @param trackId - Audio or video track. * @param {string} trackId - Id of audio or video track to replace. * @param {MediaStreamTrack} newTrack * @param {any} [newTrackMetadata] - Optional track metadata to apply to the new track. If no * track metadata is passed, the old track metadata is retained. * @returns {Promise<boolean>} success * @example * ```ts * // setup camera * let localStream: MediaStream = new MediaStream(); * try { * localVideoStream = await navigator.mediaDevices.getUserMedia( * VIDEO_CONSTRAINTS * ); * localVideoStream * .getTracks() * .forEach((track) => localStream.addTrack(track)); * } catch (error) { * console.error("Couldn't get camera permission:", error); * } * let oldTrackId; * localStream * .getTracks() * .forEach((track) => trackId = webrtc.addTrack(track, localStream)); * * // change camera * const oldTrack = localStream.getVideoTracks()[0]; * let videoDeviceId = "abcd-1234"; * navigator.mediaDevices.getUserMedia({ * video: { * ...(VIDEO_CONSTRAINTS as {}), * deviceId: { * exact: videoDeviceId, * }, * } * }) * .then((stream) => { * let videoTrack = stream.getVideoTracks()[0]; * webrtc.replaceTrack(oldTrackId, videoTrack); * }) * .catch((error) => { * console.error('Error switching camera', error); * }) * ``` */ replaceTrack(trackId: string, newTrack: MediaStreamTrack, newTrackMetadata?: any): Promise<void>; private replaceTrackHandler; /** * Updates maximum bandwidth for the track identified by trackId. * This value directly translates to quality of the stream and, in case of video, to the amount of RTP packets being sent. * In case trackId points at the simulcast track bandwidth is split between all of the variant streams proportionally to their resolution. * * @param {string} trackId * @param {BandwidthLimit} bandwidth in kbps * @returns {Promise<boolean>} success */ setTrackBandwidth(trackId: string, bandwidth: BandwidthLimit): Promise<boolean>; /** * Updates maximum bandwidth for the given simulcast encoding of the given track. * * @param {string} trackId - id of the track * @param {string} rid - rid of the encoding * @param {BandwidthLimit} bandwidth - desired max bandwidth used by the encoding (in kbps) * @returns */ setEncodingBandwidth(trackId: string, rid: string, bandwidth: BandwidthLimit): Promise<boolean>; /** * Removes a track from connection that was sent to the RTC Engine. * @param {string} trackId - Id of audio or video track to remove. * @example * ```ts * // setup camera * let localStream: MediaStream = new MediaStream(); * try { * localVideoStream = await navigator.mediaDevices.getUserMedia( * VIDEO_CONSTRAINTS * ); * localVideoStream * .getTracks() * .forEach((track) => localStream.addTrack(track)); * } catch (error) { * console.error("Couldn't get camera permission:", error); * } * * let trackId * localStream * .getTracks() * .forEach((track) => trackId = webrtc.addTrack(track, localStream)); * * // remove track * webrtc.removeTrack(trackId) * ``` */ removeTrack(trackId: string): Promise<void>; private removeTrackHandler; /** * Sets track variant that server should send to the client library. * * The variant will be sent whenever it is available. * If chosen variant is temporarily unavailable, some other variant * will be sent until the chosen variant becomes active again. * * @param {string} trackId - id of track * @param {TrackEncoding} variant - variant to receive * @example * ```ts * webrtc.setTargetTrackEncoding(incomingTrackCtx.trackId, "l") * ``` */ setTargetTrackEncoding(trackId: string, variant: TrackEncoding): void; /** * Enables track encoding so that it will be sent to the server. * @param {string} trackId - id of track * @param {TrackEncoding} encoding - encoding that will be enabled * @example * ```ts * const trackId = webrtc.addTrack(track, stream, {}, {enabled: true, activeEncodings: ["l", "m", "h"]}); * webrtc.disableTrackEncoding(trackId, "l"); * // wait some time * webrtc.enableTrackEncoding(trackId, "l"); * ``` */ enableTrackEncoding(trackId: string, encoding: TrackEncoding): void; /** * Disables track encoding so that it will be no longer sent to the server. * @param {string} trackId - id of track * @param {rackEncoding} encoding - encoding that will be disabled * @example * ```ts * const trackId = webrtc.addTrack(track, stream, {}, {enabled: true, activeEncodings: ["l", "m", "h"]}); * webrtc.disableTrackEncoding(trackId, "l"); * ``` */ disableTrackEncoding(trackId: string, encoding: TrackEncoding): void; private findSender; /** * Updates the metadata for the current endpoint. * @param metadata - Data about this endpoint that other endpoints will receive upon being added. * * If the metadata is different from what is already tracked in the room, the optional * event `endpointUpdated` will be emitted for other endpoint in the room. */ updateEndpointMetadata: (metadata: any) => void; /** * Updates the metadata for a specific track. * @param trackId - trackId (generated in addTrack) of audio or video track. * @param trackMetadata - Data about this track that other endpoint will receive upon being added. * * If the metadata is different from what is already tracked in the room, the optional * event `trackUpdated` will be emitted for other endpoints in the room. */ updateTrackMetadata: (trackId: string, trackMetadata: any) => void; private getMidToTrackId; /** * Disconnects from the room. This function should be called when user disconnects from the room * in a clean way e.g. by clicking a dedicated, custom button `disconnect`. * As a result there will be generated one more media event that should be * sent to the RTC Engine. Thanks to it each other endpoint will be notified * that endpoint was removed in {@link WebRTCEndpointEvents.endpointRemoved}, */ disconnect: () => void; /** * Cleans up {@link WebRTCEndpoint} instance. */ cleanUp: () => void; private getTrackId; private sendMediaEvent; private onAnswer; private addTransceiversIfNeeded; private createAndSendOffer; private getTrackIdToMetadata; private getTrackBitrates; private getTrackIdToTrackBitrates; private checkIfTrackBelongToEndpoint; private onOfferData; private onRemoteCandidate; private onLocalCandidate; private onIceCandidateError; private onConnectionStateChange; private onIceConnectionStateChange; private onIceGatheringStateChange; private onSignalingStateChange; private onTrack; private setTurns; private addEndpoint; private eraseEndpoint; private eraseTrack; private getEndpointId; private mapMediaEventTracksToTrackContextImpl; } export {}; //# sourceMappingURL=webRTCEndpoint.d.ts.map