JSPM

quickrtc-server

1.0.1
    • ESM via JSPM
    • ES Module Entrypoint
    • Export Map
    • Keywords
    • License
    • Repository URL
    • TypeScript Types
    • README
    • Created
    • Published
    • Downloads 104
    • Score
      100M100P100Q41312F
    • License ISC

    QuickRTC Server - High-level WebRTC server abstraction

    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.