Skip to main content

MediaSFU ReactJS

This guide gives you the public setup path for the MediaSFU ReactJS package and points to generated API references when you need exact signatures or types.

Quick start

  • Best for: Web apps with full React control
  • Package/artifact: mediasfu-reactjs
  • Install: npm i mediasfu-reactjs

Start in 60 seconds

  1. Install the package: npm i mediasfu-reactjs
  2. Pick backend mode: MediaSFU Cloud or self-hosted MediaSFU Open.
  3. Follow the first setup section below for your framework.

Before you continue

  • Best for: Web apps with full React control
  • New to MediaSFU? Start at /sdks to compare frameworks quickly.

Copy/paste starter

Start with install + backend config, then follow the first integration section below.

npm i mediasfu-reactjs
export const mediaSFUConfig = {
// Cloud mode
credentials: {
apiUserName: process.env.MEDIASFU_API_USERNAME ?? '',
apiKey: process.env.MEDIASFU_API_KEY ?? '',
},
localLink: '',
connectMediaSFU: true,
};
export const mediaSFULocalConfig = {
// Self-hosted mode
credentials: undefined,
localLink: 'http://localhost:3000',
connectMediaSFU: true,
};

Do not skip this order

  1. Decide backend mode first: MediaSFU Cloud or self-hosted MediaSFU Open.
  2. Validate one successful create or join flow with the default room surface from this SDK.
  3. Only then customize the shell, cards, or room ownership model.
  4. Use the generated API reference when you need exact symbols or signatures, not as the first stop.

This order prevents most early confusion and keeps backend issues separate from UI customization work.

Choose your backend mode

ModeBest forWhat you must provide
MediaSFU CloudFastest onboarding, managed infrastructure, less operational workCloud credentials stored in secure runtime or build configuration.
MediaSFU Open / self-hostedPrivate infrastructure, local control, custom deployment requirementsA self-hosted MediaSFU Open deployment plus the URL or config you pass into localLink or the equivalent connection setting.

If you have not made this choice yet, make it before going deeper into customization or API reference material.

API reference

  • Start with the portal overview at /api-reference.
  • Use the MediaSFU ReactJS entry on that page to open the staged TypeDoc site for this package at /api/reactjs/.

Use the SDK guide for workflow guidance and the staged TypeDoc site for exact package details, generated symbols, and signatures.

Common setup mistakes

  • Using self-hosted mode without setting localLink to your server.
  • Forgetting to pass credentials in cloud mode.
  • Mixing cloud credentials with disabled connectMediaSFU during production tests.
  • Backend endpoint unreachable (Cloud credentials invalid or self-hosted server offline).
  • Credentials committed directly in source files instead of secure environment configuration.

If setup fails, verify install → backend mode → credentials/local link in that order.

Troubleshooting quick checks

CheckSymptomQuick fix
Backend mode mismatchJoin/create flow fails earlyConfirm Cloud credentials for cloud mode, or set localLink for self-hosted mode.
Credentials not loadedAuth/connect errorsVerify env loading and pass credentials explicitly to SDK config.
Dependency mismatchBuild/install warningsReinstall dependencies and avoid force-install flags unless absolutely required.

Use this table first before diving into deeper API sections.

Production readiness checklist

  • Backend mode decided (Cloud vs self-hosted) and documented.
  • Credentials/keys sourced from secure environment config (not hard-coded).
  • SDK configuration is centralized and reused across app entrypoints.
  • Happy-path join/create flow validated end-to-end.
  • Release build passes cleanly in the target app environment.

Mark all items before release.


MediaSFU ReactJS SDK

Browser WebRTC SDK for video calling, voice calling, conferencing, webinars, live streaming, chat, recording, screen sharing, whiteboards, polls, live subtitles, translation, AI agents, and SIP workflows.

MediaSFU ReactJS gives you prebuilt, fully-featured room components with real-time video/audio, screen sharing, recording, chat, polls, whiteboards, real-time translation, and more. Drop them into your React app with a few lines of code and go live.

It is designed for teams that want to start with prebuilt room UI and then progressively customize or replace that UI without rebuilding the media runtime, signaling, or room orchestration layers from scratch.

Quick Start: First Working Room

npm install mediasfu-reactjs
import { MediasfuGeneric } from "mediasfu-reactjs";

export default function App() {
return (
<MediasfuGeneric
credentials={{ apiUserName: "your-user", apiKey: "your-key" }}
connectMediaSFU={true}
/>
);
}

