Giter VIP home page Giter VIP logo

mediasoup-broadcast-example's Introduction

Mediasoup Broadcast Example

Mediasoup is a Javascript library that provides a WebRTC SFU (Selective Forwarding Unit), which enables modern browsers on all platforms (Chrome, Edge, Firefox, and Safari, desktop and mobile) to use Real Time Communications for sending and receiving audio/video streams with just a single publically-accessible server (no need for transcoding or direct connections between peers as is necessary for other WebRTC setups).

This project is a vanilla Javascript example of how to use Mediasoup to support the specific case of one-to-many broadcast audio/video on individual "channels". I prefer writing Typescript, but I wanted to demonstrate a minimal implementation for learning purposes.

There are no techniques borrowed from other code, just the docs. Accordingly, the ISC license (simple, permissive) is used for this code to encourage you to derive your own software from it without legal worries. Pull requests are welcome! I don't want to add more features, but polishing and simplifying this example are important to me. See the TODO.md for suggested contributions.

Quickstart

For simple tests, run:

$ PORT=8080 node server/index.js

and connect subscribers to:

http://localhost:8080/

and a publisher (one per channel) to:

http://localhost:8080/publish.html

Click "Capture" and then "Publish" to send the A/V stream to any attached subscribers. A subscriber can "Subscribe" at any time. The default passwords in the interfaces will work out-of-the-box. Read the browser console log and Node.js output when you want to learn more about what's happening.

If you have problems with black screens or choppiness/delays, it is probably due to your network/firewall configuration. First try to get things working with simply localhost, then reread the below notes on RTC_ANNOUNCED_IPV4 before you log an issue.

I deliberately chose Opus and H.264 for the only supported A/V codecs, because that's the only combination that will work for both modern Safari and Edge (Chrome and Firefox are much more tolerant). There are still some problems with Edge that I'm working with the Mediasoup folks to resolve, but my default settings seem to work well enough.

Simulcast

If you want to experiment with Simulcast (publishing multiple resolutions at a time, so that subscribers can choose between them), currently only Chrome publishers support it for H264, and only then if you specify the --force-fieldtrials=WebRTC-H264Simulcast/Enabled/ command-line option when you start Chrome for the first time.

MJPEG

If you have access to an MJPEG IP camera, you can specify it in the publisher. Note that most cameras don't set the CORS headers to allow cross-origin access, and their content can't even be accessed from HTTPS pages since they are not on localhost, so you may have to use a localhost proxy or browser extension such as Cacao in order to allow access.

Architecture

Read the following sections to understand more about what you will need to change when you build your own broadcast system.

app/

This directory contains the subscriber (index.html) and publisher (publish.html) for the server. It uses the Mediasoup Client library to handle the protocol requests to and from the Mediasoup server. The manipulation of the video and stream objects was the hardest to get right for all browsers, so I encourage you to crib the techniques I used.

Until I have a chance to refactor, you should know that I tend to write code from bottom to top... the more high-level code comes at the end of each file. Also, more inline documentation will be added in the future.

  • common.js - Look for the FIXMEs to see what may need to change, specifically the authentication process.

server/

This directory contains the Node.js server-side code that coordinates interaction between the publisher, the subscriber, and Mediasoup itself. Mediasoup does not specify a signalling protocol, so this server uses plain WebSocket (via the ws module) with JSON-formatted messages.

NOTE: In order to run this example, the server/index.js must be running either on localhost, or a publically-accessible IP address. Note that private IP ranges and VPN connections are filtered out by some browser WebRTC implementations (notably Safari), so your streams will probably not be forwarded correctly if you run locally.

Note the following environment variables affect the server:

  • HOST, PORT - IP address, TCP port to listen on for HTTP connections (default: 0.0.0.0 80). Connect to http://<HOST>:<PORT>/ for the subscriber, http://<HOST>:<PORT>/publish.html for the publisher.

  • RTC_ANNOUNCED_IPV4, RTC_ANNOUNCED_IPV6 - Default, autodetect. These are IP addresses that the publisher and subscriber can use to connect to the Mediasoup worker (running as a subprocess of the Node.js server). Make sure your firewalls allow inbound TCP and UDP ports 10000-59999 to this address, as well as no limits on outbound connections.

  • SEND_PASSWORD, RECV_PASSWORD - plaintext passwords used for authentication.

  • auth.js - replace this file with your own implementation of authentication for your publisher and subscriber.

