INTEGRITY Documentation

Manage Participants in a Session

Use RealtimeKit host controls to manage other participants in a live session. You can mute audio or video, pin a participant, or remove participants from the session. These actions require specific host control permissions enabled in the local participant's Preset. Before you show UI controls or call these methods, verify that the local participant has the necessary permissions. In this guide, the local participant refers to the user performing the actions.

Select a remote participant

To perform actions on a specific participant, you first need to retrieve their participant object. Remote participants (other participants) are available in meeting.participants. The local participant is available in meeting.self. Refer to Meeting Object Explained for details.

const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
	// No remote participants are currently joined.
}

To perform actions on a specific participant, you first need to retrieve their participant object. Remote participants (other participants) are available in meeting.participants. The local participant is available in meeting.self. Refer to Meeting Object Explained for details.

const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
	// No remote participants are currently joined.
}

To perform actions on a specific participant, you first need to retrieve their participant object. Remote participants (other participants) are available in meeting.participants. The local participant is available in meeting.self. Refer to Meeting Object Explained for details.

const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
	// No remote participants are currently joined.
}

To perform actions on a specific participant, retrieve their participant object from the participants property. Remote participants are available in meeting.participants.joined. The local participant is available in meeting.localUser.

val joinedParticipants = meeting.participants.joined
val participant = joinedParticipants.firstOrNull()
if (participant == null) {
	// No remote participants are currently joined.
}

To perform actions on a specific participant, retrieve their participant object from the participants property. Remote participants are available in meeting.participants.joined. The local participant is available in meeting.localUser.

let joinedParticipants = meeting.participants.joined
guard let participant = joinedParticipants.first else {
	// No remote participants are currently joined.
	return
}

To perform actions on a specific participant, retrieve their participant object from the participants property. Remote participants are available in meeting.participants.joined. The local participant is available in meeting.self.

const joinedParticipants = meeting.participants.joined;
const participant = joinedParticipants.toArray()[0];
if (!participant) {
	// No remote participants are currently joined.
}

Or use the useRealtimeKitSelector hook:

import { useRealtimeKitSelector } from '@cloudflare/realtimekit-react-native';

const joinedParticipants = useRealtimeKitSelector((m) => m.participants.joined);

Mute audio

Mute audio of participants when you need to manage background noise, moderate a classroom or webinar, or prevent interruptions during a session. This action requires the Mute Audio (disable_participant_audio) host control permission enabled in the local participant's preset.

Mute a participant

To mute a specific participant's audio:

  1. Check that the local participant has permission to mute other participants' audio.

    const canMuteAudio =
    	meeting.self.permissions.canDisableParticipantAudio === true;
    if (!canMuteAudio) {
    	// Disable the control in your UI.
    }
  2. Call disableAudio() on the target participant.

    If the local participant does not have the required permission, disableAudio() throws a ClientError with code 1201.

    try {
    	await participant.disableAudio();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to mute other participants’ audio.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, the target participant's audioEnabled becomes false, and the SDK emits an audioUpdate event.

    Option A: Listen on the participant object

    participant.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    	// audioEnabled is false
    	// Update UI for the participant
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on(
    	"audioUpdate",
    	(participant, { audioEnabled, audioTrack }) => {
    		if (participant.id === targetParticipantId) {
    			// audioEnabled is false
    			// Update UI for the participant
    		}
    	},
    );
  1. Check that the local participant has permission to mute other participants' audio.

    const canMuteAudio =
    	meeting.self.permissions.canDisableParticipantAudio === true;
    if (!canMuteAudio) {
    	// Disable the control in your UI.
    }
  2. Call disableAudio() on the target participant.

    If the local participant does not have the required permission, disableAudio() throws a ClientError with code 1201.

    try {
    	await participant.disableAudio();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to mute other participants’ audio.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, the target participant's audioEnabled becomes false, and the SDK emits an audioUpdate event.

    Option A: Listen on the participant object

    participant.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    	// audioEnabled is false
    	// Update UI for the participant
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on(
    	"audioUpdate",
    	(participant, { audioEnabled, audioTrack }) => {
    		if (participant.id === targetParticipantId) {
    			// audioEnabled is false
    			// Update UI for the participant
    		}
    	},
    );
  1. Check that the local participant has permission to mute other participants' audio.

    const canMuteAudio =
    	meeting.self.permissions.canDisableParticipantAudio === true;
    if (!canMuteAudio) {
    	// Disable the control in your UI.
    }
  2. Call disableAudio() on the target participant.

    If the local participant does not have the required permission, disableAudio() throws a ClientError with code 1201.

    try {
    	await participant.disableAudio();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to mute other participants’ audio.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, the target participant's audioEnabled becomes false, and the SDK emits an audioUpdate event.

    Option A: Listen on the participant object

    participant.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    	// audioEnabled is false
    	// Update UI for the participant
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on(
    	"audioUpdate",
    	(participant, { audioEnabled, audioTrack }) => {
    		if (participant.id === targetParticipantId) {
    			// audioEnabled is false
    			// Update UI for the participant
    		}
    	},
    );
  1. Check that the local participant has permission to mute other participants' audio.
val canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if (!canMuteAudio) {
	// Disable the control in your UI.
}
  1. Call disableAudio() on the target participant. If the local participant does not have the required permission, disableAudio() returns a HostError.
val error = participant.disableAudio()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's audioEnabled becomes false.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// audioEnabled is false
		// Update UI for the participant
	}
})
  1. Check that the local participant has permission to mute other participants' audio.
let canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if !canMuteAudio {
	// Disable the control in your UI.
}
  1. Call disableAudio() on the target participant. If the local participant does not have the required permission, disableAudio() returns a HostError.
if let error = participant.disableAudio() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's audioEnabled becomes false.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// audioEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to mute other participants' audio.
const canDisableParticipantAudio = meeting.self.permissions.canDisableParticipantAudio;
if (!canDisableParticipantAudio) {
	// Disable the control in your UI.
}
  1. Call disableAudio() on the target participant.
participant
	.disableAudio()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
  1. Handle the result by listening for updates. After the call succeeds, the target participant's audioEnabled becomes false.
meeting.participants.joined.on('audioUpdate', (participant) => {
	// participant.audioEnabled is false
	// Update UI for the participant
});

Mute all participants

This affects all participants, including the local participant. To mute audio for all participants in the session:

  1. Check that the local participant has permission to mute other participants' audio.

    const canMuteAudio =
    	meeting.self.permissions.canDisableParticipantAudio === true;
    if (!canMuteAudio) {
    	// Disable the control in your UI.
    }
  2. Call disableAllAudio().

    If the local participant does not have the required permission, disableAllAudio() throws a ClientError with code 1201.

    try {
    	await meeting.participants.disableAllAudio();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to mute other participants’ audio.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, each participant’s audioEnabled becomes false, and the SDK emits an audioUpdate event. The local participant also receives audioUpdate on meeting.self.

    Listen to remote participant updates on the joined map:

    meeting.participants.joined.on(
    	"audioUpdate",
    	(participant, { audioEnabled, audioTrack }) => {
    		// audioEnabled is false
    		// Update UI for the participant
    	},
    );

    Listen to the local participant update on meeting.self:

    meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    	// audioEnabled is false
    	// Update UI for the local participant
    });
  1. Check that the local participant has permission to mute other participants' audio.

    const canMuteAudio =
    	meeting.self.permissions.canDisableParticipantAudio === true;
    if (!canMuteAudio) {
    	// Disable the control in your UI.
    }
  2. Call disableAllAudio().

    If the local participant does not have the required permission, disableAllAudio() throws a ClientError with code 1201.

    try {
    	await meeting.participants.disableAllAudio();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to mute other participants’ audio.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, each participant’s audioEnabled becomes false, and the SDK emits an audioUpdate event. The local participant also receives audioUpdate on meeting.self.

    Listen to remote participant updates on the joined map:

    meeting.participants.joined.on(
    	"audioUpdate",
    	(participant, { audioEnabled, audioTrack }) => {
    		// audioEnabled is false
    		// Update UI for the participant
    	},
    );

    Listen to the local participant update on meeting.self:

    meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    	// audioEnabled is false
    	// Update UI for the local participant
    });
  1. Check that the local participant has permission to mute other participants' audio.

    const canMuteAudio =
    	meeting.self.permissions.canDisableParticipantAudio === true;
    if (!canMuteAudio) {
    	// Disable the control in your UI.
    }
  2. Call disableAllAudio().

    If the local participant does not have the required permission, disableAllAudio() throws a ClientError with code 1201.

    try {
    	await meeting.participants.disableAllAudio();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to mute other participants’ audio.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, each participant’s audioEnabled becomes false, and the SDK emits an audioUpdate event. The local participant also receives audioUpdate on meeting.self.

    Listen to remote participant updates on the joined map:

    meeting.participants.joined.on(
    	"audioUpdate",
    	(participant, { audioEnabled, audioTrack }) => {
    		// audioEnabled is false
    		// Update UI for the participant
    	},
    );

    Listen to the local participant update on meeting.self:

    meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    	// audioEnabled is false
    	// Update UI for the local participant
    });
  1. Check that the local participant has permission to mute other participants' audio.
val canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if (!canMuteAudio) {
	// Disable the control in your UI.
}
  1. Call disableAllAudio() on the participants object. If the local participant does not have the required permission, disableAllAudio() returns a HostError.
val error = meeting.participants.disableAllAudio()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, each participant's audioEnabled becomes false.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// audioEnabled is false
		// Update UI for the participant
	}
})
  1. Check that the local participant has permission to mute other participants' audio.
let canMuteAudio = meeting.localUser.permissions.host.canMuteAudio
if !canMuteAudio {
	// Disable the control in your UI.
}
  1. Call disableAllAudio() on the participants object. If the local participant does not have the required permission, disableAllAudio() returns a HostError.
if let error = meeting.participants.disableAllAudio() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, each participant's audioEnabled becomes false.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onAudioUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// audioEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to mute other participants' audio.
const canDisableParticipantAudio = meeting.self.permissions.canDisableParticipantAudio;
if (!canDisableParticipantAudio) {
	// Disable the control in your UI.
}
  1. Call disableAllAudio() on the participants object.
meeting.participants
	.disableAllAudio(true)
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
  1. Handle the result by listening for updates. After the call succeeds, each participant's audioEnabled becomes false.
meeting.participants.joined.on('audioUpdate', (participant) => {
	// participant.audioEnabled is false
	// Update UI for the participant
});

Disable video

Disable video of participants when you need to moderate a session, enforce privacy, or prevent unwanted video during a classroom or webinar. This action requires the Mute Video (disable_participant_video) host control permission enabled in the local participant's preset.

Disable video for a participant

To disable a specific participant's video:

  1. Check that the local participant has permission to disable other participants' video.

    const canDisableVideo =
    	meeting.self.permissions.canDisableParticipantVideo === true;
    if (!canDisableVideo) {
    	// Disable the control in your UI.
    }
  2. Call disableVideo() on the target participant.

    If the local participant does not have the required permission, disableVideo() throws a ClientError with code 1201.

    try {
    	await participant.disableVideo();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to disable other participants’ video.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, the target participant's videoEnabled becomes false, and the SDK emits a videoUpdate event.

    Option A: Listen on the participant object

    participant.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    	// videoEnabled is false
    	// Update UI for the participant
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on(
    	"videoUpdate",
    	(participant, { videoEnabled, videoTrack }) => {
    		// videoEnabled is false
    		// Update UI for the participant
    	},
    );
  1. Check that the local participant has permission to disable other participants' video.

    const canDisableVideo =
    	meeting.self.permissions.canDisableParticipantVideo === true;
    if (!canDisableVideo) {
    	// Disable the control in your UI.
    }
  2. Call disableVideo() on the target participant.

    If the local participant does not have the required permission, disableVideo() throws a ClientError with code 1201.

    try {
    	await participant.disableVideo();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to disable other participants’ video.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, the target participant's videoEnabled becomes false, and the SDK emits a videoUpdate event.

    Option A: Listen on the participant object

    participant.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    	// videoEnabled is false
    	// Update UI for the participant
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on(
    	"videoUpdate",
    	(participant, { videoEnabled, videoTrack }) => {
    		// videoEnabled is false
    		// Update UI for the participant
    	},
    );
  1. Check that the local participant has permission to disable other participants' video.

    const canDisableVideo =
    	meeting.self.permissions.canDisableParticipantVideo === true;
    if (!canDisableVideo) {
    	// Disable the control in your UI.
    }
  2. Call disableVideo() on the target participant.

    If the local participant does not have the required permission, disableVideo() throws a ClientError with code 1201.

    try {
    	await participant.disableVideo();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to disable other participants’ video.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, the target participant's videoEnabled becomes false, and the SDK emits a videoUpdate event.

    Option A: Listen on the participant object

    participant.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    	// videoEnabled is false
    	// Update UI for the participant
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on(
    	"videoUpdate",
    	(participant, { videoEnabled, videoTrack }) => {
    		// videoEnabled is false
    		// Update UI for the participant
    	},
    );
  1. Check that the local participant has permission to disable other participants' video.
val canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if (!canMuteVideo) {
	// Disable the control in your UI.
}
  1. Call disableVideo() on the target participant. If the local participant does not have the required permission, disableVideo() returns a HostError.
val error = participant.disableVideo()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's videoEnabled becomes false.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// videoEnabled is false
		// Update UI for the participant
	}
})
  1. Check that the local participant has permission to disable other participants' video.
let canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if !canMuteVideo {
	// Disable the control in your UI.
}
  1. Call disableVideo() on the target participant. If the local participant does not have the required permission, disableVideo() returns a HostError.
if let error = participant.disableVideo() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's videoEnabled becomes false.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// videoEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to disable other participants' video.
const canDisableParticipantVideo = meeting.self.permissions.canDisableParticipantVideo;
if (!canDisableParticipantVideo) {
	// Disable the control in your UI.
}
  1. Call disableVideo() on the target participant.
participant
	.disableVideo()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
  1. Handle the result by listening for updates. After the call succeeds, the target participant's videoEnabled becomes false.
meeting.participants.joined.on('videoUpdate', (participant) => {
	// participant.videoEnabled is false
	// Update UI for the participant
});

Disable video for all participants

This affects all participants, including the local participant. To disable video for all participants in the session:

  1. Check that the local participant has permission to disable other participants' video.

    const canDisableVideo =
    	meeting.self.permissions.canDisableParticipantVideo === true;
    if (!canDisableVideo) {
    	// Disable the control in your UI.
    }
  2. Call disableAllVideo().

    If the local participant does not have the required permission, disableAllVideo() throws a ClientError with code 1201.

    try {
    	await meeting.participants.disableAllVideo();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to disable other participants’ video.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, each participant’s videoEnabled becomes false, and the SDK emits a videoUpdate event. The local participant also receives videoUpdate on meeting.self.

    Listen to remote participant updates on the joined map:

    meeting.participants.joined.on(
    	"videoUpdate",
    	(participant, { videoEnabled, videoTrack }) => {
    		// videoEnabled is false
    		// Update UI for the participant
    	},
    );

    Listen to local participant update on meeting.self:

    meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    	// videoEnabled is false
    	// Update UI for the local participant
    });
  1. Check that the local participant has permission to disable other participants' video.

    const canDisableVideo =
    	meeting.self.permissions.canDisableParticipantVideo === true;
    if (!canDisableVideo) {
    	// Disable the control in your UI.
    }
  2. Call disableAllVideo().

    If the local participant does not have the required permission, disableAllVideo() throws a ClientError with code 1201.

    try {
    	await meeting.participants.disableAllVideo();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to disable other participants’ video.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, each participant’s videoEnabled becomes false, and the SDK emits a videoUpdate event. The local participant also receives videoUpdate on meeting.self.

    Listen to remote participant updates on the joined map:

    meeting.participants.joined.on(
    	"videoUpdate",
    	(participant, { videoEnabled, videoTrack }) => {
    		// videoEnabled is false
    		// Update UI for the participant
    	},
    );

    Listen to local participant update on meeting.self:

    meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    	// videoEnabled is false
    	// Update UI for the local participant
    });
  1. Check that the local participant has permission to disable other participants' video.

    const canDisableVideo =
    	meeting.self.permissions.canDisableParticipantVideo === true;
    if (!canDisableVideo) {
    	// Disable the control in your UI.
    }
  2. Call disableAllVideo().

    If the local participant does not have the required permission, disableAllVideo() throws a ClientError with code 1201.

    try {
    	await meeting.participants.disableAllVideo();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to disable other participants’ video.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, each participant’s videoEnabled becomes false, and the SDK emits a videoUpdate event. The local participant also receives videoUpdate on meeting.self.

    Listen to remote participant updates on the joined map:

    meeting.participants.joined.on(
    	"videoUpdate",
    	(participant, { videoEnabled, videoTrack }) => {
    		// videoEnabled is false
    		// Update UI for the participant
    	},
    );

    Listen to local participant update on meeting.self:

    meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    	// videoEnabled is false
    	// Update UI for the local participant
    });
  1. Check that the local participant has permission to disable other participants' video.
val canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if (!canMuteVideo) {
	// Disable the control in your UI.
}
  1. Call disableAllVideo() on the participants object. If the local participant does not have the required permission, disableAllVideo() returns a HostError.
val error = meeting.participants.disableAllVideo()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, each participant's videoEnabled becomes false.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Boolean) {
		// videoEnabled is false
		// Update UI for the participant
	}
})
  1. Check that the local participant has permission to disable other participants' video.
let canMuteVideo = meeting.localUser.permissions.host.canMuteVideo
if !canMuteVideo {
	// Disable the control in your UI.
}
  1. Call disableAllVideo() on the participants object. If the local participant does not have the required permission, disableAllVideo() returns a HostError.
