Open-source project
versatica/mediasoup-demo avatar
versatica/mediasoup-demo

mediasoup-demo is the reference WebRTC application for the mediasoup stack

mediasoup official demo application

1,273 stars672 forksTypeScriptISC

At a glance

What is it?
mediasoup-demo is the official demo application for mediasoup, a TypeScript browser client and server that exercise a video conferencing stack through dozens of URL parameters covering codecs, simulcast, encryption and diagnostics. It is ISC licensed, the default branch is v3, and the last push was on 2026-10-15.
Who is it for?
mediasoup-demo suits a developer who needs a working reference for mediasoup, a way to reproduce a specific WebRTC configuration, or a testbed for tuning simulcast and scalability modes, and it is the wrong tool for a production conferencing product, since it is a demo and the README does not describe hardening, authentication or scale beyond the rooms limit.
Can I use it commercially?
Yes. ISC is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A demo whose configuration surface is the documentation

mediasoup-demo is the official demo application of mediasoup, and the README is direct about its purpose. It is a demo application, and it exists so that people can see the library working and then read its source.

The interesting design decision is that the configuration is done through query parameters in the URL, and the README devotes a large table to them. There are more than thirty, and they cover every axis of a WebRTC session.

Some control what the application does at all. The roomId sets the room, displayName sets the participant name, and handlerName is the handler name of the mediasoup-client Device instance. The produce and consume booleans enable sending and receiving of audio and video, mic and webcam enable the microphone and webcam by default, and datachannel enables DataChannels.

Others pick the transport and the codecs. forceTcp forces RTC for audio, video and datachannel over TCP instead of UDP, which is the switch you reach for when a network blocks UDP. preferLocalCodecsOrder prefers the browser's codec order instead of the server's configured order. Then there is a family of force flags, forcePCMA for the microphone, and forceVP8, forceH264, forceVP9 and forceAV1 for webcam and screen sharing, so you can pin exactly one codec and see what happens.

The rest is diagnostics and simulation, and that is where the demo earns its keep for anyone debugging a real application.

The licence is ISC, the default branch is v3, and the authors are Iñaki Baz Castillo and José Luis Millán Villegas. The live version is at v3demo.mediasoup.org.

Simulcast, scalability modes and the parameters that control them

The simulcast parameters are the most technically interesting group, because simulcast is where a WebRTC application most often goes wrong.

enableWebcamLayers and enableSharingLayers turn on simulcast or SVC for the webcam and for screen sharing respectively, both defaulting to true. The scalabilityMode parameters then pick the shape of those layers, with the webcam defaulting to L1T3 for VP8 and H264 in each simulcast encoding and L3T3_KEY for VP9, and the screen sharing defaulting to L1T3 for VP8 and H264 and L3T3 for VP9.

The two scalability defaults differ in a way that is not accidental. The webcam uses L3T3_KEY, a temporal mode with a key frame in the lowest layer, because a camera feed changes gradually and the low layer can be reconstructed from the key frame. Screen sharing uses L3T3 without the key requirement, because a screen's lower layers are useful on their own as a static background when the top layer is not yet available.

The stream counts are separate from the modes, with numWebcamSimulcastStreams and numSharingSimulcastStreams both defaulting to 3. So the demo lets you hold the number of encodings fixed while changing the mode, and change the number while holding the mode, which is exactly the two-axis comparison a developer making that decision needs.

Two more parameters shape the video itself. videoContentHint applies a value to track.contentHint in produced video tracks, for webcam and screen sharing, and screenSharing4K switches screen sharing to 4K resolution, off by default.

The scalability mode strings themselves are not free text, they are the standard values from the WebRTC simulcast specification, which is why the table quotes them exactly.

The diagnostic parameters let you reproduce a broken call

Four parameters exist purely so that a developer can look at what the stack is doing, and they are the reason the demo is useful beyond a screenshot.

The info parameter displays detailed information about media transmission over each peer. The stats parameter displays detailed information about WebRTC stats. The faceDetection parameter runs face detection, which is a way to see the video pipeline producing something usable. And consumerReplicas creates artificial replicas of yourself and receives their audio and video, not displayed in the UI, which is a load test in a query string.

That last one is a genuinely useful trick. Duplicating your own consumer and rendering it invisibly lets you put several receive pipelines on one page and see whether the server, the transport or the browser degrades first, without needing several machines.

Two more parameters probe specific behaviours. disableBwe disables Bandwidth Estimation, and if true no BWE logic will be run in mediasoup-worker. enableAbsCaptureTime enables the abs-capture-time RTP extension, which is how you measure end to end latency properly. And usePipeTransports makes each room use separate mediasoup routers to produce and consume and communicate them with pipe transports, which is a way to see the difference between a single shared router and a router per stream.

There is also a parameter for a synthetic external video, externalVideo sends an external video instead of the local webcam, so you can drive the pipeline with a known source.

And the rtcstatsUrl parameter connects to an rtcstats-server, including a token, and overrides the providers.rtcstatsUrl value in config.mjs in the server. That is the hook for an external rtcstats-server, and it is a reminder that a demo that has a metrics backend behind it was built by people who run this in earnest.

