Skip to main content

Working with Individual Participants

Each remote participant in a RealtimeKit meeting is represented by an RtkRemoteParticipant instance that provides access to their properties, media states, and participant-specific controls.

The RtkRemoteParticipant object provides the following properties:

  • id: Session-specific identifier generated when the participant joins meeting session (also known as peerId). A single user joining from multiple devices or tabs will have different id values for each connection.
  • userId: Permanent identifier of the participant generated when adding the participant to a meeting. This remains unchanged across multiple connections, sessions, or devices.
  • name: Display name of the participant
  • picture: String URL to the participant's display picture (if any).
  • isHost: Boolean value whether this participant has host privileges
  • customParticipantId: Custom identifier that can be set while adding participant to a meeting by customer
  • videoEnabled: Whether the participant's camera is currently enabled
  • audioEnabled: Whether the participant's microphone is currently unmuted
  • screenshareEnabled:
  • stageStatus: Indicates the participant's current stage status (applicable only in stage-enabled meetings)
  • isPinned: Whether this participant is currently pinned in the meeting
  • presetName: Name of the preset applied to this participant while adding to meeting
// Example: Access participant properties
final participant = meeting.participants.joined[0];

print('Participant: ${participant.name} (ID: ${participant.id})');
print('Audio: ${participant.audioEnabled ? "On" : "Off"}');
print('Video: ${participant.videoEnabled ? "On" : "Off"}');

Finding Specific Participants

You can search for specific participants using standard Dart list operations:

// Find a participant by peer ID
final participant = meeting.participants.joined
.where((p) => p.id == "<peerId>")
.firstOrNull;

Displaying Participant Video

To display a participant's video stream in your UI, use the video view methods which return a Widget that you can place directly in your UI hierarchy.

// Create a widget to display the participant's camera video
final cameraView = VideoView(meetingParticipant: participant);

// Create a widget to display the participant's screen share
final screenShareView = ScreenshareView(meetingParticipant: participant);

Host Controls

If your local user has the necessary host permissions, you can perform the following actions on individual remote participants:

Disabling Media

// Disable a remote participant's video
participant.disableVideo(onResult: (e) {
// handle error if any
});

// Disable a remote participant's audio
participant.disableAudio(onResult: (e) {
// handle error if any
});

Removing Participant

// Remove the participant from the meeting
participant.kick();

Required Permission: permissions.host.canDisableVideo, permissions.host.canDisableAudio must be true

Pin-Unpin Participant

// Pin a remote participant
participant.pin();

// Unpin a previously pinned participant
participant.unpin();

Required Permission: permissions.host.canPinParticipant must be true

For operations that affect all participants at once, see the Participants Host Controls documentation.

Individual Participant Events

To receive updates about a specific participant's state changes, implement the RtkParticipantUpdateListener interface and add the listener on that participant using participant.addParticipantEventsListener(). Available event callbacks:

  • onAudioUpdate: Called when the participant's audio state changes
  • onVideoUpdate: Called when the participant's video state changes
  • onPinned: Called when the participant is pinned
  • onUnpinned: Called when the participant is unpinned
  • onScreenShareUpdate: Called when the participant's screen sharing state changes
  • onUpdate: Called whenever any property of the participant changes
// Create a listener class
class ParticipantUpdateHandler extends RtkParticipantUpdateListener {

void onVideoUpdate(RtkRemoteParticipant participant, bool isEnabled) {
print("${participant.name}'s video is now ${isEnabled ? 'on' : 'off'}");
}


void onAudioUpdate(RtkRemoteParticipant participant, bool isEnabled) {
print("${participant.name}'s audio is now ${isEnabled ? 'on' : 'off'}");
}


void onPinned(RtkRemoteParticipant participant) {
print("${participant.name} was pinned");
}


void onUnpinned(RtkRemoteParticipant participant) {
print("${participant.name} was unpinned");
}


void onScreenShareUpdate(RtkRemoteParticipant participant, bool isEnabled) {
print("${participant.name}'s screen-share is now ${isEnabled ? 'on' : 'off'}");
}


void onUpdate(RtkRemoteParticipant participant) {
print("${participant.name} was updated");
}
}

// Register the listener with a specific participant
final listener = ParticipantUpdateHandler();
participant.addParticipantUpdateListener(listener);

// When you're done listening to events, remove the listener
participant.removeParticipantUpdateListener(listener);

For events that apply to all participants collectively, see all Participants Events documentation.