Skip to main content

Mute audio and video

In the previous lesson we have learnt how to connect to a conference, even if it's protected by a PIN. Now we will add some new features. We will start by allowing the user to protect their own privacy - and for that we will set two new buttons in our interface to allow the user to mute their microphone and camera.

During this lesson we will complete the following tasks:

  • Hide the local video in case we don't have a local stream active.
  • Define the function that will be triggered when we push the mute microphone button.
  • Define the function that will be triggered when we push the mute camera button.
  • Modify the toolbar to include both buttons.

You can download the starter code from Step.03-Exercise-Mute-audio-and-video.

Conference component

First of all, we will make a small improvement in the src/components/Conference/Conference.js file. In this case, we would like to hide the local video element when the user mutes their camera. It's a small improvement, but important for the user experience.

For this task, we only have to modify one line of code. We will add a condition for rendering the localStream. This condition is that props.localStream should exist:

props.localStream && (
<Video className="local-video" mediaStream={props.localStream} />

Toolbar component

Now we will implement the main part of this feature by modifying src/components/Conference/Toolbar/Toolbar.js file and adding all the logic for this functionality.

The first step is to define the state variables:

const [audioMuted, setAudioMuted] = useState(false);
const [videoMuted, setVideoMuted] = useState(false);

Now we will add the function that will be triggered each time the user pushes the mute audio button:

const handleAudioMute = () => {
const muted = props.pexRTC.muteAudio(!audioMuted);

The muteAudio function will return the new mute state and we will save it in the state variable. This way the button style will be updated.

Now we do the same for the mute video button:

const handleVideoMute = async () => {
const muted = props.pexRTC.muteVideo(!videoMuted);
if (muted) {
} else {

The only difference with mute audio is that we call onSetup with two different values depending on the muted state. This way the localStream will change and the video will appear or disappear from the interface.

The final step is to create the buttons themselves:

icon={audioMuted ? <MicOffIcon /> : <MicIcon />}
icon={videoMuted ? <VideocamOffIcon /> : <VideocamIcon />}

One detail that you should notice is that the icon changes depending on the mute state of the variables.

Run the app

When you run the app, you will see your two new buttons in the interface. If you click on any of them, you will see that the audio/video is muted and the styles changes. In case of the mute video, the local video will also be hidden when it's active.

You can compare your code with the solution in Step.03-Solution-Mute-audio-and-video. You can also check the differences with the previous lesson in the git diff.