You still need a MediaSFU-compatible backend for room lifecycle, signaling, and media routing. Use MediaSFU Cloud for managed infrastructure or MediaSFU Open for self-hosting.

Choose your UI model

  • Keep the bundled room UI for the fastest route to production.
  • Replace targeted surfaces with uiOverrides, custom cards, and custom shells.
  • Run MediaSFU headless with returnUI={false} when your product owns the entire browser experience.

Why browser teams choose MediaSFU

Without MediaSFUWith MediaSFU
6–12 months of WebRTC, TURN/STUN, codec worknpm install mediasfu-reactjs → done
$1–5 per 1,000 minutes (Twilio, Vonage, Daily)$0.10 per 1,000 minutes — 10–50× cheaper
Build every modal, card, and control from scratchPrebuilt components — classic & modern themes
Wire up third-party AI, TTS, vision APIs yourselfBuilt-in AI agents, voice translation, transcription
Separate codebases per platformOne API surface → React, React Native, Flutter, Angular, Vue
Weeks of infrastructure setupUnder 5 minutes

🔥 What Makes MediaSFU Different

Embeddable by Design — Other platforms give you raw APIs and leave you to build the UI. MediaSFU gives you finished, production-ready components — video grids, control bars, modals, chat panels, recording controls — that you drop in and customize.Pricing That Makes Sense — $0.10 per 1,000 minutes. MediaSFU runs its own media infrastructure. No reselling. No hidden fees. Free tier included, no credit card required.
AI-Native, Not Bolted On — AI agents, real-time voice translation (50+ languages), live transcription, and intelligent routing are built into the platform — not third-party add-ons you wire up yourself.Full Stack, One Platform — Voice + video + chat + screen sharing + recording + polls + whiteboards + breakout rooms + AI + translation + SIP. All included. Replace 5 communication tools with one SDK.

⚠️ Important: Backend Server Required

MediaSFU is a frontend SDK that requires a backend media server to function.

You have two options:

OptionDescriptionBest For
☁️ MediaSFU CloudManaged service at mediasfu.comProduction apps, zero infrastructure
🏠 MediaSFU OpenSelf-hosted open-source serverFull control, on-premise requirements
# Option 1: Use MediaSFU Cloud
# Sign up at https://www.mediasfu.com and get your API credentials

# Option 2: Self-host with MediaSFU Open
git clone https://github.com/MediaSFU/MediaSFUOpen
cd MediaSFUOpen

📖 MediaSFU Cloud Documentation →
📖 MediaSFU Open Repository →


✨ Platform Features

Everything you need for enterprise-grade real-time communication — included at $0.10/1K min:

🎥 Video & Audio

  • Multi-party video conferencing with adaptive quality
  • Screen sharing with real-time annotation
  • Virtual backgrounds and video effects
  • Audio-only participant support

🎤 Real-time Translation 🌍

  • Speak in any language — The system auto-detects what language you're speaking
  • Listen in any language — Hear others translated to your preferred language in real time
  • Live transcription — See real-time transcripts during meetings
  • 50+ languages supported — True borderless communication
  • No interpreters. No delay. Works with voice, video, and chat.

🤖 AI-Powered Features

  • AI voice agents that answer, resolve, and escalate
  • Multimodal AI with voice + vision capabilities
  • AI-generated meeting summaries and transcription
  • Intelligent call routing and warm handoffs
  • Voice cloning options with custom TTS configurations

👥 Participant Management

  • Panelists Mode — Designate speakers in webinars with audience Q&A
  • Individual Permissions — Granular per-participant control (video/audio/screen/chat)
  • Group Permissions — Apply permission templates to participant groups
  • Waiting room with manual admit
  • Co-host delegation with configurable responsibilities
  • Breakout rooms for focused discussions

📊 Engagement Tools

  • Live polls with real-time results
  • In-meeting chat (direct & group)
  • Collaborative whiteboards

🎬 Recording & Analytics

  • Cloud recording with track-based customization
  • Watermarks, name tags, custom backgrounds
  • Real-time call analytics

🔒 Security & Control

  • End-to-end encryption option
  • Domain-locked API keys
  • Managed events with time/capacity limits
  • Abandoned participant handling

📖 Table of Contents

  • Quick Start
  • Installation
  • Component Storybook
  • Prebuilt Event Rooms
  • Modern UI Components
  • Usage Examples
  • Key Components
  • Customization
  • API Reference
  • Self-Hosting / Community Edition
  • Advanced Features (Panelists, Permissions, Translation)
  • sourceParameters - The Power API
  • AudioGrid - Display All Audio Participants
  • Using Modals Standalone
  • Building Your Own UI
  • SDKs for Every Framework
  • Detailed Documentation

