Skip to main content
Version: 0.x.x

Rendering Host and Audience Views - React

In a live stream setup, only hosts (participants in SEND_AND_RECV mode) can broadcast their audio and video. Audience members (in RECV_ONLY mode) are passive viewers who do not share their audio/video.

To ensure optimal performance and a clean user experience, your app should:

  • Render audio and video elements only for hosts (i.e., participants in SEND_AND_RECV mode).
  • Display the total audience count to give context on viewership without rendering individual audience tiles.

Filtering and Rendering Hosts​

The steps involved in rendering the audio and video of hosts are as follows.

  1. Filtering Hosts and Checking their Mic/Webcam Status
  2. Rendering Video Streams of Hosts
  3. Rendering Audio Streams of Hosts

1. Filtering Hosts and Checking their Mic/Webcam Status ​

In a live stream, only participants in SEND_AND_RECV mode (i.e., hosts) actively share their audio and video. To render their streams, begin by accessing all participants using the useMeeting hook. Then, filter out only those in SEND_AND_RECV mode.

For each of these participants, use the useParticipant hook, which provides real-time information like displayName, micOn, and webcamOn. Display their name along with the current status of their microphone and webcam. If the webcam is off, show a simple placeholder with their name. If it's on, render their video feed. This ensures only hosts are visible to the audience, keeping the experience clean and intentional.

const LiveStreamView = () => {
const { participants } = useMeeting();

// Filter hosts only
const hostParticipants = [...participants.values()].filter(
(participant) => participant.mode === "SEND_AND_RECV"
);

return (
<div
style={{
display: "grid",
gridTemplateColumns: "repeat(3, 1fr)",
gap: "12px",
}}
>
{hostParticipants.map((participant) => (
<ParticipantView key={participant.id} participantId={participant.id} />
))}
</div>
);
};

const ParticipantView = ({ participantId }) => {
const { displayName, micOn, webcamOn, webcamStream } =
useParticipant(participantId);

return (
<div
style={{
height: "300px",
background: "#C0C2C9",
}}
>
<p>{displayName}</p>
<p>
Webcam: {webcamOn ? "On" : "Off"} | Mic: {micOn ? "On" : "Off"}
</p>
</div>
);
};

participant status

2. Rendering Video Streams of Hosts​

Once you've filtered for participants in SEND_AND_RECV mode (i.e., hosts), you can use the useParticipant hook to access their real-time data, including their webcamStream, webcamOn, and whether they are the local participant.

To render their video feed, create a <video> element and link it to the webcamStream using a ref and the useEffect hook. If the webcam is off, display a simple placeholder.

You can also apply styling to maintain the video’s aspect ratio using object-fit, and optionally mirror the video for the local participant.

import { useEffect, useRef } from "react";
import { useParticipant } from "@videosdk.live/react-sdk";

const ParticipantView = ({ participantId }) => {
const { displayName, micOn, webcamOn, webcamStream, isLocal } =
useParticipant(participantId);

const webcamRef = useRef(null);

useEffect(() => {
if (webcamRef.current) {
if (webcamOn && webcamStream) {
const mediaStream = new MediaStream();
mediaStream.addTrack(webcamStream.track);

webcamRef.current.srcObject = mediaStream;
webcamRef.current
.play()
.catch((error) =>
console.error("videoElem.current.play() failed", error)
);
} else {
webcamRef.current.srcObject = null;
}
}
}, [webcamStream, webcamOn]);

return (
<div
style={{
height: "300px",
background: "#C0C2C9",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
>
<p>{displayName}</p>
<p>
Webcam: {webcamOn ? "On" : "Off"} | Mic: {micOn ? "On" : "Off"}
</p>
{webcamOn ? (
<video
width={"100%"}
height={"100%"}
ref={webcamRef}
autoPlay
style={{
objectFit: "contain", //Maintaining the aspect ratio
...(isLocal
? { transform: "scaleX(-1)", WebkitTransform: "scaleX(-1)" }
: {}), //Mirror view for local participant
}}
/>
) : (
<div
style={{
width: "100%",
height: "100%",
background: "#aaa",
display: "flex",
justifyContent: "center",
alignItems: "center",
fontSize: "1.2rem",
}}
>
{displayName}
</div>
)}
</div>
);
};

participant grid

3. Rendering Audio Streams of Hosts​

Alongside video rendering, you can also play a participant’s audio whenever their mic is turned on. Use the useParticipant hook to access the micStream and isLocal properties. Create an <audio> element and update it dynamically using a ref. To prevent audio echo, mute the audio element if the participant is local.

import { useEffect, useRef } from "react";
import { useParticipant } from "@videosdk.live/react-sdk";

const ParticipantView = ({ participantId }) => {
const {
displayName,
micOn,
micStream,
webcamOn,
webcamStream,
isLocal,
} = useParticipant(participantId);

const webcamRef = useRef(null);
const audioRef = useRef(null);

// Attach webcam stream
useEffect(() => {
if (webcamRef.current) {
if (webcamOn && webcamStream) {
const mediaStream = new MediaStream();
mediaStream.addTrack(webcamStream.track);

webcamRef.current.srcObject = mediaStream;
webcamRef.current
.play()
.catch((error) =>
console.error("videoElem.current.play() failed", error)
);
} else {
webcamRef.current.srcObject = null;
}
}
}, [webcamStream, webcamOn]);

// Attach mic stream
useEffect(() => {
if (audioRef.current) {
if (micOn && micStream) {
const mediaStream = new MediaStream();
mediaStream.addTrack(micStream.track);

audioRef.current.srcObject = mediaStream;
audioRef.current
.play()
.catch((error) =>
console.error("audioElem.current.play() failed", error)
);
} else {
audioRef.current.srcObject = null;
}
}
}, [micStream, micOn]);

return (
<div
style={{
height: "300px",
background: "#C0C2C9",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
>
<p>{displayName}</p>
<p>
Webcam: {webcamOn ? "On" : "Off"} | Mic: {micOn ? "On" : "Off"}
</p>

{/* Webcam Video */}
{webcamOn ? (
<video
width={"100%"}
height={"100%"}
ref={webcamRef}
autoPlay
style={{
objectFit: "contain",
...(isLocal
? { transform: "scaleX(-1)", WebkitTransform: "scaleX(-1)" }
: {}),
}}
/>
) : (
<div
style={{
width: "100%",
height: "100%",
background: "#aaa",
display: "flex",
justifyContent: "center",
alignItems: "center",
fontSize: "1.2rem",
}}
>
{displayName}
</div>
)}

{/* Audio Element */}
<audio ref={audioRef} autoPlay muted={isLocal} /> //Muted for local participant
</div>
);
};

Autoplay Audio and Video​

autoplay is a parameter passed to <audio> and <video> elements, indicating that their media should play automatically without requiring the user to click on the video or hit the play button.

When developing an audio-video calling app, ensure that the autoplay flag is set to true, allowing any loaded media to play even if the play() method was not explicitly called.

You can learn more about the autoplay flag in the official documentation.

API Reference​

The API references for all the methods and events utilized in this guide are provided below.

Got a Question? Ask us on discord