mediasfu-vue
v1.0.1
Published
MediaSFU Prebuilt Vue 3 SDK - Pre-built video conferencing components for Vue applications
Maintainers
Keywords
Readme
🚨 BREAKING: AI Phone Agents at $0.10 per 1,000 minutes
📞 Call our live AI demos right now:
- 🇺🇸 +1 (785) 369-1724 - Mixed Support Demo
- 🇬🇧 +44 7445 146575 - AI Conversation Demo
- 🇨🇦 +1 (587) 407-1990 - Technical Support Demo
- 🇨🇦 +1 (647) 558-6650 - Friendly AI Chat Demo
Traditional providers charge $0.05 per minute. We charge $0.10 per 1,000 minutes. That's 500x cheaper.
✅ Deploy AI phone agents in 30 minutes
✅ Works with ANY SIP provider (Twilio, Telnyx, Zadarma, etc.)
✅ Seamless AI-to-human handoffs
✅ Real-time call analytics & transcription
📖 Complete SIP/PSTN Documentation →
MediaSFU Vue SDK
🎉 Welcome to MediaSFU Vue! This is the official Vue 3 SDK for MediaSFU. While most code examples have been adapted from React to Vue's Composition API, some sections may still show React-style JSX. Please adapt these examples to Vue template syntax as needed. We're actively updating all examples.
⚠️ REQUIRED: Import CSS Styles
MediaSFU UI will NOT display correctly without importing the CSS file!
Add this import to your main entry file (main.ts or App.vue):
import 'mediasfu-vue/dist/mediasfu-vue.css';This is required for all MediaSFU components to render with proper styling. Without it, buttons, modals, and other UI elements will appear unstyled.
Quick Reference: Component Props & UI Overrides
New: UI override parity now extends across Webinar and Chat layouts, unifying customization for every MediaSFU interface.
Every primary MediaSFU UI export—MediasfuGeneric, MediasfuBroadcast, MediasfuConference, MediasfuWebinar, and MediasfuChat—now ships with a consistent prop surface and a powerful uiOverrides map, so you can bend the bundled experience to match your product without losing MediaSFU’s hardened real-time logic.
Shared component props (applies to every MediaSFU UI component)
| Prop | Type | Default | What it does |
| --- | --- | --- | --- |
| PrejoinPage | (options) => Component | WelcomePage | Swap in a custom pre-join experience. Receives unified pre-join options so you can add branding, legal copy, or warm-up flows. |
| localLink | string | "" | Point the SDK at your self-hosted MediaSFU server. Leave empty when using MediaSFU Cloud. |
| connectMediaSFU | boolean | true | Toggle automatic socket/WebRTC connections. Set to false when you only need the UI shell. |
| credentials | { apiUserName: string; apiKey: string } | { apiUserName: "", apiKey: "" } | Supply cloud credentials without hard-coding them elsewhere. |
| useLocalUIMode | boolean | false | Run the interface in local/demo mode with no remote signaling. |
| seedData, useSeed | SeedData, boolean | {}, false | Pre-populate the UI for demos, snapshot tests, or onboarding tours. |
| imgSrc | string | https://mediasfu.com/images/logo192.png | Default artwork used across pre-join and modal flows. |
| sourceParameters | Record<string, unknown> | undefined | Shared helper bag (media devices, participant helpers, layout handlers). Pair with updateSourceParameters to mirror the SDK’s internal utilities. |
| updateSourceParameters | (helpers) => void | undefined | Receive the latest helper bundle so you can bridge MediaSFU logic into your own components. |
| returnUI | boolean | true | When false, mount the logic only—a perfect stepping stone to a fully bespoke interface. |
| noUIPreJoinOptions | CreateMediaSFURoomOptions \| JoinMediaSFURoomOptions | undefined | Feed pre-join data when returnUI is false and you want to bypass the on-screen wizard. |
| joinMediaSFURoom, createMediaSFURoom | Functions | undefined | Inject your own networking layers for joining or creating rooms. |
| customComponent | CustomComponentType | undefined | Replace the entire UI while retaining transports, sockets, and helpers. |
| customVideoCard, customAudioCard, customMiniCard | Factories | undefined | Override participant card renders to add metadata, CTAs, or badges. |
| containerStyle | StyleValue | undefined | Apply inline styles to the root wrapper (dashboards, split views, etc.). |
| uiOverrides | MediasfuUICustomOverrides | undefined | Targeted component/function overrides described below. |
Power combo: Set
returnUI={false}to run MediaSFU logic headless, capture helpers viaupdateSourceParameters, and selectively bring UI pieces back withuiOverrides. That gives you progressive migration with minimal code churn.
import type { MediasfuUICustomOverrides } from "mediasfu-vue";
const overrides: MediasfuUICustomOverrides = { /* ... */ };Bring the types into your project to unlock full IntelliSense for every override slot.
Custom UI Playbook
Use a toggle-driven "playbook" component to experiment with MediaSFU’s customization layers. Flip a couple of booleans and you can watch the SDK jump between prebuilt layouts, headless logic, or a fully bespoke workspace driven by customComponent.
What the playbook demonstrates
- Connection presets: toggle
connectionScenariobetweencloud,hybrid, orceto swap credentials, local links, and connection modes in one place. - Experience selector: the
selectedExperienceswitch rendersMediasfuGeneric,MediasfuBroadcast,MediasfuWebinar,MediasfuConference, orMediasfuChatwithout touching the rest of your stack. - UI strategy flags: booleans like
showPrebuiltUI,enableFullCustomUI, andenableNoUIPreJoindemonstrate how to run the MediaSFU logic with or without the bundled UI. - Layered overrides: toggles enable the custom video/audio/mini cards, drop-in
uiOverridesfor layout and modal surfaces, container styling, and backend proxy helpers. - Custom workspace demo: a
customComponentreceives live MediaSFU helpers so you can build dashboards, CRM surfaces, or any bespoke host interface. - Debug panel & helpers: optional JSON panel exposes the
updateSourceParameterspayload so you can see exactly what to wire into your own components.
Try it quickly
const connectionScenario: "cloud" | "hybrid" | "ce" = "cloud";
const selectedExperience = "generic" as const;
const showPrebuiltUI = true;
const enableFullCustomUI = false;
const connectionPresets = {
cloud: { credentials: { apiUserName: "demo", apiKey: "demo" }, localLink: "", connectMediaSFU: true },
hybrid: { credentials: { apiUserName: "demo", apiKey: "demo" }, localLink: "http://localhost:3000", connectMediaSFU: true },
ce: { credentials: undefined, localLink: "http://localhost:3000", connectMediaSFU: false },
};
const Experience = {
generic: MediasfuGeneric,
broadcast: MediasfuBroadcast,
webinar: MediasfuWebinar,
conference: MediasfuConference,
chat: MediasfuChat,
}[selectedExperience];
export const CustomUIPlaybook = () => {
const overrides = useMemo(() => ({
mainContainer: enableFullCustomUI
? {
render: (props) => (
<div style={{ border: "4px dashed purple", borderRadius: 24, padding: 16 }}>
<MainContainerComponent {...props} />
</div>
),
}
: undefined,
}), [enableFullCustomUI]);
const current = connectionPresets[connectionScenario];
return (
<Experience
{...current}
showPrebuiltUI={showPrebuiltUI}
uiOverrides={overrides}
containerStyle={{ background: "linear-gradient(135deg, #0f172a, #1e3a8a)", minHeight: "100vh" }}
/>
);
};Toggle the configuration values at the top of the playbook and watch the UI reconfigure instantly. It’s the fastest path to understand MediaSFU’s override surface before you fold the patterns into your production entrypoint.
Passing custom props and UI overrides
Use the same playbook to validate bespoke cards, override bundles, and fully custom workspaces before you move them into production code:
const videoCard: CustomVideoCardType = (props) => (
<VideoCard
{...props}
customStyle={{
borderRadius: 20,
border: "3px solid #4c1d95",
boxShadow: "0 28px 65px rgba(76,29,149,0.35)",
background: "linear-gradient(140deg, rgba(15,23,42,0.78), rgba(30,64,175,0.45))",
...(props.customStyle ?? {}),
}}
/>
);
const audioCard: CustomAudioCardType = (props) => (
<AudioCard
{...props}
barColor="#22c55e"
customStyle={{ borderRadius: 22, background: "rgba(34,197,94,0.1)" }}
/>
);
const miniCard: CustomMiniCardType = (props) => (
<MiniCard
{...props}
renderContainer={({ defaultContainer }) => (
<div style={{ display: "grid", placeItems: "center", height: "100%" }}>{defaultContainer}</div>
)}
/>
);
const uiOverrides = useMemo<MediasfuUICustomOverrides>(() => ({
mainContainer: {
render: (props) => (
<div style={{ border: "4px dashed rgba(139,92,246,0.8)", borderRadius: 28, padding: 16 }}>
<MainContainerComponent {...props} />
</div>
),
},
menuModal: {
component: (modalProps) => <MenuModal {...modalProps} variant="glass" />,
},
consumerResume: {
wrap: (original) => async (params) => {
const startedAt = performance.now();
const result = await original(params);
analytics.track("consumer_resume", {
durationMs: performance.now() - startedAt,
consumerId: params?.consumer?.id,
});
return result;
},
},
}), []);
return (
<Experience
{...current}
customVideoCard={videoCard}
customAudioCard={audioCard}
customMiniCard={miniCard}
customComponent={enableFullCustomUI ? CustomWorkspace : undefined}
containerStyle={{ background: "#0f172a", borderRadius: 32, overflow: "hidden" }}
uiOverrides={uiOverrides}
/>
);Because the playbook surfaces updateSourceParameters, you can also log or snapshot the helper bundle (getParticipantMedia, toggleMenuModal, showAlert, and more) to ensure your custom UI always receives the hooks it expects.
uiOverrides map — override keys at a glance
Each key accepts a CustomComponentOverride<Props> object with optional component and render fields. You can fully replace the default implementation or wrap it while forwarding props.
Layout & control surfaces
| Key | Default component | Typical use |
| --- | --- | --- |
| mainContainer | MainContainerComponent | Inject theming providers or dashboard layouts. |
| mainAspect | MainAspectComponent | Tune how the main region splits space. |
| mainScreen | MainScreenComponent | Orchestrate hero video + gallery interplay. |
| mainGrid | MainGridComponent | Modify layout or layering of primary participants. |
| subAspect | SubAspectComponent | Restyle fixed control strips in webinar/conference modes. |
| otherGrid | OtherGridComponent | Change presentation of off-stage attendees. |
| flexibleGrid, flexibleGridAlt | FlexibleGrid | Implement AI-driven or branded array layouts. |
| flexibleVideo | FlexibleVideo | Add captions, watermarks, or overlays to highlighted speakers. |
| audioGrid | AudioGrid | Customise audio-only attendee presentation. |
| pagination | Pagination | Introduce infinite scroll or auto-cycling carousels. |
| controlButtons | ControlButtonsComponent | Rebrand the primary action bar. |
| controlButtonsAlt | ControlButtonsAltComponent | Control secondary button clusters. |
| controlButtonsTouch | ControlButtonsComponentTouch | Deliver mobile-first controls (used heavily by MediasfuChat). |
Participant cards & widgets
| Key | Default component | Typical use |
| --- | --- | --- |
| videoCard | VideoCard | Add host badges, vueions, or CRM overlays. |
| audioCard | AudioCard | Swap avatars or expose spoken-language info. |
| miniCard | MiniCard | Customize thumbnails in picture-in-picture modes. |
| miniAudio | MiniAudio | Re-style the audio-only mini indicators. |
| meetingProgressTimer | MeetingProgressTimer | Replace the elapsed-time widget with countdowns or milestones. |
| miniAudioPlayer | MiniAudioPlayer | Provide alternative UI for recorded clip playback. |
Modals, dialogs, and collaboration surfaces
| Key | Default component | Typical use |
| --- | --- | --- |
| loadingModal | LoadingModal | Show branded skeletons while connecting. |
| alert | AlertComponent | Route alerts through your notification system. |
| menuModal | MenuModal | Redesign quick-action trays. |
| eventSettingsModal | EventSettingsModal | Extend host tools with your own settings. |
| requestsModal | RequestsModal | Build moderation queues tailored to your workflows. |
| waitingRoomModal | WaitingRoomModal | Deliver custom waiting-room experiences. |
| coHostModal | CoHostModal | Manage co-hosts with bespoke UX. |
| mediaSettingsModal | MediaSettingsModal | Embed device tests or instructions. |
| participantsModal | ParticipantsModal | Introduce advanced filters, search, or notes. |
| messagesModal | MessagesModal | Drop in your full-featured chat module. |
| displaySettingsModal | DisplaySettingsModal | Let users pick layouts, themes, or captions. |
| confirmExitModal | ConfirmExitModal | Meet compliance wording requirements. |
| confirmHereModal | ConfirmHereModal | Customize attendance confirmations for webinars. |
| shareEventModal | ShareEventModal | Add referral codes or QR sharing. |
| recordingModal | RecordingModal | Tailor recording confirmation flows. |
| pollModal | PollModal | Integrate your polling/quiz engine. |
| backgroundModal | BackgroundModal | Hook AI background replacement or brand presets. |
| breakoutRoomsModal | BreakoutRoomsModal | Implement drag-and-drop or AI room suggestions. |
| configureWhiteboardModal | ConfigureWhiteboardModal | Adjust collaboration permissions before launch. |
| whiteboard | Whiteboard | Replace with your whiteboard provider. |
| screenboard | Screenboard | Modify shared-screen annotation layers. |
| screenboardModal | ScreenboardModal | Reimagine how users enable shared annotations. |
Entry flows & custom renderers
| Key | Default component | Typical use |
| --- | --- | --- |
| welcomePage | WelcomePage | Provide a fully branded welcome/marketing splash. |
| preJoinPage | PrejoinPage | Override the wizard used before joining live sessions. |
| customMenuButtonsRenderer | ControlButtonsAltComponent | Supply a bespoke renderer for menu button groups without overriding each button. |
Function overrides
| Key | Default function | Typical use |
| --- | --- | --- |
| consumerResume | consumerResume | Wrap errors, capture analytics, or rate-limit consumer resume behavior. |
| addVideosGrid | addVideosGrid | Replace participant ordering or layout heuristics on the fly. |
Function overrides support
{ implementation, wrap }. Provideimplementationfor a full replacement, orwrapto intercept the default behavior before/after it runs.
Example: swap the chat modal and theme the controls
import { MediasfuGeneric } from "mediasfu-vue";
import { MyChatModal } from "./ui/MyChatModal";
import { MyControls } from "./ui/MyControls";
const uiOverrides = {
messagesModal: {
component: MyChatModal,
},
controlButtons: {
render: (props) => <MyControls {...props} variant="glass" />,
},
};
export const MyMeeting = () => (
<MediasfuGeneric credentials={credentials} uiOverrides={uiOverrides} />
);Example: wrap a MediaSFU helper instead of replacing it
const uiOverrides = {
consumerResume: {
wrap: (original) => async (params) => {
const startedAt = performance.now();
const result = await original(params);
analytics.track("consumer_resume", {
durationMs: performance.now() - startedAt,
consumerId: params?.consumer?.id,
});
return result;
},
},
};
<MediasfuConference uiOverrides={uiOverrides} />;The same override hooks power the newly refreshed MediasfuWebinar and MediasfuChat layouts, so you can guarantee a unified experience across events, webinars, or chat-first rooms.
MediaSFU offers a cutting-edge streaming experience that empowers users to customize their recordings and engage their audience with high-quality streams. Whether you're a content creator, educator, or business professional, MediaSFU provides the tools you need to elevate your streaming game.
MediaSFU Vue Module Documentation
Unlock the Power of MediaSFU Community Edition
MediaSFU Community Edition is free and open-source—perfect for developers who want to run their own media server without upfront costs. With robust features and simple setup, you can launch your media solution in minutes. Ready to scale? Upgrade seamlessly to MediaSFU Cloud for enterprise-grade performance and global scalability.
✅ Vue SDK Setup Guide

