Skip to main content

Room and Events

We've made it much easier to add video capability to your web application using our Javascript SDK. The Room object and the Events that occur in a Room is the API you will use to build your video application. We've extensively documented the interface for the Room and Events objects, below.

Room

export type Room = Immutable<{
/// The unique identifier of the Room instance
id: string;

/// Event listener/handler for various events that are triggered in the room.
/// See the Events interface for a list.
on<E extends keyof Events>(event: E, callback: Events[E]): Unsubscribe;

/// Connects a Room instance to the server
/// The state of the room, specifically the status of the room, will change while it's connecting,
/// if you can listen to these changes with the state_changed event.
/// Once the room is connected its local partipant will available in State.
connect: () => Promise<void>;

/// Disconnect a Room instance from the server
/// The status of the state of the room will change while it's disconnecting.
disconnect: () => Promise<void>;

/// Updates the client token
/// The client token is a short lived access token that expires after a time to live in seconds,
/// which needs to be refreshed using a refresh token.
/// If you are farmilar with how JWT's work you'll understand, head here for [more details](https://jwt.io)
/// This was set when the client token was created - the default TTL is 600 seconds or 10 minutes.
///
/// Client tokens need to refreshed before they expire otherise the Room instance will automatically
/// disconnect.
/// It's up to the developer to keep the client token fresh.
/// To create a client token please use the `generate_join_client_token` endpoint
/// To refresh a token please use `refresh_client_token` endpoint
updateClientToken: (clientToken: string) => Promise<void>;

/// Gets the state of the Room
/// What does the state of the room look like?
/*
type Status =
| 'initialized'
| 'connecting'
| 'connected'
| 'disconnecting'
| 'disconnected';

interface State {
status: Status;
localParticipantId: Participant['id'];
participants: {
[id: string]: Participant;
};
streams: {
[id: string]: Stream;
};
}
*/

/// State is important because there can be lot of things changing in a room at any given moment, especially for really large rooms.
/// Participants leaving the room, new participants joining, other starting/stopping their video, a moderator kicking
/// a participant out.
/// It would be a lot to keep track of manually, which is why we have state.
/// Don't worry we've abstracted all the accounting, inside our SDK, and provided you with helper methods
/// like this one, getParticipant(), and getLocalStreams() to make access simple.
getState: () => State;


/// Participants and Streams
/// There's a two entities that are important to understand
/// and as you can see from the State interface above they are big
/// part of the State of the Room.
///
/// Stream
/// A stream represents media stream published by Participant in a Room.
/// It's identified by it's participantId and streamKey and typically has a audio track or a video
/// track, or both.


/// Participants
/// There are two type of participants: local and remote.
/// Remote Participant - other participants in the room who are not the local participant.
/// A local partipant subscribes to streams published by remote participants.
///
/// Local Participant - is the person on a mobile device or desktop that joins the room to publish a stream.
/// **NOTE**: There can only be one local participant in a room at a given time.


/// Gets the local participant for a given Room instance
/// You can use this method to find more details about the local participant in the Room
///
/// What does a Participant look like?
/*
export type Participant = Immutable<{
id: string;
context?: string;
streams: {
[key: string]: Stream['id'];
};
canReceiveMessages: boolean;
origin: 'local' | 'remote' | 'telephony_engine';
}>;
*/
getLocalParticipant: () => Participant;


/// Get the streams associated to the local participant
getLocalStreams: () => { [key: Stream['key']]: Stream };

/// Add a stream to a Room
/// key - is the unique identifier for the stream based on its realted participant.
/// tracks.audio - the audio track
/// tracks.video - the video track
/// Once the promise is completed you can assume that the stream has started publishing in the room.
addStream: (
key: Stream['key'],
tracks?: {
audio?: MediaStreamTrack;
video?:
| MediaStreamTrack
| { track?: MediaStreamTrack; options?: { enableSimulcast?: boolean } };
}
) => Promise<void>;

/// Update an existing stream in a Room
/// key - identifier of the stream
/// tracks.audio - the audio track
/// tracks.video - the video track
///
/// Why would you update a Stream?
/// If you wanted to mute the audio of a particular stream you would update
/// it and set the track to null
updateStream: (
key: Stream['key'],
tracks?: {
audio?: MediaStreamTrack;
video?:
| MediaStreamTrack
| { track?: MediaStreamTrack; options?: { enableSimulcast?: boolean } };
}
) => Promise<void>;

/// Remove a stream
/// key - identifier of the stream
/// Removing a stream removes or unpublishes it from the room.
removeStream: (key: string) => Promise<void>;


/// Subscriptions
/// A subscription is used to subscribed to a stream published by a Remote Participant


/// Subscribe to a stream belonging to a remote participant
/// participantId - the id of the remote participant
/// key - the stream key of the stream
/// config.audio - flag to indicate if you'd like to subscribe to the remote streams' audio
// config.video - flag to indicate if you'd like to subscribe to the remote streams' video
/// When the promise is fullfilled a remote stream is added to state.streams
/// which then can be used to render the audio or video of that stream.
/// You can access remote participant streams more easily using the getParticipantsStreams
// and getParticipantStreams helper methods below.
///
/// A developer is not required to subscribe to every remote stream being published in the room instead
/// they can choose. This is very useful in situations conserving bandwidth and cpu resources is a priority,
/// For example:
/// A developer building a vidoe conferencing application and wants to support 100+ participants may only want subscribe
/// to 15-20 participants at a time display each set in a seperate page, thus significantly saving bandwith and resources.
addSubscription: (
participantId: Participant['id'],
key: Stream['key'],
config: { audio: boolean; video: boolean }
) => Promise<void>;


/// Update an existing subscription
/// participantId - the id of the remote participant
/// key - the stream key of the stream
/// config.audio - flag to indicate if you'd like to subscribe to the remote streams' audio
// config.video - flag to indicate if you'd like to subscribe to the remote streams' video
/// When a remote participant toggles audio or video on a stream that you're subscribed to
/// you'll need to update that subscription.
updateSubscription: (
participantId: Participant['id'],
key: Stream['key'],
config: { audio: boolean; video: boolean }
) => Promise<void>;

/// Remove or stop subscribing to a remote participant's stream
removeSubscription: (
participantId: Participant['id'],
key: Stream['key']
) => Promise<void>;

/// Helper method to easily access all streams for a given remote participant
getParticipantStreams: (
participantId: Participant['id']
) => Map<Stream['key'], Stream>;

/// Helper method to easily access a remote participant stream
getParticipantStream: (
participantId: Participant['id'],
key: Stream['key']
) => Stream | undefined;

/// Provides statistics for a local or remote stream
/// It presents the same data you'd get from doing:
/// RTCRtpSender.getStats() - https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpSender/getStats
/// RTCRtpReceiver.getStats() - https://developer.mozilla.org/en-US/docs/Web/API/RTCRtpReceiver/getStats
/// using the standard WebRTC APIs but in a much more readable format.
getWebRTCStatsForStream: (
participantId: Participant['id'],
key: Stream['key']
) => Promise<WebRTCStats>;

/// Send a message to one, more than one, or all participants in the room
/// message - a message type, current only 'text' is supported
/// receipients? - an array of participants to send the message, if
/// null the message is broadcasted to everyone in the room.
sendMessage: (
message: Message,
recipients?: Array<Participant['id']>
) => Promise<void>;


enableNetworkMetricsReport: (
participantIds: Array<Participant['id']>,
options?: { includeStreams?: boolean }
) => Promise<void>;

disableNetworkMetricsReport: (
participantIds?: Array<Participant['id']>
) => Promise<void>;
}>;

