@jellyfish-dev/ts-client-sdk
Version:
Typescript client library for Jellyfish.
513 lines • 20.9 kB
TypeScript
import { BandwidthLimit, Endpoint, SimulcastConfig, TrackBandwidthLimit, TrackContext, TrackEncoding, MetadataParser, WebRTCEndpointEvents } from "./webrtc";
import TypedEmitter from "typed-emitter";
import { ReconnectConfig } from "./reconnection";
import { AuthErrorReason } from "./auth";
export type Peer<PeerMetadata, TrackMetadata> = Endpoint<PeerMetadata, TrackMetadata> & {
type: "webrtc";
};
export type Component<PeerMetadata, TrackMetadata> = Omit<Endpoint<PeerMetadata, TrackMetadata>, "type"> & {
type: "recording" | "hls" | "file" | "rtsp" | "sip";
};
/**
* Events emitted by the client with their arguments.
*/
export interface MessageEvents<PeerMetadata, TrackMetadata> {
/**
* Emitted when the websocket connection is closed
*
* @param {CloseEvent} event - Close event object from the websocket
*/
socketClose: (event: CloseEvent) => void;
/**
* Emitted when occurs an error in the websocket connection
*
* @param {Event} event - Event object from the websocket
*/
socketError: (event: Event) => void;
/**
* Emitted when the websocket connection is opened
*
* @param {Event} event - Event object from the websocket
*/
socketOpen: (event: Event) => void;
/** Emitted when authentication is successful */
authSuccess: () => void;
/** Emitted when authentication fails */
authError: (reason: AuthErrorReason) => void;
/** Emitted when the connection is closed */
disconnected: () => void;
/**
* Called when peer was accepted.
*/
joined: (peerId: string, peers: Peer<PeerMetadata, TrackMetadata>[], components: Component<PeerMetadata, TrackMetadata>[]) => void;
/**
* Called when peer was not accepted
* @param metadata - Pass through for client application to communicate further actions to frontend
*/
joinError: (metadata: any) => void;
/**
* Called when data in a new track arrives.
*
* This callback is always called after {@link MessageEvents.trackAdded}.
* It informs user that data related to the given track arrives and can be played or displayed.
*/
trackReady: (ctx: TrackContext<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time the peer 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 MessageEvents.trackReady}
*/
trackAdded: (ctx: TrackContext<PeerMetadata, TrackMetadata>) => void;
/**
* Called when some track will no longer be sent.
*
* It will also be called before {@link MessageEvents.peerLeft} for each track of this peer.
*/
trackRemoved: (ctx: TrackContext<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time peer has its track metadata updated.
*/
trackUpdated: (ctx: TrackContext<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time new peer joins the room.
*/
peerJoined: (peer: Peer<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time peer leaves the room.
*/
peerLeft: (peer: Peer<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time peer has its metadata updated.
*/
peerUpdated: (peer: Peer<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time new peer joins the room.
*/
componentAdded: (peer: Component<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time peer leaves the room.
*/
componentRemoved: (peer: Component<PeerMetadata, TrackMetadata>) => void;
/**
* Called each time peer has its metadata updated.
*/
componentUpdated: (peer: Component<PeerMetadata, TrackMetadata>) => void;
/**
* Called in case of errors related to multimedia session e.g. ICE connection.
*/
connectionError: (message: string) => void;
/**
* Currently, this callback is only invoked when DisplayManager in RTC Engine is
* enabled and simulcast is disabled.
*
* Called 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<PeerMetadata, TrackMetadata>[], disabledTracks: TrackContext<PeerMetadata, TrackMetadata>[]) => void;
/**
* Called every time the server estimates client's bandiwdth.
*
* @param {bigint} estimation - client's available incoming bitrate estimated
* by the server. It's measured in bits per second.
*/
bandwidthEstimationChanged: (estimation: bigint) => void;
targetTrackEncodingRequested: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["targetTrackEncodingRequested"]>[0]) => void;
localTrackAdded: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackAdded"]>[0]) => void;
localTrackRemoved: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackRemoved"]>[0]) => void;
localTrackReplaced: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackReplaced"]>[0]) => void;
localTrackBandwidthSet: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackBandwidthSet"]>[0]) => void;
localTrackEncodingBandwidthSet: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackEncodingBandwidthSet"]>[0]) => void;
localTrackEncodingEnabled: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackEncodingEnabled"]>[0]) => void;
localTrackEncodingDisabled: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackEncodingDisabled"]>[0]) => void;
localEndpointMetadataChanged: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localEndpointMetadataChanged"]>[0]) => void;
localTrackMetadataChanged: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["localTrackMetadataChanged"]>[0]) => void;
disconnectRequested: (event: Parameters<WebRTCEndpointEvents<PeerMetadata, TrackMetadata>["disconnectRequested"]>[0]) => void;
}
export type SignalingUrl = {
/**
* Protocol of the websocket server
* Default is `"ws"`
*/
protocol?: string;
/**
* Host of the websocket server
* Default is `"localhost:5002"`
*/
host?: string;
/**
* Path of the websocket server
* Default is `"/socket/peer/websocket"`
*/
path?: string;
};
/** Configuration object for the client */
export interface ConnectConfig<PeerMetadata> {
/** Metadata for the peer */
peerMetadata: PeerMetadata;
/** Token for authentication */
token: string;
signaling?: SignalingUrl;
}
export type CreateConfig<PeerMetadata, TrackMetadata> = {
peerMetadataParser?: MetadataParser<PeerMetadata>;
trackMetadataParser?: MetadataParser<TrackMetadata>;
reconnect?: ReconnectConfig | boolean;
};
declare const JellyfishClient_base: new <PeerMetadata_1, TrackMetadata_1>() => TypedEmitter<Required<MessageEvents<PeerMetadata_1, TrackMetadata_1>>>;
/**
* JellyfishClient is the main class to interact with Jellyfish.
*
* @example
* ```typescript
* const client = new JellyfishClient<PeerMetadata, TrackMetadata>();
* const peerToken = "YOUR_PEER_TOKEN";
*
* // You can listen to events emitted by the client
* client.on("joined", (peerId, peersInRoom) => {
* console.log("join success");
* });
*
* // Start the peer connection
* client.connect({
* peerMetadata: {},
* isSimulcastOn: false,
* token: peerToken
* });
*
* // Close the peer connection
* client.disconnect();
* ```
*
* You can register callbacks to handle the events emitted by the Client.
*
* @example
* ```typescript
*
* client.on("trackReady", (ctx) => {
* console.log("On track ready");
* });
* ```
*/
export declare class JellyfishClient<PeerMetadata, TrackMetadata> extends JellyfishClient_base<PeerMetadata, TrackMetadata> {
private websocket;
private webrtc;
private removeEventListeners;
status: "new" | "initialized";
private connectConfig;
private reconnectManager;
private readonly peerMetadataParser;
private readonly trackMetadataParser;
constructor(config?: CreateConfig<PeerMetadata, TrackMetadata>);
/**
* Uses the {@link !WebSocket} connection and {@link !WebRTCEndpoint | WebRTCEndpoint} to join to the room. Registers the callbacks to
* handle the events emitted by the {@link !WebRTCEndpoint | WebRTCEndpoint}. Make sure that peer metadata is serializable.
*
* @example
* ```typescript
* const client = new JellyfishClient<PeerMetadata, TrackMetadata>();
*
* client.connect({
* peerMetadata: {},
* token: peerToken
* });
* ```
*
* @param {ConnectConfig} config - Configuration object for the client
*/
connect(config: ConnectConfig<PeerMetadata>): void;
private initConnection;
private initWebsocket;
/**
* 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 (client.getRemoteTracks()[trackId]?.simulcastConfig?.enabled) {
* client.setTargetTrackEncoding(trackId, encoding);
* }
*/
getRemoteTracks(): Readonly<Record<string, TrackContext<PeerMetadata, TrackMetadata>>>;
/**
* Returns a snapshot of currently received remote endpoints.
*/
getRemoteEndpoints(): Record<string, Endpoint<PeerMetadata, TrackMetadata>>;
/**
* Returns a snapshot of currently received remote peers.
*/
getRemotePeers(): Record<string, Peer<PeerMetadata, TrackMetadata>>;
getRemoteComponents(): Record<string, Component<PeerMetadata, TrackMetadata>>;
getLocalEndpoint(): Endpoint<PeerMetadata, TrackMetadata> | null;
getBandwidthEstimation(): bigint;
private setupCallbacks;
/**
* Register a callback to be called when the event is emitted.
* Full list of callbacks can be found here {@link MessageEvents}.
*
* @example
* ```ts
* const callback = ()=>{ };
*
* client.on("onJoinSuccess", callback);
* ```
*
* @param event - Event name from {@link MessageEvents}
* @param listener - Callback function to be called when the event is emitted
* @returns This
*/
on<E extends keyof MessageEvents<PeerMetadata, TrackMetadata>>(event: E, listener: Required<MessageEvents<PeerMetadata, TrackMetadata>>[E]): this;
/**
* Remove a callback from the list of callbacks to be called when the event is emitted.
*
* @example
* ```ts
* const callback = ()=>{ };
*
* client.on("onJoinSuccess", callback);
*
* client.off("onJoinSuccess", callback);
* ```
*
* @param event - Event name from {@link MessageEvents}
* @param listener - Reference to function to be removed from called callbacks
* @returns This
*/
off<E extends keyof MessageEvents<PeerMetadata, TrackMetadata>>(event: E, listener: Required<MessageEvents<PeerMetadata, TrackMetadata>>[E]): this;
private handleWebRTCNotInitialized;
/**
* Adds track that will be sent to the RTC Engine.
*
* @example
* ```ts
* const localStream: MediaStream = new MediaStream();
* try {
* const localAudioStream = await navigator.mediaDevices.getUserMedia(
* { audio: true }
* );
* localAudioStream
* .getTracks()
* .forEach((track) => localStream.addTrack(track));
* } catch (error) {
* console.error("Couldn't get microphone permission:", error);
* }
*
* try {
* const localVideoStream = await navigator.mediaDevices.getUserMedia(
* { video: true }
* );
* localVideoStream
* .getTracks()
* .forEach((track) => localStream.addTrack(track));
* } catch (error) {
* console.error("Couldn't get camera permission:", error);
* }
*
* localStream
* .getTracks()
* .forEach((track) => client.addTrack(track, localStream));
* ```
*
* @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 peers will receive in
* {@link MessageEvents.peerJoined}. E.g. this can source of the track - wheather 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 | 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 JellyfishClient.setTrackBandwidth}.
* @returns {string} Returns id of added track
*/
addTrack(track: MediaStreamTrack, stream: MediaStream, trackMetadata?: TrackMetadata, simulcastConfig?: SimulcastConfig, maxBandwidth?: TrackBandwidthLimit): Promise<string>;
/**
* Replaces a track that is being sent to the RTC Engine.
*
* @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);
* })
* ```
*
* @param {string} trackId - Id of audio or video track to replace.
* @param {MediaStreamTrack} newTrack - New audio or video track.
* @param {TrackMetadata} [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
*/
replaceTrack(trackId: string, newTrack: MediaStreamTrack, newTrackMetadata?: TrackMetadata): Promise<void>;
/**
* 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 being sent to the RTC Engine.
*
* @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)
* ```
*
* @param {string} trackId - Id of audio or video track to remove.
*/
removeTrack(trackId: string): Promise<void>;
/**
* Sets track encoding that server should send to the client library.
*
* The encoding will be sent whenever it is available. If chosen encoding is temporarily unavailable, some other
* encoding will be sent until chosen encoding becomes active again.
*
* @example
* ```ts
* webrtc.setTargetTrackEncoding(incomingTrackCtx.trackId, "l")
* ```
*
* @param {string} trackId - Id of track
* @param {TrackEncoding} encoding - Encoding to receive
*/
setTargetTrackEncoding(trackId: string, encoding: TrackEncoding): void;
/**
* Enables track encoding so that it will be sent to the server.
*
* @example
* ```ts
* const trackId = webrtc.addTrack(track, stream, {}, {enabled: true, active_encodings: ["l", "m", "h"]});
* webrtc.disableTrackEncoding(trackId, "l");
* // wait some time
* webrtc.enableTrackEncoding(trackId, "l");
* ```
*
* @param {string} trackId - Id of track
* @param {TrackEncoding} encoding - Encoding that will be enabled
*/
enableTrackEncoding(trackId: string, encoding: TrackEncoding): void;
/**
* Disables track encoding so that it will be no longer sent to the server.
*
* @example
* ```ts
* const trackId = webrtc.addTrack(track, stream, {}, {enabled: true, active_encodings: ["l", "m", "h"]});
* webrtc.disableTrackEncoding(trackId, "l");
* ```
*
* @param {string} trackId - Id of track
* @param {rackEncoding} encoding - Encoding that will be disabled
*/
disableTrackEncoding(trackId: string, encoding: TrackEncoding): void;
/**
* Updates the metadata for the current peer.
*
* @param peerMetadata - Data about this peer that other peers will receive upon joining.
*
* If the metadata is different from what is already tracked in the room, the event {@link MessageEvents.peerUpdated} will
* be emitted for other peers in the room.
*/
updatePeerMetadata: (peerMetadata: PeerMetadata) => 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 peers will receive upon joining.
*
* If the metadata is different from what is already tracked in the room, the event {@link MessageEvents.trackUpdated} will
* be emitted for other peers in the room.
*/
updateTrackMetadata: (trackId: string, trackMetadata: TrackMetadata) => void;
/**
* Leaves the room. This function should be called when user leaves 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 peer will be notified that peer left in {@link MessageEvents.peerLeft},
*/
leave: () => void;
private isOpen;
/**
* Disconnect from the room, and close the websocket connection. Tries to leave the room gracefully, but if it fails,
* it will close the websocket anyway.
*
* @example
* ```typescript
* const client = new JellyfishClient<PeerMetadata, TrackMetadata>();
*
* client.connect({ ... });
*
* client.disconnect();
* ```
*/
disconnect(): void;
}
export {};
//# sourceMappingURL=JellyfishClient.d.ts.map