Upskill/Reskill
Oct 1, 2024

Try Mediasoup: An Open Source Streaming Media Tool

Emmanuel Yusufu Kimaswa

Mediasoup, an open source server-side WebRTC library, revolutionizes the development of scalable real-time applications. Known for its superior codec support, Mediasoup offers a creative platform for building advanced real-time media streaming services.

It builds on WebRTC’s capability to enable browser-based interactions such as video calls and data transfers without plugins, enhancing it with a strong server-side solution for large-scale media handling. It features a flexible and scalable architecture, making it a top choice for developers focused on delivering high-quality real-time communication experiences.

Scalability: Uninterrupted Media Flow

Mediasoup’s scalability comes from its specialized architecture. It’s a Node.js library that works with C++ subprocesses called workers, each running on a separate CPU core to handle media streams.

Routers in these workers manage audio and video real-time transport protocol (RTP) packet exchanges, similar to managing multiparty conference rooms. For example, in a setting with several conference rooms, each room uses a different Mediasoup router, spreading the load across multiple workers.

As the number of users increases, especially in large broadcast events with hundreds or thousands of viewers, Mediasoup allows for adding more workers or spreading rooms across several hosts for smooth media flow. A key feature here is the router.pipeToRouter() function, enabling routers to communicate with each other for workload distribution, whether on the same or different hosts. This setup helps avoid overloading any single server and reduces latency and packet loss.

Mediasoup also efficiently manages video RTP transmission for large-scale broadcasts. It uses a server-side re-encoder to handle video packet retransmissions and keyframe requests, maintaining smooth video streams as the audience grows. This re-encoder processes streams from the broadcaster, re-encodes them and sends them to various Mediasoup routers serving many viewers. This way, it efficiently manages packet loss or keyframe requests without straining the broadcaster’s endpoint or affecting the viewing quality.

Versatility: Supporting Diverse Media Codecs

Mediasoup’s versatility shines through its robust support for a multitude of media codecs, an essential feature that empowers developers to design applications catering to a wide range of user preferences concerning video and audio formats. This codec support is not static but flexible, allowing the RTP parameters from producer endpoints to have different values from the preferred router capabilities, although they must still be present in the router’s capabilities.

The framework accommodates various popular codecs such as VP8, VP9, H.264 and Opus. Moreover, it’s possible to use different video codecs for different producers, for instance, utilizing H264 for webcam and VP8 for screen sharing. This enables fine-grained control over media encoding and decoding processes to achieve the desired balance between performance and quality.

Extensibility: Adapting and Enhancing

Mediasoup’s architecture is robust and flexible, ideal for developers who need to add extra features or to adapt the platform for specific business requirements. A key example of its flexibility is its integrations with FFmpeg and GStreamer.

Mediasoup allows easy media production and consumption from external sources, crucial for recording, transcoding and HTTP live streaming (HLS). Developers can simply create a server-side plain transport in Mediasoup and use the produce() or consume() functions with the necessary parameters to manage media.

Mediasoup’s Architecture

Mediasoup’s architectural entities are comprised of workers, routers, transports, producers and consumers. Together they provide the building blocks for real-time media applications.

Worker: Powering Media Processing

A Mediasoup worker is a C++ subprocess responsible for media processing, performing the computation necessary for media manipulation. Workers host multiple routers and run in separate threads to ensure non-blocking operations within an application.

To create a worker, you can use the mediasoup.createWorker() method, which is then used to instantiate a router.

Router: Orchestrating Media Streams

A router is a core entity acting as a container and manager for media streams. It’s the hub where media streams are routed between producers and consumers. Each router operates within the context of a worker and can manage multiple producers and consumers, orchestrating the flow of media streams within a specific room or context.

Transport: Enabling Communication Channels

Transports are responsible for carrying media streams between peers and the router. Transports are created within the context of a router and are pivotal for establishing communication channels for media streams. Each transport has a set of parameters and events, facilitating the connection, error handling and closure of media transmission channels.