🚀 Quick Start

Three steps. Under 5 minutes. First video call live.

1. Install

npm install mediasfu-reactjs

2. Import & Render

import { MediasfuGeneric } from 'mediasfu-reactjs';

function App() {
return (
<MediasfuGeneric
credentials={{ apiUserName: "yourUsername", apiKey: "yourAPIKey" }}
/>
);
}

3. Run

npm start

That's it. You have a fully-featured video conferencing room with screen sharing, chat, recording, and more.

ℹ️ Critical component styles are automatically injected at runtime. For additional styling options, see Optional CSS Import.

Want to try without a server? Use demo mode:

<MediasfuGeneric
useLocalUIMode={true}
useSeed={true}
seedData={{ member: "DemoUser", eventType: "conference" }}
/>

📦 Installation

# npm
npm install mediasfu-reactjs

# yarn
yarn add mediasfu-reactjs

# pnpm
pnpm add mediasfu-reactjs

Peer Dependencies

The following are required peer dependencies:

{
"react": "^18.2.0 || ^19.0.0",
"react-dom": "^18.2.0 || ^19.0.0",
"@fortawesome/fontawesome-svg-core": "^6.0.0",
"@fortawesome/free-solid-svg-icons": "^6.0.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"bootstrap": "^5.0.0",
"mediasoup-client": "^3.7.0",
"socket.io-client": "^4.0.0",
"universal-cookie": "^7.0.0"
}

Optional Peer Dependencies

For virtual background support (blur, image backgrounds):

npm install @mediapipe/selfie_segmentation@0.1.1675465747

This is optional — if not installed, virtual backgrounds simply won't be available.

Optional CSS Import

Critical styles for control buttons, containers, and core components are automatically injected at runtime — no manual import needed.

If you need additional styling (e.g., custom modal themes, waiting room lists), you can optionally import the full stylesheet:

// Optional: Import for additional component styles
import 'mediasfu-reactjs/dist/main.css';

Most applications work perfectly without this import.


📚 Component Storybook

This package owns the React Storybook used for visual inspection of runtime-light MediaSFU surfaces. It is intended to sit beside the main Docusaurus docs portal, not replace it.

Run it from the MediaSFUReactJS package directory:

npm run storybook

Build the static Storybook output for deployment:

npm run build-storybook

For local visual inspection, the most reliable path in this repo is to serve the built storybook-static output after that command completes:

python3 -m http.server 6006 -d storybook-static

The dev server remains useful for iterative authoring, but its indexer can be stricter than the static build for generated TS-heavy stories.

Baseline stories for safe, presentational, or seeded modern components are generated automatically before both commands run. The current automated targets cover the modern widget barrel, a safe subset of display components, misc entry flows, most exported modal-style modern barrels, the whiteboard configuration modal, and ModernMediasfuGeneric in seeded local-UI mode. To refresh them directly:

npm run generate-storybook-stories

The initial stories live under src/stories and focus on components that do not need a live MediaSFU session:

  • UiOverridesGuide
  • PremiumButton
  • GradientCard
  • GlassmorphicContainer
  • ModernBackgroundModal

Curated internal modal stories also live under src/stories/InternalComponents for ModernPermissionsModal, ModernPanelistsModal, and TranslationSettingsModal.

Curated display and canvas stories live under src/stories/DisplayComponents and src/stories/WhiteboardComponents for surfaces that are too stateful for the generated baseline set, including ModernVideoCard, ModernAudioCard, ModernControlButtonsComponent, ModernPagination, ModernFlexibleGrid, ModernFlexibleVideo, ModernMainContainerComponent, and the collaborative Whiteboard canvas.

That same display story surface now also includes classic display primitives that are still relevant in the mixed modern/classic room stack, including MiniAudio, MiniCardAudio, ControlButtonsComponent, ControlButtonsAltComponent, and ControlButtonsComponentTouch.

Generated baseline coverage is written to src/stories/generated and is intended for runtime-light or safely stubbed components only. Media-stream-driven and highly stateful meeting surfaces such as video grids, control stacks, pagination, and virtual-background flows still need curated stories with explicit fixtures.

If you want the public docs site to expose Storybook in navigation, deploy the generated storybook-static output separately and point the docs portal at it with MEDIASFU_STORYBOOK_URL.


