Package Exports
- quickrtc-server
- quickrtc-server/dist/index.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (quickrtc-server) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
π QuickRTC Server
A powerful yet simple MediaSoup server with dependency injection support. Bring your own HTTP server and Socket.IO instance for maximum flexibility.
π Table of Contents
β¨ Features
- π Dependency Injection: Inject your own HTTP/HTTPS and Socket.IO servers.
- π Auto Conference Management: Automatically handle conference lifecycle.
- π₯ Participant Tracking: Real-time participant management.
- π Event-Driven Architecture: Comprehensive event system.
- π‘οΈ Error Handling: Robust error management.
- π§ Admin Tools: Conference and participant management APIs.
- π± TypeScript: Full type safety and IntelliSense.
π¦ Installation
npm install quickrtc_serverπ Quick Start
Basic Setup with Express
import express from "express";
import http from "http";
import { Server as SocketIOServer } from "socket.io";
import { QuickRTCServer } from "quickrtc_server";
// 1. Create your servers
const app = express();
const httpServer = http.createServer(app);
const socketServer = new SocketIOServer(httpServer);
// 2. Create QuickRTCServer with dependency injection
const mediaServer = new QuickRTCServer({
httpServer,
socketServer,
});
// 3. Start the server
await mediaServer.start();
httpServer.listen(3000, () => {
console.log("π Server running on port 3000");
});π Architecture Flow
Server Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β HTTP/HTTPS SERVER β
β (User-provided Express/etc) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Socket.IO SERVER β
β (User-provided) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β QuickRTCServer β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Worker β β Conference β β Socket β β
β β Service ββ β Management ββ β Controller β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MediaSoup Core β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
β β Workers β β Routers β β Transports β β
β β ββ β ββ β β β
β ββββββββββββββββ ββββββββββββββββ ββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββConference Lifecycle Flow
Client Request QuickRTCServer MediaSoup
β β β
βββ1. Join Conferenceβββββββββββ β
β β β
β β Check if conference β
β β exists β
β β β
β β If not exists: β
β βββCreate Routerβββββββββββββ
β βββRouter Createdββββββββββββ
β β Create Conference β
β β Add to Map β
β β β
β β Add Participant β
β β to Conference β
β β β
βββ2. Router Capabilitiesβββββββ β
β β β
βββ3. Create Transportsβββββββββ β
β βββCreate WebRTC Transportβββ
β βββTransport Paramsββββββββββ
βββ4. Transport Paramsββββββββββ β
β β β
βββ5. Produce Mediaβββββββββββββ β
β βββCreate Producerβββββββββββ
β βββProducer Createdββββββββββ
β β β
β β Notify other participantsβ
β β (newProducer event) β
β β β
βββ6. Consume Mediaβββββββββββββ β
β βββCreate Consumerβββββββββββ
β βββConsumer Createdββββββββββ
βββ7. Consumer Paramsβββββββββββ β
β β β
βββ8. Disconnectββββββββββββββββ β
β β Remove Participant β
β β Close Transports β
β β Close Producers/Consumersβ
β β β
β β If last participant: β
β β Destroy Conference β
β βββClose Routerββββββββββββββ
β β βπ API Reference
Constructor
new QuickRTCServer(config: QuickRTCServerConfig)Parameters:
interface QuickRTCServerConfig {
// Required: Inject your servers
httpServer: http.Server | https.Server;
socketServer: SocketIOServer;
// Optional: MediaSoup configuration
mediasoup?: {
workerSettings?: WorkerSettings;
routerOptions?: RouterOptions;
transportOptions?: WebRtcTransportOptions;
};
}Methods
start(): Promise<void>
Initialize and start the MediaSoup server.
await mediaServer.start();stop(): Promise<void>
Stop the server and clean up all resources.
await mediaServer.stop();getConferences(): Conference[]
Get all active conferences.
const conferences = mediaServer.getConferences();
console.log(`Active conferences: ${conferences.length}`);getParticipants(): Participant[]
Get all participants across all conferences.
const participants = mediaServer.getParticipants();
console.log(`Total participants: ${participants.length}`);getConferenceParticipants(conferenceId: string): Participant[]
Get participants in a specific conference.
const participants = mediaServer.getConferenceParticipants("room-123");getStats(): ServerStats
Get server statistics.
const stats = mediaServer.getStats();
console.log(`Conferences: ${stats.conferences}`);
console.log(`Participants: ${stats.participants}`);
console.log(`Producers: ${stats.producers}`);
console.log(`Consumers: ${stats.consumers}`);closeConference(conferenceId: string, reason?: string): Promise<void>
Close a conference and remove all participants.
await mediaServer.closeConference("room-123", "Maintenance");kickParticipant(participantId: string, reason?: string): Promise<void>
Remove a participant from their conference.
await mediaServer.kickParticipant("user-456", "Violated rules");broadcastToConference(conferenceId: string, event: string, data: any): void
Send a message to all participants in a conference.
mediaServer.broadcastToConference("room-123", "announcement", {
message: "Meeting will end in 5 minutes",
});βοΈ Configuration
MediaSoup Worker Settings
{
mediasoup: {
workerSettings: {
logLevel: "warn", // Log level: "debug" | "warn" | "error" | "none"
logTags: ["info", "ice", "dtls", "rtp", "srtp", "rtcp"],
rtcMinPort: 40000, // Minimum RTC port
rtcMaxPort: 49999, // Maximum RTC port
}
}
}Router Options
{
mediasoup: {
routerOptions: {
mediaCodecs: [
{
kind: "audio",
mimeType: "audio/opus",
clockRate: 48000,
channels: 2,
},
{
kind: "video",
mimeType: "video/H264",
clockRate: 90000,
parameters: {
"packetization-mode": 1,
"profile-level-id": "42e01f",
},
},
{
kind: "video",
mimeType: "video/VP8",
clockRate: 90000,
},
],
}
}
}Transport Options
{
mediasoup: {
transportOptions: {
listenIps: [
{
ip: "0.0.0.0", // Listen on all interfaces
announcedIp: "YOUR_PUBLIC_IP", // Your public IP (for remote clients)
},
],
enableUdp: true, // Enable UDP
enableTcp: true, // Enable TCP
preferUdp: true, // Prefer UDP over TCP
enableSctp: false, // Enable SCTP for data channels
}
}
}π Events
The server uses Node.js EventEmitter. Listen to events using on() or addEventListener().
serverStarted
Fired when the server initializes successfully.
mediaServer.on("serverStarted", (event) => {
console.log("π MediaSoup server started");
});serverError
Fired when a server error occurs.
mediaServer.on("serverError", (event) => {
console.error("Server error:", event.detail.error);
});clientConnected
Fired when a client connects via Socket.IO.
mediaServer.on("clientConnected", (event) => {
console.log("Client connected:", event.detail.socketId);
});clientDisconnected
Fired when a client disconnects.
mediaServer.on("clientDisconnected", (event) => {
console.log("Client disconnected:", event.detail.socketId);
});conferenceCreated
Fired when a conference is created.
mediaServer.on("conferenceCreated", (event) => {
const { conference } = event.detail;
console.log(`Conference created: ${conference.id}`);
});conferenceDestroyed
Fired when a conference is destroyed.
mediaServer.on("conferenceDestroyed", (event) => {
console.log(`Conference destroyed: ${event.detail.conferenceId}`);
});participantJoined
Fired when a participant joins a conference.
mediaServer.on("participantJoined", (event) => {
const { participant } = event.detail;
console.log(`${participant.name} joined ${participant.conferenceId}`);
});participantLeft
Fired when a participant leaves.
mediaServer.on("participantLeft", (event) => {
const { participant } = event.detail;
console.log(`${participant.name} left`);
});producerCreated
Fired when a producer is created.
mediaServer.on("producerCreated", (event) => {
const { producerId, participantId, kind } = event.detail;
console.log(`Producer created: ${kind} for ${participantId}`);
});producerClosed
Fired when a producer is closed.
mediaServer.on("producerClosed", (event) => {
const { producerId, participantId } = event.detail;
console.log(`Producer closed for ${participantId}`);
});consumerCreated
Fired when a consumer is created.
mediaServer.on("consumerCreated", (event) => {
const { consumerId, participantId, producerId } = event.detail;
console.log(`Consumer created for ${participantId}`);
});consumerClosed
Fired when a consumer is closed.
mediaServer.on("consumerClosed", (event) => {
const { consumerId, participantId } = event.detail;
console.log(`Consumer closed for ${participantId}`);
});π‘ Integration Examples
Express + HTTPS
import express from "express";
import https from "https";
import fs from "fs";
import { Server as SocketIOServer } from "socket.io";
import { QuickRTCServer } from "quickrtc_server";
const app = express();
// Load SSL certificates
const httpsOptions = {
key: fs.readFileSync("./certs/key.pem"),
cert: fs.readFileSync("./certs/cert.pem"),
};
// Create HTTPS server
const httpsServer = https.createServer(httpsOptions, app);
// Create Socket.IO server
const socketServer = new SocketIOServer(httpsServer, {
cors: { origin: "*" },
});
// Create MediaSoup server
const mediaServer = new QuickRTCServer({
httpServer: httpsServer,
socketServer,
mediasoup: {
workerSettings: {
logLevel: "warn",
rtcMinPort: 40000,
rtcMaxPort: 49999,
},
transportOptions: {
listenIps: [
{
ip: "0.0.0.0",
announcedIp: "YOUR_PUBLIC_IP",
},
],
},
},
});
// Start server
await mediaServer.start();
httpsServer.listen(3443, () => {
console.log("π HTTPS Server running on port 3443");
});Fastify Integration
import Fastify from "fastify";
import { Server as SocketIOServer } from "socket.io";
import { QuickRTCServer } from "quickrtc_server";
const fastify = Fastify();
// Get underlying HTTP server
await fastify.listen({ port: 3000 });
const httpServer = fastify.server;
// Create Socket.IO server
const socketServer = new SocketIOServer(httpServer, {
cors: { origin: "*" },
});
// Create MediaSoup server
const mediaServer = new QuickRTCServer({
httpServer,
socketServer,
});
await mediaServer.start();
console.log("π Fastify + MediaSoup running");Complete Express Example with API Routes
import express from "express";
import http from "http";
import { Server as SocketIOServer } from "socket.io";
import { QuickRTCServer } from "quickrtc_server";
import cors from "cors";
const app = express();
app.use(cors());
app.use(express.json());
// Create servers
const httpServer = http.createServer(app);
const socketServer = new SocketIOServer(httpServer, {
cors: { origin: "*" },
});
const mediaServer = new QuickRTCServer({
httpServer,
socketServer,
});
// API Routes
app.get("/api/conferences", (req, res) => {
const conferences = mediaServer.getConferences();
res.json(conferences);
});
app.get("/api/conferences/:id/participants", (req, res) => {
const participants = mediaServer.getConferenceParticipants(req.params.id);
res.json(participants);
});
app.get("/api/stats", (req, res) => {
const stats = mediaServer.getStats();
res.json(stats);
});
app.post("/api/conferences/:id/close", async (req, res) => {
try {
await mediaServer.closeConference(req.params.id, "Admin closed");
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.post("/api/participants/:id/kick", async (req, res) => {
try {
await mediaServer.kickParticipant(req.params.id, req.body.reason);
res.json({ success: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Start server
await mediaServer.start();
httpServer.listen(3000, () => {
console.log("π Server running on port 3000");
});Event Monitoring
import { QuickRTCServer } from "quickrtc_server";
const mediaServer = new QuickRTCServer({
httpServer,
socketServer,
});
// Monitor all server events
mediaServer.on("serverStarted", () => {
console.log("β
Server started");
});
mediaServer.on("conferenceCreated", (event) => {
const { conference } = event.detail;
console.log(`π Conference created: ${conference.id}`);
// Log to database, analytics, etc.
logToDatabase("conference_created", conference);
});
mediaServer.on("participantJoined", (event) => {
const { participant } = event.detail;
console.log(`π ${participant.name} joined ${participant.conferenceId}`);
// Update participant count
updateAnalytics("participant_joined", participant);
});
mediaServer.on("producerCreated", (event) => {
const { kind, participantId } = event.detail;
console.log(`πΉ ${kind} producer created for ${participantId}`);
});
mediaServer.on("serverError", (event) => {
console.error("β Server error:", event.detail.error);
// Alert admins
alertAdmins("server_error", event.detail.error);
});
await mediaServer.start();Graceful Shutdown
const mediaServer = new QuickRTCServer({
httpServer,
socketServer,
});
await mediaServer.start();
// Graceful shutdown
const shutdown = async (signal) => {
console.log(`\nπ‘ Received ${signal}, shutting down gracefully...`);
try {
// Stop accepting new connections
await mediaServer.stop();
// Close HTTP server
httpServer.close(() => {
console.log("β
Server shut down successfully");
process.exit(0);
});
} catch (error) {
console.error("Error during shutdown:", error);
process.exit(1);
}
};
process.on("SIGINT", () => shutdown("SIGINT"));
process.on("SIGTERM", () => shutdown("SIGTERM"));π TypeScript Support
Full TypeScript definitions are included.
import {
QuickRTCServer,
QuickRTCServerConfig,
Conference,
Participant,
ServerStats,
QuickRTCServerEvents,
} from "quickrtc_server";
// Type-safe configuration
const config: QuickRTCServerConfig = {
httpServer,
socketServer,
mediasoup: {
workerSettings: {
logLevel: "warn",
rtcMinPort: 40000,
rtcMaxPort: 49999,
},
},
};
const server = new QuickRTCServer(config);
// Type-safe event handling
server.on(
"participantJoined",
(event: CustomEvent<QuickRTCServerEvents["participantJoined"]>) => {
const { participant } = event.detail;
// TypeScript knows the event structure
}
);π€ Contributing
Contributions are welcome! Please see the main project README for guidelines.
π License
MIT License - see LICENSE file for details.