Producer: Sending Media Streams

A producer represents a media source, serving as an endpoint that sends media streams to a router. Producers are created when a peer intends to start sending media.

Consumer: Receiving Media Streams

A consumer is an endpoint that receives media streams from a router. Consumers are created when a peer aims to start receiving media.

Try Mediasoup With a Demo Project

The demo project showcases a simplistic implementation of a real-time video communication platform using mediasoup, mediasoup-client and socket.io. The project has both server and client parts that work together to establish a real-time video communication channel between users.

Prerequisites for the Demo

Before beginning the demo, you need the following:

Tools, Libraries and Technologies

  1. mediasoup for WebRTC communication on the server.
  2. socket.io for real-time, bidirectional communication between the server and client.
  3. Nextjs for building the user interface.
  4. mediasoup-client for client-side Mediasoup functionalities.

Background Knowledge

  1. A basic understanding of JavaScript/TypeScript.
  2. Familiarity with React.
  3. Understanding of WebRTC concepts.

Project Setup

Begin by cloning or downloading the project repository. Start the server and client, per the instructions in the repository README.

Project Walkthrough

This demonstration establishes a basic Mediasoup server for sharing video streams. In this demo, a single participant both produces and consumes media: They generate the media using a producer from their device and simultaneously consume it using a consumer on the same device. This setup offers a clear illustration of the basic functionalities and interactions within a Mediasoup environment for video streaming.

Initialize the Server

Create an HTTP server using express, the http module. This server serves as the foundation for handling incoming client requests and WebSocket connections.

WebSocket connections are facilitated using the socket.io library, which provides the infrastructure for real-time, bidirectional communication between the server and clients.

To introduce the Mediasoup component for managing media streams, routing and transcoding, you need to initialize and configure Mediasoup within your server code. This typically involves creating a Mediasoup router, producers and consumers and handling various media-related events.

import express from "express";
import http from "http";
import { Server } from "socket.io";
import cors from "cors";
import mediasoup from "mediasoup";

const app = express();
const port = 4000;
const server = http.createServer(app);

// Initialize a Socket.IO server for WebSocket connections
const io = new Server(server, {
  cors: {
    origin: "*",
    credentials: true,
  },
});

// Create a namespace "/mediasoup" for mediasoup-related socket events
const peers = io.of("/mediasoup");

Initialize the Mediasoup Worker and Router

Start by initializing the core variables. These will be assigned to the actual Mediasoup components once they are created:

  • worker: Manages media transmission processes.
  • router: Directs media streams between producers and consumers.
  • producerTransport and consumerTransport: WebRTC transports for sending and receiving media.
  • producer and consumer: Handle the outgoing and incoming media streams, respectively.

The createWorker function initializes a Mediasoup worker.

let worker: mediasoup.types.Worker<mediasoup.types.AppData>;
let router: mediasoup.types.Router<mediasoup.types.AppData>;
let producerTransport:
  | mediasoup.types.WebRtcTransport<mediasoup.types.AppData>
  | undefined;
let consumerTransport:
  | mediasoup.types.WebRtcTransport<mediasoup.types.AppData>
  | undefined;
let producer: mediasoup.types.Producer<mediasoup.types.AppData> | undefined;
let consumer: mediasoup.types.Consumer<mediasoup.types.AppData> | undefined;

const createWorker = async (): Promise<
  mediasoup.types.Worker<mediasoup.types.AppData>
  
// Create a mediasoup worker with specific configuration
    const newWorker = await mediasoup.createWorker({
    rtcMinPort: 2000, // Minimum port number for RTC traffic
    rtcMaxPort: 2020, // Maximum port number for RTC traffic
  });

// Log the worker process ID for reference
  console.log(`Worker process ID ${newWorker.pid}`);

