How to Remove a Participant From a Twilio Video Call

February 28, 2022
Written by
Mia Adjei
Twilion
Reviewed by

How to Remove a Participant From a Twilio Video Call

This article is for reference only. We're not onboarding new customers to Programmable Video. Existing customers can continue to use the product until December 5, 2024.


We recommend migrating your application to the API provided by our preferred video partner, Zoom. We've prepared this migration guide to assist you in minimizing any service disruption.

With so much of today's communication happening over video chat, people hosting meetings want to have some level of control over who is attending that meeting. For example, if a participant is being disruptive, the host will want a way to remove that person from the call.

Thankfully, Twilio Video provides an easy way to remove a participant with a single API call. In this tutorial, you will learn how to add a host panel to a video chat application that will display participants' names and allow you to remove them from the call at the click of a button.

While this tutorial will not go into user roles and management, it may be helpful to keep these in mind, as you will likely want a way to distinguish between users who should have permissions to manage other users and users who should not be granted those privileges.

Let's get started!

Prerequisites

Setup

This tutorial will add a new feature on top of an already-built video application. The starter project is built using Twilio Video, Twilio Functions, and vanilla JavaScript.

To get started, clone the starter video application by running the following command on your command line:

git clone https://github.com/adjeim/video-chat-serverless.git

Copy the placeholder values in .env.template into a new file called .env. Then, replace the placeholder text with the values for your Twilio Account SID, Auth Token, API Key SID, and API Key Secret. You can find or generate these values in the Twilio Console.

Once you have completed this step, run the following command from the root of the project to install the necessary dependencies:

npm install

To run the application locally on port 3000, run the following command:

npm start

Once the application is running, you will be able to see it by navigating to http://localhost:3000/ in your browser.

Then, if you would like to deploy the application, run the following command:

npm run deploy

Once deployed, you will see output in your terminal, part of which will look like the text below:

✔ Serverless project successfully deployed

Deployment Details
Domain: video-chat-serverless-XXXX-dev.twil.io
Service:
   video-chat-serverless (ZSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)

The application will be available at a URL with the format https://video-chat-serverless-XXXX-dev.twil.io. You will see your specific URL in the terminal output. Paste this URL into your browser, and you will see the video application. Feel free to test out joining and leaving a video room if you wish.

The starter video application

Now you're ready to add the host panel to your application.

Add a backend function to remove a participant

The backend of this application runs on Twilio Functions. If you take a look inside the functions directory, you will see that there is a file called token.js containing the function that grants access tokens for the user to join a video room.

Inside the functions directory, create a new file called removeParticipant.js. Inside that file, paste the following code:

const twilio = require('twilio');

exports.handler = async function(context, event, callback) {
  if (!event.roomSid || !event.participantSid) {
    const response = new twilio.Response();
    response.setStatusCode(400);
    response.setBody({
      message: 'Missing one of: sid, participantIdentity',
    });
    return callback(null, response);
  }

  const twilioClient = context.getTwilioClient();
  const roomSid = event.roomSid;
  const participantSid = event.participantSid;
  let removedParticipant;

  try {
    removedParticipant = await twilioClient.video.rooms(roomSid).participants(participantSid).update({status: 'disconnected'});
  } catch (error) {
    const response = new twilio.Response();
    response.setStatusCode(401);
    response.setBody({
      message: 'Unable to remove participant',
      error: error
    });
    return callback(null, response);
  }

  return callback(null, {
    message: `Successfully removed participant ${removedParticipant.sid}`,
    removedSid: removedParticipant.sid
  });
}

This is the new function that will take a participant's sid and a video room's sid and then remove that participant from the video room. You will call this function from a button in the host panel, which you will add to the UI in the next step.

Add the host panel to the HTML layout

You may have noticed that there are two files named index.html — one inside the assets directory, and the other nested inside assets/assets. This is because Twilio Runtime has an interesting way of hosting root assets. Keep this in mind when developing your project and make sure to update the code in both places.