Room events

export interface Events {
/// Triggered when the state of the room changes
/// For more
/// TODO
state_changed: (state: State) => void;

/// Triggers on a Room instance when it connects to the server
connected: (state: State) => void;

/// Triggers on a Room instance when it disconnects from the server
disconnected: (state: State) => void;

/// Triggered when a remote participant joins the room
/// Only triggered for remote participants the local participant does not
/// need to be notified that they've joined the room since they've initiated
/// that action themselves by connecting to the Room
participant_joined: (participant: Participant['id'], state: State) => void;


/// Triggered when a participant is leaving the room because they were kicked
/// due to a moderator event
/// Unlike the joined and left events the local participant can be kicked from the room
participant_leaving: (
participant: Participant['id'],
reason: 'kicked' | null,
state: State
) => void;

/// Triggered when a remote participant leaves the room
participant_left: (participantId: Participant['id'], state: State) => void;

/// Triggered after successfully adding or publishing a stream to the room
/// This event is triggered for local and remote streams.
/// A local stream is one that's published by the local participant in the Room
/// A remote stream is one that's published by a remote participant in the Room
stream_published: (
participantId: Participant['id'],
key: Stream['key'],
state: State
) => void;

/// Triggered after successfully unregistering a stream
/// This event is triggered for both local and remote streams.
/// It triggered when the local or remote participant remove or stops publishing a stream.
/// When a remote participant leaves a room it will trigger for any of their related streams.
stream_unpublished: (
participantId: Participant['id'],
key: Stream['key'],
state: State
) => void;

/// Triggered when a local stream or a remote stream track has been enabled.
/// Notifies consumers about remote stream tracks being enabled.
/// For example: when audio is unmuted or video has started on a remote stream.
track_enabled: (
participantId: Participant['id'],
key: Stream['key'],
kind: 'audio' | 'video',
state: State
) => void;

/// The oposite of track_enabled
/// Triggers when a local stream or a remote stream track has been disabled.
/// Notifies consumers about remote stream tracks being disabled.
/// For example: when audio is muted or video has stopped on a remote stream.
track_disabled: (
participantId: Participant['id'],
key: Stream['key'],
kind: 'audio' | 'video',
state: State
) => void;

/// Triggered when a track is censored due to a moderator event
/// Like the kick moderator event in participant_leaving, both local and remote streams can be
/// censored.
///
/// Since a Stream consists of an audio and video track, either can be censored by a moderator
/// If the audio or video track on given stream is null, effectively nothing happens.
track_censored: (
participantId: Participant['id'],
key: Stream['key'],
kind: 'audio' | 'video',
state: State
) => void;

/// Triggered when a track is uncensored due to a moderator event
/// Opposite of track_censored
/// Naturally, a track must be censored to order be uncensored.
track_uncensored: (
participantId: Participant['id'],
key: Stream['key'],
kind: 'audio' | 'video',
state: State
) => void;

/// Triggered when there is audio activity from a particular stream or participant talking in the Room
/// When there's audio activity when a participant speaking this event will trigger with the participant id that's talking and the stream key will be null
audio_activity: (
participantId: Participant['id'],
key: Stream['key'] | null,
state: State
) => void;

/// Triggered a subscription to a remote stream is started
subscription_started: (
participantId: Participant['id'],
key: Stream['key'],
state: State
) => void;

/// Triggered when the subscription is reconfigured using the updateSubscription method
subscription_reconfigured: (
participantId: Participant['id'],
key: Stream['key'],
state: State
) => void;

/// Triggered when subscription is removed or ended for a remote stream
/// A subscription can be ended by calling `removeSubscription(ParticipantId,StreamKey)`
/// This is also triggered when a remote participant leaves the room.
subscription_ended: (
participantId: Participant['id'],
key: Stream['key'],
state: State
) => void;

/// onMessageReceived
/// Triggered when a new message is recieved either by one or more participants or broadcasted to all participants
/// in the room.
/// participantId - sender of the message
/// recipients - an array of participants the message was sent to. when null the message was broadcasted to the all participants in the room.
message_received: (
participantId: Participant['id'], // the participant that sent the message
message: Message,
recipients: Array<Participant['id']> | null,
state: State
) => void;

network_metrics_report: (networkMetrics: NetworkMetrics) => void;
}

On this page