// Event handler for the 'died' event on the worker
newWorker.on("died", (error) => {
    console.error("mediasoup worker has died");
    // Gracefully shut down the process to allow for recovery or troubleshooting.
    setTimeout(() => {
      process.exit();
    }, 2000);
  });

  return newWorker;
};

Configure the Media Codecs

This code segment sets up the core client-server communication by defining an essential array of media codecs, including audio and video formats. This setup is pivotal for ensuring compatible and reliable media transmission between clients and the server.

I chose the Opus codec for its superior audio quality and the VP8 codec for video due to its real-time communication efficiency. Critical parameters such as the audio clock rate and channels and the video payload type are also specified. These configurations are not merely technical details; they are crucial for high-quality, low-latency media delivery.

/**
 * The media codecs configuration array.
 * Each object in this array provides configuration for a specific audio or video codec.
 */
const mediaCodecs: mediasoup.types.RtpCodecCapability[] = [
  {
    /** Indicates this is an audio codec configuration */
    kind: "audio",
    /**
     * Specifies the MIME type for the Opus codec, known for good audio quality at various bit rates.
     * Format: <type>/<subtype>, e.g., audio/opus
     */
    mimeType: "audio/opus",
    /**
     * Specifies the number of audio samples processed per second (48,000 samples per second for high-quality audio).
     * Higher values generally allow better audio quality.
     */
    clockRate: 48000,
    /** Specifies the number of audio channels (2 for stereo audio). */
    channels: 2,
    /**
     * Optional: Specifies a preferred payload type number for the codec.
     * Helps ensure consistency in payload type numbering across different sessions or applications.
     */
    preferredPayloadType: 96, // Example value
    /**
     * Optional: Specifies a list of RTCP feedback mechanisms supported by the codec.
     * Helps optimize codec behavior in response to network conditions.
     */
    rtcpFeedback: [
      // Example values
      { type: "nack" },
      { type: "nack", parameter: "pli" },
    ],
  },
  {
    /** Indicates this is a video codec configuration */
    kind: "video",
    /** Specifies the MIME type for the VP8 codec, commonly used for video compression. */
    mimeType: "video/VP8",
    /** Specifies the clock rate, or the number of timing ticks per second (commonly 90,000 for video). */
    clockRate: 90000,
    /**
     * Optional: Specifies codec-specific parameters.
     * In this case, sets the starting bitrate for the codec.
     */
    parameters: {
      "x-google-start-bitrate": 1000,
    },
    preferredPayloadType: 97, // Example value
    rtcpFeedback: [
      // Example values
      { type: "nack" },
      { type: "ccm", parameter: "fir" },
      { type: "goog-remb" },
    ],
  },
];

Set Up Event Handlers for Peer Connections

This code segment outlines the setup and management of peer connections for media streaming using WebRTC and Mediasoup. Below is a summarized overview:

  • connection: When a new peer connects, its connection is logged, and a success message is emitted back to the peer with its socket ID. A router is also created for each connected peer, enabling the routing of media streams. The router is configured with predefined media codecs.
  • disconnect: An event handler is set up to log when a peer disconnects, allowing for resource cleanup.
  • getRouterRtpCapabilities: An event handler allows peers to request the router’s RTP capabilities, which are essential for setting up transports and producers/consumers.
  • createTransport: An event handler manages requests to create transports (either for sending or receiving media), using a callback to provide transport parameters to the peer.
  • connectProducerTransport: An event handler is used to connect the sending transport with the necessary security parameters (DTLS).
  • transport-produce: An event handler sets up a media producer on the sending transport, handling the source of a single media track.
  • connectConsumerTransport: A similar event handler is used for connecting the receiving transport.
  • consumeMedia: An event handler facilitates media consumption from peers, checking router capabilities and creating a consumer on the consumer transport.
  • resumePausedConsumer: Another event handler allows for resuming media reception if it was previously paused.