🎥 Watch the Vue SDK Setup Guide
Table of Contents
- Quick Reference: Component Props & UI Overrides
- Custom UI Playbook
- Features
- Getting Started
- 📘 Vue SDK Guide
- API Reference
- Troubleshooting
- Contributing
Features
MediaSFU's Vue SDK comes with a host of powerful features out of the box:
- Screen Sharing with Annotation Support: Share your screen with participants and annotate in real-time for enhanced presentations and collaborations.
- Collaborative Whiteboards: Create and share whiteboards for real-time collaborative drawing and brainstorming sessions.
- Breakout Rooms: Create multiple sub-meetings within a single session to enhance collaboration and focus.
- Pagination: Efficiently handle large participant lists with seamless pagination.
- Polls: Conduct real-time polls to gather instant feedback from participants.
- Media Access Requests Management: Manage media access requests with ease to ensure smooth operations.
- Video Effects: Apply various video effects, including virtual backgrounds, to enhance the visual experience.
- Chat (Direct & Group): Facilitate communication with direct and group chat options.
- Cloud Recording (track-based): Customize recordings with track-based options, including watermarks, name tags, background colors, and more.
- Managed Events: Manage events with features to handle abandoned and inactive participants, as well as enforce time and capacity limits.
🆕 New Advanced Media Access
Interested in getting just the media stream of a specific participant? You can now easily retrieve individual participant streams using sourceParameters.getParticipantMedia() Learn more →
Need to access available cameras and microphones? Use sourceParameters.getMediaDevicesList() to enumerate all available media devices on the user's system programmatically.
Getting Started
This section will guide users through the initial setup and installation of the npm module.
Documentation Reference
For comprehensive documentation on the available methods, components, and functions, please visit mediasfu.com. This resource provides detailed information for this guide and additional documentation.
Installation
Instructions on how to install the module using npm.
1. Add the Package to Your Project
```bash
npm install mediasfu-vue
```2. Import Required Styles
🎨 CRITICAL: MediaSFU requires its CSS file to render the UI correctly. Add this import to your main entry file (e.g.,
main.tsorApp.vue):
// Add this to your main.ts or App.vue
import 'mediasfu-vue/dist/mediasfu-vue.css';Without this CSS import, the MediaSFU UI components will not display properly!
1.1 Important Installation Notes
🚫 Avoid Using --force or --legacy-peer-deps
Using these flags can override important dependency checks, potentially causing unstable builds or unexpected behavior.
- Why Avoid Them?
They bypass compatibility checks, which can introduce bugs or conflicts within your project.
⚙️ Use Package Overrides (Recommended)
If you encounter peer dependency conflicts, use the overrides field in your package.json instead of forcing installations.
✅ Example of Safe Overrides:
{
"overrides": {
"some-package": {
"dependency-name": "^1.2.3"
}
}
}- Why This Works:
Overrides let you resolve conflicts safely without compromising the integrity of your project.
🚩 If You Absolutely Need to Use --force or --legacy-peer-deps
- Some peer dependencies might be skipped.
- You’ll need to manually install them to avoid runtime errors.
🔑 Install the Required Peer Dependencies:
npm install \
"@fortawesome/fontawesome-svg-core@^6.6.0" \
"@fortawesome/free-brands-svg-icons@^6.6.0" \
"@fortawesome/free-solid-svg-icons@^6.6.0" \
"@fortawesome/vue-fontawesome@^0.2.2" \
"@mediapipe/[email protected]" \
"bootstrap@^5.3.3" \
"mediasoup-client@^3.16.0" \
"vue@^19.0.0" \
"vue-dom@^19.0.0" \
"[email protected]" \
"universal-cookie@^7.2.0"- Why This Is Important:
These peer dependencies are critical formediasfu-vueto function correctly.
🔍 How to Check for Peer Dependencies
Open your
package.json.Look for the
peerDependenciessection:"peerDependencies": { "@fortawesome/fontawesome-svg-core": "^6.6.0", "@fortawesome/free-brands-svg-icons": "^6.6.0", "@fortawesome/free-solid-svg-icons": "^6.6.0", "@fortawesome/vue-fontawesome": "^0.2.2", "@mediapipe/selfie_segmentation": "0.1.1675465747", "bootstrap": "^5.3.3", "mediasoup-client": "^3.16.0", "vue": "^19.0.0", "vue-dom": "^19.0.0", "socket.io-client": "4.8.0", "universal-cookie": "^7.2.0" }Ensure all are installed. If not, run the install command above.
✅ Final Recommendations:
- Always try to resolve conflicts using overrides first.
- Only use
--forceor--legacy-peer-depsas a last resort.
2. Obtain an API Key (If Required)
You can get your API key by signing up or logging into your account at mediasfu.com.
Self-Hosting MediaSFU
If you plan to self-host MediaSFU or use it without MediaSFU Cloud services, you don't need an API key. You can access the open-source version of MediaSFU from the MediaSFU Open Repository.
This setup allows full flexibility and customization while bypassing the need for cloud-dependent credentials.
📘 Vue SDK Guide
This comprehensive guide will walk you through everything you need to know about building real-time communication apps with MediaSFU's Vue SDK. Whether you're a beginner or an experienced developer, you'll find clear explanations, practical examples, and best practices.
Quick Start (5 Minutes)
Get your first MediaSFU app running in just a few minutes.
Step 1: Install the Package
npm install mediasfu-vueStep 2: Import Styles and Components
⚠️ IMPORTANT: You MUST import the CSS file for MediaSFU UI to display correctly!
// ✅ REQUIRED: Import MediaSFU styles first
import 'mediasfu-vue/dist/mediasfu-vue.css';
// Then import components
import { MediasfuGeneric } from 'mediasfu-vue';
function App() {
// Option 1: Use without credentials (for testing)
return <MediasfuGeneric />;
// Option 2: Use with MediaSFU Cloud credentials
// const credentials = { apiUserName: 'your_username', apiKey: 'your_api_key' };
// return <MediasfuGeneric credentials={credentials} />;
}
export default App;Step 3: Run Your App
npm startThat's it! You now have a fully functional video conferencing app with:
- ✅ Video and audio streaming
- ✅ Screen sharing
- ✅ Chat messaging
- ✅ Participant management
- ✅ Recording capabilities
- ✅ Breakout rooms
- ✅ Polls and whiteboards
Understanding MediaSFU Architecture
Before diving deeper, let's understand how MediaSFU is structured.
The Three-Layer Architecture
┌─────────────────────────────────────────────┐
│ Your Vue Application │
│ (App.js, components, business logic) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ MediaSFU Components Layer │
│ (MediasfuGeneric, MediasfuBroadcast, etc.) │
│ - Pre-built UI components │
│ - Event handling │
│ - State management │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ MediaSFU Core Methods Layer │
│ (Stream control, room management, │
│ WebRTC handling, socket communication) │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ MediaSFU Backend Services │
│ (MediaSFU Cloud or Community Edition) │
└─────────────────────────────────────────────┘Key Concepts
1. Event Room Types
MediaSFU provides 5 specialized room types, each optimized for specific use cases:
| Room Type | Best For | Key Features | |-----------|----------|--------------| | MediasfuGeneric | General purpose meetings | Flexible layout, all features enabled | | MediasfuBroadcast | Live streaming events | Optimized for one-to-many communication | | MediasfuWebinar | Educational sessions | Presenter focus, Q&A features | | MediasfuConference | Business meetings | Equal participant layout, collaboration tools | | MediasfuChat | Interactive discussions | Chat-first interface, quick connections |
// ⚠️ IMPORTANT: Always import CSS first!
import 'mediasfu-vue/dist/mediasfu-vue.css';
// Choose the right room type for your use case
import { MediasfuWebinar, MediasfuBroadcast, MediasfuConference } from 'mediasfu-vue';
// For a webinar
<MediasfuWebinar credentials={credentials} />
// For a broadcast
<MediasfuBroadcast credentials={credentials} />
// For a conference
<MediasfuConference credentials={credentials} />2. The Three Usage Modes
MediaSFU offers three progressive levels of customization:
Mode 1: Default UI (Simplest)
Use MediaSFU's complete pre-built interface - perfect for rapid development.
import { MediasfuGeneric } from 'mediasfu-vue';
function App() {
return <MediasfuGeneric credentials={credentials} />;
}When to use:
- ✅ Prototyping or MVP development
- ✅ Need a production-ready UI quickly
- ✅ Standard video conferencing features are sufficient
Mode 2: Custom UI with MediaSFU Backend (Most Flexible)
Build your own UI while using MediaSFU's powerful backend infrastructure.
import { MediasfuGeneric } from 'mediasfu-vue';
import { ref } from 'vue';
function App() {
const sourceParameters = ref(null);
const handleUpdateSourceParameters = (params) => {
setSourceParameters(params);
};
return (
<div>
<MediasfuGeneric
returnUI={false}
sourceParameters={sourceParameters}
updateSourceParameters={handleUpdateSourceParameters}
credentials={credentials}
noUIPreJoinOptions={{
action: 'create',
userName: 'Your Name',
capacity: 50,
duration: 30,
eventType: 'conference'
}}
/>
{/* Your custom UI */}
{sourceParameters && (
<div className="custom-controls">
<button onClick={() => sourceParameters.clickVideo({ parameters: sourceParameters })}>
Toggle Video
</button>
<button onClick={() => sourceParameters.clickAudio({ parameters: sourceParameters })}>
Toggle Audio
</button>
</div>
)}
</div>
);
}When to use:
- ✅ Need complete control over UI/UX
- ✅ Building a custom branded experience
- ✅ Integrating into existing app design
Mode 3: Component Replacement (Balanced)
Replace specific MediaSFU components while keeping the rest of the infrastructure.
import { MediasfuGeneric, FlexibleVideo, FlexibleGrid } from 'mediasfu-vue';
function CustomMainScreen({ parameters }) {
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
{/* Custom header */}
<div className="custom-header">
<h1>{parameters.roomName}</h1>
<span>{parameters.participants.length} participants</span>
</div>
{/* Use MediaSFU's components in your layout */}
<FlexibleVideo
customWidth={window.innerWidth}
customHeight={600}
parameters={parameters}
/>
<FlexibleGrid
customWidth={window.innerWidth}
customHeight={400}
parameters={parameters}
/>
{/* Custom footer */}
<div className="custom-footer">
<button onClick={() => parameters.clickVideo({ parameters })}>
{parameters.videoAlreadyOn ? 'Stop Video' : 'Start Video'}
</button>
</div>
</div>
);
}
function App() {
return (
<MediasfuGeneric
credentials={credentials}
PrejoinPage={WelcomePage}
customComponent={CustomMainScreen}
/>
);
}When to use:
- ✅ Need custom main interface but want to keep MediaSFU's components
- ✅ Partial customization with minimal effort
- ✅ Want to maintain MediaSFU's functionality while customizing layout
3. Parameters: Your Control Center
The sourceParameters object (or parameters in custom components) is your gateway to all MediaSFU functionality:
// Available in sourceParameters or parameters object
{
// Media Controls
clickVideo: (options) => {},
clickAudio: (options) => {},
clickScreenShare: (options) => {},
// Room State
roomName: 'meeting-123',
participants: [...],
allVideoStreams: [...],
allAudioStreams: [...],
// UI State
videoAlreadyOn: false,
audioAlreadyOn: false,
screenAlreadyOn: false,
// Update Functions
updateVideoAlreadyOn: (value) => {},
updateAudioAlreadyOn: (value) => {},
// And 200+ more properties and methods...
}Access patterns:
// In Mode 1 (Default UI): Parameters are managed internally
// You don't need to access them directly
// In Mode 2 (Custom UI): Access via sourceParameters state
const sourceParameters = ref(null);
sourceParameters?.clickVideo({ parameters: sourceParameters });
// In Mode 3 (Component Replacement): Passed to your custom component
function CustomComponent({ parameters }) {
parameters.clickVideo({ parameters });
}Core Concepts & Components
Now that you understand the architecture, let's explore the building blocks.
1. Display Components: Building Your Video Layout
MediaSFU provides powerful components for organizing and displaying media streams.
Primary Layout Components
FlexibleVideo - Main video display area
import { FlexibleVideo } from 'mediasfu-vue';
<FlexibleVideo
customWidth={window.innerWidth}
customHeight={600}
parameters={parameters}
/>- Automatically handles main presenter or screen share
- Smooth transitions between different video sources
- Responsive sizing
FlexibleGrid - Participant grid layout
import { FlexibleGrid } from 'mediasfu-vue';
<FlexibleGrid
customWidth={window.innerWidth}
customHeight={800}
parameters={parameters}
/>- Intelligent grid sizing (2x2, 3x3, 4x4, etc.)
- Pagination for large participant lists
- Automatic reflow on window resize
AudioGrid - Audio-only participants
import { AudioGrid } from 'mediasfu-vue';
<AudioGrid parameters={parameters} />- Displays participants without video
- Audio level indicators
- Compact layout for efficiency
Container Components
| Component | Purpose | Use Case | |-----------|---------|----------| | MainContainerComponent | Primary content wrapper | Wraps all main content areas | | MainAspectComponent | Aspect ratio container | Maintains proper video proportions | | MainScreenComponent | Screen layout manager | Organizes screen regions | | SubAspectComponent | Secondary content container | For picture-in-picture, sidebars |
Example: Building a custom layout
import {
MainContainerComponent,
FlexibleVideo,
FlexibleGrid,
AudioGrid
} from 'mediasfu-vue';
function CustomLayout({ parameters }) {
return (
<MainContainerComponent>
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
{/* Main video area */}
<div style={{ flex: 3 }}>
<FlexibleVideo
customWidth={window.innerWidth}
customHeight={window.innerHeight * 0.6}
parameters={parameters}
/>
</div>
{/* Participant grid */}
<div style={{ flex: 2 }}>
<FlexibleGrid
customWidth={window.innerWidth}
customHeight={window.innerHeight * 0.3}
parameters={parameters}
/>
</div>
{/* Audio-only participants */}
<div style={{ height: 80 }}>
<AudioGrid parameters={parameters} />
</div>
</div>
</MainContainerComponent>
);
}2. Control Components: User Interactions
ControlButtonsComponent - Standard control bar
import { ControlButtonsComponent } from 'mediasfu-vue';
<ControlButtonsComponent
parameters={parameters}
position="bottom" // or 'top', 'left', 'right'
/>Includes: mute, video, screenshare, participants, chat, settings, etc.
ControlButtonsAltComponent - Alternative layout
import { ControlButtonsAltComponent } from 'mediasfu-vue';
<ControlButtonsAltComponent
parameters={parameters}
position="top"
/>Different button arrangement optimized for specific layouts.
ControlButtonsComponentTouch - Touch-optimized controls
import { ControlButtonsComponentTouch } from 'mediasfu-vue';
<ControlButtonsComponentTouch parameters={parameters} />Floating action buttons optimized for mobile/tablet interfaces.
3. Modal Components: Feature Interfaces
MediaSFU includes modals for various features:
import {
ParticipantsModal,
MessagesModal,
SettingsModal,
DisplaySettingsModal,
RecordingModal,
PollModal,
BreakoutRoomsModal
} from 'mediasfu-vue';
// These are automatically rendered when enabled
// Control their visibility via parameters
parameters.updateIsParticipantsModalVisible(true);
parameters.updateIsMessagesModalVisible(true);
parameters.updateIsSettingsModalVisible(true);Available modals:
- ParticipantsModal - Participant list management
- MessagesModal - Chat interface
- SettingsModal - Event and room settings
- DisplaySettingsModal - Layout and display options
- RecordingModal - Recording controls and settings
- PollModal - Create and manage polls
- BreakoutRoomsModal - Breakout room management
- MediaSettingsModal - Camera/microphone selection
- BackgroundModal - Virtual background settings
- ConfigureWhiteboardModal - Whiteboard configuration
Example: Programmatically showing modals
function CustomControls({ parameters }) {
return (
<div className="custom-toolbar">
<button onClick={() => parameters.updateIsParticipantsModalVisible(true)}>
Show Participants ({parameters.participants.length})
</button>
<button onClick={() => parameters.updateIsMessagesModalVisible(true)}>
Open Chat
</button>
<button onClick={() => parameters.launchPoll.launchPoll({ parameters })}>
Create Poll
</button>
</div>
);
}4. Video Cards: Individual Participant Display
VideoCard - Individual participant video element
import { VideoCard } from 'mediasfu-vue';
<VideoCard
videoStream={participantStream}
remoteProducerId="producer-id"
eventType="conference"
forceFullDisplay={false}
participant={participantObject}
backgroundColor="#000000"
showControls={true}
showInfo={true}
name="Participant Name"
parameters={parameters}
/>AudioCard - Individual audio-only participant
import { AudioCard } from 'mediasfu-vue';
<AudioCard
name="Participant Name"
barColor="#4CAF50"
textColor="#FFFFFF"
customStyle={{ borderRadius: '10px' }}
controlsPosition="topLeft"
infoPosition="topRight"
participant={participantObject}
parameters={parameters}
/>MiniCard - Compact participant display (for grids)
import { MiniCard } from 'mediasfu-vue';
<MiniCard
participant={participantObject}
showControls={false}
parameters={parameters}
/>Example: Custom Video Card
function MyCustomVideoCard({ stream, participant, parameters }) {
return (
<div style={{
border: '3px solid #00ff88',
borderRadius: '15px',
overflow: 'hidden',
position: 'relative'
}}>
<video
ref={videoRef => {
if (videoRef && stream) {
videoRef.srcObject = stream;
videoRef.play();
}
}}
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
autoPlay
muted
/>
<div style={{
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
background: 'rgba(0, 255, 136, 0.8)',
color: 'black',
padding: '8px',
fontWeight: 'bold'
}}>
{participant.name} {participant.muted && '🔇'}
</div>
</div>
);
}
// Use it
<MediasfuGeneric
credentials={credentials}
customVideoCard={MyCustomVideoCard}
/>Working with Methods
MediaSFU provides 200+ methods for controlling every aspect of your real-time communication experience. Let's explore the most important categories.
Media Control Methods
Video Control
// Toggle video on/off
parameters.clickVideo({ parameters });
// Switch camera (front/back on mobile)
parameters.switchVideoAlt({ parameters });
// Switch to specific camera by ID
const cameras = await parameters.getMediaDevicesList('videoinput');
parameters.switchUserVideo({
videoPreference: cameras[1].deviceId,
parameters
});
// Get current video state
const isVideoOn = parameters.videoAlreadyOn;
// Update video state programmatically
parameters.updateVideoAlreadyOn(true);Audio Control
// Toggle audio on/off
parameters.clickAudio({ parameters });
// Switch microphone
const microphones = await parameters.getMediaDevicesList('audioinput');
parameters.switchUserAudio({
audioPreference: microphones[1].deviceId,
parameters
});
// Get current audio state
const isAudioOn = parameters.audioAlreadyOn;
const hasHostPermission = parameters.micAction; // Host approval status
// Mute/unmute specific participant (host only)
parameters.controlMedia({
participantId: 'participant-id',
participantName: 'John Doe',
type: 'audio',
socket: parameters.socket,
roomName: parameters.roomName
});Screen Sharing
// Start screen sharing
parameters.clickScreenShare({ parameters });
// Stop screen sharing
parameters.stopShareScreen({ parameters });
// Check if screen sharing is available
const canShare = await parameters.checkScreenShare({ parameters });
// Get screen share state
const isSharing = parameters.screenAlreadyOn;
const shareAudio = parameters.shareScreenStarted; // Sharing with audioDevice Management Methods
// Get available cameras
const cameras = await parameters.getMediaDevicesList('videoinput');
cameras.forEach(camera => {
console.log(`Camera: ${camera.label} (${camera.deviceId})`);
});
// Get available microphones
const microphones = await parameters.getMediaDevicesList('audioinput');
microphones.forEach(mic => {
console.log(`Microphone: ${mic.label} (${mic.deviceId})`);
});
// Building a device selector UI
function DeviceSelector({ parameters }) {
const cameras = ref([]);
const microphones = ref([]);
onMounted(() => {
const loadDevices = async () => {
const cams = await parameters.getMediaDevicesList('videoinput');
const mics = await parameters.getMediaDevicesList('audioinput');
setCameras(cams);
setMicrophones(mics);
};
loadDevices();
}, []);
return (
<div>
<select onChange={(e) => {
parameters.switchUserVideo({
videoPreference: e.target.value,
parameters
});
}}>
{cameras.map(camera => (
<option key={camera.deviceId} value={camera.deviceId}>
{camera.label}
</option>
))}
</select>
<select onChange={(e) => {
parameters.switchUserAudio({
audioPreference: e.target.value,
parameters
});
}}>
{microphones.map(mic => (
<option key={mic.deviceId} value={mic.deviceId}>
{mic.label}
</option>
))}
</select>
</div>
);
}Participant Management Methods
// Get all participants
const participants = parameters.participants;
const participantCount = parameters.participantsCounter;
// Filter participants
const videoParticipants = participants.filter(p => p.videoOn);
const audioOnlyParticipants = participants.filter(p => !p.videoOn);
const mutedParticipants = participants.filter(p => p.muted);
// Find specific participant
const participant = participants.find(p => p.name === 'John Doe');
// Remove participant from room (host only)
parameters.disconnectUserInitiate({
member: participantId,
roomName: parameters.roomName,
socket: parameters.socket
});
// Change participant role (host only)
parameters.updateParticipant({
participantId: 'participant-id',
islevel: '2', // '2' = host, '1' = co-host, '0' = participant
parameters
});
// Request to unmute participant (sends request)
parameters.requestScreenShare({ parameters });Chat & Messaging Methods
// Send a group message
parameters.sendMessage({
message: 'Hello everyone!',
type: 'group',
parameters
});
// Send direct message
parameters.sendMessage({
message: 'Private message',
type: 'direct',
receivers: ['participant-id'],
parameters
});
// Access message history
const messages = parameters.messages;
// Listen for new messages (via update function)
parameters.updateMessages = (newMessages) => {
console.log('New messages:', newMessages);
};
// Example: Custom chat component
function CustomChat({ parameters }) {
const message = ref('');
const sendMessage = () => {
parameters.sendMessage({
message,
type: 'group',
parameters
});
setMessage('');
};
return (
<div>
<div className="messages">
{parameters.messages.map((msg, index) => (
<div key={index}>
<strong>{msg.sender}:</strong> {msg.message}
</div>
))}
</div>
<input
value={message}
onChange={(e) => setMessage(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && sendMessage()}
/>
<button onClick={sendMessage}>Send</button>
</div>
);
}Recording Methods
// Start recording
parameters.startRecording({ parameters });
// Stop recording
parameters.stopRecording({ parameters });
// Pause recording
parameters.pauseRecording({ parameters });
// Resume recording
parameters.resumeRecording({ parameters });
// Configure recording settings
parameters.updateRecording({
recordingMediaOptions: 'video', // or 'audio'
recordingAudioOptions: 'all', // or 'host'
recordingVideoOptions: 'all', // or 'host'
recordingVideoType: 'fullDisplay', // or 'bestDisplay', 'all'
recordingDisplayType: 'video', // 'media', 'video', 'all'
recordingBackgroundColor: '#000000',
recordingNameTagsColor: '#ffffff',
recordingOrientationVideo: 'landscape', // or 'portrait'
recordingNameTags: true,
recordingAddHLS: false,
parameters
});
// Check recording state
const isRecording = parameters.recordStarted;
const isPaused = parameters.recordPaused;
const recordingTime = parameters.recordElapsedTime;Polls & Surveys Methods
// Create a poll
parameters.handleCreatePoll({
poll: {
question: 'What time works best?',
type: 'multiple', // or 'single'
options: ['10 AM', '2 PM', '5 PM']
},
parameters
});
// Vote on a poll
parameters.handleVotePoll({
pollId: 'poll-id',
optionIndex: 1,
parameters
});
// End a poll
parameters.handleEndPoll({
pollId: 'poll-id',
parameters
});
// Access poll data
const polls = parameters.polls;
const activePoll = polls.find(p => p.status === 'active');
// Example: Custom poll component
function CustomPoll({ parameters }) {
const activePoll = parameters.polls.find(p => p.status === 'active');
if (!activePoll) return null;
return (
<div className="poll">
<h3>{activePoll.question}</h3>
{activePoll.options.map((option, index) => (
<button
key={index}
onClick={() => {
parameters.handleVotePoll({
pollId: activePoll.id,
optionIndex: index,
parameters
});
}}
>
{option} ({activePoll.votes?.[index] || 0} votes)
</button>
))}
</div>
);
}Breakout Rooms Methods
// Create breakout rooms
parameters.createBreakoutRooms({
numberOfRooms: 3,
participants: parameters.participants,
parameters
});
// Assign participant to room
parameters.assignParticipantToRoom({
participantId: 'participant-id',
roomIndex: 0,
parameters
});
// Start breakout rooms
parameters.startBreakoutRooms({ parameters });
// Stop breakout rooms
parameters.stopBreakoutRooms({ parameters });
// Access breakout room data
const breakoutRooms = parameters.breakoutRooms;
const currentRoom = parameters.currentBreakoutRoom;Whiteboard Methods
// Show/hide whiteboard
parameters.updateWhiteboardStarted(true);
parameters.updateWhiteboardEnded(false);
// Configure whiteboard
parameters.launchConfigureWhiteboard.launchConfigureWhiteboard({ parameters });
// Access whiteboard state
const isWhiteboardActive = parameters.whiteboardStarted;
const whiteboardData = parameters.whiteboardUsers;Utility Methods
// Check permissions
const hasPermission = await parameters.checkPermission({
permissionType: 'video', // or 'audio'
parameters
});
// Format large numbers
const formatted = parameters.formatNumber(1250000); // Returns "1.25M"
// Sleep/delay
await parameters.sleep({ ms: 1000 });
// Update display settings
parameters.updateMainWindow(true); // Show/hide main window
// Trigger layout recalculation
parameters.onScreenChanges({ changed: true, parameters });
// Get room information
const roomInfo = {
name: parameters.roomName,
host: parameters.host,
capacity: parameters.capacity,
eventType: parameters.eventType,
duration: parameters.duration
};Complete method documentation: Visit mediasfu.com/vue for detailed documentation on all 200+ methods.
Media Streams & Participants
Understanding how to work with media streams and participant data is crucial for building custom features.
Understanding Participants
// Participant object structure
{
id: string; // Unique identifier
name: string; // Display name
muted: boolean; // Audio state
videoOn: boolean; // Video state
audioID: string | null; // Audio producer ID
videoID: string | null; // Video producer ID
islevel: string; // '2' = host, '1' = co-host, '0' = participant
// ... more properties
}
// Accessing participants
const participants = parameters.participants;
// Filter participants by criteria
const videoParticipants = participants.filter(p => p.videoOn);
const hosts = participants.filter(p => p.islevel === '2');
// Find specific participant
const participant = participants.find(p => p.id === 'participant-id');Working with Streams
// Stream object structure
{
producerId: string; // Producer identifier
stream: MediaStream; // Actual media stream
kind: string; // 'video' or 'audio'
producerId: string; // Associated producer ID
// ... more properties
}
// Get all video streams
const videoStreams = parameters.allVideoStreams;
// Get all audio streams
const audioStreams = parameters.allAudioStreams;
// Find stream by producer ID
const stream = videoStreams.find(s => s.producerId === 'producer-id');Using the New Utility Methods
// Get specific participant's video stream
const videoStream = await parameters.getParticipantMedia({
id: 'participant-id',
name: 'John Doe',
kind: 'video'
});
// Get specific participant's audio stream
const audioStream = await parameters.getParticipantMedia({
name: 'Alice Smith',
kind: 'audio'
});
// Example: Display specific participant's video
function ParticipantSpotlight({ participantName, parameters }) {
const stream = ref(null);
const videoRef = useRef(null);
onMounted(() => {
const loadStream = async () => {
const mediaStream = await parameters.getParticipantMedia({
name: participantName,
kind: 'video'
});
setStream(mediaStream);
};
loadStream();
}, [participantName]);
onMounted(() => {
if (videoRef.current && stream) {
videoRef.current.srcObject = stream;
}
}, [stream]);
return (
<div>
<h3>{participantName}'s Video</h3>
<video ref={videoRef} autoPlay playsInline muted style={{ width: '100%' }} />
</div>
);
}Monitoring Participant State Changes
// Listen for participant updates
parameters.updateParticipants = (updatedParticipants) => {
console.log('Participants updated:', updatedParticipants);
// Handle participant changes
};
// Example: Participant counter
function ParticipantCounter({ parameters }) {
return (
<div>
<span>👥 {parameters.participantsCounter} participants</span>
<span>🎥 {parameters.participants.filter(p => p.videoOn).length} with video</span>
<span>🔇 {parameters.participants.filter(p => p.muted).length} muted</span>
</div>
);
}Advanced Stream Management
// Custom grid with specific participants
function CustomParticipantGrid({ parameters }) {
const selectedParticipants = ref([]);
const renderParticipantVideo = (participant) => {
if (!participant.videoID) return null;
const stream = parameters.allVideoStreams.find(
s => s.producerId === participant.videoID
);
return (
<video
key={participant.id}
ref={videoRef => {
if (videoRef && stream?.stream) {
videoRef.srcObject = stream.stream;
videoRef.play();
}
}}
autoPlay
playsInline
muted
style={{ width: '200px', height: '150px' }}
/>
);
};
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: '10px' }}>
{selectedParticipants.map(participant => (
<div key={participant.id}>
{renderParticipantVideo(participant)}
<p>{participant.name}</p>
</div>
))}
</div>
);
}Customization & Styling
Make MediaSFU match your brand and design requirements.
1. Customizing the Pre-Join Page
Replace the default pre-join page with your own:
import { MediasfuGeneric } from 'mediasfu-vue';
function CustomPreJoinPage({ parameters, credentials }) {
const name = ref('');
const roomId = ref('');
const joinRoom = async () => {
// Your validation logic
if (!name || !roomId) {
alert('Please enter your name and room ID');
return;
}
// Join the room
parameters.updateMember(name);
parameters.updateRoomName(roomId);
parameters.updateValidated(true);
};
return (
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
minHeight: '100vh',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
}}>
<img src="/your-logo.png" alt="Logo" style={{ width: 150, marginBottom: 40 }} />
<h1 style={{ color: 'white', marginBottom: 30 }}>Welcome to Our Meeting</h1>
<input
type="text"
placeholder="Your Name"
value={name}
onChange={(e) => setName(e.target.value)}
style={{
padding: '12px 20px',
marginBottom: 15,
width: 300,
borderRadius: 8,
border: 'none'
}}
/>
<input
type="text"
placeholder="Room ID"
value={roomId}
onChange={(e) => setRoomId(e.target.value)}
style={{
padding: '12px 20px',
marginBottom: 20,
width: 300,
borderRadius: 8,
border: 'none'
}}
/>
<button
onClick={joinRoom}
style={{
padding: '14px 40px',
background: '#4CAF50',
color: 'white',
border: 'none',
borderRadius: 8,
fontSize: 18,
cursor: 'pointer',
fontWeight: 'bold'
}}
>
Join Meeting
</button>
</div>
);
}
// Use it
function App() {
return (
<MediasfuGeneric
credentials={credentials}
PrejoinPage={CustomPreJoinPage}
/>
);
}2. Custom Control Buttons
Create your own control bar:
function CustomControls({ parameters }) {
return (
<div style={{
position: 'fixed',
bottom: 20,
left: '50%',
transform: 'translateX(-50%)',
display: 'flex',
gap: 15,
background: 'rgba(0, 0, 0, 0.8)',
padding: 20,
borderRadius: 15,
boxShadow: '0 4px 20px rgba(0,0,0,0.3)'
}}>
{/* Video button */}
<button
onClick={() => parameters.clickVideo({ parameters })}
style={{
width: 60,
height: 60,
borderRadius: '50%',
border: 'none',
background: parameters.videoAlreadyOn ? '#4CAF50' : '#f44336',
color: 'white',
fontSize: 24,
cursor: 'pointer'
}}
>
📹
</button>
{/* Audio button */}
<button
onClick={() => parameters.clickAudio({ parameters })}
style={{
width: 60,
height: 60,
borderRadius: '50%',
border: 'none',
background: parameters.audioAlreadyOn ? '#4CAF50' : '#f44336',
color: 'white',
fontSize: 24,
cursor: 'pointer'
}}
>
{parameters.audioAlreadyOn ? '🎤' : '🔇'}
</button>
{/* Screen share button */}
<button
onClick={() => parameters.clickScreenShare({ parameters })}
style={{
width: 60,
height: 60,
borderRadius: '50%',
border: 'none',
background: parameters.screenAlreadyOn ? '#2196F3' : '#666',
color: 'white',
fontSize: 24,
cursor: 'pointer'
}}
>
🖥️
</button>
{/* Leave button */}
<button
onClick={() => parameters.launchConfirmExit({ parameters })}
style={{
width: 60,
height: 60,
borderRadius: '50%',
border: 'none',
background: '#f44336',
color: 'white',
fontSize: 24,
cursor: 'pointer'
}}
>
📞
</button>
</div>
);
}3. Themed Application
Apply your app's theme to MediaSFU:
import { MediasfuGeneric } from 'mediasfu-vue';
import './custom-theme.css';
function App() {
return (
<div className="themed-app">
<MediasfuGeneric
credentials={credentials}
// Custom styles for container
containerStyle={{
backgroundColor: '#1a1a2e',
borderRadius: '15px',
overflow: 'hidden'
}}
// Custom card components
customVideoCard={CustomVideoCard}
customAudioCard={CustomAudioCard}
customMiniCard={CustomMiniCard}
/>
</div>
);
}
// custom-theme.css
/*
.themed-app {
--primary-color: #6c5ce7;
--secondary-color: #a29bfe;
--background-color: #1a1a2e;
--text-color: #ffffff;
}
.themed-app button {
background: var(--primary-color);
color: var(--text-color);
border: none;
border-radius: 8px;
padding: 10px 20px;
cursor: pointer;
transition: all 0.3s ease;
}
.themed-app button:hover {
background: var(--secondary-color);
transform: translateY(-2px);
}
*/4. Complete Custom UI Example
Here's a complete example combining everything:
import { ref } from 'vue';
import {
MediasfuGeneric,
FlexibleVideo,
FlexibleGrid,
AudioGrid
} from 'mediasfu-vue';
function CompleteCustomInterface({ parameters }) {
return (
<div style={{
display: 'flex',
flexDirection: 'column',
height: '100vh',
background: '#0f0f1e'
}}>
{/* Custom Header */}
<header style={{
padding: '20px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
color: 'white',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center'
}}>
<h1>{parameters.roomName}</h1>
<div>
<span>👥 {parameters.participantsCounter} participants</span>
<span style={{ marginLeft: 20 }}>
⏱️ {Math.floor(parameters.recordElapsedTime / 60)}:{(parameters.recordElapsedTime % 60).toString().padStart(2, '0')}
</span>
</div>
</header>
{/* Main Content */}
<div style={{ flex: 1, display: 'flex', overflow: 'hidden' }}>
{/* Video Area */}
<div style={{ flex: 3, display: 'flex', flexDirection: 'column', padding: 20 }}>
<FlexibleVideo
customWidth={window.innerWidth * 0.7}
customHeight={window.innerHeight * 0.5}
parameters={parameters}
/>
<div style={{ marginTop: 20 }}>
<FlexibleGrid
customWidth={window.innerWidth * 0.7}
customHeight={window.innerHeight * 0.3}
parameters={parameters}
/>
</div>
</div>
{/* Sidebar */}
<div style={{
flex: 1,
background: '#1a1a2e',
padding: 20,
overflowY: 'auto'
}}>
<h3 style={{ color: 'white' }}>Participants</h3>
{parameters.participants.map(participant => (
<div key={participant.id} style={{
padding: 10,
margin: '10px 0',
background: '#2a2a3e',
borderRadius: 8,
color: 'white'
}}>
{participant.name}
{participant.muted && ' 🔇'}
{participant.videoOn && ' 📹'}
</div>
))}
</div>
</div>
{/* Custom Controls */}
<div style={{
padding: 20,
background: '#1a1a2e',
display: 'flex',
justifyContent: 'center',
gap: 15
}}>
<button onClick={() => parameters.clickVideo({ parameters })}>
{parameters.videoAlreadyOn ? '📹 Stop Video' : '📹 Start Video'}
</button>
<button onClick={() => parameters.clickAudio({ parameters })}>
{parameters.audioAlreadyOn ? '🎤 Mute' : '🎤 Unmute'}
</button>
<button onClick={() => parameters.clickScreenShare({ parameters })}>
🖥️ Share Screen
</button>
<button onClick={() => parameters.updateIsMessagesModalVisible(true)}>
💬 Chat
</button>
<button onClick={() => parameters.launchConfirmExit({ parameters })} style={{ background: '#f44336' }}>
📞 Leave
</button>
</div>
</div>
);
}
function App() {
return (
<MediasfuGeneric
credentials={credentials}
customComponent={CompleteCustomInterface}
/>
);
}
export default App;Basic Usage Guide
A basic guide on how to use the module for common tasks.
This section will guide users through the initial setup and installation of the npm module.
Introduction
MediaSFU is a 2-page application consisting of a prejoin/welcome page and the main events room page. This guide will walk you through the basic usage of the module for setting up these pages.
Documentation Reference
For comprehensive documentation on the available methods, components, and functions, please visit mediasfu.com. This resource provides detailed information for this guide and additional documentation.
Prebuilt Event Rooms
MediaSFU provides prebuilt event rooms for various purposes. These rooms are rendered as full pages and can be easily imported and used in your application. Here are the available prebuilt event rooms:
- MediasfuGeneric: A generic event room suitable for various types of events.
- MediasfuBroadcast: A room optimized for broadcasting events.
- MediasfuWebinar: Specifically designed for hosting webinars.
- MediasfuConference: Ideal for hosting
