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);
setAudioMuted(muted);
};
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);
setVideoMuted(muted);
if (muted) {
props.pexRTC.onSetup(null);
} else {
props.pexRTC.onSetup(props.pexRTC.call.mediaStream);
}
};
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:
<Button
onClick={handleAudioMute}
selected={audioMuted}
icon={audioMuted ? <MicOffIcon /> : <MicIcon />}
/>
<Button
onClick={handleVideoMute}
selected={videoMuted}
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.