Skip to content
Cloudflare Docs

Manage other 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.

Before you start

Prerequisites

  • The local participant (for example, a host or moderator) must have the required Host Controls permissions enabled in their preset. For details, refer to Preset.

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.

TypeScript
const joinedParticipants = meeting.participants.joined.toArray();
const participant = joinedParticipants[0];
if (!participant) {
// No remote participants are currently 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.

    TypeScript
    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.

    TypeScript
    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

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

    Option B: Listen on the joined map

    TypeScript
    meeting.participants.joined.on(
    "audioUpdate",
    (participant, { audioEnabled, audioTrack }) => {
    if (participant.id === targetParticipantId) {
    // 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.

    TypeScript
    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.

    TypeScript
    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:

    TypeScript
    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:

    TypeScript
    meeting.self.on("audioUpdate", ({ audioEnabled, audioTrack }) => {
    // audioEnabled is false
    // Update UI for the local 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.

    TypeScript
    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.

    TypeScript
    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

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

    Option B: Listen on the joined map

    TypeScript
    meeting.participants.joined.on(
    "videoUpdate",
    (participant, { videoEnabled, videoTrack }) => {
    // 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.

    TypeScript
    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.

    TypeScript
    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:

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

    Listen to local participant update on meeting.self:

    TypeScript
    meeting.self.on("videoUpdate", ({ videoEnabled, videoTrack }) => {
    // videoEnabled is false
    // Update UI for the local 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.

    TypeScript
    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.

    TypeScript
    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

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

    Option B: Listen on the joined map

    TypeScript
    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:

    TypeScript
    meeting.self.on("pinned", (selfParticipant) => {
    // Update the local UI to indicate the participant is pinned.
    });

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.

    TypeScript
    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.

    TypeScript
    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

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

    Option B: Listen on the joined map

    TypeScript
    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:

    TypeScript
    meeting.self.on("unpinned", (selfParticipant) => {
    // Update the local UI to indicate the participant is no longer pinned.
    });

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.

    TypeScript
    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.

    TypeScript
    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.
    TypeScript
    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.

    TypeScript
    meeting.self.on("roomLeft", ({ state }) => {
    if (state === "kicked") {
    // Show a message and navigate the user out of the meeting 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.

    TypeScript
    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.

    TypeScript
    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.

    TypeScript
    meeting.self.on("roomLeft", ({ state }) => {
    if (state === "ended") {
    // Show a message and navigate the user out of the meeting UI.
    }
    });

Next steps

  • Review how presets control permissions in Preset.
  • Review error handling details in Error Codes.