ObserveRTC Client Integration Core Library
@observertc/client-observer-js is a client side library to process WebRTCStats and to integrate you app to observertc components.
Table of Contents:
Qucik Start
Install it from npm package repository.
npm i @observertc/client-observer-js
Collect WebRTC Stats
import { ClientObserver } from "@observertc/client-observer-js";
const config = {
collectingPeriodInMs: 5000,
};
const observer = ClientObserver.create(config);
observer.addStatsCollector({
id: "collectorId",
getStats: () => peerConnection.getStats(),
});
observer.events.onStatsCollected(() => {
for (const transport of observer.stats.transports()) {
console.log(transport.stats.packetsSent);
}
})
The above example collect stats in every 5s.
When stats are collected and stored it emits an event to notify the
application.
You can navigate through related stats:
for (const outboundRtp of observer.stats.outboundRtps()) {
const remoteInboundRtp = outboundRtp.getRemoteInboundRtp();
console.log(outboundRtp.stats, remoteInboundRtp.stats);
}
The example above shows how to get the remote inbound rtp stats related to the outbound rtp stats.
With stats
you accessing to the StatsStorage. StatsStorage provided entries can be used to navigate from stats type to another.

Sample and Send
Sampling means the client-observer creates a so-called ClientSample. ClientSample is a compound object contains a snapshot from the polled stats, added devices, constrainments, user errors, etc. ClientSample is created by a Sampler component.
A created ClientSample is added to Samples object. Samples can be sent to the server by a Sender component.
The above shown example can be extended to sample and send by adding the following configurations:
import { ClientObserver } from "@observertc/client-observer-js";
const config = {
collectingPeriodInMs: 5000,
samplingPeriodInMs: 10000,
sendingPeriodInMs: 10000,
sampler: {
roomId: "testRoom",
},
sender: {
websocket: {
urls: ["ws://localhost:7080/samples/myServiceId/myMediaUnitId"]
}
}
};
const observer = ClientObserver.create(config);
observer.addStatsCollector({
id: "collectorId",
getStats: () => peerConnection.getStats(),
});
API docs
https://observertc.github.io/client-observer-js/modules/ClientObserver.html
NPM package
https://www.npmjs.com/package/@observertc/client-observer-js
Schema
The schema used to send samples can be found here.
Examples
Calculate video tracks Fps
Assuming you have a configured and running observer and a collector you added to poll the stats from
peer connection, here is an example to calculate the frame per sec for tracks.
const observer =
observer.onStatsCollected(() => {
const results = [];
const now = Date.now();
for (const inboundRtp of observer.stats.inboundRtps()) {
const trackId = inboundRtp.getTrackId();
const SSRC = inboundRtp.getSsrc();
const traceId = `${trackId}-${SSRC}`;
const { framesReceived, kind } = inboundRtp.stats;
if (kind !== "video") continue;
const trace = traces.get(traceId);
if (!trace) {
traces.set(traceId, {
framesReceived,
timestamp: now,
});
continue;
}
const elapsedTimeInS = now - trace.timestamp;
const fps = (framesReceived - trace.framesReceived) / elapsedTimeInS;
const peerConnectionId = inboundRtp.getPeerConnection()?.id;
results.push({
fps,
trackId,
peerConnectionId,
})
trace.timestamp = now;
}
console.log(results);
});
Collect RTT measurements for peer connections
const observer =
observer.onStatsCollected(() => {
const RTTs = new Map();
for (const outboundRtp of observer.stats.outboundRtps()) {
const remoteInboundRtp = outboundRtp.getRemoteInboundRtp();
const { roundTripTime } = remoteInboundRtp.stats;
const peerConnectionId = outboundRtp.getPeerConnection()?.collectorId;
let measurements = results.get(peerConnectionId);
if (!measurements) {
measurements = [];
RTTs.set(peerConnectionId, measurements);
}
measurements.push(roundTripTime);
}
console.log(Array.from(RTTs.entries()));
});
Configurations
const config = {
collectingPeriodInMs: 5000,
samplingPeriodInMs: 10000,
sendingPeriodInMs: 10000;
statsExpirationTimeInMs: 60000,
collectors: {
adapter: {
browserType: "chrome",
browserVersion: "97.1111.111",
},
},
sampler: {
roomId: "testRoom",
clientId: "clientId",
callId: "callId",
userId: "testUser",
incrementalSampling: true,
},
sender: {
format: "json",
websocket: {
urls: ["ws://localhost:7080/samples/myServiceId/myMediaUnitId"],
maxRetries: 1,
}
}
};
License
Apache-2.0