Two server secrets gate the features that cost money

A few parameters only work if the server was started with a matching secret, and that is a small design lesson worth reading.

The throttleSecret enables network throttling, and the server must run with a NETWORK_THROTTLE_SECRET environment variable with the same value. The unlimitedRoomSecret enables an unlimited room, and otherwise rooms are limited to 10 minutes, with the server again needing an UNLIMITED_ROOM_SECRET environment variable with the same value.

So the demo has a resource policy that the client cannot override. The room time limit exists because a public demo has finite capacity and an open-ended room would let one participant hold a slot indefinitely, and the throttle exists because a public demo with unthrottled uploads is a bandwidth bill with no owner. Putting the secret on the server side means the client can ask, and the server decides.

There is one more secret in the list, and it is a different kind. e2eKey is a key for media E2E encryption and decryption, and the README notes it just works with some OPUS and VP8 codecs. That is a narrow limitation stated honestly, since end to end encryption in WebRTC is only possible for a codec whose bitstream can be encrypted in a way the browser will still decode, which in practice means not every codec and not every layer.

The three secrets together tell you the shape of the deployment. A public demo instance sets the room secret and the throttle secret and gives out the e2e key per session. A private instance that sets nothing keeps the ten minute room limit and no throttling.

Running it: a client, a server and a compiled worker

The installation is four steps, and the third one is the one people miss.

Clone the project:

sh
git clone https://github.com/versatica/mediasoup-demo.git
cd mediasoup-demo

Then ensure you have installed the dependencies required by mediasoup to build, with the link pointing at the mediasoup installation requirements for v3. That is the native toolchain step, because mediasoup runs a compiled worker process and the demo server needs it built.

Set up the mediasoup-demo server, and the README points at server/README.md for that rather than repeating it. Then set up the browser app:

sh
cd app
npm install --legacy-peer-deps

The --legacy-peer-deps flag is worth noticing, because it is the standard npm escape hatch for a dependency tree whose peer ranges do not line up. In a demo that is being updated against several moving parts at once, that is a pragmatic choice rather than a clean one, and it means a future npm version could change what gets installed.

The repository layout matches the two halves. There is app/ for the browser client, server/ for the Node server, deploy/ for the deployment, and tmp-scripts/ for helper scripts. There are broadcaster/ and broadcasters/ directories, and aiortc/ is present alongside the browser app.

The CI setup is in the badge row, and it describes the project's own maintenance. There are separate workflows for the demo server, for updating mediasoup, for updating the mediasoup client and for deploying the demo, all pointing at the v3 branch. The separate update workflows are the interesting ones, because they mean the demo tracks the library and the client library automatically rather than by hand, which is what keeps a reference implementation honest.

The CHANGELOG.md at the top of the repository is there for the release history, and the licence is ISC.

Editorial conclusion

mediasoup-demo suits a developer who needs a working reference for mediasoup, a way to reproduce a specific WebRTC configuration, or a testbed for tuning simulcast and scalability modes, and it is the wrong tool for a production conferencing product, since it is a demo and the README does not describe hardening, authentication or scale beyond the rooms limit. Before running it, install the mediasoup build dependencies the README points to, because the server needs a compiled worker rather than just npm packages. Verify first that the parameter you want to test is actually exposed as a query parameter, since the configuration surface is deliberately wide but entirely client side.

Frequently asked questions

What is mediasoup-demo?

It is the official demo application of mediasoup, consisting of a TypeScript browser client and a Node server. It exists to show the library in use and to serve as a reference implementation, and a hosted version is available at v3demo.mediasoup.org.

How is mediasoup-demo configured?

Through query parameters in the URL, with more than thirty available. They cover identity such as roomId and displayName, transport with forceTcp, media with produce, consume, mic, webcam and datachannel, and codec selection with forcePCMA, forceVP8, forceH264, forceVP9 and forceAV1.

What do the simulcast parameters control in mediasoup-demo?

enableWebcamLayers and enableSharingLayers turn simulcast or SVC on for the webcam and screen sharing, the scalabilityMode parameters pick the layer shape, with webcam defaults of L1T3 for VP8 and H264 and L3T3_KEY for VP9, and the stream count parameters set the number of streams, 3 for both by default.

How do I install and run mediasoup-demo?

Clone the repository, install the native dependencies mediasoup needs to build, follow server/README.md for the server, and install the browser app with cd app and npm install --legacy-peer-deps. The server needs a compiled mediasoup worker, so the native build step is not optional.

What are the server secrets in mediasoup-demo for?

The throttleSecret enables network throttling and the unlimitedRoomSecret lifts the ten minute room limit, and in both cases the server must be running with the matching NETWORK_THROTTLE_SECRET or UNLIMITED_ROOM_SECRET environment variable. The e2eKey enables media end to end encryption, which the README says just works with some OPUS and VP8 codecs.

Official sources

  1. Issues
  2. License: ISC
  3. Project website
  4. README
  5. versatica/mediasoup-demo on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/versatica-mediasoup-demo.svg)](https://hysenlabs.com/projects/versatica-mediasoup-demo)

Was this useful?