val clientState = streamVideo.state
val callState = call.state
val participants = call.state.participantsCall & Participant State
Video Call State
When you join a call, we’ll automatically expose 3 StateFlow objects:
Call State
Here’s an example of how you can access the call state:
val call = client.call("default", "mycall")
val joinResult = call.join(create=true)
// state is now available at
val state = call.stateThe following fields are available on the call
| Attribute | Description |
|---|---|
connection | Your connection state if you’re currently connected to the call |
participants | The list of call participants |
totalParticipants | The count of the total number of participants. This includes anonymous participants |
me | Shortcut to your own participant state |
remoteParticipants | The list of call participants other than yourself |
activeSpeakers | The list of participants who are currently speaking |
dominantSpeaker | The dominant speaker |
sortedParticipants | Participants sorted using the default sorting logic |
members | The list of call members |
screenSharingSession | If someone is screensharing, it will be available here |
recording | Boolean if the call is being recorded or not |
blockedUsers | The users who are blocked from this call |
ringingState | For ringing calls we expose additional state |
settings | The settings for this call |
ownCapabilities | Which actions you have permission to do |
hasPermission | function for checking if you have a certain permission |
capabilitiesByRole | What different roles (user, admin, moderator etc.) are allowed to do |
permissionRequests | If there are active permission requests |
backstage | If a call is in backstage mode or not |
broadcasting | If a call is broadcasting (to HLS) or not |
createdAt | When the call was created |
updatedAt | When the call was updated |
startsAt | When the call is scheduled to start |
endedAt | When the call ended |
endedByUser | User who ended the call |
custom | Custom data on the call |
team | Team that the call is restricted to. Default to null. |
createdBy | Who created the call |
ingress | If there is an active ingress session to this call. IE if you’re sending RTMP into the call |
reactions | List of reactions this call received |
errors | Any errors we’ve encountered during this call |
isCaptioning | Tracks whether closed captioning is currently active for the call. |
closedCaptions | Holds the current list of closed captions. This list is updated dynamically and contains at most ClosedCaptionsSettings.maxVisibleCaptions captions. |
ccMode | Holds the current closed caption mode for the video call. This object contains information about closed captioning feature availability. Possible values: - ClosedCaptionMode.Available - ClosedCaptionMode.Disabled - ClosedCaptionMode.AutoOn - ClosedCaptionMode.Unknown |
Participant State
The ParticipantsState is the most essential component used to render a participant in a call. It contains all of the information to render a participant, such as audio & video renderers, availabilities of audio & video, the screen sharing session, reactions, and etc. Here’s how you iterate over the participants:
// all participants
val participants: StateFlow<List<ParticipantState>> = call.state.participants
coroutineScope.launch {
participants.collectLatest { participants ->
// ..
}
}
// all participants in Jetpack Compose
val participants: List<ParticipantState> by call.state.participants.collectAsState()
participants.forEach { participantState ->
// ..
}
// you
val me: StateFlow<ParticipantState?> = call.state.meIn Jetpack Compose, you can observe the ParticipantsState and render videos like the example below:
// all participants
val participants by call.state.participants.collectAsState()
LazyColumn {
items(items = participants, key = { it.sessionId }) { participant ->
ParticipantVideo(call = call, participant = participant)
}
}
// you
val me by call.state.me.collectAsState()
ParticipantVideo(
call = call,
participant = me
)The following fields are available on the participant
| Attribute | Description |
|---|---|
user | The user object for this participant |
video | The video object for this participant |
audio | The participant’s audio object |
screenSharing | The screensharing object |
joinedAt | When this participant joined |
audioLevel | How loudly this user is talking. Float |
audioLevels | A list of the last 10 audio levels. Convenient for audio visualizations |
speaking | If the user is speaking |
connectionQuality | The participant’s connection quality |
dominantSpeaker | If this participant is the dominant speaker or not |
lastSpeakingAt | When this user last spoke (used for sorting in some apps) |
Participants Sorting
If you want to change the default sorting of the participants, you can use the Call.state object’s method updateParticipantSortingOrder.
Here’s an example that will sort participants alphabetically, by their name:
call.state.updateParticipantSortingOrder(
compareByDescending {
it.name.value
},
)Detecting participant source
Participants can be created from different sources (WebRTC, RTMP/OBS, WHIP, SIP, etc…).
The source property of the ParticipantState object indicates the source of the participant.
val participants = call.state.participants.value
// participants joining through OBS have RTMP source
val rtmpParticipants = participants.filter {
it.source == ParticipantSource.PARTICIPANT_SOURCE_RTMP
}Client State
// client state is available on the client object
val state = client.stateAnd contains these fields:
| Attribute | Description |
|---|---|
user | The user you’re currently authenticated as |
connection | The connection state. See ConnectionState |
activeCall | The call you’ve currently joined |
ringingCall | Contains the call if you’re calling someone or someone is calling you |
callConfigRegistry | A registry for managing call configurations related to different call types like default, livestream, audio, etc. |