Skip to main content

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 to receiving a presentation.
  • Define a function to choose which video display in the main region (remote participants or presentation).
  • Modify the useEffect hook to configure the bind the handler to the onRemotePresentationStream.
  • Create the HTML Video elements 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.

App component

We will start the journey by editing the file src/App.tsx.

The first step is to define a state variable that will contain the MediaStream with the presentation.

const [presentationStream, setPresentationStream] = useState<MediaStream | null>(null);

Now we need to add a handler to the onRemotePresentationStream signal that will set the value of the previous state:

useEffect(() => {
callSignals.onRemotePresentationStream.add((stream) => setPresentationStream(stream));
...
});

Now we pass the presentationStream to the conference:

<Conference
localStream={localStream}
remoteStream={remoteStream}
presentationStream={presentationStream}
onAudioMute={handleAudioMute}
onVideoMute={handleVideoMute}
onDisconnect={handleDisconnect}
/>

Conference component

Now we will open the file src/components/Conference/Conference.tsx 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.

We need to update the list of props that the conference receives and add presentationStream:

interface ConferenceProps {
localStream: MediaStream | null;
remoteStream: MediaStream | null;
presentationStream: MediaStream | null;
onAudioMute: (mute: boolean) => void;
onVideoMute: (mute: boolean) => void;
onDisconnect: () => void;
}

Now we will define a state variable that will indicate which video will be displayed on the main region of the conference. 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(false);

Now we will define the function that will be triggered every time. Notice that we use useCallback to cache the switchVideos function between re-renders. This will avoid flickering.

const switchVideos = (event: React.MouseEvent<HTMLVideoElement>) => {
if (event.target instanceof HTMLVideoElement) {
if (event.target.className === 'presentation-video') {
setPresentationInMain(true);
} else {
setPresentationInMain(false);
}
}
};
const memoizedSwitchVideos = React.useCallback(switchVideos , []);

The next step is use the useEffect hook to define what should happen what happen when the component should be re-rendered due to a change in the dependencies. In this case we do the following:

  useEffect(() => {
if (!props.presentationStream) {
setPresentationInMain(true)
}
}, [props.presentationStream]);

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), we will see it in a smaller thumbnail.

We call the memoized function that we have defined before when we click on the remote-video element:

<Video className='remote-video'
mediaStream={props.remoteStream} onClick={ memoizedSwitchVideos }/>

We define a new video that will contain the presentation that we 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.

Receive Presentation