🏛️ Prebuilt Event Rooms

Choose the room type that fits your use case — or use MediasfuGeneric for maximum flexibility:

ComponentUse CaseDescription
MediasfuGenericUniversalSupports all event types dynamically
ModernMediasfuGenericUniversal (Premium)Theme-aware, glassmorphism UI
MediasfuConferenceMeetingsMulti-party video conferencing
MediasfuWebinarWebinarsPresenters + audience model
MediasfuBroadcastBroadcastingOne-to-many live streaming
MediasfuChatChat RoomsText-based with optional media

All prebuilt components share the same props interface:

interface MediasfuProps {
// Authentication
credentials?: { apiUserName: string; apiKey: string };

// Connection
localLink?: string; // Self-hosted server URL
connectMediaSFU?: boolean; // Toggle auto-connection

// Customization
PrejoinPage?: (options) => ReactNode;
customVideoCard?: CustomVideoCardType;
customAudioCard?: CustomAudioCardType;
customMiniCard?: CustomMiniCardType;
uiOverrides?: MediasfuUICustomOverrides;

// Advanced
returnUI?: boolean; // Set false for headless mode
useLocalUIMode?: boolean; // Demo/local mode
seedData?: SeedData; // Pre-populate for demos
}

💡 Usage Examples

Basic Conference Room

import { MediasfuConference } from 'mediasfu-reactjs';

function ConferenceApp() {
return (
<MediasfuConference
credentials={{
apiUserName: "yourUsername",
apiKey: "yourAPIKey"
}}
/>
);
}

Webinar with Custom Branding

import { MediasfuWebinar, PreJoinPage } from 'mediasfu-reactjs';

function WebinarApp() {
return (
<MediasfuWebinar
credentials={{ apiUserName: "user", apiKey: "key" }}
PrejoinPage={(options) => (
<PreJoinPage
{...options}
imgSrc="/your-logo.png"
/>
)}
containerStyle={{
background: "linear-gradient(135deg, #1a1a2e, #16213e)"
}}
/>
);
}

Demo/Preview Mode (No Server)

import { 
MediasfuGeneric,
generateRandomParticipants,
generateRandomMessages
} from 'mediasfu-reactjs';

function DemoApp() {
return (
<MediasfuGeneric
useLocalUIMode={true}
useSeed={true}
seedData={{
member: "DemoUser",
participants: generateRandomParticipants({ count: 5 }),
messages: generateRandomMessages({ count: 10 }),
eventType: "conference"
}}
/>
);
}

Custom Video Cards

import { MediasfuGeneric, VideoCard, CustomVideoCardType } from 'mediasfu-reactjs';

const customVideoCard: CustomVideoCardType = (props) => (
<VideoCard
{...props}
customStyle={{
border: "3px solid #4c1d95",
borderRadius: 20,
boxShadow: "0 10px 40px rgba(76, 29, 149, 0.4)"
}}
/>
);

function App() {
return (
<MediasfuGeneric
credentials={{ apiUserName: "user", apiKey: "key" }}
customVideoCard={customVideoCard}
/>
);
}

Headless Mode (Custom UI)

import { MediasfuGeneric } from 'mediasfu-reactjs';
import { useState, useCallback } from 'react';

function CustomApp() {
const [helpers, setHelpers] = useState<Record<string, unknown>>({});

const updateSourceParameters = useCallback((data: Record<string, unknown>) => {
setHelpers(data);
}, []);

return (
<>
<MediasfuGeneric
credentials={{ apiUserName: "user", apiKey: "key" }}
returnUI={false} // No default UI
noUIPreJoinOptions={{
action: "create",
capacity: 10,
eventType: "conference",
userName: "Host"
}}
sourceParameters={helpers}
updateSourceParameters={updateSourceParameters}
/>

{/* Use `helpers` to build your completely custom UI */}
{/* helpers.clickVideo(), helpers.clickAudio(), helpers.participants, etc. */}
</>
);
}

UI Overrides

import { 
MediasfuGeneric,
MainContainerComponent,
MediasfuUICustomOverrides
} from 'mediasfu-reactjs';

const overrides: MediasfuUICustomOverrides = {
// Override component rendering
mainContainer: {
render: (props) => (
<div style={{ border: "4px dashed purple", padding: 16 }}>
<MainContainerComponent {...props} />
</div>
)
},

// Wrap function behavior
consumerResume: {
wrap: (originalFn) => async (params) => {
console.log("Consumer resuming:", params);
return await originalFn(params);
}
}
};

