{"id":15700,"library":"mediasoup-client","title":"mediasoup-client for WebRTC","description":"mediasoup-client is a TypeScript client-side library designed for building robust WebRTC applications that interact with a mediasoup Selective Forwarding Unit (SFU) server. Currently at version 3.19.0, it provides a low-level, signaling-agnostic API that abstracts away much of the underlying WebRTC/ORTC complexities. Unlike its v2 predecessor, v3 removes the 'Peer' concept, focusing directly on Devices, Transports, Producers, and Consumers, offering greater flexibility. It's actively maintained with a consistent release cadence to align with WebRTC standards and mediasoup server updates, making it a powerful choice for developers requiring fine-grained control over their real-time media flows.","status":"active","version":"3.19.0","language":"javascript","source_language":"en","source_url":"https://github.com/versatica/mediasoup-client","tags":["javascript","webrtc","ortc","browser","nodejs","typescript"],"install":[{"cmd":"npm install mediasoup-client","lang":"bash","label":"npm"},{"cmd":"yarn add mediasoup-client","lang":"bash","label":"yarn"},{"cmd":"pnpm add mediasoup-client","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary entry point for client-side WebRTC logic. mediasoup-client is primarily an ESM-first library, and ships TypeScript types.","wrong":"const Device = require('mediasoup-client').Device;","symbol":"Device","correct":"import { Device } from 'mediasoup-client';"},{"note":"Represents a local track being sent to the mediasoup server. This is a type, the instance is created via `sendTransport.produce()`.","wrong":"import { MediaProducer } from 'mediasoup-client';","symbol":"Producer","correct":"import { Producer } from 'mediasoup-client';"},{"note":"Represents a local DataChannel being sent to the mediasoup server. This is a type, the instance is created via `sendTransport.produceData()`.","wrong":"import { DataChannelProducer } from 'mediasoup-client';","symbol":"DataProducer","correct":"import { DataProducer } from 'mediasoup-client';"}],"quickstart":{"code":"import { Device } from 'mediasoup-client';\nimport mySignaling from './my-signaling'; // Our own signaling stuff.\n\n// Create a device (use browser auto-detection).\nconst device = new Device();\n\n// Communicate with our server app to retrieve router RTP capabilities.\nconst routerRtpCapabilities = await mySignaling.request(\n\t'getRouterCapabilities'\n);\n\n// Load the device with the router RTP capabilities.\nawait device.load({ routerRtpCapabilities });\n\n// Check whether we can produce video to the router.\nif (!device.canProduce('video')) {\n\tconsole.warn('cannot produce video');\n\n\t// Abort next steps.\n}\n\n// Create a transport in the server for sending our media through it.\nconst { id, iceParameters, iceCandidates, dtlsParameters, sctpParameters } =\n\tawait mySignaling.request('createTransport', {\n\t\tsctpCapabilities: device.sctpCapabilities,\n\t});\n\n// Create the local representation of our server-side transport.\nconst sendTransport = device.createSendTransport({\n\tid,\n\ticeParameters,\n\ticeCandidates,\n\tdtlsParameters,\n\tsctpParameters,\n});\n\n// Set transport \"connect\" event handler.\nsendTransport.on('connect', async ({ dtlsParameters }, callback, errback) => {\n\t// Here we must communicate our local parameters to our remote transport.\n\ttry {\n\t\tawait mySignaling.request('transport-connect', {\n\t\t\ttransportId: sendTransport.id,\n\t\t\tdtlsParameters,\n\t\t});\n\n\t\t// Done in the server, tell our transport.\n\t\tcallback();\n\t} catch (error) {\n\t\t// Something was wrong in server side.\n\t\terrback(error);\n\t}\n});\n\n// Set transport \"produce\" event handler.\nsendTransport.on(\n\t'produce',\n\tasync ({ kind, rtpParameters, appData }, callback, errback) => {\n\t\t// Here we must communicate our local parameters to our remote transport.\n\t\ttry {\n\t\t\tconst { id } = await mySignaling.request('produce', {\n\t\t\t\ttransportId: sendTransport.id,\n\t\t\t\tkind,\n\t\t\t\trtpParameters,\n\t\t\t\tappData,\n\t\t\t});\n\n\t\t\t// Done in the server, pass the response to our transport.\n\t\t\tcallback({ id });\n\t\t} catch (error) {\n\t\t\t// Something was wrong in server side.\n\t\t\terrback(error);\n\t\t}\n\t}\n);\n\n// Set transport \"producedata\" event handler.\nsendTransport.on(\n\t'producedata',\n\tasync (\n\t\t{ sctpStreamParameters, label, protocol, appData },\n\t\tcallback,\n\t\terrback\n\t) => {\n\t\t// Here we must communicate our local parameters to our remote transport.\n\t\ttry {\n\t\t\tconst { id } = await mySignaling.request('produceData', {\n\t\t\t\ttransportId: sendTransport.id,\n\t\t\t\tsctpStreamParameters,\n\t\t\t\tlabel,\n\t\t\t\tprotocol,\n\t\t\t\tappData,\n\t\t\t});\n\n\t\t\t// Done in the server, pass the response to our transport.\n\t\t\tcallback({ id });\n\t\t} catch (error) {\n\t\t\t// Something was wrong in server side.\n\t\t\terrback(error);\n\t\t}\n\t}\n);\n\n// Produce our webcam video.\nconst stream = await navigator.mediaDevices.getUserMedia({ video: true });\nconst webcamTrack = stream.getVideoTracks()[0];\nconst webcamProducer = await sendTransport.produce({ track: webcamTrack });\n\n// Produce data (DataChannel).\nconst dataProducer = await sendTransport.produceData({\n\tordered: true,\n\tlabel: 'foo',\n});","lang":"typescript","description":"This quickstart initializes a mediasoup-client Device, loads it with router capabilities, establishes a WebRTC send transport through a custom signaling layer, and then demonstrates producing both a webcam video stream and a DataChannel."},"warnings":[{"fix":"Ensure your mediasoup server instance is also running version 3 or later. Downgrade `mediasoup-client` if you must use a v2 server.","message":"`mediasoup-client` v3 is strictly compatible ONLY with `mediasoup` (server) v3. Attempting to use it with a v2 `mediasoup` server will lead to incompatibility issues and errors.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Refactor existing v2 code to interact directly with `Device` for loading capabilities, and then create `SendTransport` and `RecvTransport` instances, followed by `Producer` and `Consumer` for media handling.","message":"The `Peer` abstraction was removed in `mediasoup-client` v3. Applications must now directly manage `Device`, `Transport`, `Producer`, and `Consumer` entities.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Review the official `mediasoup-client` v3 documentation and update your event handler implementations to match the new `callback` and `errback` parameter types and expected return values.","message":"The signatures for `sendTransport.on('produce')` and `sendTransport.on('producedata')` event handlers, specifically their `callback` and `errback` arguments, have changed in v3.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Design and implement a robust signaling mechanism (e.g., using `socket.io` or plain WebSockets) that can exchange the necessary SDP offers/answers, ICE candidates, and mediasoup-specific parameters between the client and server.","message":"`mediasoup-client` is signaling-agnostic and requires developers to implement their own signaling layer (e.g., via WebSockets) to communicate with the `mediasoup` server. The `mySignaling` object in examples is a placeholder.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Ensure your Node.js development and deployment environments meet the `engines.node` requirement (>=22). Use a Node.js version manager like `nvm` to easily switch or upgrade versions.","message":"While primarily a browser library, `mediasoup-client` can be used in Node.js environments but explicitly requires Node.js version 22 or higher as per its `engines` field.","severity":"gotcha","affected_versions":">=3.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure `await device.load({ routerRtpCapabilities });` is called and has resolved with valid capabilities from the server before proceeding to create transports or access device properties.","cause":"`device.load()` has not been called or completed successfully before attempting to access `device.sctpCapabilities` or create a transport.","error":"TypeError: Cannot read properties of undefined (reading 'sctpCapabilities')"},{"fix":"Always call `await device.load({ routerRtpCapabilities });` and wait for its completion before performing any operations that depend on the `Device` being initialized with router capabilities.","cause":"Attempting to create a `SendTransport` or `RecvTransport` instance, or perform other operations requiring a loaded device, when `device.load()` has not been successfully invoked.","error":"Mediasoup-client: `Device` not loaded"},{"fix":"Thoroughly review the `routerRtpCapabilities` retrieved from the server, ensure `device.load()` is using the correct data, and verify that the `dtlsParameters` and other transport-related parameters exchanged via your signaling server are accurate and consistent with the mediasoup server's expectations.","cause":"This generic WebRTC error often indicates a mismatch in RTP capabilities negotiated between the client and the mediasoup server during the signaling phase, or incorrect SDP provided by the signaling server.","error":"DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp."},{"fix":"Ensure that your signaling server logic handles transport connection idempotently. The `callback()` should only be called once per `connect` event. Implement safeguards on the client or server to prevent duplicate connection requests.","cause":"The `sendTransport.on('connect')` event handler's `callback()` function was invoked multiple times, or the `connect` event itself was triggered more than once for the same transport instance due to a signaling race condition.","error":"Error: Transport has already been connected"}],"ecosystem":"npm"}