// Event handler for new peer connections
peers.on("connection", async (socket) => {
 // ... Peer connection event handling ...

 /**
  * Create a router.
  * Since there are only two peers in this application, we only need one router for each peer.
  * In a more complex application, you may need multiple routers to handle multiple peers.
  * A router is required to route media to/from this peer.
  */
 router = await worker.createRouter({
   mediaCodecs: mediaCodecs,
 });

 /**
  * Event handler for fetching router RTP capabilities.
  * RTP capabilities are required for configuring transports and producers/consumers.
  * This function is called when a peer requests the router RTP capabilities.
  * The callback function is used to send the router RTP capabilities to the peer.
  */
 socket.on("getRouterRtpCapabilities", (callback) => {
   // ... Handling router RTP capabilities ...
 });

/**
  * Event handler for creating a transport.
  * A transport is required for sending or producing media.
  * The callback function is used to send the transport parameters to the peer.
  * @param {boolean} data.sender - Indicates whether the transport is for sending or receiving media.
  * @param {function} callback - A callback function to handle the result of the transport creation.
  */
 socket.on("createTransport", async ({ sender }, callback) => {
   // ... Creating sender/receiver transports ...
 });


 /**
  * Event handler for producing media.
  * This function sets up a producer for sending media to the peer.
  * A producer represents the source of a single media track (audio or video).
  * @param {object} data.dtlsParameters - Datagram Transport Layer Security (DTLS) parameters.
  * These parameters are necessary for securing the transport with encryption.
  */
 socket.on("connectProducerTransport", async ({ dtlsParameters }) => {
   // ... Connecting the sending transport ...
 });

 // Event handler for producing media
 socket.on("transport-produce", async ({ kind, rtpParameters }, callback) => {
   // ... Producing media ...
 });

 // Event handler for connecting the receiving transport
 socket.on("connectConsumerTransport", async ({ dtlsParameters }) => {
   // ... Connecting the receiving transport ...
 });

 /**
  * Event handler for consuming media.
  * This function sets up a consumer for receiving media from the peer.
  * A consumer represents the endpoint for receiving media of a single kind
  * (audio or video) from a remote peer. Creating a consumer involves multiple
  * steps to ensure that the media can be received and decoded correctly.
  */
 socket.on("consumeMedia", async ({ rtpCapabilities }, callback) => {
   // ... Consuming media ...
 });

 // Event handler for resuming media consumption
 socket.on("resumePausedConsumer", async (data) => {
   // ... Resuming media consumption ...
 });
});

Configure the WebRTC Transport Creation Function

The createWebRtcTransport function is the backbone of WebRTC media transfer in this application. It’s an asynchronous function that creates WebRTC transports and provides the necessary parameters for establishing and handling WebRTC connections.

const createWebRtcTransport = async (
  callback: (arg0: {
    params: mediasoup.types.WebRtcTransportOptions | { error: unknown };
  }) => void
) => {
 // ... WebRTC transport creation, configuration, and event handling ...
};

Set Up Server Listening

The HTTP server listens on port 4000 to start the application. This is the main entry point of the server where it begins accepting client connections.

const createWebRtcTransport = async (
  callback: (arg0: {
    params: mediasoup.types.WebRtcTransportOptions | { error: unknown };
  }) => void
) => {
 // ... WebRTC transport creation, configuration, and event handling ...
};

Initialize the Client

This client application sets up a connection to the /mediasoup namespace on the server using the socket.io-client library. This connection is essential for signaling and coordinating media transmission between the client and server.

Upon connecting to the server, the client triggers the startCamera function, which attempts to access the camera and capture a media stream. This media stream is then attached to the local video element for preview.

import { useEffect, useRef, useState } from "react";
import { io } from "socket.io-client";
import { Device } from "mediasoup-client";

