### Install Project Dependencies Source: https://github.com/videosdk-live/videosdk-rtc-react-sdk-example/blob/main/README.md Install all the necessary packages for the React SDK example application using npm. ```bash npm install ``` -------------------------------- ### Clone Video SDK React Example Repository Source: https://github.com/videosdk-live/videosdk-rtc-react-sdk-example/blob/main/README.md Use this command to clone the sample application repository from GitHub. ```bash git clone https://github.com/videosdk-live/videosdk-rtc-react-sdk-example.git ``` -------------------------------- ### Copy Environment File Source: https://github.com/videosdk-live/videosdk-rtc-react-sdk-example/blob/main/README.md Copy the example environment file to create your own configuration file. This is a necessary step before configuring your API keys and tokens. ```bash cp .env.example .env ``` -------------------------------- ### Launch the Video SDK React App Source: https://github.com/videosdk-live/videosdk-rtc-react-sdk-example/blob/main/README.md Start the development server to run the sample application. This command compiles the code and launches the app in your default browser. ```bash npm run start ``` -------------------------------- ### Get VideoSDK Auth Token Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Fetches an authentication token from environment variables or an external auth server. Ensure only one configuration source is provided. ```javascript const API_BASE_URL = "https://api.videosdk.live"; const VIDEOSDK_TOKEN = process.env.REACT_APP_VIDEOSDK_TOKEN; const API_AUTH_URL = process.env.REACT_APP_AUTH_URL; export const getToken = async () => { if (VIDEOSDK_TOKEN && API_AUTH_URL) { console.error("Error: Provide only ONE PARAMETER - either Token or Auth API"); } else if (VIDEOSDK_TOKEN) { return VIDEOSDK_TOKEN; } else if (API_AUTH_URL) { const res = await fetch(`${API_AUTH_URL}/get-token`, { method: "GET" }); const { token } = await res.json(); return token; } else { console.error("Error: ", Error("Please add a token or Auth Server URL")); } }; // Usage: const token = await getToken(); // Returns: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` -------------------------------- ### useMediaDevice() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Enumerate and monitor input/output devices. Provides methods to list cameras, microphones, and speakers, check browser permissions, and request them if not yet granted. ```APIDOC ## useMediaDevice() ### Description Provides methods to list cameras, microphones, and speakers, check browser permissions, and request them if not yet granted. ### Methods - `checkPermissions()`: Asynchronously checks the current browser permissions for audio and video. - `requestPermission(mediaType)`: Asynchronously requests permission for a specified media type (audio or video). - `getCameras()`: Asynchronously retrieves a list of available camera devices. - `getMicrophones()`: Asynchronously retrieves a list of available microphone devices. - `getPlaybackDevices()`: Asynchronously retrieves a list of available speaker (playback) devices. ### Events - `onDeviceChanged`: A callback function that fires when an audio or video device is plugged in or unplugged. ### Usage Example ```javascript // Check existing permissions: const permissions = await checkPermissions(); const cameraAllowed = permissions.get(Constants.permission.VIDEO); const micAllowed = permissions.get(Constants.permission.AUDIO); // Request if not granted: if (!micAllowed) { const result = await requestPermission(Constants.permission.AUDIO); const isAudioAllowed = result.get(Constants.permission.AUDIO); } // List all available cameras: const cameras = await getCameras(); // cameras: [{ deviceId: "abc123", label: "FaceTime HD Camera", kind: "videoinput" }, ...] // List all microphones: const mics = await getMicrophones(); // mics: [{ deviceId: "def456", label: "Built-in Microphone", kind: "audioinput" }, ...] // List all speakers: const speakers = await getPlaybackDevices(); // speakers: [{ deviceId: "ghi789", label: "Built-in Output", kind: "audiooutput" }, ...] ``` ``` -------------------------------- ### createMeeting({ token }) Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Creates a new meeting room by calling the VideoSDK REST API. It returns the `meetingId` upon successful creation or an error object if the creation fails. ```APIDOC ## createMeeting({ token }) ### Description Calls the VideoSDK REST API (`POST /v2/rooms`) to create a new meeting room and returns its `meetingId`. Handles API errors gracefully. ### Parameters #### Request Body Parameters - **token** (string) - Required - The authentication token for the VideoSDK API. ### Request Example ```javascript const token = await getToken(); const { meetingId, err } = await createMeeting({ token }); if (meetingId) { console.log("Created meeting:", meetingId); // e.g. "abc-1234-xyz" } else { console.error("Failed to create meeting:", err); } ``` ### Response #### Success Response - **meetingId** (string) - The unique identifier for the newly created meeting room. - **err** (null) - Indicates no error occurred. #### Error Response - **meetingId** (null) - Indicates no meeting ID was generated. - **err** (object) - An object containing error details from the API. ### Equivalent curl ```bash curl -X POST https://api.videosdk.live/v2/rooms \ -H "Authorization: YOUR_TOKEN" \ -H "Content-Type: application/json" ``` ### Source Code (src/api.js) ```javascript const API_BASE_URL = "https://api.videosdk.live"; export const createMeeting = async ({ token }) => { const url = `${API_BASE_URL}/v2/rooms`; const options = { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, }; const response = await fetch(url, options); const data = await response.json(); if (data.roomId) { return { meetingId: data.roomId, err: null }; } else { return { meetingId: null, err: data.error }; } }; ``` ``` -------------------------------- ### Configure .env File with Video SDK Token Source: https://github.com/videosdk-live/videosdk-rtc-react-sdk-example/blob/main/README.md Update the .env file with your temporary Video SDK token. This token is required for authentication and is generated from your Video SDK account. ```env REACT_APP_VIDEOSDK_TOKEN="YOUR_TEMPORARY_TOKEN" ``` -------------------------------- ### Initialize Meeting with MeetingProvider Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Use MeetingProvider as the root component to wrap your meeting UI. Configure meeting settings like ID, participant name, and media states. It provides meeting context to all child hooks. ```jsx import { MeetingProvider } from "@videosdk.live/react-sdk"; import { MeetingContainer } from "./meeting/MeetingContainer"; function App() { const [token, setToken] = useState(""); const [meetingId, setMeetingId] = useState(""); const [participantName, setParticipantName] = useState(""); const [micOn, setMicOn] = useState(false); const [webcamOn, setWebcamOn] = useState(false); const [customAudioStream, setCustomAudioStream] = useState(null); const [customVideoStream, setCustomVideoStream] = useState(null); return ( { setToken(""); setMeetingId(""); setWebcamOn(false); setMicOn(false); }} setIsMeetingLeft={setIsMeetingLeft} /> ); } ``` -------------------------------- ### Manage Media Devices with useMediaDevice Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Use this hook to enumerate and monitor input/output devices like cameras, microphones, and speakers. It also handles browser permission checks and requests. ```javascript import { Constants, useMediaDevice } from "@videosdk.live/react-sdk"; const { checkPermissions, // async () => Map<"audio"|"video", boolean> requestPermission, // async (mediaType) => Map getCameras, // async () => MediaDeviceInfo[] getMicrophones, // async () => MediaDeviceInfo[] getPlaybackDevices, // async () => MediaDeviceInfo[] (speakers) } = useMediaDevice({ onDeviceChanged: () => { // Fires when a device is plugged/unplugged getCameraDevices(); getAudioDevices(); }, }); // Check existing permissions: const permissions = await checkPermissions(); const cameraAllowed = permissions.get(Constants.permission.VIDEO); // true/false/null const micAllowed = permissions.get(Constants.permission.AUDIO); // Request if not granted: if (!micAllowed) { const result = await requestPermission(Constants.permission.AUDIO); const isAudioAllowed = result.get(Constants.permission.AUDIO); // true | false } // List all available cameras: const cameras = await getCameras(); // cameras: [{ deviceId: "abc123", label: "FaceTime HD Camera", kind: "videoinput" }, ...] // List all microphones: const mics = await getMicrophones(); // mics: [{ deviceId: "def456", label: "Built-in Microphone", kind: "audioinput" }, ...] // List all speakers: const speakers = await getPlaybackDevices(); // speakers: [{ deviceId: "ghi789", label: "Built-in Output", kind: "audiooutput" }, ...] ``` -------------------------------- ### useMediaStream() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Create custom media tracks. Custom hook wrapping `createCameraVideoTrack` and `createMicrophoneAudioTrack` from the SDK. Used to obtain optimized `MediaStream` objects before entering the meeting, which are then passed as `customCameraVideoTrack` / `customMicrophoneAudioTrack` to `MeetingProvider`. ```APIDOC ## useMediaStream() ### Description Creates custom media tracks for video and audio. This hook wraps `createCameraVideoTrack` and `createMicrophoneAudioTrack` to provide optimized `MediaStream` objects that can be passed to `MeetingProvider`. ### Methods - `getVideoTrack({ webcamId, encoderConfig })`: Asynchronously creates a video track using the specified camera ID and encoder configuration. - `webcamId` (string): The ID of the camera device to use. - `encoderConfig` (string, optional): The desired encoder configuration (e.g., "h540p_w960p"). Defaults to "h540p_w960p". - `getAudioTrack({ micId })`: Asynchronously creates an audio track using the specified microphone ID. - `micId` (string): The ID of the microphone device to use. ### Usage Example ```javascript const { getVideoTrack, getAudioTrack } = useMediaStream(); const videoStream = await getVideoTrack({ webcamId: "abc123" }); const audioStream = await getAudioTrack({ micId: "def456" }); // Pass to MeetingProvider: setCustomVideoStream(videoStream); setCustomAudioStream(audioStream); ``` ``` -------------------------------- ### Create Custom Media Tracks with useMediaStream Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt This hook simplifies creating custom media streams for video and audio tracks using `createCameraVideoTrack` and `createMicrophoneAudioTrack`. These streams can be passed to `MeetingProvider` as custom tracks. ```javascript import { createCameraVideoTrack, createMicrophoneAudioTrack } from "@videosdk.live/react-sdk"; const useMediaStream = () => { const getVideoTrack = async ({ webcamId, encoderConfig }) => { try { const track = await createCameraVideoTrack({ cameraId: webcamId, encoderConfig: encoderConfig || "h540p_w960p", // 960x540 @ 30fps optimizationMode: "motion", // "motion" | "text" | "detail" multiStream: false, }); return track; // MediaStream with one video track } catch (error) { return null; } }; const getAudioTrack = async ({ micId }) => { try { const track = await createMicrophoneAudioTrack({ microphoneId: micId }); return track; // MediaStream with one audio track } catch (error) { return null; } }; return { getVideoTrack, getAudioTrack }; }; // Usage (inside JoiningScreen / BottomBar): const { getVideoTrack, getAudioTrack } = useMediaStream(); const videoStream = await getVideoTrack({ webcamId: "abc123" }); const audioStream = await getAudioTrack({ micId: "def456" }); // Pass to MeetingProvider: setCustomVideoStream(videoStream); setCustomAudioStream(audioStream); ``` -------------------------------- ### Create VideoSDK Meeting Room Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Creates a new meeting room using the VideoSDK REST API. Handles potential API errors and returns the meeting ID. Requires a valid auth token. ```javascript export const createMeeting = async ({ token }) => { const url = `${API_BASE_URL}/v2/rooms`; const options = { method: "POST", headers: { Authorization: token, "Content-Type": "application/json" }, }; const response = await fetch(url, options); const data = await response.json(); if (data.roomId) { return { meetingId: data.roomId, err: null }; } else { return { meetingId: null, err: data.error }; } }; // Usage: const token = await getToken(); const { meetingId, err } = await createMeeting({ token }); if (meetingId) { console.log("Created meeting:", meetingId); // e.g. "abc-1234-xyz" } else { console.error("Failed to create meeting:", err); } // Equivalent curl: // curl -X POST https://api.videosdk.live/v2/rooms \ // -H "Authorization: YOUR_TOKEN" \ // -H "Content-Type: application/json" ``` -------------------------------- ### useMeeting() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt The core meeting hook for accessing meeting state and actions. It allows toggling media, leaving the meeting, managing recording, screen sharing, and subscribing to meeting-level events. ```APIDOC ## useMeeting() ### Description Core hook for accessing meeting state and actions. Use this hook to toggle media, leave the meeting, manage recording, screen sharing, and subscribe to meeting-level events. ### Returns An object containing meeting state and actions: - **isMeetingJoined** (boolean) - True once the SDK has fully connected. - **localParticipant** (object) - The local participant's data. - **participants** (Map) - A map of all participants in the meeting. - **presenterId** (string | null) - The ID of the participant currently screen sharing. - **localMicOn** (boolean) - Whether the local participant's microphone is on. - **localWebcamOn** (boolean) - Whether the local participant's webcam is on. - **localScreenShareOn** (boolean) - Whether the local participant is screen sharing. - **recordingState** (Constants.recordingEvents.*) - The current state of the meeting recording. - **meetingId** (string) - The ID of the current meeting. ### Actions - **toggleMic** () => void - Toggles the local participant's microphone. - **toggleWebcam** (track?) => void - Toggles the local participant's webcam. Optionally accepts a track. - **toggleScreenShare** () => void - Toggles screen sharing. - **changeMic** (deviceId) => void - Changes the microphone device. - **changeWebcam** (deviceId) => void - Changes the webcam device. - **startRecording** () => void - Starts the meeting recording. - **stopRecording** () => void - Stops the meeting recording. - **leave** () => void - Leaves the meeting. ### Callbacks - **onParticipantJoined**: (participant) => void - Called when a new participant joins the meeting. - **onMeetingLeft**: () => void - Called when the local participant leaves the meeting. - **onRecordingStateChanged**: ({ status }) => void - Called when the recording state changes. - **onError**: ({ code, message }) => void - Called when an error occurs. - **onMeetingStateChanged**: ({ state }) => void - Called when the meeting state changes. ``` -------------------------------- ### getToken() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Retrieves a VideoSDK authentication token. It prioritizes the REACT_APP_VIDEOSDK_TOKEN environment variable. If not found, it fetches a token from an external auth server specified by REACT_APP_AUTH_URL. ```APIDOC ## getToken() ### Description Fetches a VideoSDK authentication token either from the `REACT_APP_VIDEOSDK_TOKEN` environment variable or from an external auth server at `REACT_APP_AUTH_URL`. Exactly one source must be configured. ### Usage ```javascript const token = await getToken(); // Returns: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." ``` ### Source Code (src/api.js) ```javascript const API_BASE_URL = "https://api.videosdk.live"; const VIDEOSDK_TOKEN = process.env.REACT_APP_VIDEOSDK_TOKEN; const API_AUTH_URL = process.env.REACT_APP_AUTH_URL; export const getToken = async () => { if (VIDEOSDK_TOKEN && API_AUTH_URL) { console.error("Error: Provide only ONE PARAMETER - either Token or Auth API"); } else if (VIDEOSDK_TOKEN) { return VIDEOSDK_TOKEN; } else if (API_AUTH_URL) { const res = await fetch(`${API_AUTH_URL}/get-token`, { method: "GET" }); const { token } = await res.json(); return token; } else { console.error("Error: ", Error("Please add a token or Auth Server URL")); } }; ``` ``` -------------------------------- ### MeetingAppContext / useMeetingAppContext() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt React context and hook for accessing and managing application-level shared state, such as selected audio/video devices, sidebar visibility, raised hands, and PiP mode, across different components without prop drilling. ```APIDOC ## MeetingAppContext / useMeetingAppContext() ### Description React context providing shared UI state (selected devices, sidebar mode, raised hands, PiP mode, permissions) to all components without prop drilling. The `useMeetingAppContext` hook provides easy access to this context. ### Usage ```jsx import { useMeetingAppContext } from "@videosdk.live/react-sdk"; const MyComponent = () => { const { sideBarMode, setSideBarMode, selectedMic } = useMeetingAppContext(); const openChat = () => { setSideBarMode("CHAT"); }; return (