Open assets/index.html and assets/assets/index.html in your code editor. The code here is the same in both files. Here, you will see the basic structure of the application's interface, which currently consists of a gallery where the participants' video feeds will appear, a controls section where the participants will be able to join or leave the video chat, and a status section where any status messages will appear.

Just below these sections in each HTML file, add a new section with an id of admin-controls where the host panel will live:

    <section id='admin-controls'>
      <div class='host-panel'>
        <h3>Participants <button id='button-panel-close'>Close</button></h3>
        <ul id='participants'></ul>
      </div>
    </section>

Inside this new section is the host-panel div as well as an empty list where the names of the participants will appear. The host panel also includes a button which will allow users to close it from the inside.

Now that you have added the host panel section, add a new button to the controls section that will toggle whether the host panel will be shown or hidden:


    <section id='controls'>
        <input type='text' id='identity' placeholder='Enter your name' required>
        <button id='button-join'>Join Room</button>
        <button id='button-leave' disabled>Leave Room</button>
        <button id='button-panel-toggle' disabled>Toggle Host Panel</button>
    </section>

This new button will start off as disabled — you'll want it to only be available once a participant has joined the video chat.

To style these new elements, grab the extra CSS styles from this gist and add them to the bottom of assets/styles.css.

If you are running the application locally and refresh your browser window, you will see that the updated application looks like the image below:

Updated app, showing the "Toggle Host Panel" button and the closed host panel.

Add logic to open and close the host panel

Now that you have the HTML set up, it's time to add some logic to control opening and closing the host panel. Open assets/app.js. Add the following constants for the host panel, the toggle button, and the close panel button:


const video = document.getElementById('video');
const gallery = document.getElementById('gallery');
const identityInput = document.getElementById('identity');
const statusDiv = document.getElementById('status-message');
const hostPanel = document.querySelector('.host-panel');

// buttons
const joinRoomButton = document.getElementById('button-join');
const leaveRoomButton = document.getElementById('button-leave');
const toggleButton = document.getElementById('button-panel-toggle');
const closePanelButton = document.getElementById('button-panel-close');

Now, scroll down to the list of event listeners at the end of the file. Add the following new event listeners for the toggle button and the close panel button:

 


// Event listeners
joinRoomButton.addEventListener('click', joinRoom);
leaveRoomButton.addEventListener('click', leaveRoom);

toggleButton.addEventListener('click', () => {
  hostPanel.classList.toggle('open');
  hostPanel.classList.contains('open') ?  openHostPanel() : closeHostPanel()
});

closePanelButton.addEventListener('click', () => {
  hostPanel.classList.toggle('open');
  closeHostPanel();
});

Toggling the host panel will add or remove the open class from the panel. On opening, the function openHostPanel() will be called, and on closing, closeHostPanel() will be called.

Just below the participantDisconnected() function, paste in the following openHostPanel() function:

const openHostPanel = async () => {
  // Get the empty participants list
  const participants = document.getElementById('participants');

  videoRoom.participants.forEach(participant => {
    const participantDetails = document.createElement('li');
    participantDetails.classList.add('participantDetails')

    participantDetails.setAttribute('data-sid', participant.sid);
    participantDetails.innerText = participant.identity;

    const participantDeleteButton = document.createElement('button');
    participantDeleteButton.innerText = 'Remove';
    participantDetails.appendChild(participantDeleteButton);
    participantDeleteButton.addEventListener('click', removeParticipant);

    participants.appendChild(participantDetails);
  })

  hostPanel.appendChild(participants);
}

This function gets the list of remote participants in the video room and shows them in the host panel. It also adds a Remove button next to each name, which when clicked, will kick the participant out of the video chat.

Since you're calling removeParticipant() in the function above, add it to the code next, just below openHostPanel():

const removeParticipant = async (event) => {
  event.preventDefault();

  try {
    const response = await fetch('/removeParticipant', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        'roomSid': videoRoom.sid,
        'participantSid': event.target.parentElement.dataset.sid
      })
    });

    const data = await response.json();
    const participantDetails = Array.from(document.getElementsByClassName('participantDetails'));
    participantDetails.find(participant => participant.dataset.sid === data.removedSid).remove();

  } catch (error) {
    console.log(error)
  }
}

