Call & Participant State

Video Call State

When you join a call, we’ll automatically expose observable objects in 3 different places:

let clientState = streamVideo.state
let callState = call.state
let participants = call.state.participants

Call State

The call state is kept in sync (updates are received) only when you join the call.

Here’s an example of how you can access the call state:

let call = streamVideo.call(callType: "default", callId: "mycall")
let joinResult = try await call.join(create: true)
// state is now available at
let state = call.state

The following fields are available on the call:

AttributeDescription
participantsFor calls with less than 250 participants, the property contains all participants. For calls with more than 250 participants, the property contains the first 250 participants.
participantsMapA dictionary mapping participant IDs to CallParticipant objects.
localParticipantThe current user’s participant object.
remoteParticipantsList of participants other than the current user.
activeSpeakersList of participants who are actively speaking.
dominantSpeakerThe participant recognized as the dominant speaker.
membersThe list of call members.
screenSharingSessionInformation about the active screen sharing session, if any.
recordingStateThe current recording state of the call.
blockedUserIdsA set of user IDs that are blocked in the call.
settingsThe call settings fetched from the backend.
ownCapabilitiesThe capabilities the current user has in the call.
capabilitiesByRoleA map of role to allowed capabilities.
backstageIndicates whether the call is in backstage mode.
broadcastingWhether the call is broadcasting (e.g., via RTMP or HLS).
createdAtThe date when the call was created.
updatedAtThe date when the call was last updated.
startsAtThe scheduled start time of the call, if any.
startedAtThe actual time the call started.
endedAtThe time when the call ended.
endedByThe user who ended the call.
customCustom data associated with the call.
teamTeam restriction on the call, if any.
createdByThe user who created the call.
ingressRTMP ingress configuration if active.
permissionRequestsList of pending permission requests.
transcribingIndicates if transcriptions are active.
captioningIndicates if closed captions are active.
egressInformation about egress (recording, broadcasting) of the call.
sessionThe session information for the ongoing call.
reconnectionStatusThe current reconnection status of the call.
anonymousParticipantCountNumber of anonymous participants.
participantCountTotal number of participants (connected and anonymous).
isInitializedIndicates whether the call has been initialized.
callSettingsThe call settings currently active.
isCurrentUserScreensharingIndicates if the current user is sharing their screen.
durationDuration of the current session in seconds.
statsReportPeriodic stats report updated at regular intervals.
closedCaptionsList of active closed caption entries.
statsCollectionIntervalInterval at which call stats are collected, in seconds.
incomingVideoQualitySettingsIncoming video policy applied for the session.
disconnectionErrorError describing the reason for a disconnection, if any.

Participant State

The CallParticipant 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 tracks, availabilities of audio & video, the screen sharing session, reactions, and etc. Here’s how you can subscribe to participants updates:

// all participants
let cancellable = call.state.$participants.sink { participants in
    // ..
}

Filtering of the participants is also supported. You can get all the participants with the role “host”, with the following code:

var hosts: [CallParticipant] {
    call.state.participants.filter { $0.roles.contains("host") }
}

When you join a call with many participants, maximum of 250 participants are returned in the join response. The list of participants is updated dynamically when there are join call events.

The participants that are publishing video, audio or screensharing are prioritized over the other participants in the list.

The total number of participants is updated realtime via health check events. This value is available from the call state’s participantCount property.

You can get the current user with the following code:

let localParticipant: CallParticipant? = call.state.localParticipant

The following fields are available on the participant:

AttributeDescription
userThe User object for the participant.
idThe unique call id of the participant.
rolesThe user’s roles in the call.
trackLookupPrefixThe id of the track that’s connected to the participant.
hasVideoReturns whether the participant has video.
hasAudioReturns whether the participant has audio.
isScreensharingReturns whether the participant is screen sharing.
trackReturns the participant’s video track.
trackSizeReturns the size of the track for the participant.
screenshareTrackReturns the screensharing track for the participant.
showTrackReturns whether the track should be shown.
isSpeakingReturns whether the participant is speaking.
isDominantSpeakerReturns whether the participant is a dominant speaker.
sessionIdReturns the session id of the participant.
connectionQualityThe participant’s connection quality.
joinedAtReturns the date when the user joined the call.
audioLevelThe audio level for the user.
audioLevelsA list of the last 10 audio levels. Convenient for audio visualizations.
pinHolds pinning information.
isPinnedReturns whether the user is pinned.
pausedTracksThe set of media track types currently paused for this participant.

Participants Sorting

If you want to change the default sorting of the participants, you can use the Call object’s method updateParticipantsSorting.

Here’s an example that will sort participants alphabetically, by their name:

let nameComparator: StreamSortComparator<CallParticipant> = {
    comparison($0, $1, keyPath: \.name)
}
let call = streamVideo.call(callType: callType, callId: callId)
call.updateParticipantsSorting(with: [nameComparator])

Client State

// client state is available on the client object
let state = streamVideo.state

And contains these fields:

AttributeDescription
userThe user you’re currently authenticated as.
connectionThe connection state. See ConnectionState.
activeCallThe call you’ve currently joined.
ringingCallContains the call if you’re calling someone or someone is calling you.
© Getstream.io, Inc. All Rights Reserved.