Receive presentation
An important feature in any video conference application is screen sharing or "presentation". This feature allows the users to collaborate in a more flexible way. They can share any type of document or tools, such a whiteboard, powerpoint or even videos.
We have divided the lessons about presentation into two parts. We will start by receiving a presentation, and in the next lesson, we will learn how to send a presentation.
During this tutorial we will perform the following tasks:
- Set handlers related for receiving a presentation.
- Define a function to choose which video display in the main region (remote participants or presentation).
- Define the
useEffect
hook to configure the initial state of the component after re-rendering. - Create the
HTML Video
element for the presentation. - Set the
onClick
listener for changing between the video with the remote participants and the presentation.
After all these changes, we will be able to receive a presentation and in the next lesson we will learn how to send it.
You can download the starter code from Step.04-Exercise-Receive-presentation.
App component
We will start the journey by editing the file src/App.js
. We will attach
functions for three events:
pexRTC.onPresentation = handlePresentation;
pexRTC.onPresentationConnected = handlePresentationConnected;
pexRTC.onPresentationDisconnected = handlePresentationDisconnected;
First we define the handler for when a new incoming presentation is received:
const handlePresentation = (setting, presenter, uuid, presenter_source) => {
if (setting) pexRTC.getPresentation();
};
This event receives information about the presentation, but not the presentation
itself. For that we have to trigger pexRTC.getPresentation()
manually.
After launching getPresentation
the event onPresentationConnected
will be
triggered and will contain the MediaStream
with the presentation.
In the handler we save this stream in the app state:
const handlePresentationConnected = stream => {
setPresentationStream(stream);
};
The last handler is triggered when the user stops sharing their screen. In this
case we will set the MediaStream
to null to indicate the rest of the
application that the presentation ended:
const handlePresentationDisconnected = reason => {
if (!pexRTC.screenshare_requested) {
setPresentationStream(null);
}
};
Before removing the presentation, we must check that the current user of the application didn't enable screen sharing themself.
Conference component
Now we will edit the file src/components/Conference/Conference.js
and in this
file we will define a new HTML Video
tag. This new tag will be used to display
a secondary media stream. We also will exchange the video located in the main
region if the user click on this video.
Next we will define a state variable that will indicate which video stream will be displayed in the main region of the page. It could be the video with the remote participants or the presentation. The video that is not in the main region will be positioned in the top-left corner and it will be much smaller:
const [presentationInMain, setPresentationInMain] = useState();
Next we will define the function that will be triggered every time the user clicks over the video that is not in the main region:
const switchVideos = event => {
if (event.target.className === 'presentation-video') {
setPresentationInMain(true);
} else {
setPresentationInMain(false);
}
};
Next we use the useCallback
hook over the switchVideos
function, since this
will help to avoid video flickering when the component is re-rendered:
const memoizedSwitchVideos = React.useCallback(switchVideos, []);
The next step is to use the useEffect
hook to define what should happen when
the component is re-rendered due to a change in the dependencies:
useEffect(() => {
if (!props.presentationStream) {
if (presentationInMain != null) setPresentationInMain(null);
} else {
if (presentationInMain == null && !props.pexRTC.screenshare_requested) {
setPresentationInMain(true);
}
}
}, [
presentationInMain,
props.localStream,
props.pexRTC.screenshare_requested,
props.presentationStream,
]);
With this code we will have to cope with two different situations:
If the presentation isn't active and the value of
presentationInMain
changed, we reset its value to the original value (null
).If the presentation is active,
presentationInMain
is uninitialized andscreenshare_requested
isfalse
, that means that we are receiving a presentation and not sending it, we setpresentationInMain
totrue
.
With this modification, we will display by default the remote presentation in the main video region, and in case the user is the one that is sending the presentation (next lesson), they will see it in a small thumbnail.
Next we will modify the remote-video
element and add the onClick
attribute
to call the memoized function that we have defined before:
<Video
className="remote-video"
mediaStream={props.remoteStream}
onClick={memoizedSwitchVideos}
/>
The last thing that we need is to define a new video that will contain the
presentation that we will receive. In the similar way that before, we assign a
function to the onClick
event that will switch the video that is displayed in
the main region:
{
props.presentationStream && (
<Video
className="presentation-video"
mediaStream={props.presentationStream}
onClick={memoizedSwitchVideos}
/>
);
}
With this last modification we have everything in place that we will need for receiving a presentation. In the next tutorial we will see how to share our screen with other participants.
Run the app
To test your new feature, you will need an application that already has the capability to send a presentation. Our recommendation is to test it with the Pexip Web App 3. This way, a participant will join to the conference using your app and a second participant will use the Web App 3.
You can compare your code with the solution in Step.04-Solution-Receive-presentation. You can also check the differences with the previous lesson in the git diff.