Selected Microphone: {selectedMic.label || "None"}

); }; ``` ### Context Values - `selectedMic` (object): Details of the selected microphone. - `setSelectedMic` (function): Function to set the selected microphone. - `selectedWebcam` (object): Details of the selected webcam. - `setSelectedWebcam` (function): Function to set the selected webcam. - `selectedSpeaker` (object): Details of the selected speaker device. - `setSelectedSpeaker` (function): Function to set the selected speaker device. - `raisedHandsParticipants` (array): List of participants who have raised their hands. - `setRaisedHandsParticipants` (function): Function to update the list of raised hands. - `sideBarMode` (string | null): Current mode of the sidebar (e.g., "CHAT", "PARTICIPANTS", null). - `setSideBarMode` (function): Function to set the sidebar mode. - `pipMode` (boolean): Indicates if Picture-in-Picture mode is active. - `setPipMode` (function): Function to toggle PiP mode. - `useRaisedHandParticipants` (function): Hook to manage participant raised hand events. ``` -------------------------------- ### Responsive Participant Grid with ParticipantGrid Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Component that renders participant tiles in a dynamic grid. The column count automatically adjusts based on the number of participants, screen share status, and viewport size. Use this to display multiple participants efficiently. ```jsx import { MemoizedParticipantGrid } from "./ParticipantGrid"; // In meeting/components/ParticipantView.js: function ParticipantView({ isPresenting }) { const { participants } = useMeeting(); const [participantsData, setParticipantsData] = useState([]); useEffect(() => { // Debounce 500ms to avoid rapid re-renders on join/leave const timeout = setTimeout(() => { setParticipantsData(Array.from(participants.keys())); }, 500); return () => clearTimeout(timeout); }, [participants]); return ( ); } ``` ```plaintext // Grid column logic (from ParticipantGrid.js): // isPresenting / isMobile: 1–3 columns (1 col if <4p, 2 if <9p, else 3) // Desktop without presenter: 2–4 columns (2 col if <5p, 3 if <7p, 4 if <9p, ...) // Memoized: only re-renders when participantIds array or isPresenting changes ``` -------------------------------- ### Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt The root SDK component that wraps the entire meeting UI and provides meeting context to all child hooks. It is configured with meeting ID, participant name, media state, and custom tracks. ```APIDOC ## ### Description Initializes and provides a meeting session. This is the root SDK component that wraps the entire meeting UI and provides meeting context to all child hooks. It is configured with the meeting ID, participant name, media state, and custom tracks. ### Props - **config** (object) - Configuration object for the meeting. - **meetingId** (string) - Room ID from createMeeting/validateMeeting. - **micEnabled** (boolean) - Start with mic on/off. - **webcamEnabled** (boolean) - Start with webcam on/off. - **name** (string) - Display name. Defaults to "Guest". - **multiStream** (boolean) - Enables simulcast video layers. - **customCameraVideoTrack** (MediaStreamTrack) - Pre-built video track from useMediaStream. - **customMicrophoneAudioTrack** (MediaStreamTrack) - Pre-built audio track from useMediaStream. - **token** (string) - Authentication token for the meeting. - **reinitialiseMeetingOnConfigChange** (boolean) - Whether to reinitialize the meeting when configuration changes. - **joinWithoutUserInteraction** (boolean) - Whether to join the meeting without user interaction. ``` -------------------------------- ### Core Meeting Hook: useMeeting Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt The useMeeting hook provides access to meeting state and actions like toggling media, leaving, recording, and screen sharing. It also allows subscribing to meeting-level events. ```js import { Constants, useMeeting } from "@videosdk.live/react-sdk"; const { isMeetingJoined, localParticipant, participants, presenterId, localMicOn, localWebcamOn, localScreenShareOn, recordingState, meetingId, toggleMic, toggleWebcam, toggleScreenShare, changeMic, changeWebcam, startRecording, stopRecording, leave } = useMeeting({ onParticipantJoined: (participant) => { participant.setQuality("high"); // Force high quality for new participants }, onMeetingLeft: () => { // Clean up selected devices in context setSelectedMic({ id: null, label: null }); }, onRecordingStateChanged: ({ status }) => { if (status === Constants.recordingEvents.RECORDING_STARTED) { toast("Meeting recording is started"); } }, onError: ({ code, message }) => { const joiningErrCodes = [4001, 4002, 4003, 4004, 4005, 4006, 4007, 4008, 4009, 4010]; const isJoiningError = joiningErrCodes.includes(code); new Audio("https://static.videosdk.live/prebuilt/notification_err.mp3").play(); setMeetingError({ code, message: isJoiningError ? "Unable to join meeting!" : message }); }, onMeetingStateChanged: ({ state }) => { console.log("Meeting state:", state); // CONNECTING | CONNECTED | FAILED | ... }, }); ``` -------------------------------- ### useParticipant Hook for Participant Media and Stats Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Use this hook to subscribe to a single participant's media streams, check their media status, and retrieve real-time WebRTC quality statistics. It provides access to webcam and mic status, display name, and media streams. ```javascript import { useParticipant, VideoPlayer } from "@videosdk.live/react-sdk"; function ParticipantVideoSection({ participantId }) { const { webcamOn, micOn, displayName, isLocal, isActiveSpeaker, micStream, webcamStream, screenShareStream, getVideoStats, getAudioStats, getShareStats, mode, } = useParticipant(participantId); return webcamOn ? ( ) : (