export default function Home() {
 /**
  * References to the local and remote video HTML elements.
  * These refs are used to attach media streams to the video elements for playback.
  */
 const videoRef = useRef<HTMLVideoElement | null>(null);
 const remoteVideoRef = useRef<HTMLVideoElement | null>(null);

 /**
  * State to hold encoding parameters for the media stream.
  * Encoding parameters control the quality and bandwidth usage of the transmitted video.
  * Each object in the encoding array represents a different layer of encoding,
  * allowing for scalable video coding (SVC). The parameters defined here are:
  * - rid: The encoding layer identifier.
  * - maxBitrate: The maximum bitrate for this layer.
  * - scalabilityMode: The scalability mode which specifies the temporal and spatial scalability.
  *
  * Additionally, codecOptions are provided to control the initial bitrate.
  */
 const [params, setParams] = useState({
   encoding: [
     { rid: "r0", maxBitrate: 100000, scalabilityMode: "S1T3" }, // Lowest quality layer
     { rid: "r1", maxBitrate: 300000, scalabilityMode: "S1T3" }, // Middle quality layer
     { rid: "r2", maxBitrate: 900000, scalabilityMode: "S1T3" }, // Highest quality layer
   ],
   codecOptions: { videoGoogleStartBitrate: 1000 }, // Initial bitrate
 });

 /**
  * State to hold references to various mediasoup client-side entities.
  * These entities are crucial for managing the media transmission and reception.
  */
 const [device, setDevice] = useState<any>(null); // mediasoup Device
 const [socket, setSocket] = useState<any>(null); // Socket for signaling
 const [rtpCapabilities, setRtpCapabilities] = useState<any>(null); // RTP Capabilities for the device
 const [producerTransport, setProducerTransport] = useState<any>(null); // Transport for sending media
 const [consumerTransport, setConsumerTransport] = useState<any>(null); // Transport for receiving media

 /**
  * Effect to initialize the socket connection on component mount.
  * The socket is used for signaling to coordinate media transmission.
  * On successful connection, the camera is started to obtain a media stream.
  */
 useEffect(() => {
   const socket = io("http://localhost:4000/mediasoup");

   setSocket(socket);
   socket.on("connection-success", (data) => {
     startCamera();
   });
   return () => {
     socket.disconnect();
   };
 }, []);

 /**
  * Function to start the camera and obtain a media stream.
  * This stream is then attached to the local video element for preview.
  */
 const startCamera = async () => {
   try {
     const stream = await navigator.mediaDevices.getUserMedia({ video: true });
     if (videoRef.current) {
       const track = stream.getVideoTracks()[0];
       videoRef.current.srcObject = stream;
       setParams((current) => ({ ...current, track }));
     }
   } catch (error) {
     console.error("Error accessing camera:", error);
   }
 };

}

Set Up Local and Remote Video Elements

HTML video elements for displaying the local camera feed and the remote peer’s video stream are created and managed using React’s useRef hook. These elements are essential for visualizing the video streams on the client’s user interface.

//...
      <video ref={videoRef} id="localvideo" autoPlay playsInline />
      <video ref={remoteVideoRef} id="remotevideo" autoPlay playsInline />
//...

Prepare Button Actions for Various Workflow Steps

The client interface includes a series of buttons, each associated with a specific step in the media exchange workflow. These buttons trigger client-side functions that interact with the server to perform actions such as getting router RTP capabilities, creating devices, creating transports and consuming media.

      <div style={{ display: "flex", flexDirection: "column", gap: "20px" }}>
        <button onClick={getRouterRtpCapabilities}>
          Get Router RTP Capabilities
        </button>
        <button onClick={createDevice}>Create Device</button>
        <button onClick={createSendTransport}>Create send transport</button>
        <button onClick={connectSendTransport}>
          Connect send transport and produce
        </button>
        <button onClick={createRecvTransport}>Create recv transport</button>
        <button onClick={connectRecvTransport}>
          Connect recv transport and consume
        </button>
      </div>

Get Router RTP Capabilities