function App() {
return (
<MediasfuGeneric
credentials={{ apiUserName: "user", apiKey: "key" }}
uiOverrides={overrides}
/>
);
}

🧩 Key Components

Display Components

ComponentPurpose
MainContainerComponentRoot container for meeting UI
MainGridComponentGrid layout for video tiles
FlexibleGridDynamic responsive grid
VideoCardIndividual video participant
AudioCardAudio-only participant with waveform
MiniCardThumbnail participant card
PaginationNavigate participant pages
ComponentPurpose
LoadingModalLoading overlay
AlertComponentToast notifications
ParticipantsModalParticipant list/management
MessagesModalChat interface
RecordingModalRecording controls
PollModalCreate/vote on polls
BackgroundModalVirtual backgrounds
BreakoutRoomsModalBreakout room management
ConfigureWhiteboardModalWhiteboard settings
MediaSettingsModalAudio/video device selection

Control Methods

import { 
clickVideo, // Toggle video
clickAudio, // Toggle audio
clickScreenShare, // Toggle screen share
startRecording, // Start recording
stopRecording, // Stop recording
launchPoll, // Open poll modal
launchMessages, // Open chat modal
} from 'mediasfu-reactjs';

Socket Events

import { 
connectSocket,
disconnectSocket,
joinRoomClient,
// Event handlers
personJoined,
meetingEnded,
receiveMessage,
} from 'mediasfu-reactjs';

🎨 Customization

CSS Variables

The package uses CSS variables for theming:

:root {
--mediasfu-primary: #4c1d95;
--mediasfu-background: #1a1a2e;
--mediasfu-surface: #16213e;
--mediasfu-text: #ffffff;
}

Custom Cards

// Custom video card with overlay
const customVideoCard: CustomVideoCardType = (props) => (
<div style={{ position: 'relative' }}>
<VideoCard {...props} />
<div className="custom-overlay">
<span>{props.name}</span>
<button onClick={() => props.onMute?.()}>Mute</button>
</div>
</div>
);

Complete UI Override

const overrides: MediasfuUICustomOverrides = {
// Layout components
mainContainer: { render: CustomMainContainer },
mainGrid: { render: CustomGrid },

// Modal components
menuModal: { component: CustomMenuModal },
participantsModal: { component: CustomParticipantsModal },
messagesModal: { component: CustomMessagesModal },

// Functions
consumerResume: { wrap: loggingWrapper },
addVideosGrid: { implementation: customGridLogic },
};

📚 API Reference

Types

import type {
// Core types
Participant,
Stream,
Message,
CoHostResponsibility,
Poll,

// Event types
EventType, // 'conference' | 'webinar' | 'chat' | 'broadcast'
CreateMediaSFURoomOptions,
JoinMediaSFURoomOptions,
ResponseJoinRoom,

// UI types
MediasfuUICustomOverrides,
CustomVideoCardType,
CustomAudioCardType,
CustomMiniCardType,

// Socket types
ConnectSocketType,
ConnectLocalSocketType,
} from 'mediasfu-reactjs';

Utilities

import {
// Room management
joinRoomOnMediaSFU,
createRoomOnMediaSFU,
checkLimitsAndMakeRequest,

// Demo utilities
generateRandomParticipants,
generateRandomMessages,
generateRandomPolls,

// State
initialValuesState,

// Helpers
formatNumber,
sleep,
checkPermission,
} from 'mediasfu-reactjs';

🏠 Self-Hosting / Community Edition

For self-hosted MediaSFU servers:

<MediasfuGeneric
localLink="https://your-mediasfu-server.com"
connectMediaSFU={false} // Don't connect to cloud
/>

Hybrid Mode (Local + Cloud)

<MediasfuGeneric
localLink="https://your-server.com"
connectMediaSFU={true} // Also connect to MediaSFU cloud
credentials={{ apiUserName: "user", apiKey: "key" }}
/>

📖 Detailed Documentation

For comprehensive documentation including:

  • Advanced customization patterns
  • Full API reference
  • All component props
  • Socket event handling
  • Recording configuration
  • Breakout rooms
  • Whiteboard integration
  • And much more...

📄 See README_DETAILED.md


🎨 Modern UI Components

ModernMediasfuGeneric is the most advanced, themed variant featuring:

  • Premium glass-morphism design with backdrop blur effects
  • Smooth animations and micro-interactions
  • Dark/Light theme support built-in
  • Accessibility-first components
  • Responsive layouts for all screen sizes
