OBSERVERTC / Overview
Architecture
What runs in the browser, what reaches the server, and where your application takes over.
ObserveRTC adds a monitoring pipeline beside your existing WebRTC application. Client Monitor diagnoses an endpoint. Observer combines samples from multiple endpoints into a live view of calls and their issues.
Copyable ASCII version
BROWSER YOUR BACKEND
+----------------------+ +-----------------------------+
| Client Monitor | | Observer |
| | | |
| getStats() | sample | Live calls, clients, tracks |
| -> adapt +------->| Client issue lifecycles |
| -> derive metrics | via | Cross-client analysis |
| -> detect issues | API | Publisher / receiver links |
| -> score quality | +--------------+--------------+
+----------+-----------+ |
| local events | events / sinks
v v
+----------------------+ +-----------------------------+
| In-call diagnostics | | Your metrics, alerts, |
| and application UI | | storage and reporting |
+----------------------+ +-----------------------------+
The sample arrow carries telemetry, not audio or video. Your peer connections, media servers and signaling keep their existing roles.
Diagnose at the endpoint, correlate on the server
The browser can combine stats with local track state, application intent and a sequence of observations. That is where Client Monitor calculates metrics and decides whether an endpoint condition should raise or resolve an issue.
The server adds scope: which participants have overlapping issues, which publisher their tracks belong to, and whether similar conditions appear across calls. Shared symptoms provide evidence for a cause; they do not automatically prove an infrastructure fault.
| Responsibility | Owner |
|---|---|
| Browser adaptation, interval metrics, endpoint detectors | Client Monitor |
| Sample fields and wire types | ObserveRTC schemas |
| Delivery, authentication and input validation | Your application |
| Live call state, track correlation, cross-client analysis | Observer |
| Persistence, dashboards and actions | Your application, using events and sinks |
In the browser
Client Monitor attaches to an existing RTCPeerConnection, or to mediasoup-client devices and transports. Collection and sampling both default to five seconds, but they are separate operations.
Copyable ASCII version
RTCPeerConnection.getStats()
|
v
Browser adapters -> linked monitor graph
|
+--> interval metrics
+--> detectors -> issues / events
+--> quality scores
|
v
createSample()
|
v
ClientSample
The graph links RTP streams to tracks, codecs, remote reports and ICE transports. A track can have multiple outbound encodings; a peer connection can have multiple transports.
Local code can read metrics after stats-collected and react to issue events without sending samples anywhere. ObserveRTC reports conditions; your application chooses whether to update a quality indicator, prompt the user or change media settings.
A sample contains selected state, not every live monitor property. Explicit createSample() methods project counters, references, scores and attachments, together with buffered events, issues, metadata and extension stats. Most derived rates, detector state and declared context stay local. Sampling less often does not create an average of the intervening collections.
Monitor graph and API · Collection and sampling · Metric calculations
Across the wire
ClientSample is the shared contract. It can travel as ordinary JSON, or through an optional delta codec. The schema defines the record; it is not another processing service.
Copyable ASCII version
ClientSample -> JSON ----------------------------> ClientSample
ClientSample -> delta encoder -> your transport
|
v
delta decoder ----> ClientSample
|
v
Observer.accept()
| Representation | Integration choice |
|---|---|
| Plain JSON sample | Send complete samples through your existing telemetry endpoint. |
| JSON codec | Encode changes between samples in a JSON representation. |
| Protobuf codec | Encode changes between samples in a binary representation. |
Both delta codecs keep state. Use one encoder per client and one decoder per client stream; preserve message order and reliable delivery. Decode before passing a sample to Observer.
Your ingestion boundary authenticates the sender, validates the payload and checks call/client identity. Observer.accept() requires callId and clientId, but does not perform complete schema validation. In the documented Observer 1.0.0 implementation, middleware cannot be relied on to drop or replace samples; filter before calling accept().
ClientSample fields · Ingestion behavior
On the server
Observer creates entities as samples arrive and maintains their current state in memory:
Observer
+-- ObservedCall
| +-- ObservedClient
| | +-- ObservedPeerConnection
| | +-- Tracks and RTP streams
| | +-- Remote RTP reports
| | +-- ICE transports, pairs and candidates
| | +-- Codecs, media sources and playout
| | +-- Data channels and certificates
| +-- ObservedClient
+-- ObservedCallPeer-connection updates create, refresh and clean up child entities. Idle clients and empty calls have configurable timeouts. This model is live state, not a historical database.
Client issue records with matching keys let Observer maintain active issue intervals. The central event bus includes the relevant call, client and entity ancestry in its payloads.
A new Observer has no detectors registered. Register the analysis your application needs:
- Call detectors compare participants, linked tracks and issue overlap within a call.
- Observer detectors analyze populations and patterns across calls.
- Validators gather evidence for a structural check, then report a result when they can decide.
Analysis runs on updates, not on a separate universal detector timer. When disabling automatic updates, your application must drive them explicitly.
Entities and state · Server detectors · Event bus
Publisher, SFU and receiver
To explain a delivery problem, Observer needs to know which outbound track feeds which receivers. A RemoteTrackResolver supplies that relationship using identifiers from your signaling and track attachments.
Publisher Media path Receivers
outbound track -----------> SFU --------------------> inbound track
+----------------------> inbound track
Signaling IDs / track attachments
|
v
RemoteTrackResolver
|
v
Observer links publisher to receiversThe mediasoup resolver uses producer/consumer identifiers. Other SFUs need an appropriate resolver; matching browser stats IDs alone is not a general publisher-to-receiver mapping.
For mediasoup, Observer can also attach to a live server Router. This supplies transport, producer and consumer lifecycle data in a separate MediasoupRouterSample. It complements client samples rather than replacing them. Your application decides when and where to persist it.
Choose your deployment
Start with the smallest pipeline that answers your question. These can grow independently.
Local diagnostics
Client Monitor -> in-call UI
Support history
Client Monitor -> your endpoint -> stored samples
Live call analysis
Client Monitor -> your endpoint -> Observer -> events / alerts
| |
v v
sample archive call summariesFor full-stack deployments, per-client sinks can persist accepted samples and opt-in call summaries can record selected call-level results. Your application owns storage, retention and downstream actions.
Archived samples are useful for later analysis, but a fast replay is not timing-equivalent to live ingestion: some Observer rates use server arrival intervals. Account for those timing rules when comparing replay results.
Sinks and persistence · Call summaries · Try the live example
Implementation sources
This architecture follows the released versions listed in Versions & compatibility.