if let error = meeting.participants.disableAllVideo() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, each participant's videoEnabled becomes false.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onVideoUpdate(participant: RtkRemoteParticipant, isEnabled: Bool) {
		// videoEnabled is false
		// Update UI for the participant
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to disable other participants' video.
const canDisableParticipantVideo = meeting.self.permissions.canDisableParticipantVideo;
if (!canDisableParticipantVideo) {
	// Disable the control in your UI.
}
  1. Call disableAllVideo() on the participants object.
meeting.participants
	.disableAllVideo(true)
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
  1. Handle the result by listening for updates. After the call succeeds, each participant's videoEnabled becomes false.
meeting.participants.joined.on('videoUpdate', (participant) => {
	// participant.videoEnabled is false
	// Update UI for the participant
});

Pin participants

Pin a participant to highlight them, such as a webinar presenter or classroom teacher. This is a session-wide action. All participants will see the pinned participant as the focus. This action requires the Pin Participant (pin_participant) host control permission enabled in the local participant's preset.

Pin a participant

To pin a participant in a session:

  1. Check that the local participant has permission to pin participants.

    const canPinParticipant = meeting.self.permissions.pinParticipant === true;
    if (!canPinParticipant) {
    	// Disable the control in your UI.
    }
  2. Call pin() on the target participant.

    If the local participant does not have the required permission, pin() throws a ClientError with code 1201.

    try {
    	await participant.pin();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to pin participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The target participant's isPinned becomes true.
    • The participant is added to meeting.participants.pinned.
    • The SDK emits a pinned event.

    Option A: Listen on the participant object

    participant.on("pinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is true
    	// Update your UI.
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on("pinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is true
    	// Update your UI.
    });

    If there was an existing pinned participant before, then the SDK emits an unpinned event for that participant.

  4. On the target pinned participant's side, meeting.self.isPinned becomes true and meeting.self emits pinned:

    meeting.self.on("pinned", (selfParticipant) => {
    	// Update the local UI to indicate the participant is pinned.
    });
  1. Check that the local participant has permission to pin participants.

    const canPinParticipant = meeting.self.permissions.pinParticipant === true;
    if (!canPinParticipant) {
    	// Disable the control in your UI.
    }
  2. Call pin() on the target participant.

    If the local participant does not have the required permission, pin() throws a ClientError with code 1201.

    try {
    	await participant.pin();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to pin participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The target participant's isPinned becomes true.
    • The participant is added to meeting.participants.pinned.
    • The SDK emits a pinned event.

    Option A: Listen on the participant object

    participant.on("pinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is true
    	// Update your UI.
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on("pinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is true
    	// Update your UI.
    });

    If there was an existing pinned participant before, then the SDK emits an unpinned event for that participant.

  4. On the target pinned participant's side, meeting.self.isPinned becomes true and meeting.self emits pinned:

    meeting.self.on("pinned", (selfParticipant) => {
    	// Update the local UI to indicate the participant is pinned.
    });
  1. Check that the local participant has permission to pin participants.

    const canPinParticipant = meeting.self.permissions.pinParticipant === true;
    if (!canPinParticipant) {
    	// Disable the control in your UI.
    }
  2. Call pin() on the target participant.

    If the local participant does not have the required permission, pin() throws a ClientError with code 1201.

    try {
    	await participant.pin();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to pin participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The target participant's isPinned becomes true.
    • The participant is added to meeting.participants.pinned.
    • The SDK emits a pinned event.

    Option A: Listen on the participant object

    participant.on("pinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is true
    	// Update your UI.
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on("pinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is true
    	// Update your UI.
    });

    If there was an existing pinned participant before, then the SDK emits an unpinned event for that participant.

  4. On the target pinned participant's side, meeting.self.isPinned becomes true and meeting.self emits pinned:

    meeting.self.on("pinned", (selfParticipant) => {
    	// Update the local UI to indicate the participant is pinned.
    });
  1. Check that the local participant has permission to pin participants.
val canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if (!canPinParticipant) {
	// Disable the control in your UI.
}
  1. Call pin() on the target participant. If the local participant does not have the required permission, pin() returns a HostError.
val error = participant.pin()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's isPinned becomes true and the participant is available in meeting.participants.pinned.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onParticipantPinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is true
		// Update your UI.
	}
})
  1. Check that the local participant has permission to pin participants.
let canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if !canPinParticipant {
	// Disable the control in your UI.
}
  1. Call pin() on the target participant. If the local participant does not have the required permission, pin() returns a HostError.