{displayName?.charAt(0).toUpperCase()}

); } // Retrieve WebRTC stats every 500ms: const statsIntervalId = setInterval(async () => { const videoStats = await getVideoStats(); }, 500); ``` -------------------------------- ### validateMeeting({ roomId, token }) Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Validates an existing meeting room by calling the VideoSDK API. It confirms if a room ID is valid and active, returning the `meetingId` on success or an error message if the room is invalid or expired. ```APIDOC ## validateMeeting({ roomId, token }) ### Description Calls `GET /v2/rooms/validate/:roomId` to confirm a room is valid before joining. Returns the `meetingId` on success or an error string if the room does not exist or is expired. ### Parameters #### Path Parameters - **roomId** (string) - Required - The ID of the meeting room to validate. #### Request Body Parameters - **token** (string) - Required - The authentication token for the VideoSDK API. ### Request Example ```javascript const token = await getToken(); const { meetingId, err } = await validateMeeting({ roomId: "abc-1234-xyz", token }); if (meetingId) { // Proceed to join setToken(token); setMeetingId(meetingId); onClickStartMeeting(); } else { toast(`${err}`, { position: "bottom-left", autoClose: 4000 }); } ``` ### Response #### Success Response - **meetingId** (string) - The validated meeting room ID. - **err** (null) - Indicates no error occurred. #### Error Response (Status Code 400) - **meetingId** (null) - Indicates the room is invalid. - **err** (string) - A message describing the validation error (e.g., room not found or expired). ### Source Code (src/api.js) ```javascript const API_BASE_URL = "https://api.videosdk.live"; export const validateMeeting = async ({ roomId, token }) => { const url = `${API_BASE_URL}/v2/rooms/validate/${roomId}`; const options = { method: "GET", headers: { Authorization: token, "Content-Type": "application/json" }, }; const response = await fetch(url, options); if (response.status === 400) { const data = await response.text(); return { meetingId: null, err: data }; } const data = await response.json(); return data.roomId ? { meetingId: data.roomId, err: null } : { meetingId: null, err: data.error }; }; ``` ``` -------------------------------- ### Display Screen Share with PresenterView Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Component to render the active presenter's screen share stream. It plays system audio separately and shows a 'Stop Presenting' button for the local presenter. Ensure VideoPlayer is imported. ```jsx import { useMeeting, useParticipant, VideoPlayer } from "@videosdk.live/react-sdk"; export function PresenterView({ height }) { const { presenterId, toggleScreenShare } = useMeeting(); // PresenterAudioPlayer: plays screen share audio for remote presenter const { isLocal, screenShareAudioStream, screenShareOn } = useParticipant(presenterId); useEffect(() => { if (!isLocal && audioPlayer.current && screenShareOn && screenShareAudioStream) { const mediaStream = new MediaStream(); mediaStream.addTrack(screenShareAudioStream.track); audioPlayer.current.srcObject = mediaStream; audioPlayer.current.play().catch(console.error); } }, [screenShareAudioStream, screenShareOn, isLocal]); return (
{/* Screen share video */} {/* "STOP PRESENTING" overlay shown only to the local presenter */} {isLocal && ( )}
); } ``` -------------------------------- ### usePubSub(topic) Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Enables broadcast messaging between all meeting participants over a named topic. Used for in-meeting chat and raise-hand notifications. ```APIDOC ## usePubSub(topic) ### Description Enables broadcast messaging between all meeting participants over a named topic. Used for in-meeting chat and raise-hand notifications. ### Parameters #### Path Parameters - **topic** (string) - Required - The name of the topic for publish/subscribe messaging. ### Methods - **publish(message, options?)** - Publishes a message to the specified topic. - **message** (any) - The message content to publish. - **options** (object) - Optional configuration for publishing. - **persist** (boolean) - If true, the message history will be kept. ### Return Values - **messages** (array) - An array of received messages for the topic. Each message object has the following structure: `{ senderId, senderName, message, timestamp }`. ### Event Handlers - **onMessageReceived(callback)** - A callback function that is invoked when a new message is received on the topic. - The callback receives an object with message details: `{ senderId, senderName, message, timestamp }`. ### Request Example ```javascript // --- Sending a chat message --- import { usePubSub } from "@videosdk.live/react-sdk"; const ChatInput = () => { const { publish } = usePubSub("CHAT"); const [message, setMessage] = useState(""); const sendMessage = () => { const text = message.trim(); if (text.length > 0) { publish(text, { persist: true }); // persist: true keeps message history setMessage(""); } }; // ... }; // --- Receiving all chat messages --- const ChatMessages = () => { const { messages } = usePubSub("CHAT"); // messages: [{ senderId, senderName, message, timestamp }, ...] return messages.map(({ senderId, senderName, message, timestamp }) => (
{senderName}: {message}
)); }; // --- Raise Hand notification --- // Publishing (in BottomBar.js): const { publish: publishHand } = usePubSub("RAISE_HAND"); publishHand("Raise Hand"); // broadcast to all participants // Subscribing (in MeetingContainer.js): usePubSub("RAISE_HAND", { onMessageReceived: ({ senderId, senderName }) => { new Audio("https://static.videosdk.live/prebuilt/notification.mp3").play(); toast(`${senderName} raised hand 🖐🏼`); participantRaisedHand(senderId); // update context state }, }); ``` ``` -------------------------------- ### Measure Network Speed with getNetworkStats Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Use this utility function to measure real-time upload and download bandwidth. It's useful for pre-call network status checks. Handle potential 'no Network' or 'timeout' errors. ```javascript import { getNetworkStats } from "@videosdk.live/react-sdk"; const getNetworkStatistics = async () => { try { const options = { timeoutDuration: 45000 }; // 45-second timeout const networkStats = await getNetworkStats(options); console.log(networkStats.downloadSpeed); // e.g. "12.34" (MBPS) console.log(networkStats.uploadSpeed); // e.g. "8.56" (MBPS) } catch (ex) { if (ex === "Not able to get NetworkStats due to no Network") { // Show offline warning UI } if (ex === "Not able to get NetworkStats due to timeout") { // Show timeout warning UI } } }; ``` -------------------------------- ### MeetingAppContext for Shared State Management Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt This React context and hook provide a way to share application-level UI state across components without prop drilling. It manages device selection, sidebar visibility, raised hands, and PiP mode. Use `MeetingAppProvider` to wrap your application and `useMeetingAppContext` in any child component to access shared state. ```jsx // src/MeetingAppContextDef.js import { createContext, useContext, useState, useEffect, useRef } from "react"; export const MeetingAppContext = createContext(); export const useMeetingAppContext = () => useContext(MeetingAppContext); export const MeetingAppProvider = ({ children }) => { const [selectedMic, setSelectedMic] = useState({ id: null, label: null }); const [selectedWebcam, setSelectedWebcam] = useState({ id: null, label: null }); const [selectedSpeaker, setSelectedSpeaker] = useState({ id: null, label: null }); const [raisedHandsParticipants, setRaisedHandsParticipants] = useState([]); const [sideBarMode, setSideBarMode] = useState(null); // "CHAT" | "PARTICIPANTS" | null const [pipMode, setPipMode] = useState(false); const useRaisedHandParticipants = () => { const raisedHandsParticipantsRef = useRef(); const participantRaisedHand = (participantId) => { const list = [...raisedHandsParticipantsRef.current]; const newItem = { participantId, raisedHandOn: Date.now() }; const idx = list.findIndex(({ participantId: pID }) => pID === participantId); if (idx === -1) list.push(newItem); else list[idx] = newItem; setRaisedHandsParticipants(list); }; // Auto-clear raised hands after 15 seconds useEffect(() => { const interval = setInterval(() => { const now = Date.now(); setRaisedHandsParticipants((prev) => prev.filter(({ raisedHandOn }) => raisedHandOn + 15000 > now) ); }, 1000); return () => clearInterval(interval); }, []); return { participantRaisedHand }; }; return ( {children} ); }; // Consuming in any child component: const { sideBarMode, setSideBarMode, selectedMic } = useMeetingAppContext(); setSideBarMode("CHAT"); // open chat panel ``` -------------------------------- ### useParticipant(participantId) Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Subscribes to a single participant's streams, media state, and provides methods to retrieve real-time WebRTC quality statistics. ```APIDOC ## useParticipant(participantId) ### Description Subscribes to a single participant's streams, media state, and provides methods to retrieve real-time WebRTC quality statistics. ### Parameters #### Path Parameters - **participantId** (string) - Required - The unique identifier for the participant. ### Return Values - **webcamOn** (boolean) - Indicates if the participant's webcam is on. - **micOn** (boolean) - Indicates if the participant's microphone is on. - **displayName** (string) - The display name of the participant. - **isLocal** (boolean) - Indicates if the participant is the local user. - **isActiveSpeaker** (boolean) - Indicates if the participant is currently the active speaker. - **micStream** (MediaStream object) - The MediaStream object for the participant's audio. - **webcamStream** (MediaStream object) - The MediaStream object for the participant's video. - **screenShareStream** (MediaStream object) - The MediaStream object for the participant's screen share. - **mode** (string) - The current media mode of the participant ('SEND_AND_RECV', 'RECV_ONLY', 'SEND_ONLY'). ### Methods - **getVideoStats()** - async () => stats[] - Retrieves real-time video statistics. - **getAudioStats()** - async () => stats[] - Retrieves real-time audio statistics. - **getShareStats()** - async () => stats[] - Retrieves real-time screen share statistics. ### Request Example ```javascript import { useParticipant, VideoPlayer } from "@videosdk.live/react-sdk"; function ParticipantVideoSection({ participantId }) { const { webcamOn, micOn, displayName, isLocal, isActiveSpeaker, micStream, webcamStream, screenShareStream, getVideoStats, getAudioStats, getShareStats, mode, } = useParticipant(participantId); // Render video stream using SDK's VideoPlayer component return webcamOn ? ( ) : (

