Function Description
In live viewing scenarios, the same content is often available in multiple quality levels, such as 1080p, 720p, and 480p. When the user's network condition, device capability, or business requirement changes, you may need to switch between these levels to achieve a better balance between clarity and smoothness.
TRTC Web SDK provides the experimental API switchPlaybackQuality for switching playback quality across multiple live streams. The SDK handles playback transition and main-stream audio synchronization.
This article describes how to integrate multi-resolution switching for live playback and the recommended best practices.
Applicable Scenarios
switchPlaybackQuality is suitable for the following scenarios:
- Multiple playback qualities for live audiences: The same live content is provided in multiple resolutions, and the audience can switch quality manually.
- Weak-network playback on mobile: When bandwidth drops, packet loss increases, or rendering becomes unstable, the SDK can switch to a lower level to prioritize playback continuity.
This solution is more suitable for single live playback scenarios. For multi-user call or gallery-view scenarios, it is recommended to use Enable Dual Stream.
Prerequisites
Before using this capability, make sure that:
- The same live content is available in multiple quality levels, and each level can be identified by a unique
userId(and optionallystreamType). - You have already entered the room through trtc.enterRoom().
- The audience side has already started playing one of the streams in
streamListthrough trtc.startRemoteVideo(). streamList[].bitrateis filled with the actual bitrate of each level inkbps, which is used for sorting and auto-switching decisions.
API Description
Call this capability through callExperimentalAPI:
await trtc.callExperimentalAPI('switchPlaybackQuality', options);
interface PlaybackQualityStream {
name: string;
userId: string;
streamType?: TRTCStreamType;
bitrate: number;
}
interface ResolutionConfig {
userId: string;
streamType: TRTCStreamType;
name: string;
}
interface SwitchPlaybackQualityOptions {
quality?: string;
streamList?: PlaybackQualityStream[];
onSwitched?: (from: ResolutionConfig, to: ResolutionConfig) => void;
}
Parameter Description
| Parameter | Type | Required | Description |
|---|---|---|---|
quality |
string | No | Target quality name. It must exactly match streamList[].name. Pass auto to enable auto-switch mode. If omitted, the SDK only caches streamList. |
streamList |
array | No | The list of available playback qualities. If omitted, the SDK reuses the cached list from the previous call. |
streamList[].name |
string | Yes | Quality name, such as 1080p or 720p. |
streamList[].userId |
string | Yes | The userId of the stream for that quality level. |
streamList[].streamType |
TRTCStreamType | No | Stream type. The default is main stream. |
streamList[].bitrate |
number | Yes | Bitrate in kbps. In auto mode, the SDK sorts qualities from high to low by bitrate. |
onSwitched |
function | No | Callback invoked after a successful switch. It returns the previous and current quality information. |
Manual Switch Mode
1. Prepare streamList
It is recommended to maintain a quality list in your business layer, for example:
const streamList = [
{ name: '1080p', userId: 'anchor_1080p', bitrate: 2000 },
{ name: '720p', userId: 'anchor_720p', bitrate: 1000 },
{ name: '480p', userId: 'anchor_480p', bitrate: 500 },
];
2. Cache streamList after entering the room
If you only pass streamList without quality, the SDK caches the quality information and does not switch immediately.
await trtc.callExperimentalAPI('switchPlaybackQuality', {
streamList,
});
3. Start playing the default quality
Start playing one of the streams through trtc.startRemoteVideo(). The currently playing stream must exist in streamList.
await trtc.startRemoteVideo({
userId: 'anchor_720p',
streamType: TRTC.TYPE.STREAM_TYPE_MAIN,
view: document.getElementById('live-player'),
});
4. Switch to the target quality
When the user selects another quality level in the UI, call switchPlaybackQuality:
await trtc.callExperimentalAPI('switchPlaybackQuality', {
quality: '1080p',
onSwitched(from, to) {
console.log(`playback quality switched: ${from.name} -> ${to.name}`);
},
});
5. What happens during the switch
By default, when switchPlaybackQuality is executed, the SDK keeps rendering the currently playing quality first and starts pulling the target quality stream asynchronously in the background. Only after the target stream has been pulled successfully and becomes playable does the SDK stop the old video stream and complete the switch.
This means:
- After the switch API is called, the old picture does not disappear immediately.
- In most cases, the business layer does not need to show a full-screen loading state immediately when the switch starts.
- It is recommended to update the current quality UI state in the
onSwitchedcallback, instead of proactively clearing the old picture when the switch is triggered.
6. Complete Example
const streamList = [
{ name: '1080p', userId: 'anchor_1080p', bitrate: 2000 },
{ name: '720p', userId: 'anchor_720p', bitrate: 1000 },
{ name: '480p', userId: 'anchor_480p', bitrate: 500 },
];
await trtc.enterRoom({
sdkAppId: 1400000000,
userId: 'audience_123',
userSig: 'xxx',
roomId: 12345,
scene: 'live',
role: 'audience',
});
await trtc.callExperimentalAPI('switchPlaybackQuality', { streamList });
await trtc.startRemoteVideo({
userId: 'anchor_720p',
streamType: TRTC.TYPE.STREAM_TYPE_MAIN,
view: document.getElementById('live-player'),
});
// When the user clicks the HD button
await trtc.callExperimentalAPI('switchPlaybackQuality', {
quality: '1080p',
onSwitched(from, to) {
console.log(`switch success: ${from.name} -> ${to.name}`);
},
});
Auto Switch Mode
If you want the SDK to switch between quality levels automatically according to the current playback state, pass quality: 'auto' to enable auto mode.
How to Enable It
const streamList = [
{ name: '1080p', userId: 'anchor_1080p', bitrate: 2000 },
{ name: '720p', userId: 'anchor_720p', bitrate: 1000 },
{ name: '480p', userId: 'anchor_480p', bitrate: 500 },
];
await trtc.callExperimentalAPI('switchPlaybackQuality', { streamList });
await trtc.startRemoteVideo({
userId: 'anchor_720p',
streamType: TRTC.TYPE.STREAM_TYPE_MAIN,
view: document.getElementById('live-player'),
});
await trtc.callExperimentalAPI('switchPlaybackQuality', {
quality: 'auto',
onSwitched(from, to) {
console.log(`auto switch: ${from.name} -> ${to.name}`);
},
});
Default Strategy
In auto mode, the SDK sorts streamList from high to low by streamList[].bitrate and decides whether to switch based on current network and playback conditions.
Conditions for Downgrading
The SDK attempts to switch to a lower quality if any of the following conditions is met:
- Weak network and low frame rate: Downlink packet loss is high while the current decode frame rate is low.
- Noticeable render freeze: The SDK detects a relatively long rendering stall.
Default thresholds are as follows:
| Metric | Default Value |
|---|---|
| Downlink packet loss threshold | 20% |
| Decode frame rate threshold | 5fps |
| Render freeze duration threshold | 1500ms |
Conditions for Upgrading
When network conditions recover, the SDK attempts to switch back to a higher quality if the following conditions are met:
- Downlink packet loss remains at a low level for a period of time.
- Enough time has passed since the last downgrade.
- The number of consecutive upgrade failures in the current session has not reached the limit.
Default thresholds are as follows:
| Metric | Default Value |
|---|---|
| Good packet loss threshold | 15% |
| Upgrade cooldown time | 120s |
| Maximum consecutive upgrade failures | 3 |
Decode Failure Fallback
If the current quality level encounters a video decode failure, the SDK automatically falls back to a lower level and records the highest stable quality level for the current session to avoid repeated upgrade failures.
If you call
switchPlaybackQualityagain with a specific quality such asquality: '720p'while auto mode is enabled, the SDK exits auto mode and treats the operation as a manual switch.
Difference from Dual Stream
Both switchPlaybackQuality and dual stream can be used to change playback quality, but they target different scenarios:
| Solution | Applicable Scenario | Characteristics |
|---|---|---|
| Dual stream | Multi-user calls, gallery layouts, switching between big and small stream under the same userId |
Suitable for RTC multi-subscription optimization |
switchPlaybackQuality |
Single live playback, multi-resolution switching | Suitable for audience-side manual or automatic quality switching in live streaming |
If your scenario is one anchor, multiple quality levels, and the audience only plays one of them at a time, switchPlaybackQuality is the recommended solution.
Best Practice Recommendations
If you want to balance default experience, weak-network adaptation, and explicit user selection, the following integration pattern is recommended:
- Use a middle quality as the default: for example, start from
720pfor a better balance between startup experience and compatibility. - Enable auto mode by default on mobile: let the SDK downgrade automatically when weak network or render stalls are detected.
- Switch to a specified quality when the user makes a manual choice: once the user selects
1080p,720p, or480p, callswitchPlaybackQualitywith that specificqualityto override auto mode. - Use
onSwitchedto update UI state: after a successful switch, update quality buttons, prompt text, or business metrics.
FAQ
1. Why does nothing happen after calling the API?
Check the following first:
- Whether
switchPlaybackQuality({ streamList })has been called once to cache the quality list. - Whether the currently playing stream exists in
streamList. - Whether
qualityexactly matchesstreamList[].name. - Whether the target quality is already the current one.
3. Why does auto mode not switch back to a higher quality?
Auto-upgrade depends not only on network recovery, but also on cooldown time, historical upgrade failures, and the recorded device capability ceiling. If a higher quality caused decode failures before, the SDK lowers the maximum target quality for later automatic upgrades.
4. Do I need to switch audio manually during a manual quality switch?
In main-stream switching scenarios, the SDK synchronizes audio switching automatically. In most cases, the business layer does not need to handle audio separately.
5. Can auto mode and manual mode be used together?
Yes. A common pattern is to enable auto mode by default and switch to a specific quality when the user explicitly selects one.