if let error = participant.pin() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's isPinned becomes true and the participant is available in meeting.participants.pinned.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onParticipantPinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is true
		// Update your UI.
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to pin participants.
const canPinParticipant = meeting.self.permissions.pinParticipant;
if (!canPinParticipant) {
	// Disable the control in your UI.
}
  1. Call pin() on the target participant.
participant.pin();
  1. Handle the result by listening for updates. After the call succeeds, the target participant's isPinned becomes true and the participant is available in meeting.participants.pinned.
meeting.participants.pinned.on('participantPinned', (participant) => {
	// participant.isPinned is true
	// Update your UI.
});

Unpin a participant

Unpin a participant when you need to undo the highlight and return the session to a standard grid or active speaker view. To unpin a pinned participant in a session:

  1. Check that the local participant has permission to unpin participants.

    const canUnpinParticipant = meeting.self.permissions.pinParticipant === true;
    if (!canUnpinParticipant) {
    	// Disable the control in your UI.
    }
  2. Call unpin() on the target participant.

    If the local participant does not have the required permission, unpin() throws a ClientError with code 1201.

    try {
    	await participant.unpin();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to unpin participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The target participant's isPinned becomes false.
    • The participant is removed from meeting.participants.pinned.
    • The SDK emits an unpinned event.

    Option A: Listen on the participant object

    participant.on("unpinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is false
    	// Update your UI.
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on("unpinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is false
    	// Update your UI.
    });
  4. On the target unpinned participant's side, meeting.self.isPinned becomes false and meeting.self emits unpinned:

    meeting.self.on("unpinned", (selfParticipant) => {
    	// Update the local UI to indicate the participant is no longer pinned.
    });
  1. Check that the local participant has permission to unpin participants.

    const canUnpinParticipant = meeting.self.permissions.pinParticipant === true;
    if (!canUnpinParticipant) {
    	// Disable the control in your UI.
    }
  2. Call unpin() on the target participant.

    If the local participant does not have the required permission, unpin() throws a ClientError with code 1201.

    try {
    	await participant.unpin();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to unpin participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The target participant's isPinned becomes false.
    • The participant is removed from meeting.participants.pinned.
    • The SDK emits an unpinned event.

    Option A: Listen on the participant object

    participant.on("unpinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is false
    	// Update your UI.
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on("unpinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is false
    	// Update your UI.
    });
  4. On the target unpinned participant's side, meeting.self.isPinned becomes false and meeting.self emits unpinned:

    meeting.self.on("unpinned", (selfParticipant) => {
    	// Update the local UI to indicate the participant is no longer pinned.
    });
  1. Check that the local participant has permission to unpin participants.

    const canUnpinParticipant = meeting.self.permissions.pinParticipant === true;
    if (!canUnpinParticipant) {
    	// Disable the control in your UI.
    }
  2. Call unpin() on the target participant.

    If the local participant does not have the required permission, unpin() throws a ClientError with code 1201.

    try {
    	await participant.unpin();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to unpin participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The target participant's isPinned becomes false.
    • The participant is removed from meeting.participants.pinned.
    • The SDK emits an unpinned event.

    Option A: Listen on the participant object

    participant.on("unpinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is false
    	// Update your UI.
    });

    Option B: Listen on the joined map

    meeting.participants.joined.on("unpinned", (updatedParticipant) => {
    	// updatedParticipant.isPinned is false
    	// Update your UI.
    });
  4. On the target unpinned participant's side, meeting.self.isPinned becomes false and meeting.self emits unpinned:

    meeting.self.on("unpinned", (selfParticipant) => {
    	// Update the local UI to indicate the participant is no longer pinned.
    });
  1. Check that the local participant has permission to unpin participants.
val canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if (!canPinParticipant) {
	// Disable the control in your UI.
}
  1. Call unpin() on the target participant. If the local participant does not have the required permission, unpin() returns a HostError.
val error = participant.unpin()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's isPinned becomes false.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onParticipantUnpinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is false
		// Update your UI.
	}
})
  1. Check that the local participant has permission to unpin participants.
let canPinParticipant = meeting.localUser.permissions.host.canPinParticipant
if !canPinParticipant {
	// Disable the control in your UI.
}
  1. Call unpin() on the target participant. If the local participant does not have the required permission, unpin() returns a HostError.
if let error = participant.unpin() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the target participant's isPinned becomes false.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onParticipantUnpinned(participant: RtkRemoteParticipant) {
		// participant.isPinned is false
		// Update your UI.
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to unpin participants.
const canPinParticipant = meeting.self.permissions.pinParticipant;
if (!canPinParticipant) {
	// Disable the control in your UI.
}
  1. Call unpin() on the target participant.