import { ModernMediasfuGeneric } from 'mediasfu-reactjs';

function App() {
return (
<ModernMediasfuGeneric
credentials={{ apiUserName: "user", apiKey: "key" }}
containerStyle={{
background: "linear-gradient(135deg, #0f172a, #1e3a8a)",
minHeight: "100vh"
}}
/>
);
}

Modern Components Available

Modern ComponentClassic EquivalentFeatures
ModernVideoCardVideoCardGlass effect, animated borders
ModernAudioCardAudioCardGradient waveforms, glow effects
ModernMiniCardMiniCardSleek thumbnails with status
ModernMenuModalMenuModalSlide animations, blur backdrop
ModernMessagesModalMessagesModalChat bubbles, typing indicators
ModernRecordingModalRecordingModalStatus animations, progress rings
ModernParticipantsModalParticipantsModalSearch, filters, role badges
ModernBackgroundModalBackgroundModalImage gallery, blur previews
ModernPollModalPollModalReal-time voting, animations
ModernBreakoutRoomsModalBreakoutRoomsModalDrag-and-drop, room previews
ModernPanelistsModalPanelistsModalPanelist management for webinars
ModernPermissionsModalPermissionsModalPer-participant permission control
TranslationSettingsModalReal-time translation configuration

🌐 Advanced Features

Panelists Mode (Webinars)

In webinar mode, designate specific participants as panelists who can speak, while others remain audience members.

// Panelists are managed via sourceParameters
const { panelists, updatePanelists } = sourceParameters;

// Listen for panelist changes
// Events: panelistsUpdated, addedAsPanelist, removedFromPanelists, panelistFocusChanged

Individual Permissions

Control each participant's capabilities individually:

import { ModernPermissionsModal } from 'mediasfu-reactjs';

// Permission levels:
// "0" - Standard participant
// "1" - Elevated (co-host level)
// "2" - Host (full control)

// Configure per-participant capabilities:
// - Video on/off
// - Audio on/off
// - Screen sharing
// - Chat access

Real-time Translation 🌍

Enable participants to speak in their native language and listen in any language with live AI translation.

import { TranslationSettingsModal } from 'mediasfu-reactjs';

function TranslationExample({ sourceParameters }) {
const [showTranslation, setShowTranslation] = useState(false);

return (
<>
<button onClick={() => setShowTranslation(true)}>
🌐 Translation Settings
</button>

<TranslationSettingsModal
isVisible={showTranslation}
onClose={() => setShowTranslation(false)}
parameters={sourceParameters}
/>
</>
);
}

// Translation events available:
// - translation:roomConfig
// - translation:languageSet
// - translation:subscribed
// - translation:transcript

Features include:

  • Set your spoken language — The system knows what language you're speaking
  • Choose listening language — Hear others translated to your preferred language
  • Real-time transcription — See live transcripts
  • Multiple language support — 50+ languages available

🔧 sourceParameters - The Power API

When building custom UIs or using headless mode (returnUI={false}), you need both props:

PropPurpose
sourceParametersInitial state object (can be empty {})
updateSourceParametersCallback that receives the complete helper bundle

The updateSourceParameters callback delivers a comprehensive object containing all room state, methods, and streams. This is your bridge to building completely custom UIs.

import { MediasfuGeneric } from 'mediasfu-reactjs';
import { useState, useCallback } from 'react';

function CustomUI() {
const [helpers, setHelpers] = useState<Record<string, unknown>>({});

// This callback receives ALL MediaSFU state and methods
const updateSourceParameters = useCallback((data: Record<string, unknown>) => {
setHelpers(data);
}, []);

return (
<>
<MediasfuGeneric
credentials={{ apiUserName: "user", apiKey: "key" }}
returnUI={false} // Headless mode - no UI rendered
noUIPreJoinOptions={{
action: "create",
capacity: 10,
eventType: "conference",
userName: "Host"
}}
sourceParameters={helpers} // Required: pass state object
updateSourceParameters={updateSourceParameters} // Required: receive updates
/>

{helpers.validated && <MyCustomMeetingUI sourceParameters={helpers} />}
</>
);
}

Key sourceParameters Properties

Media Streams

const {
allVideoStreams, // All video MediaStream objects
allAudioStreams, // All audio MediaStream objects
localStream, // Your local camera stream
localStreamAudio, // Your local microphone stream
localStreamScreen, // Your screen share stream (if active)
remoteScreenStream, // Remote screen share stream
} = sourceParameters;