Running under Docker

For extra credit, you can run the server under Docker, see example repository. You will need host networking (--network host, which doesn't work on Windows or MacOS versions of Docker, since they are actually running in a VM) to allow the Docker instance to access all the TCP and UDP ports it needs (see above RTC_ANNOUNCED_IPV4). Docker doesn't allow exposing port ranges.

Bonus: Kubernetes

If you like Kubernetes, there is a Helm chart in charts/mediasoup-broadcast-example. See the values.yaml in that directory for instructions on using hostNetworkIP. In short, you will need to schedule the mediasoup-broadcast-example pod (single replica only) to run on a node that has an external IP that meets the requirements of RTC_ANNOUNCED_IPV4. To accomplish this, you will use hostNetworkIP: <MY-IP> in your Helm yaml settings, and then label the node that receives traffic for that public IP with:

$ kubectl label node <MY-NODE> hostNetworkIP=<MY-IP>

Refer to build.sh and charts/example.yaml for rudimentary hints on how to install it.

Credits

Thanks a lot to Iñaki Baz Castillo for the wonderful Mediasoup software, and quick and responsive support of it.

I, Michael FIG, implemented the first working version of this example within a week, from scratch, using only the Mediasoup and Mediasoup Client API documentation and publically-accessible Web API documentation as references. I hope this helps you jumpstart your own projects!

Have fun!

Michael FIG [email protected], 2018-10-13

mediasoup-broadcast-example's People

Contributors

dependabot[bot] avatar michaelfig avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mediasoup-broadcast-example's Issues

Error: WebSocket is not open

Greetings, I'm trying to run the project on my local machine. I was able to get the server started with PORT=8080 node server/index.js. Going to http://localhost:8080/publish.html and checking Publish instantly gives me a Error: WebSocket is not open error on the browser console.

For context, the last received message is:

{
    "type": "MS_RESPONSE",
    "payload": {
        "kind": "publish",
        "turnServers": []
    },
    "meta": {
        "id": 1,
        "channel": "test"
    }
}

And in the server logs, I see:

::1 58240 Authorizing publisher to test
::1 58240 cannot authorize klass [InvalidStateError]: Server closed

I've set the video source to my webcam. I see the same error on the subscriber side of things. I'd really appreciate some help here!

broadcast avi video

Hi, MichaelFig,

I just ran the example, and it ran well.

It also can broadcast the big_buck_bunny.mp4 video. I copy a avi file, test.avi, to the app/videos/ directory , and change the Video SRC from big_buck_bunny.mp4 to test.avi. But It can not broadcast the avi stream.

Would you please tell me how to broadcast the avi video like mp4 video ?

Thank you very much.

unable to run

when i run the PORT=8080 node server/index.js

i see the following issue, can advise how to resolve? i have already installed all the required packages:

/home/mediasoup-broadcast-example/node_modules/ws/lib/websocket.js:16
const {
^

SyntaxError: Unexpected token {
at exports.runInThisContext (vm.js:53:16)
at Module._compile (module.js:374:25)
at Object.Module._extensions..js (module.js:417:10)
at Module.load (module.js:344:32)
at Function.Module._load (module.js:301:12)
at Module.require (module.js:354:17)
at require (internal/module.js:12:17)
at Object. (/home/guest/mediasoup-broadcast-example/node_modules/ws/index.js:3:19)
at Module._compile (module.js:410:26)
at Object.Module._extensions..js (module.js:417:10)

Publish from iOS

I have set the server up behind Nginx with a valid SSL cert.

Chrome, Firefox and Safari are able to publish from MacOS. But iOS does not prompt to allow for the camera/mic.

Any ideas?

i want thumbnail on broadcast .

I would like to extract a thumbnail image while broadcasting with WebRTC. What should I do ?

i want thumbnail on broadcast .
how to get thumbnail ?

Unable to see video stream at Client

Hi

My current setup is in a VM for ubuntu 18.04

i had installed and try the demo to publish the video file and then have the client to receive and display. However i have a black screen and unable to show despite the video shows received values for kB/s at the Client(chrome browser) end and not showing blue screen.

I had read the instructions on the "black" screen and think i have eliminate most of the possible issues:

  1. disable firewall
  2. use my chrome browser to see the video to prove that it can play which it does.

And can i able to stream using ffmpeg to the server to stream out to the client?

pls advise. thanks

Uncaught TypeError: Cannot read property 'getUserMedia' of undefined at HTMLButtonElement.captureStreams (publisher.js:129)

I have set up an AWS cluster with the provided Docker container - which appears to be running correctly. The firewall has been opened up as requested - and I see no errors from a server side perspective to indicate any problems.

However, when I go to visit publish.html and click capture - I get the following error;

image

I see no errors from a Subscriber side - and so the above seems to be limited to the issue regarding resolving what devices my browser has access to. I am running latest Chrome - and my same machine works fine on the MediaSoup demo site.

how to intall it

i have problem installing this example,when i run npm install ,it always returns socket time out errory
image

Well done, some minor issues

Thanks for sharing this project. I just have a problem to publish big_buck_bunny. Only the first frame is shown and published.

How to run this service on a server with a publicly accessible IP address

Hi
Michael

I want run this service on a server with a publicly accessible IP address
Now,I have a problem.
The specific steps are as follows
Step 1
HTTPS_HOST=0.0.0.0 PORT=443 node server/index.js
return
Listening for HTTPS on 0.0.0.0:443
Step 2
Enter in browser https://starcloud.work/publish.html Selection Publish Click Capture
return

xx.xx.xxx.xx 33546 Authorizing publisher to test
xx.xx.xxx.xx 33546 new peer joined the room publisher

Step 3
Enter in browser https://starcloud.work/ Selection Subscribe
return

xx.xx.xxx.xx 33618 Authorizing subscriber to test
xx.xx.xxx.xx 33618 new peer joined the room 0.8056946895632191

There was an error in Step 3 Can not see publisher

Thanks
Xiu Feng

Websocket error during handshake. Response code 404

Everything works on my local machine.

But when I deploy on my web server I got an error, complaining about pubsub with error 404.

The capture of camera and miccrophone works fine.

The error occurs on publish (publisher.html) and on subscribe (index.html).

What am I missing?

Error getting media (error code 0) under iPad for publishing

hello!

Thanks for your works.
On an iPad Safari ( latest iOS, v12.1.1 ), I can play correctly a stream, but I can't publish anything from the iPad.

I've tried to enable/disable camera/audio, nothing works.
I've also tried to inject webrtc-adapter but this doesn't help.

Regards,

Recording stream

Hi, is there way to record broadcast?
I was trying with createRtpStreamer, i added it inside Server.js
room.on('newpeer', (peer) => { peer.on('newproducer', (producer) => { let rtpParams = { remoteIP: '127.0.0.1', remotePort: (producer.kind === 'audio') ? 10000 : 10002}; room.createRtpStreamer(producer, rtpParams).then((streamer) => { console.log('started mirroring RTP for', producer.kind); }); }); });
So when i publish broadcast i get in console:
::ffff:127.0.0.1 59300 new peer joined the room publisher
started mirroring RTP for audio
started mirroring RTP for video

I tried to access stream with vlc but i cant connect over rtmp://127.0.0.1:1935/stream.
When i try gstreamer
command:
gst-launch-1.0 -em rtpbin name=rtpbin latency=5 udpsrc port=10000 caps="application/x-rtp,media=(string)audio,clock-rate=(int)48000,encoding-name=(string)OPUS" ! rtpbin.recv_rtp_sink_0 rtpbin. ! queue ! rtpopusdepay ! opusdec ! audioconvert ! audioresample ! voaacenc ! mux. udpsrc port=10002 caps="application/x-rtp,media=(string)video,clock-rate=(int)90000,encoding-name=(string)H264" ! rtpbin.recv_rtp_sink_1 rtpbin. ! queue ! rtph264depay ! h264parse ! mux. flvmux name=mux streamable=true ! rtmpsink sync=false location=rtmp://127.0.0.1:1935/stream
then when i publish broadcast i get in terminal:
Got message #185 from element "rtpsession0" (element): application/x-rtp-source-sdes, cname=(string)"\{f02b34db-da4f-456b-a964-0eb4d3e9f383\}";
Do you have any idea why i cant access stream?
Im still learning webrtc/mediasoup

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.