Today I would like to show you a WebRTC many to many video streaming demo with Kurento server and Scala Actors. Video broadcasting to wide audience from private rooms is the main feature.
Let me specify the advantages of Scala Actors concept such as:
– asynchronous calls involvement
– concurrent access to a state
– presenters may broadcast webcam and microphone to wide audience of up to 100 users
– simultaneous multiple room broadcasting
– a quick jump into one of the multiple rooms
– simple chat and list of connected users
– easy to run locally or deploy on server
– low latency
Let’s make participants life easier by skipping additional software like Flash Player. Flash Player is good enough for RTMP streaming, while it might be blocked or completely eliminated by browser in the nearest future.
WebRTC is the perfect replacement solution. WebRTC is compatible with Chrome, Firefox, Edge and Android browsers. WebRTC allows browsers sending media streams directly to each other. It works very well, as long as there are no more than 5 or 6 participants. With more participants video becomes laggy and choppy.
Since we are going to allow up to 100 users to watch the stream, streaming server should be sandwiched between the broadcaster and participants. There are few WebRTC streaming servers in the market, and we are going to use Kurento – the most mature one.
For those who wonder why we don’t take HLS into account,we believe, it’s just not applicable for low latency streaming.
Let’s examine how Kurento unloads traffic from a broadcaster.
Grey lines represent media streams, which in fact are RTP packets transmitted via TCP or UDP.
On the left side, there is a common for WebRTC applications peer to peer architecture, where browsers exchange media streams directly.
And on the right – Kurento component delivering stream from the broadcaster to all participants.
Beside Kurento component, that works with media streams, we would also need a signaling component that helps to establish a direct connection between browsers. Kurento website provides excellent documentation and code samples for Java and NodeJS signaling servers. However, Java and NodeJS might not be enough for well scaled video conferencing product with complex asynchronous logic, I believe Scala Actors is the right choice in this case.
The diagram below represents the sequence of calls which is almost the same for any kind of signaling server. It describes messaging flow when a user joins a room and starts video broadcasting – all communications via WebSockets and in JSON format.
We can see that a client needs to send a single “join” message to enter the room. And then the diagram shows which call should be made to start broadcasting.
There is a projection of real life items in OOP classes and instances. Scala Actors, on the other hand, don’t have any relations to OOP, but I would also describe Actors as projection. The crucial point is that Actors communicate asynchronously, like real life people.
RoomActor implements Scala Actors concept. It keeps conference room state and handles all requests to change room state. Each chat message and each connected user are recorded as room state. The connected user is represented by UserActor instance and RoomActor may communicate with clients by sending messages to those user actors instances. Same principle applied for receiving messages from clients.
Please, find all the benefits of using Actors concept with signaling server below:
– State and state change requests are being kept in one place
– Parallelism instead of concurrency. Since an actor works in single threaded mode, there is no need for locks and synchronization
– Asynchronous by definition. Representing room as an asynchronous actor is natural in any point of room lifecycle. For example, there is a starting and ending points with Scala Actors. Rooms as actors would work independently, could be with different threads and errors with one of the actors would not not affect others
– There is a full bag of useful patterns and tools with Scala Actors. For example, we could achieve room persistence by using persisted actors. Also it’s worth mentioning Actor FSM (Finite State Machine) pattern, that could make actor state fully strict typed and define exact rules of how a state may be transitioned.
For sure there could be drawbacks. But to my mind Scala pros overweight cons.
How to run
docker-compose build kurento
docker run -p 8888:8888 -d kurento
Visit http://localhost:9000 in 2 browsers and start broadcasting with one of them.
Running on a remote server:
Same steps should be made, as for the local environment. But we would also need HTTPS access to allow camera access with Google Chrome. It could be done with nginx proxy and HTTPS certificate generated with Let’s Encrypt.
Please take a look at GitHub repo with sources
Feedback is highly appreciated.
Also you can check similar demos and tutorials from Kurento: https://github.com/Kurento/kurento-tutorial-java/blob/master/kurento-group-call/ .