This function takes the sid of the participant to remove, then calls the removeParticipant() backend function you created earlier. Once the participant has been removed, their video feed is disconnected, and this function cleans up their associated divs.

Now, add the following closeHostPanel() function, which will remove the name and button elements in the host panel when it slides closed:

const closeHostPanel = () => {
  const participants = document.getElementById('participants');

  if (participants.children) {
    for (child of participants.children) {child.remove()};
  }
}

You now have the logic for opening and closing the host panel, as well as removing a participant. There are just a few more small tweaks you'll need to make to some of the other functions in assets/app.js.

In the joinRoom() function, add the following highlighted line of code to activate the toggleButton:


    localParticipantDiv.appendChild(identityDiv);
    leaveRoomButton.disabled = false;
    toggleButton.disabled = false;

Then scroll down in this same function and add the following highlighted lines to reset the UI when the localParticipant is the person who gets removed from the call:


    videoRoom.participants.forEach(participantConnected);
    videoRoom.on('participantConnected', participantConnected);
    videoRoom.on('participantDisconnected', participantDisconnected);

    // If the localParticipant is the one who has been removed, reset their UI to a non-joined state
    videoRoom.localParticipant.on('disconnected', leaveRoom);

  } catch (error) {
    console.log(error);
  }

When a participant joins a room, this code will make the toggle panel button active and able to be clicked. Also, a new listener is added so that if the local participant is the one who is removed from the video chat, their UI will be reset to show that they are disconnected.

There's also a small tweak to make in the leaveRoom() function:


  joinRoomButton.disabled = false;
  leaveRoomButton.disabled = true;
  identityInput.disabled = false;
  toggleButton.disabled = true;

  // Close the host panel if the local participant leaves the call
  if (hostPanel.classList.contains('open')) {
    hostPanel.classList.toggle('open');
  }

When a participant leaves the video chat or is kicked out, the toggle panel button will return to being disabled. If a user is not currently participating in the video chat, they should not be able to remove other users. Additionally, if the local participant leaves or is kicked from the call, the host panel will be closed if it was open.

Now that you have made these changes, redeploy your application. From your command line, run the following command:

npm run deploy

The project will be updated, and you can refresh your browser window to see the new layout and functionality:

Updated and deployed video application

You now have all the code you need! It's time to test out removing a participant from a video chat.

Test removing a participant from the video call

Join the video chat from two or more different browser tabs, with two different names. Alternatively, you could try testing this out with a friend.

Video chat with two participants: "mia" and "CHAOS"

                                                  Here, I've joined the video chat with two different identities — "mia" and "CHAOS".

Once you're in the video chat, you will see the toggle panel button become active. Click on the toggle button to show the host panel. Inside the host panel, you will see a list of the remote participants, each with a Remove button next to their name:

Video app with host panel open, showing "CHAOS" in the list of participants.

From my chat window, I can see CHAOS in the list of participants here.

If you click the button next to a name, this person will be removed from the chat, and their video feed will disappear from your window. The person who is removed will also see a message that they have been disconnected from the chat.

CHAOS has been removed from the chat and is now disconnected.

                                                                 CHAOS has been removed from the chat!

 

What's next for video chat host tools?

In a video chat with multiple participants, it is important that hosts have a way to remove a participant who may be disrupting the video call. While this tutorial walks through the logic of how to add this feature to your application, you will still need to devise a strategy for roles and permissions so that you can identify which users will be allowed to carry out host actions.

If you're interested in getting even more details about what's going on in your video rooms, you might also want to check out the Room Monitor — there's even a great tutorial that will teach you how to add it to your application.

I can't wait to see what you build!

Mia Adjei is a Software Developer on the Developer Voices team. They love to help developers build out new project ideas and discover aha moments. Mia can be reached at madjei [at] twilio.com.