Participant Data

const {
participants, // Full participant list
participantsCounter, // Current count
filteredParticipants, // Filtered by search
waitingRoomList, // Users in waiting room
coHost, // Current co-host name
member, // Your username
islevel, // Your permission level ('0', '1', '2')
youAreHost, // Boolean
youAreCoHost, // Boolean
} = sourceParameters;

Room State

const {
roomName, // Current room name
eventType, // 'conference' | 'webinar' | 'broadcast' | 'chat'
recordStarted, // Is recording active
recordPaused, // Is recording paused
shareScreenStarted, // Is screen sharing active
validated, // Is room validated/connected
messages, // Chat messages array
polls, // Active polls
} = sourceParameters;

Helper Methods

getParticipantMedia - Get Individual Streams

const { getParticipantMedia } = sourceParameters;

// Get video stream by participant name
const videoStream = await getParticipantMedia({
name: "Alice",
kind: "video"
});

// Get audio stream by producer ID
const audioStream = await getParticipantMedia({
id: "producer-id-123",
kind: "audio"
});

// Use in a video element
if (videoStream) {
videoRef.current.srcObject = videoStream;
}

Media Control Methods

const {
clickVideo, // Toggle local video
clickAudio, // Toggle local audio
clickScreenShare, // Toggle screen share
switchVideoAlt, // Switch camera device
switchUserAudio, // Switch audio input device
} = sourceParameters;

// Toggle video with parameters
await clickVideo({ parameters: sourceParameters });
const {
updateIsMenuModalVisible,
updateIsRecordingModalVisible,
updateIsParticipantsModalVisible,
updateIsMessagesModalVisible,
updateIsPollModalVisible,
updateIsBackgroundModalVisible,
updateIsBreakoutRoomsModalVisible,
updateIsMediaSettingsModalVisible,
} = sourceParameters;

// Open the chat modal
updateIsMessagesModalVisible(true);

🎵 AudioGrid - Display All Audio Participants

Use AudioGrid with audio streams from sourceParameters:

import { AudioGrid, AudioCard } from 'mediasfu-reactjs';

function AudioParticipantsView({ sourceParameters }) {
const { allAudioStreams, participants } = sourceParameters;

// Build audio components from streams
const audioComponents = allAudioStreams.map((streamObj, index) => {
const participant = participants.find(p => p.audioID === streamObj.producerId);

return (
<AudioCard
key={streamObj.producerId || index}
name={participant?.name || 'Unknown'}
audioStream={streamObj.stream}
showWaveform={true}
barColor="#22c55e"
customStyle={{
background: "rgba(34, 197, 94, 0.1)",
borderRadius: 16,
padding: 12
}}
/>
);
});

return (
<AudioGrid
componentsToRender={audioComponents}
containerProps={{
style: {
display: 'grid',
gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))',
gap: 16,
padding: 20
}
}}
/>
);
}

🎬 Using Modals Standalone

You can use any modal component independently with sourceParameters:

Recording Modal

import { ModernRecordingModal } from 'mediasfu-reactjs';

function MyRecordingButton({ sourceParameters }) {
const [showRecording, setShowRecording] = useState(false);

return (
<>
<button onClick={() => setShowRecording(true)}>
🔴 Recording Settings
</button>

<ModernRecordingModal
isVisible={showRecording}
onClose={() => setShowRecording(false)}
parameters={sourceParameters}
position="center"
/>
</>
);
}

Virtual Background Modal

import { ModernBackgroundModal } from 'mediasfu-reactjs';

function BackgroundSelector({ sourceParameters }) {
const [showBg, setShowBg] = useState(false);

return (
<>
<button onClick={() => setShowBg(true)}>
🖼️ Change Background
</button>

<ModernBackgroundModal
isVisible={showBg}
onClose={() => setShowBg(false)}
parameters={sourceParameters}
/>
</>
);
}

Media Settings Modal

import { ModernMediaSettingsModal } from 'mediasfu-reactjs';

function DeviceSelector({ sourceParameters }) {
const [showSettings, setShowSettings] = useState(false);

return (
<>
<button onClick={() => setShowSettings(true)}>
⚙️ Audio/Video Settings
</button>

<ModernMediaSettingsModal
isVisible={showSettings}
onClose={() => setShowSettings(false)}
parameters={sourceParameters}
/>
</>
);
}

🏗️ Building Your Own UI