The client initiates a request to the server to obtain the router’s RTP capabilities. RTP capabilities describe the supported media formats and configurations for the server’s router. This information is crucial for configuring the Mediasoup device on the client side to ensure compatibility with the server.

   * Step 1: Retrieve the Router's RTP Capabilities.
   * This function requests the router's RTP capabilities from the server,
   * which are essential to configure the mediasoup Device.
   * The router's RTP capabilities describe the codecs and RTP parameters supported by the router.
   * This information is crucial for ensuring that the Device is compatible with the router.
   */
  const getRouterRtpCapabilities = async () => {
    socket.emit("getRouterRtpCapabilities", (data: any) => {
      setRtpCapabilities(data.routerRtpCapabilities);
      console.log(`getRouterRtpCapabilities: ${data.routerRtpCapabilities}`);
    });
  };

Create a Device

Upon receiving the router’s RTP capabilities from the server, the client creates a Mediasoup device. The device is a client-side entity that interacts with the server’s router to manage media communication. Loading the router’s RTP capabilities into the device ensures that it can use compatible codecs and parameters for media transmission.

  /**
   * Step 2: Create and Initialize the mediasoup Device.
   * This function creates a new mediasoup Device instance and loads the router's RTP capabilities into it.
   * The Device is a client-side entity that provides an API for managing sending/receiving media with a mediasoup server.
   * Loading the router's RTP capabilities ensures that the Device is aware of the codecs and RTP parameters it needs to use
   * to successfully send and receive media with the server.
   *
   * If the Device is unable to load the router's RTP capabilities (e.g., due to an unsupported browser),
   * an error is logged to the console.
   */
  const createDevice = async () => {
    try {
      const newDevice = new Device();

      await newDevice.load({ routerRtpCapabilities: rtpCapabilities });

      setDevice(newDevice);
    } catch (error: any) {
      console.log(error);
      if (error.name === "UnsupportedError") {
        console.error("Browser not supported");
      }
    }
  };

Create a Send Transport

The client sends a request to the server to create a send transport. A send transport is used for sending media from the client to the server. The server replicates the transport parameters on the client side, and the client initializes its own send transport based on these parameters.

/**
* Step 3: Create a Transport for Sending Media.
* This function initiates the creation of a transport on the server-side for sending media,
* and then replicates the transport on the client-side using the parameters returned by the server.
*/
const createSendTransport = async () => {
 // Request the server to create a send transport
 socket.emit(
   "createSendTransport",
   { sender: true },
   ({ params }: { params: any }) => {
     if (params.error) {
       console.log(params.error);
       return;
     }

     /**
      * Replicate the send transport on the client-side.
      * The `device.createSendTransport` method creates a send transport instance on the client-side
      * using the parameters provided by the server.
      */
     let transport = device.createSendTransport(params);

     // Update the state to hold the reference to the created transport
     setProducerTransport(transport);

     /**
        * Event handler for the "connect" event on the transport.
        * This event is triggered when the transport is ready to be connected.
        * The `dtlsParameters` are provided by the transport and are required to establish
        * the DTLS connection between the client and the server.
        * This event it emitted as a result of calling the `producerTransport?.produce(params)`
        * method in the next step. The event will only be emitted if this is the first time
        */
     transport.on(
       "connect",
       async ({ dtlsParameters }: any, callback: any, errback: any) => {
         try {
           console.log("----------> producer transport has connected");
           // Notify the server that the transport is ready to connect with the provided DTLS parameters
           await socket.emit("transport-connect", { dtlsParameters });
           // Callback to indicate success
           callback();
         } catch (error) {
           // Errback to indicate failure
           errback(error);
         }
       }
     );

     /**
        * Event handler for the "produce" event on the transport.
        * This event is triggered when the transport is ready to start producing media.
        * The `parameters` object contains the necessary information for producing media,
        * including the kind of media (audio or video) and the RTP parameters.
        * The event is emitted as a result of calling the `producerTransport?.produce(params)`
        * method in the next step.
        */
     transport.on(
       "produce",
       async (parameters: any, callback: any, errback: any) => {
         const { kind, rtpParameters } = parameters;

         console.log("----------> transport-produce");

         try {
           // Notify the server to start producing media with the provided parameters
           socket.emit(
             "transport-produce",
             { kind, rtpParameters },
             ({ id }: any) => {
               // Callback to provide the server-generated producer ID back to the transport
               callback({ id });
             }
           );
         } catch (error) {
           // Errback to indicate failure
           errback(error);
         }
       }
     );
   }
 );
};

