@mufconnect/live-sdk
Drop-in WebRTC live-streaming SDK for the web. Powers the host / viewer / cohost flows on top of MUF Engine.
Status: 0.1.0-alpha.0 — API surface is stable but the package is a thin TypeScript facade over the existing JS runtime. A full TS port follows in 0.1.0-beta. Pin a specific version in production.
Install
npm install @mufconnect/live-sdk socket.io-clientsocket.io-client is a peer dependency — your bundler resolves it
from your node_modules so we don't ship a duplicate copy.
Quickstart — host
import { MufLiveManager, LiveEvent } from '@mufconnect/live-sdk';
const manager = new MufLiveManager({
orgId: 'your-org-id', // omit for standalone deployments
orgKey: 'your-org-key',
displayName: 'Saad',
});
manager.on(LiveEvent.LOCAL_STREAM, ({ stream }) => {
document.getElementById('local-video').srcObject = stream;
});
manager.on(LiveEvent.VIEWER_COUNT, ({ count }) => {
document.getElementById('viewer-count').textContent = String(count);
});
manager.on(LiveEvent.SHARE_LINK, ({ link }) => {
console.log('Share this with viewers:', link);
});
await manager.preloadCamera();
await manager.startBroadcast({
title: 'My first MUF stream',
category: 'gaming',
});Quickstart — viewer
import { MufLiveManager } from '@mufconnect/live-sdk';
const manager = new MufLiveManager({
orgId: 'your-org-id',
orgKey: 'your-org-key',
displayName: 'Viewer Name', // shown in chat
});
manager.on('REMOTE_STREAM', ({ peerId, kind, stream }) => {
if (kind === 'video') {
const tile = createTileFor(peerId);
tile.querySelector('video').srcObject = stream;
}
});
await manager.joinAsViewer(roomId, {
displayName: 'Viewer Name',
hostPeerId, // identifies which broadcaster's audience to join
});Slot system
The prebuilt pages (broadcaster.html, viewer.html) include named DOM mount points where you plug in your own widgets. The slot names are part of the public API and won't be renamed without a major-version bump.
Three layers depending on your stack:
// Layer 1 — static config (simplest)
manager.fillSlot('header.actionPill', '<button>+ Follow</button>');
manager.fillSlot('actionBar.bottomRight', myCustomElement);
manager.fillSlot('endScreen.statsCards', (ctx) => `…${ctx.broadcasters[0]?.displayName}`);
// Layer 2 — events + reactive components
manager.on('SLOT_RENDER', ({ name, mount, ctx }) => {
if (name === 'header.actionPill') {
ReactDOM.render(<FollowBtn ctx={ctx} />, mount);
}
});
// Layer 3 — imperative escape hatch
const node = manager.getSlotMount('header.actionPill');
if (node) node.appendChild(myCustomElement);See SLOT_CONTRACT.md for the full slot taxonomy.
Standalone deployment (no MUF App backend)
If you have your own user database / billing / auth, you can deploy just the WebRTC + chat services and skip the MUF App API:
// Mint your own JWTs against the shared JWT_SECRET
import jwt from 'jsonwebtoken';
const token = jwt.sign({
room_id: roomId,
role: 'host',
room_type: 'live',
display_name: 'Saad',
host_peer_id: hostPeerId, // L.9 audience anchor
exp: Math.floor(Date.now() / 1000) + 86400,
}, process.env.JWT_SECRET);See STANDALONE_DEPLOYMENT.md for the full guide.
Server requirement
Your backend must run the MUF Engine signaling-server + media-sfu + chat-engine. Quickstart with Docker:
git clone https://github.com/MufConnect/muf-engine
cd muf-logic-engine
cp .env.example .env # edit JWT_SECRET + DB creds
docker compose up -dSee muf-engine README for self-hosting + deployment guides.
License
Proprietary. 2026 MUF Engine. All rights reserved.