Canonical Ltd.

09/18/2023 | News release | Distributed by Public on 09/18/2023 08:18

Display graphs for WebRTC Statistics API data using ChartJS and React

WebRTC is an open-source technology that enables Real-Time Communications (RTC) in a web browser. It provides software developers with a set of application programming interfaces (APIs) to enable real-time data exchange between peers - e.g. for audio calls, video conferencing, or even game streaming. One of our products, Anbox Cloud, uses this technology to stream a session of an Android application running in the cloud to the Anbox Cloud web dashboard. Learn more about Anbox Cloud here.

Being peer-to-peer based, WebRTC does not need a server in the middle, which brings many benefits, like low latency, enhanced security, and a better stability. In general, what makes WebRTC great is that two users (peers) only need a web browser to establish a communication with each other.

More information on the technology can be found on the official WebRTC website.

The WebRTC Statistics API

One of the APIs we want to focus on in this post is the Statistics API. This essentially provides the developer with real-time information about the current connection between two peers. We will show how to display these statistics using ChartJS in a React application written in TypeScript.

WebRTC samples

The WebRTC samples page includes a collection of samples that demonstrate how the many APIs work. We will use these samples first to check some generic implementations of the WebRTC APIs, and then as a starting point to build our React app.

The demo "Stream from a video to a peer connection ", for example, can be a good starting point. In this example, we simulate two video peers exchanging data on the same web page. The sender video, on the left, sends video and audio data, and the receiver video, on the right, receives it using the WebRTC protocol.

However, this example does not show how to use the Statistics API. For that, we need to check another one, called "Constraints & statistics". This example has some hardware requirements, because the two peers are exchanging data coming from a camera stream, so it is less generalisable than the previous example, which is a simple streaming of video files. We can take from this example only what we need, which is: the way the Statistics API is used.

This load of text data updated in real-time is not very user friendly. What about displaying this information through some nice graphs instead? That is where ChartJS, a powerful JavaScript charting library, comes in handy.

So, what we will do in the next steps of this tutorial is to stitch these two examples together in a React app, and then feed the data coming from the Statistics API to ChartJS, which allows us to display it through some nice graphs.

Bootstrapping the React application

We can use the tool to bootstrap a React application and get started with development quickly. We can then customise the project, for example by switching the app bundler to Vite for a better development experience, but this is totally optional and will not be treated in detail here.

So, to bootstrap a React app in TypeScript we use the following command:

Note that you can find the full code for this tutorial in this repo. In order not to make the tutorial too long and complex, we will omit some steps, e.g. dependency installation, styling inside the file, linter configuration, etc. Please clone the repo locally and start the project using if you just want to see it running on your machine quickly, and then you can follow the rest of the tutorial to understand better what is going on in the code.

Adding a component with a sender video and a receiver video

Once created the app, we can start adding our components to it. But even before that, let's add some types that we will need. We can create a folder and put these 2 files in it:

  • - types for the stats, will be used later in the project
  • - types for the video files:

Let's create an folder and copy into it the 2 video files from the WebRTC samples repo ( and , but feel free to use any other video if you prefer).

Then, we can add a component that will be the general container of our application.

Let's now import and adapt some code from the first WebRTC sample we have seen above, which here goes in the body of our functional component:

We had to make some adjustments due to the fact that we are using TypeScript here, not JavaScript. Apart from that, it is the same code that one can find in the file of the example in the repo.

Now we should add the elements that the FC should return:

Let's now open and replace the code there with the following:

With this, we get the two videos in our page:

We can play both videos and see that the data streamed in the sender video gets correctly displayed by the receiver one. So far so good.

Adding helper functions, hooks and context for statistics

Let's now focus on adding a proper way to handle the statistics once we receive them from the Statistics API. First, we can add a new file with some helper functions for the statistics that we are interested in:

These will be used in many places. Let's also create a Context that we can share between components to handle some common operations on the data object that is used to collect and update the stats:

And then we simply provide access to the return value of the Context with a hook:

We can now wrap the around the component in the file:

Function-wise, nothing has changed in our app yet, because we have just set up a mechanism to parse the stats. Now we need to add a component that calls the function in the Context to add the new values that we poll from the Statistics API.

Adding a wrapper component for statistics

Let's create a new component, naming it e.g. . This will be the general wrapper for the single graph components, but more importantly, it will poll the Statistics API periodically to get fresh data using , as shown in the second WebRTC sample above.

You can see that we basically created a function that extracts only the data that we care about from the map. We parse this data using the type that we created before, and then send it to our Context function to add the latest set of stats that we just received.

Adding a component for the graph and chaining all together

We have now reached the leaf of our component tree - the graph component. In this component, we will finally use ChartJS (for which we need some dependencies to be installed, check the file) to display some graphs. Here is the code for it:

It is important to note that we use the title to build the key () to extract the data from the object stored in the Context. Keeping this in mind, we can add a to the parent, the component, as follows:

Let's now modify the block for the component, so that it contains also the component:

With this in place, the app is ready. When we hit the play button on both videos, the stats will start showing after a few seconds, and get updated periodically. With the configuration that we passed to ChartJS ( object in the component), we have also set up a custom hover behaviour that will display detailed information when we hover over a single data point.

Wrapping up

In this tutorial, we have seen how to display some nice graphs using the data provided by the WebRTC Statistics API. The hope is that, after reading this, you are more familiar with WebRTC, its Statistics API, JS-based data visualisation tools like ChartJS and how they can be baked into a React application written in TypeScript.