Connect the Producer Transport and Producing Media

The client connects its send transport to the server. The transport’s connect event is triggered when it’s ready to establish a connection. The client uses the provided DTLS parameters to connect the transport. After connecting the transport, the client starts producing media (audio or video) using the local camera. The produced media is sent through the send transport to the server.

const connectSendTransport = async () => {
 // Producing media using the send transport
 let localProducer = await producerTransport.produce(params);

 // Event handlers for track ending and transport closing events
 localProducer.on("trackended", () => {
   console.log("trackended");
 });
 localProducer.on("transportclose", () => {
   console.log("transportclose");
 });
}

Create a Consumer Transport

The client requests that the server create a receive transport. A consumer transport is used for receiving media from the server. The server replicates the transport parameters on the client side, and the client initializes its consumer transport based on these parameters.

const createRecvTransport = async () => {
 // Requesting the server to create a receive transport
 socket.emit(
   "createTransport",
   { sender: false },
   ({ params }: { params: any }) => {
     if (params.error) {
       return;
     }

     // Creating a receive transport on the client-side using the server-provided parameters
     let transport = device.createRecvTransport(params);
     setConsumerTransport(transport);

     // Event handler for the connect event on the transport
     transport.on(
       "connect",
       async ({ dtlsParameters }: any, callback: any, errback: any) => {
         try {
           // Notifying the server to connect the receive transport with the provided DTLS parameters
           await socket.emit("transport-recv-connect", { dtlsParameters });
           callback();
         } catch (error) {
           errback(error);
         }
       }
     );
   }
 );
};

Connect the Receive Transport and Start to Consume Media

The connectRecvTransport function connects the client’s received transport to the server and starts consuming media received from the server. The transport’s connect event is triggered when it’s ready to establish a connection. The client uses the provided DTLS parameters to connect the transport. After connecting the transport, the client displays the consumed media in the remote video element on the user interface.

const connectRecvTransport = async () => {
 // Requesting the server to start consuming media
 await socket.emit(
   "consume",
   { rtpCapabilities: device.rtpCapabilities },
   async ({ params }: any) => {
     if (params.error) {
       return;
     }

     // Consuming media using the receive transport
     let consumer = await consumerTransport.consume({
       id: params.id,
       producerId: params.producerId,
       kind: params.kind,
       rtpParameters: params.rtpParameters,
     });

     // Accessing the media track from the consumer
     const { track } = consumer;

     // Attaching the media track to the remote video element for playback
     if (remoteVideoRef.current) {
       remoteVideoRef.current.srcObject = new MediaStream([track]);
     }

     // Notifying the server to resume media consumption
     socket.emit("consume-resume");
   }
 );
};

Conclusion

Mediasoup provides a comprehensive platform for building scalable and versatile real-time communication applications. Its ability to handle large-scale media streams with efficient load distribution and minimal latency makes it ideal for high-demand environments. The support for various codecs and seamless integration with external tools like FFmpeg and GStreamer offer developers flexibility in customizing their applications.

Whether used for broadcasting or interactive video communication, Mediasoup’s architecture ensures reliable performance and smooth media handling, allowing developers to create rich, high-quality user experiences.

Interested in 
Learning More?

Subscribe today to stay informed and get regular updates from Andela.

You might also be interested in

Ready to get started?

Contact Us