participant.unpin();
  1. Handle the result by listening for updates. After the call succeeds, the target participant's isPinned becomes false.
meeting.participants.pinned.on('unpinned', (participant) => {
	// participant.isPinned is false
	// Update your UI.
});

Remove participants

Remove participants from the session when you need to moderate disruptive behavior or enforce session rules. This action requires the Kick Participants (kick_participant) host control permission enabled in the local participant's preset.

Remove a participant

To remove a specific participant from the session:

  1. Check that the local participant has permission to remove participants.

    const canKickParticipant = meeting.self.permissions.kickParticipant === true;
    if (!canKickParticipant) {
    	// Disable the control in your UI.
    }
  2. Call kick() on the target participant.

    If the local participant does not have the required permission, kick() throws a ClientError with code 1201.

    try {
    	await participant.kick();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to remove participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The kicked participant is removed from meeting.participants.joined.
    • The participant is removed from other participant maps they were in (for example, meeting.participants.pinned).
    • The SDK emits participantLeft on meeting.participants.joined.
    meeting.participants.joined.on("participantLeft", (participant) => {
    	// Remove the participant tile from the UI.
    });

    Other participants in the session also observe the participant leaving through participantLeft.

  4. On the removed participant's side, the session disconnects and meeting.self emits roomLeft event with state set to kicked.

    meeting.self.on("roomLeft", ({ state }) => {
    	if (state === "kicked") {
    		// Show a message and navigate the user out of the meeting UI.
    	}
    });
  1. Check that the local participant has permission to remove participants.

    const canKickParticipant = meeting.self.permissions.kickParticipant === true;
    if (!canKickParticipant) {
    	// Disable the control in your UI.
    }
  2. Call kick() on the target participant.

    If the local participant does not have the required permission, kick() throws a ClientError with code 1201.

    try {
    	await participant.kick();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to remove participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The kicked participant is removed from meeting.participants.joined.
    • The participant is removed from other participant maps they were in (for example, meeting.participants.pinned).
    • The SDK emits participantLeft on meeting.participants.joined.
    meeting.participants.joined.on("participantLeft", (participant) => {
    	// Remove the participant tile from the UI.
    });

    Other participants in the session also observe the participant leaving through participantLeft.

  4. On the removed participant's side, the session disconnects and meeting.self emits roomLeft event with state set to kicked.

    meeting.self.on("roomLeft", ({ state }) => {
    	if (state === "kicked") {
    		// Show a message and navigate the user out of the meeting UI.
    	}
    });
  1. Check that the local participant has permission to remove participants.

    const canKickParticipant = meeting.self.permissions.kickParticipant === true;
    if (!canKickParticipant) {
    	// Disable the control in your UI.
    }
  2. Call kick() on the target participant.

    If the local participant does not have the required permission, kick() throws a ClientError with code 1201.

    try {
    	await participant.kick();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to remove participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds:

    • The kicked participant is removed from meeting.participants.joined.
    • The participant is removed from other participant maps they were in (for example, meeting.participants.pinned).
    • The SDK emits participantLeft on meeting.participants.joined.
    meeting.participants.joined.on("participantLeft", (participant) => {
    	// Remove the participant tile from the UI.
    });

    Other participants in the session also observe the participant leaving through participantLeft.

  4. On the removed participant's side, the session disconnects and meeting.self emits roomLeft event with state set to kicked.

    meeting.self.on("roomLeft", ({ state }) => {
    	if (state === "kicked") {
    		// Show a message and navigate the user out of the meeting UI.
    	}
    });
  1. Check that the local participant has permission to remove participants.
val canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if (!canKickParticipant) {
	// Disable the control in your UI.
}
  1. Call kick() on the target participant. If the local participant does not have the required permission, kick() returns a HostError.
val error = participant.kick()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the kicked participant is removed from meeting.participants.joined.
meeting.addParticipantsEventListener(object : RtkParticipantsEventListener {
	override fun onParticipantLeave(participant: RtkRemoteParticipant) {
		// Remove the participant tile from the UI.
	}
})
  1. Check that the local participant has permission to remove participants.
let canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if !canKickParticipant {
	// Disable the control in your UI.
}
  1. Call kick() on the target participant. If the local participant does not have the required permission, kick() returns a HostError.
if let error = participant.kick() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, the kicked participant is removed from meeting.participants.joined.
extension MeetingViewModel: RtkParticipantsEventListener {
	func onParticipantLeave(participant: RtkRemoteParticipant) {
		// Remove the participant tile from the UI.
	}
}

// Register the listener
meeting.addParticipantsEventListener(participantsEventListener: self)
  1. Check that the local participant has permission to remove participants.
const canKickParticipant = meeting.self.permissions.kickParticipant;
if (!canKickParticipant) {
	// Disable the control in your UI.
}
  1. Call kick() on the target participant.
participant
	.kick()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
  1. Handle the result by listening for updates. After the call succeeds, the kicked participant is removed from meeting.participants.joined.
meeting.participants.joined.on('participantLeft', (participant) => {
	// Remove the participant tile from the UI.
});

Remove all participants

This removes everyone from the session, including the local participant. This ends the session for everyone.

For a complete end-a-session flow, refer to End a session.

To remove all participants from the session:

  1. Check that the local participant has permission to remove participants.

    const canKickParticipant = meeting.self.permissions.kickParticipant === true;
    if (!canKickParticipant) {
    	// Disable the control in your UI.
    }
  2. Call kickAll().

    If the local participant does not have the required permission, kickAll() throws a ClientError with code 1201.

    try {
    	await meeting.participants.kickAll();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to remove participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, all participants exit the session. On each client, meeting.self emits roomLeft with state set to ended.

    meeting.self.on("roomLeft", ({ state }) => {
    	if (state === "ended") {
    		// Show a message and navigate the user out of the meeting UI.
    	}
    });
  1. Check that the local participant has permission to remove participants.

    const canKickParticipant = meeting.self.permissions.kickParticipant === true;
    if (!canKickParticipant) {
    	// Disable the control in your UI.
    }
  2. Call kickAll().

    If the local participant does not have the required permission, kickAll() throws a ClientError with code 1201.

    try {
    	await meeting.participants.kickAll();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to remove participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, all participants exit the session. On each client, meeting.self emits roomLeft with state set to ended.

    meeting.self.on("roomLeft", ({ state }) => {
    	if (state === "ended") {
    		// Show a message and navigate the user out of the meeting UI.
    	}
    });
  1. Check that the local participant has permission to remove participants.

    const canKickParticipant = meeting.self.permissions.kickParticipant === true;
    if (!canKickParticipant) {
    	// Disable the control in your UI.
    }
  2. Call kickAll().

    If the local participant does not have the required permission, kickAll() throws a ClientError with code 1201.

    try {
    	await meeting.participants.kickAll();
    } catch (err: any) {
    	if (err?.code === 1201) {
    		// The local participant does not have permission to remove participants.
    		return;
    	}
    	throw err;
    }
  3. Handle the result by listening for updates.

    After the call succeeds, all participants exit the session. On each client, meeting.self emits roomLeft with state set to ended.

    meeting.self.on("roomLeft", ({ state }) => {
    	if (state === "ended") {
    		// Show a message and navigate the user out of the meeting UI.
    	}
    });
  1. Check that the local participant has permission to remove participants.
val canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if (!canKickParticipant) {
	// Disable the control in your UI.
}
  1. Call kickAll() on the participants object. If the local participant does not have the required permission, kickAll() returns a HostError.
val error = meeting.participants.kickAll()
if (error != null) {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, all participants exit the session.
meeting.addMeetingRoomEventListener(object : RtkMeetingRoomEventListener {
	override fun onMeetingEnded() {
		// Show a message and navigate the user out of the meeting UI.
	}
})
  1. Check that the local participant has permission to remove participants.
let canKickParticipant = meeting.localUser.permissions.host.canKickParticipant
if !canKickParticipant {
	// Disable the control in your UI.
}
  1. Call kickAll() on the participants object. If the local participant does not have the required permission, kickAll() returns a HostError.
if let error = meeting.participants.kickAll() {
	// Handle error - permission denied.
}
  1. Handle the result by listening for updates. After the call succeeds, all participants exit the session.
extension MeetingViewModel: RtkMeetingRoomEventListener {
	func onMeetingEnded() {
		// Show a message and navigate the user out of the meeting UI.
	}
}

// Register the listener
meeting.addMeetingRoomEventListener(meetingRoomEventListener: self)
  1. Check that the local participant has permission to remove participants.
const canKickParticipant = meeting.self.permissions.kickParticipant;
if (!canKickParticipant) {
	// Disable the control in your UI.
}
  1. Call kickAll() on the participants object.
meeting.participants
	.kickAll()
	.catch((err) => {
		// Handle error - permission denied or other issue.
		console.log(err);
	});
  1. Handle the result by listening for updates. After the call succeeds, all participants exit the session.
meeting.self.on('roomLeft', ({ state }) => {
	if (state === 'kicked') {
		// Show a message and navigate the user out of the meeting UI.
	}
});

Next steps