Here's a complete example of building a custom meeting interface:

import { 
MediasfuGeneric,
VideoCard,
AudioCard,
ModernMessagesModal,
ModernParticipantsModal,
ModernRecordingModal,
} from 'mediasfu-reactjs';
import { useState, useEffect } from 'react';

function CustomMeetingApp() {
const [params, setParams] = useState<any>(null);
const [showChat, setShowChat] = useState(false);
const [showParticipants, setShowParticipants] = useState(false);
const [showRecording, setShowRecording] = useState(false);

if (!params?.validated) {
return (
<MediasfuGeneric
credentials={{ apiUserName: "user", apiKey: "key" }}
returnUI={true} // Show pre-join UI
updateSourceParameters={setParams}
/>
);
}

const {
participants,
allVideoStreams,
allAudioStreams,
member,
roomName,
clickVideo,
clickAudio,
clickScreenShare,
videoAlreadyOn,
audioAlreadyOn,
shareScreenStarted,
recordStarted,
} = params;

return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh', background: '#0f172a' }}>
{/* Header */}
<header style={{ padding: 16, borderBottom: '1px solid #334155', display: 'flex', justifyContent: 'space-between' }}>
<h1 style={{ color: 'white', margin: 0 }}>{roomName}</h1>
<span style={{ color: '#94a3b8' }}>{participants.length} participants</span>
</header>

{/* Video Grid */}
<main style={{ flex: 1, display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: 16, padding: 16 }}>
{allVideoStreams.map((stream, i) => {
const participant = participants.find(p => p.videoID === stream.producerId);
return (
<VideoCard
key={stream.producerId || i}
videoStream={stream.stream}
name={participant?.name || 'Unknown'}
customStyle={{ borderRadius: 16, overflow: 'hidden' }}
/>
);
})}
</main>

{/* Controls */}
<footer style={{ padding: 16, borderTop: '1px solid #334155', display: 'flex', justifyContent: 'center', gap: 16 }}>
<button
onClick={() => clickVideo({ parameters: params })}
style={{
padding: '12px 24px',
borderRadius: 12,
background: videoAlreadyOn ? '#22c55e' : '#ef4444',
color: 'white',
border: 'none',
cursor: 'pointer'
}}
>
{videoAlreadyOn ? '📹 Video On' : '📹 Video Off'}
</button>

<button
onClick={() => clickAudio({ parameters: params })}
style={{
padding: '12px 24px',
borderRadius: 12,
background: audioAlreadyOn ? '#22c55e' : '#ef4444',
color: 'white',
border: 'none',
cursor: 'pointer'
}}
>
{audioAlreadyOn ? '🎤 Mic On' : '🎤 Mic Off'}
</button>

<button onClick={() => setShowParticipants(true)} style={{ padding: '12px 24px', borderRadius: 12, background: '#3b82f6', color: 'white', border: 'none', cursor: 'pointer' }}>
👥 Participants
</button>

<button onClick={() => setShowChat(true)} style={{ padding: '12px 24px', borderRadius: 12, background: '#8b5cf6', color: 'white', border: 'none', cursor: 'pointer' }}>
💬 Chat
</button>

<button onClick={() => setShowRecording(true)} style={{ padding: '12px 24px', borderRadius: 12, background: recordStarted ? '#ef4444' : '#6b7280', color: 'white', border: 'none', cursor: 'pointer' }}>
🔴 Record
</button>
</footer>

{/* Modals */}
<ModernMessagesModal
isVisible={showChat}
onClose={() => setShowChat(false)}
parameters={params}
/>

<ModernParticipantsModal
isVisible={showParticipants}
onClose={() => setShowParticipants(false)}
parameters={params}
/>

<ModernRecordingModal
isVisible={showRecording}
onClose={() => setShowRecording(false)}
parameters={params}
/>
</div>
);
}

�️ SDKs for Every Framework

MediaSFU isn't just React. The same communication platform is available across 7 frameworks — same API surface, same capabilities, same pricing:

FrameworkPackage
Reactmediasfu-reactjs (you are here)
React Native@mediasfu/mediasfu-reactnative
Expo@mediasfu/mediasfu-reactnative-expo
Fluttermediasfu_sdk
Angular@mediasfu/mediasfu-angular
Vue@mediasfu/mediasfu-vue
Android (Kotlin)MediaSFU Android


📄 License

MIT © MediaSFU


Voice · Video · AI · Translation · 7 Frameworks · $0.10/1K min