How I mastered WebRTC

WebRTC, short for ‘Web Real Time Communication’, is an open source API that supports voice/video chats and peer-to-peer connections for browsers without any plugins. The project started in the beginning of 2011. Now, a couple of years later, the project is getting more mature and with that more useful. Although not all browsers support WebRTC it is supported by three major browsers, Chrome, Firefox and Opera.

WebRTC has three different features:

  • User media – With user media it is possible to access the computer’s microphone and camera from your browser. In future versions screen capture will be available too. It is unknown when this will happen. Currently screen capture is already supported in the Chrome browser after enabling the ‘Enable screen capture support in getUserMedia().‘ in chrome://flags.

  • Peer connection – This is an implementation of a peer-to-peer connection between two browsers. This connection can be used to communicate the user media and/or data from the data channel between peers.

  • Data channel – This uses the peer connection to send any data from one peer to another.

For my research I had to create a WebRTC powered game. While creating this I ran into several issues explained below.

User media

The user media streams can easily be retrieved and viewed in a html video element with use of the following code. On execution of the code below the browser prompts a request to use the media to the user. This is done to prevent privacy issues.

Notice the use of the ‘||’ operator to have compatibility with multiple browsers without having to manually check what browser is used. The same method can be applied for other browser dependant functionalities.

Demo on jsfiddle.

Signalling

To establish a peer-to-peer connection each client needs to have information on how to connect to the other client. Communicating this is called signalling. While the peer-to-peer connection doesn’t need a server to communicate through, you still need one since in most implementations signalling is done via a server. For my game I set up a websocket to signal with the use of socketIO. Signalling consists of several steps shown in the image below. This image contains pseudo code of the signalling implementation.

Beside the actions described in the image you also need to exchange ICE (Interactive Connectivity Establishment) information to complete the signalling procedure. ICE combines different techniques to find the most appropriate way of communicating. When this is not handled correctly the peer connection will not be able to connect due to lack of information. To get the ICE candidates you need to implement the ‘onicecandidate’ callback function of a RTCPeerConnection object. After obtaining the candidates through this function you can send them to the other client via the signalling server.

Before creating an offer you need to either add a media stream or a data channel to the RTCPeerConnection object else the connection will not be established.

Data channel

After the signalling process is completed a peer connection should be open for usage. To send information through the data channel you can simply call the following method:

This data is then received on the other end with the ‘onmessage’ callback method of the datachannel.

More signalling

For my game I had to take signalling a step further. Because the game required multiple connections on every end I had to think of a way that could achieve this. To solve this problem I had to rewrite both the client and server code. A client has to have a dynamic amount of connections for my implementation so I came up with the following:

When a client connects to the server it sends a request to all other connected clients. Upon receiving this request the client creates an offer for the requester and sends it. The receiver of this offer then creates an answer to this offer and sends this.

In below example clients 1 and 2 are already connected to each other. Client 3 then connects to the socket and sends a request to the server. The server broadcasts this request to all other clients (1 and 2). Each of these clients creates a response offer and send this through the server to the new client. When the new client receives an offer it creates an answer and sends this to the server which sends it to the sender of the offer. This results in two new peer connections as shown below (between 1 and 3 and between 2 and 3).

Speed

To test the speed of WebRTC in comparison to the use of a websocket I created a ping test. To get significant results I have tested in several different setups and each setup with multiple different computers. In the image below you can see that in every setup (x-axis) WebRTC (green) takes less time to ping than the websocket (red). This makes WebRTC a usefull protocol for real-time multiplayer webgames where data has to be communicated as fast as possible.

Ping testresults

Ping testresults

The game

The result of my effort is a fun multiplayer snake-like game for two or more players. Due to my signalling implementation my game should be able to connect with more than a hundred players in theory. In practice this will cause problems with bandwidth an thus lag. Also there will be too many snakes to draw separately on the canvas. The maximum amount of players i have tested with is about 7.

Multiplayer in the game uses nothing but WebRTC (except for signalling) to communicate between browsers. Instead of using existing WebRTC libraries I decided to create my own to be able to learn more about how it works. This helped me to understand WebRTC and all of it’s features.

The game has been developed in 3 and a half weeks.