@jellyfish-dev/ts-client-sdk
Version:
Typescript client library for Jellyfish.
634 lines • 25.5 kB
TypeScript
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