Video chats with Angular and WebRTC
If you’ve ever wondered how to make a web application like Skype or Zoom, or if you’re thinking about developing a video chat app with Angular, this article is for you.
We are going to create a sample application that will allow us to make a connection between remote peers using NAT-traversal technologies such as ICE, STUN, and TURN.
Let’s start by taking a brief look at WebRTC.
WebRTC (Web Real-Time Communication) is a free open source project that provides web browsers and mobile applications with real-time communication (RTC) through simple interfaces.
Enables audio and video communication to work within web pages by allowing peer-to-peer communication, eliminating the need to install plugins or download native applications.
The main WebRTC components we will use for this example are:
- getUserMedia, which allows a web browser to access the camera and microphone.
- RTCPeerConnection, which sets up audio/video calls.
In general we will need our Angular client and a server that acts as a signaller between both ends, this server will allow us to exchange data between the sender and the receiver of the call.
Signalling is the process of coordinating peer-to-peer communication through a server.
We can see it as a date with someone, first we offer to meet them and, if they accept, we both establish a meeting point, an address.
Signalling would be something similar, both devices need to know the meeting point, network interfaces, port.
This process can be divided into two steps:
1. Offer-answer: Through an offer-answer mechanism, video and audio information is shared in Session Description Protocol format (SDP).
The caller creates an offer, broadcasts it to the receiver and listens for an answer to continue the process:
2. Interactive Connectivity Establishment (ICE): network information is collected through icecandidates so that each pair knows the meeting point where to establish communication.
The RTCPeerConnection interface provides us with listening events so that we can add icecandidates as they are found:
For this example we have a server with Nodejs and socket.io that will act as a signalling.
If you are not familiar with Node and socket.io, you can see in the code below the main functionality for communication with the client.
The socket listens for the “send-message” event to be fired from Angular. When an event is received it will fire another “message” event with the same information for the client to receive.
In this simplified way, data can be shared between users.
Having seen what we’ll use to signalling, it’s time to write our video chat application in Angular.
First we create a project with angularCLI and add to the dependencies the ngx-socket.io library to communicate via websockets with the server.
In the app.module.ts we import the SocketIo module and pass the server configuration.
npm install ngx-socket-io
With this we have the communication with our websocket working and we can emit events from angular or subscribe to events with the fromEvent(‘[name-of-event]’) method.
The next step is to create a simple interface, which will contain a video element and a button, which will be used to make the call.
The application flow will be:
- A call event is triggered, we create the offer and send it to the user via the signalling service.
- When the receiver gets the offer, it creates an answer and sends it back to the sender.
- Search for icecandidates starts and they are shared, again, via websockets.
To do this, in the app.component.ts we will have to subscribe to the websockets service and check the type of message that arrives to perform the appropriate action (offer, answer or candidate).
Make a Call
When the call button is pressed, the service logic begins:
- Create an RTCPeerConnection by passing it the configuration of the servers that will carry out the negotiation (STUN) and register connection events.
With this _registerConnectionListeners() method, we will listen for most of the events provided by the RTCPeerConnection. The most important of them, onicecandidates.
When a candidate is received by one end it sends it to the other end through the signalling channel.
When this event is received, the candidate is added to the connection.
2. Capture the audio and video streams to assign to our <video> element.
3. Create an offer, add the offer data to the connection by configuring the localDescription and send the offer via the signalling service with the type ‘offer’.
Send the Answer
When the offer is sent, our signalling service receives the event and processes the response with the handleOffer method.
The receiver of the offer will follow a similar process to the sender:
- Creates a connection, captures the audio and video media, creates a response, adds it to the connection configuration as localDescription and sends it to the signalling service.
- Additionally, it performs one more action, configures the received offer as remoteDescription.
Receiving the answer
Now it is the sender who receives the response from the receiver by receiving the event of type ‘answer’ and the handleAnswer is triggered.
The sender also to configure the remote description with the received response and we would have the audio and video data flow configured at both ends.
That’s it, and now we can cross our fingers and try out the video chat application. 👏👏👏
Here is a link to the repo so you can see the full code of the Angular app
I hope this article has been useful and serves as a guide on how to start using the WebRTC api under the Angular framework.
I recommend going deeper into the api and reading the guide to be able to extend the functionality offered by this standard since, in a real application, we will have to cover many more aspects of communication, error handling and device compatibility, among many other things.