The SDK also fires events proactively when connection quality changes or when CPU/bandwidth is constrained, so your app can subscribe passively instead of polling.
1. Subscribe to events (recommended)
Connection quality events reuse the existingChannelEvent system; handle them directly in onNotifyChannelEvent:
2. Query on demand
2.1 Connection quality evaluation getConnectionQuality
qualityLimitationReason, and more.
2.2 Overall network statistics getNetworkStats
delay and up_level fields from older versions have been removed: delay is now split into the more precise rtt_up and rtt_down, and up_level is replaced by QualityEvaluation.uplink returned by getConnectionQuality().
:::
2.3 Full metric snapshot getStreamMetric
3. Track-level raw statistics
Thestats field of each track in StreamMetric corresponds to WebRTC’s native sender/receiver stats:
4. Recommended integration
Most apps only need to show a “network status indicator”. The recommended combination:5. Handling poor networks
To handle a poor network, first distinguish two things: direction and cause.- A poor uplink means you can’t send, and you can degrade proactively (lower bitrate, switch to the low stream, turn off the camera); a poor downlink means you can’t receive, and all you can do is receive less (switch to the low stream, unsubscribe from video). So look at both the
uplinkanddownlinkdirections, not justoverall. BANDWIDTH_CONSTRAINEDmeans insufficient bandwidth, andCPU_CONSTRAINEDmeans the device’s encoder can’t keep up; they call for different handling.
5.1 Show network status
Mappingoverall to a status indicator is enough. Don’t show raw data such as packet loss rate or RTT to end users:
Uplink and downlink problems need different hint messages:
poor persists for a few seconds, not on every fluctuation. The SDK already debounces the BANDWIDTH_CONSTRAINED / CPU_CONSTRAINED events; we recommend rate-limiting your popups once more in your app.
5.2 Uplink degrades
Degrade step by step, from light to heavy:- Encoder adaptation: done automatically by the browser, on by default, no action needed. If you don’t want the resolution to be lowered automatically, change the degradation mode with
degradationPreference(see 5.4). - Switch to the low stream / lower resolution: if you publish simulcast, you can switch to the low stream (320×180, about 250 Kbps). See Simulcast and resolution.
- Turn off the camera, keep audio only: audio bitrate is low (about 32 Kbps) and can almost always be kept on a poor network.
- Stop publishing entirely:
unpublishLocalTrack(localVideoTrack)is more thorough than turning off the camera and releases uplink encoding and sending resources.
CPU_CONSTRAINED, prefer lowering resolution / frame rate (to reduce encoding load); on BANDWIDTH_CONSTRAINED, lowering either bitrate or resolution works.
Turning off the camera changes the shape of the call, so we recommend notifying the user before doing it rather than doing it silently—especially in scenarios such as emergency command and law enforcement recording.
5.3 Downlink degrades
- First check whether the problem is on the remote side: only if you have downlink packet loss is your receiving path poor. If you have almost no packet loss and just one person’s video is freezing, it’s usually that person’s uplink; unsubscribing won’t help, so just show “the other party’s network is poor”. The SDK’s scoring already distinguishes these two cases and won’t lower your downlink level because of someone else’s problem.
- When the publisher sends simulcast, the SFU switches layers automatically: based on each subscriber’s own downlink bandwidth and packet loss, the SFU automatically switches it to the appropriate high / low stream, with no manual switching on the subscriber side; if only a single stream is published, it can’t degrade automatically. See Simulcast and resolution.
- Unsubscribe from video, receive audio only:
- Multi-party calls: subscribe only to the current speaker’s video, and receive audio only from everyone else.
5.4 Control the degradation mode: degradationPreference
VideoPublishOptions.degradationPreference of publishLocalTrack decides what to sacrifice on a poor network:
If you don’t want the resolution to be lowered automatically, set it to
maintain-resolution:
maintain-resolution; 360p / 180p don’t set it and use the browser default.
5.5 Connection lost (lost)
overall === 'lost' means media is interrupted. Start reconnecting and show the user “Reconnecting”; after recovery, refresh the status indicator and restore any camera or subscriptions you turned off earlier.
5.6 Quick reference
5.7 Complete example
Putting it all together: configure the degradation strategy when publishing, and at runtime subscribe to events to update the status indicator, show direction-specific hints, and degrade and restore as needed.publishLocalTrack/disableLocalTrack/enableLocalTrackin the example are all existing SDK methods. Operations that change the shape of the call, such as turning off the camera, are handed to the user for confirmation via a button rather than done silently; for regular calls and similar scenarios you can make them automatic. Implement the downlink “audio only” fallback yourself following the idea in the comments (useunsubscribeRemoteTrackto unsubscribe from video and keep audio).