Participant Class Events - iOS
- Participant events are delivered to a
ParticipantEventListener. Add your listener to each participant withaddEventListener(), for example inonParticipantJoined(), and toroom.localParticipantfor your own streams. - Every callback has an empty default implementation, so implement only the ones you need. Callbacks run on the main thread.
extension RoomViewController: RoomEventListener {
func onParticipantJoined(_ participant: Participant) {
participant.addEventListener(self)
}
}
extension RoomViewController: ParticipantEventListener {
func onStreamEnabled(_ stream: RTCStream, forParticipant participant: Participant) {
// a stream of the participant is now available
}
}
onStreamEnabled
onStreamEnabledis a callback which gets triggered whenever a participant's video, audio or screen share stream is enabled.- It is also triggered for your own streams, on the local participant. For a remote participant, it is triggered only for the streams that this device receives.
Event callback parameters
- stream: RTCStream - use
stream.kindto tellaudio,videoandsharestreams apart. - participant:
Participant- the participant the stream belongs to.
Example
func onStreamEnabled(_ stream: RTCStream, forParticipant participant: Participant) {
switch stream.kind {
case .video:
// participantVideoView is your RTCMTLVideoView
if let videoTrack = stream.track as? RTCVideoTrack {
videoTrack.add(participantVideoView)
}
case .audio:
print("\(participant.displayName) turned on their mic")
case .share:
print("\(participant.displayName) started sharing their screen")
@unknown default:
break
}
}
onStreamDisabled
onStreamDisabledis a callback which gets triggered whenever a participant's video, audio or screen share stream is disabled.
Event callback parameters
- stream: RTCStream - the stream that was disabled.
- participant:
Participant- the participant the stream belongs to.
Example
func onStreamDisabled(_ stream: RTCStream, forParticipant participant: Participant) {
if stream.kind == .video, let videoTrack = stream.track as? RTCVideoTrack {
videoTrack.remove(participantVideoView)
}
}
onStreamPaused
onStreamPausedis a callback which gets triggered when this device stops receiving one of the participant's streams because the server paused it, for example after you callenableAdaptiveSubscription()on the room. To know more, see the Scalability Guide.- The callback does not include the participant. It is delivered to the listeners added to the participant whose stream was paused.
Event callback parameters
- kind:
StreamKind?-.AUDIO,.VIDEOor.SHARE;nilfor screen-share audio. - reason:
String- why the stream was paused, for examplemutedorleastDominancewith adaptive subscription. It can be empty.
Example
func onStreamPaused(kind: StreamKind?, reason: String) {
print("\(String(describing: kind)) stream paused: \(reason)")
}
onStreamResumed
onStreamResumedis a callback which gets triggered when a paused stream of the participant is received again.- Like
onStreamPaused, it is delivered to the listeners added to that participant.
Event callback parameters
- kind:
StreamKind?-.AUDIO,.VIDEOor.SHARE;nilfor screen-share audio. - reason:
String- why the stream was resumed, for exampleadaptiveSubscriptionsDisabledornetworkStablewith adaptive subscription. It can be empty.
Example
func onStreamResumed(kind: StreamKind?, reason: String) {
print("\(String(describing: kind)) stream resumed: \(reason)")
}
onE2EEStateChanged
onE2EEStateChangedis a callback which gets triggered when the end-to-end encryption state of one of the participant's streams changes.- It reports a success state when encryption or decryption of the stream starts. Decryption failures are not reported, so a wrong or removed key raises no event.
Event callback parameters
- participant:
Participant- the participant whose stream changed. - state:
E2EEState.EncryptionSuccess: encryption of the stream started..DecryptionSuccess: decryption of the stream started..EncryptionFailed: encryption failed..DecryptionFailed: not reported..InternalError: an unexpected encryption error.
- stream:
RTCStream- the stream whose state changed.
Example
func onE2EEStateChanged(forParticipant participant: Participant, state: E2EEState, _ stream: RTCStream) {
print("\(participant.id) \(stream.kind.rawValue): \(state.rawValue)")
}
onAgentStateChanged
onAgentStateChangedis a callback which gets triggered when an AI agent moves between idle, listening, thinking and speaking.- It is triggered on agent participants, the ones whose
isAgent()returnstrue. Add your listener to the agent.
Event callback parameters
- state:
AgentState-.IDLE,.LISTENING,.THINKINGor.SPEAKING. - participant:
Participant- the agent.
Example
func onAgentStateChanged(_ state: AgentState, forParticipant participant: Participant) {
print("\(participant.displayName) is \(state.rawValue)")
}
onAgentTranscriptionReceived
onAgentTranscriptionReceivedis a callback which gets triggered for each transcript segment of the conversation with an AI agent.- It is triggered on every agent participant in the room. Add your listener to the agent, and read
participantto see who spoke.
Event callback parameters
- segment:
TranscriptionSegment-text(String) is the transcribed text, andtimestamp(Int) is when the agent created the segment, in epoch milliseconds. It is0when the agent sent no time, or one that cannot be read. - participant:
Participant?- the participant who spoke. It can be you or the agent. It isnilwhen the SDK can't find that participant.
Example
func onAgentTranscriptionReceived(_ segment: TranscriptionSegment, forParticipant participant: Participant?) {
print("\(participant?.displayName ?? "Unknown"): \(segment.text)")
}
onAgentMetrics
onAgentMetricsis a callback which gets triggered on an agent participant after each turn of the conversation, with metrics and speech data for that turn.
Event callback parameters
- metrics:
[String: Any]- containslatencyandspeech. The first turn also containsprovidersandsystemInstructions. A key can be missing, so read each value as an optional. - participant:
Participant- the agent.
Example
func onAgentMetrics(_ metrics: [String: Any], forParticipant participant: Participant) {
if let latency = metrics["latency"] {
print("Latency: \(latency)")
}
}
Got a Question? Ask us on discord