{displayName?.charAt(0).toUpperCase()}

); } // Retrieve WebRTC stats every 500ms: const statsIntervalId = setInterval(async () => { const videoStats = await getVideoStats(); // videoStats[0]: { rtt, jitter, packetsLost, totalPackets, bitrate, // size: { width, height, framerate }, codec, // currentSpatialLayer, currentTemporalLayer } }, 500); ``` ``` -------------------------------- ### usePubSub Hook for Real-time Messaging Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt This hook enables broadcast messaging between all meeting participants over a named topic, suitable for in-meeting chat or notifications. Use 'publish' to send messages and 'messages' to receive them. Configuration options for 'onMessageReceived' are available for custom handling. ```javascript import { usePubSub } from "@videosdk.live/react-sdk"; // --- Sending a chat message --- const ChatInput = () => { const { publish } = usePubSub("CHAT"); const [message, setMessage] = useState(""); const sendMessage = () => { const text = message.trim(); if (text.length > 0) { publish(text, { persist: true }); // persist: true keeps message history setMessage(""); } }; // ... }; // --- Receiving all chat messages --- const ChatMessages = () => { const { messages } = usePubSub("CHAT"); // messages: [{ senderId, senderName, message, timestamp }, ...] return messages.map(({ senderId, senderName, message, timestamp }) => (
{senderName}: {message}
)); }; // --- Raise Hand notification --- // Publishing (in BottomBar.js): const { publish: publishHand } = usePubSub("RAISE_HAND"); publishHand("Raise Hand"); // broadcast to all participants // Subscribing (in MeetingContainer.js): usePubSub("RAISE_HAND", { onMessageReceived: ({ senderId, senderName }) => { new Audio("https://static.videosdk.live/prebuilt/notification.mp3").play(); toast(`${senderName} raised hand 🖐🏼`); participantRaisedHand(senderId); // update context state }, }); ``` -------------------------------- ### ParticipantPanel Component for Participant List Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Lists all meeting participants, sorted by raised-hand status with raised hands appearing first. Displays mic/webcam status and a raised-hand indicator for each participant. Uses `useMeetingAppContext` for `raisedHandsParticipants` and `useMeeting` for `participants`. Requires `useMemo` for sorting. ```jsx // src/components/sidebar/ParticipantPanel.js import { useMeeting, useParticipant } from "@videosdk.live/react-sdk"; import { useMeetingAppContext } from "../../MeetingAppContextDef"; export function ParticipantPanel({ panelHeight }) { const { raisedHandsParticipants } = useMeetingAppContext(); const { participants } = useMeeting(); // Sort: raised-hand participants first (newest raise at top), rest below const sortedList = useMemo(() => { const ids = [...participants.keys()]; const notRaised = ids.filter( (id) => !raisedHandsParticipants.find(({ participantId }) => participantId === id) ); const raisedSorted = [...raisedHandsParticipants].sort((a, b) => b.raisedHandOn - a.raisedHandOn); return [ ...raisedSorted.map(({ participantId }) => ({ participantId, raisedHand: true })), ...notRaised.map((id) => ({ participantId: id, raisedHand: false })), ]; }, [raisedHandsParticipants, participants]); return (
{sortedList.map(({ participantId, raisedHand }) => { const { displayName, isLocal, micOn, webcamOn } = useParticipant(participantId); return (
{isLocal ? "You" : displayName} {raisedHand && 🖐} {micOn ? "🎤" : "🔇"} {webcamOn ? "📷" : "📷❌"}
); })}
); } ``` -------------------------------- ### useIsRecording() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt A custom hook that returns a boolean indicating if a recording is currently active or stopping. It derives its state from the `recordingState` provided by the `useMeeting` hook. ```APIDOC ## useIsRecording() ### Description Custom hook that derives a simple boolean from the SDK's `recordingState` enum. Returns `true` when a recording is actively running or in the process of stopping. ### Usage ```javascript import { useIsRecording } from "@videosdk.live/react-sdk"; const isRecording = useIsRecording(); // Use isRecording to conditionally render UI or trigger actions if (isRecording) { // Show stop recording button } else { // Show start recording button } ``` ### Returns - `boolean`: `true` if recording is started or stopping, `false` otherwise. ``` -------------------------------- ### getNetworkStats() Source: https://context7.com/videosdk-live/videosdk-rtc-react-sdk-example/llms.txt Measure upload/download speed. SDK utility function used in the pre-call `NetworkStats` component to display real-time upload and download bandwidth to the user before joining. ```APIDOC ## getNetworkStats() ### Description Measures the user's upload and download network speed. This utility function is useful for displaying real-time bandwidth information before joining a meeting. ### Parameters - `options` (object, optional): Configuration options for the network stats measurement. - `timeoutDuration` (number, optional): The duration in milliseconds to attempt the network speed test. Defaults to 45000 (45 seconds). ### Returns - An object containing `downloadSpeed` and `uploadSpeed` in MBPS. ### Usage Example ```javascript const options = { timeoutDuration: 45000 }; // 45-second timeout const networkStats = await getNetworkStats(options); console.log(networkStats.downloadSpeed); // e.g. "12.34" (MBPS) console.log(networkStats.uploadSpeed); // e.g. "8.56" (MBPS) ``` ### Error Handling - Throws an error if network stats cannot be determined due to network unavailability or timeout. - `"Not able to get NetworkStats due to no Network"` - `"Not able to get NetworkStats due to timeout"` ```