BigBlueButton
Add rtcstats-js to BigBlueButton with a small fork of the HTML5 client and bbb-web that mints signed rtcstats tokens.
Last updated Applies tortcstats-jsrtcstats-server
Integrations with 3rd parties9 articles
On this page7 sections

BigBlueButton is a popular open source virtual classroom and web conferencing system. Its HTML5 client builds peer connections on top of the browser's global RTCPeerConnection, which is exactly what rtcstats-js monkey-patches. Patch once when the client loads and every meeting gets traced automatically: audio, webcams and screen sharing.
BigBlueButton has no plugin hook that runs early enough to patch the globals, so the integration is a small fork of rtcstats/bigbluebutton, with one branch per BigBlueButton version:
| BigBlueButton | Branch | Based on |
|---|---|---|
| 3.0 | rtcstats-js |
v3.0.x-develop |
| 4.0 | rtcstats-js-v4 |
v4.0.x-develop |
Both branches carry the same two commits, and both commits only add code, so they are easy to carry onto your own BigBlueButton branch. Everything below applies to either version:
- Instrument the client. The HTML5 client wraps the WebRTC APIs, connects to rtcstats-server when the meeting UI mounts and closes the connection when the meeting ends.
- Authenticate with a JWT.
bbb-webgets a new/bigbluebutton/api/rtcstatsendpoint that mints a signed rtcstats token for the current user, the same way BigBlueButton already hands out TURN credentials.
Before you start
You need:
- A running
rtcstats-server(local or deployed) - A BigBlueButton 3.0 or 4.0 server you can build and deploy the HTML5 client and
bbb-webon - The JWT secret your rtcstats-server verifies tokens with (see the JWT-based authorization docs)
Step 1: build from the fork
Check out the branch for your BigBlueButton version, or cherry-pick its two commits onto your own BigBlueButton branch:
# BigBlueButton 3.0
git clone -b rtcstats-js https://github.com/rtcstats/bigbluebutton.git
# BigBlueButton 4.0
git clone -b rtcstats-js-v4 https://github.com/rtcstats/bigbluebutton.git
The branch already adds @rtcstats/rtcstats-js to bigbluebutton-html5/package.json, so a normal npm install in bigbluebutton-html5 pulls it in. Build and deploy the HTML5 client and bbb-web the way you usually do.
Step 2: how the client is wired
All the client logic sits in one small service, bigbluebutton-html5/imports/ui/services/rtcstats/index.js, called from three places in the meeting lifecycle. The order matters.
After settings load - SettingsLoader calls wrap() once the meeting client settings arrive. That is still before BigBlueButton creates any peer connection, and it is the earliest point the rtcstats endpoint is known. If no endpoint is configured, nothing is wrapped:
export const wrap = () => {
endpoint = window.meetingClientSettings.public.media.rtcstatsEndpoint;
if (trace || !endpoint) return;
trace = wrapRTCStatsWithDefaultOptions({
getStatsInterval: 1000,
countReloads: true,
log: (message) => {
logger.warn({ logCode: 'rtcstats_error' }, message);
},
});
};
getStatsInterval: 1000 collects getStats() every second, and countReloads: true tracks page reloads, which are common when a user drops out of a meeting and rejoins.
When the meeting UI mounts - the Base component calls connect(), which fetches a token from bbb-web and opens the connection to rtcstats-server:
export const connect = async () => {
if (!trace) return;
const token = await fetchToken();
if (token === undefined) return;
trace.connect(token ? `${endpoint}?rtcstats-token=${token}` : endpoint);
};
If the token request fails, the client logs rtcstats_token_fetch_failed or rtcstats_token_missing and does not connect. If bbb-web returns an empty token (no secret configured), it connects without one, which only works against an rtcstats-server with authentication turned off.
When the meeting ends - the MeetingEnded component closes the connection after a 5 second delay. Closing immediately loses the last batch of statistics:
// closes the rtcstats connection after 5 seconds, if made immediately some data is lost
setTimeout(closeRtcStats, 5000);
One connect() call opens one WebSocket connection to rtcstats-server. One close() call ends it. Everything in between is captured in the dump.
Step 3: point the client at rtcstats-server
The fork adds two settings under public.media. rtcstatsEndpoint is empty by default, which leaves rtcstats disabled. Set it in the standard BigBlueButton override file, /etc/bigbluebutton/bbb-html5.yml:
public:
media:
# WebSocket URL of an rtcstats-server, empty disables it
rtcstatsEndpoint: 'wss://your-rtcstats-server/'
rtcstatsTokenFetchAddress defaults to /bigbluebutton/api/rtcstats and only needs changing if you serve bbb-web somewhere else.
Step 4: sign tokens in bbb-web
The token is signed, so identity is decided server-side, never in the browser. The client calls /bigbluebutton/api/rtcstats?sessionToken=..., and bbb-web checks that the session token belongs to a user in a running meeting before returning an rtcstatsToken.
Configure the shared secret by creating an overlay at /etc/bigbluebutton/rtcstats.xml. bbb-web reads it in place of the bundled default, the same way it handles turn-stun-servers.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- Tokens for the rtcstats-server are signed with a secret shared with it -->
<bean id="rtcStatsService" class="org.bigbluebutton.web.services.rtcstats.RtcStatsService">
<property name="jwtSecret" value="<your-rtcstats-jwt-secret>"/>
<!-- TTL in seconds -->
<property name="tokenTtl" value="14400"/>
</bean>
</beans>
Restart BigBlueButton (sudo bbb-conf --restart) to pick it up. Keep this file readable only by the bbb-web user: anyone holding the secret can mint tokens.
What the token tells rtcStats
The rtcstats token carries an rtcStats claim that associates each dump with a call and a user. BigBlueButton fills it like this:
conference- the BigBlueButton internal meeting id, so all dumps from one meeting group together.session- the BigBlueButton internal user id, which is regenerated on every join.user- deliberately left out. The only long-lived user id BigBlueButton has is the one passed in by the integrating front end (Moodle, Greenlight, your LMS), and that is often an email address or a name. Keeping it out of the token keeps personal data out of your dumps.
The token is valid for 4 hours by default. Change it with tokenTtl in rtcstats.xml.
Verify it works
With rtcstats-server running, join a BigBlueButton meeting. The server emits one log line on connect and another on disconnect after the meeting ends:
Accepted new connection with uuid 93a750f8-223a-4c64-a39f-4c01f2731ae3
Connection with uuid 93a750f8-223a-4c64-a39f-4c01f2731ae3 disconnected, starting to process data
That pair confirms the connection opened and the dump was processed. If you see nothing, open the browser console: an rtcstats_token_* log code means the client could not get a token from bbb-web, and no request to /bigbluebutton/api/rtcstats at all means rtcstatsEndpoint is still empty.
NOTE: Can't get this to work? Need help? Contact us
Was this page helpful?