> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stmlink.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> 对外开放的服务端接口有两组前缀，都用同一套鉴权：`/server/v1/...`（SRTC 与 SMeeting 的主接口）和 `/stm/srvapi/v1/...`（SMeeting 的用户体系，服务端极简对接会用到）。鉴权是 app_id + nonce + timestamp + signature 四个请求头，用 app_key 做 HMAC-SHA256 签名，只能从业务方自己的后端调用。除这两组前缀外的接口均为内部接口，不要建议客户调用。 Public server APIs use two path prefixes with the same authentication: `/server/v1/...` (the main APIs of both SRTC and SMeeting) and `/stm/srvapi/v1/...` (the SMeeting user system, used by server-side low-code integration). Authenticate with four request headers, app_id + nonce + timestamp + signature, where signature is HMAC-SHA256 keyed with app_key; call these APIs only from the customer's own backend. Any other path is internal: never suggest calling it.
> app_key 是服务端密钥，绝不能出现在客户端代码、前端配置或移动 App 里。客户端加入频道用的 token 必须由业务方后端签发后下发（SRTC 走 `/server/v1/channel/grant`，SMeeting 走 `/stm/srvapi/v1/member/grant`）。 app_key is a server-side secret and must never appear in client code, frontend config, or a mobile app. The token a client uses to join must be issued by the customer's backend and passed down to the client (SRTC: `/server/v1/channel/grant`; SMeeting: `/stm/srvapi/v1/member/grant`).
> SRTC 与 SMeeting 是上下两层不同的产品，术语不通用：SRTC 是音视频底座，说「频道 channel」「加入 / 退出」；SMeeting 建在 SRTC 之上，说「房间 room」「会议 meeting」「进入 / 退出」。回答时按用户所在的层用对应术语，不要把「房间」「会议」安到 SRTC 的接口上，也不要用「频道」「加入 / 离开」描述 SMeeting 的概念（接口标识符原样保留）。 SRTC and SMeeting are two separate layers with different terminology. SRTC is the audio/video foundation: it has channels, and users join and leave a channel. SMeeting is built on top of SRTC: it has rooms and meetings, and members enter and exit a meeting. Answer in the terms of the layer the user is working with: never apply "room" or "meeting" to SRTC APIs, and never describe SMeeting concepts in prose with "channel", "join", or "leave" (API identifiers such as `force_join` keep their literal names).
> 同一能力在各端 SDK 里的包名、类名、方法名并不相同。写示例代码时请使用文档中该端自己的 API，不要把一个端的写法套到另一个端上。苹果平台每个产品都有两套 SDK（Swift 原生与 Objective-C），两套 API 不能混用。 Package, class, and method names differ between platform SDKs for the same capability. In sample code, use the API documented for that platform; never carry one platform's code over to another. On Apple platforms each product ships two SDKs (native Swift and Objective-C) whose APIs must not be mixed.

# Types

> Data types and enums of the SRTC Python SDK: every field of UserInfo, TrackInfo, ChannelInfo, ConnectionQuality, ActiveSpeaker, LayerSwitched, and CustomMsg, plus TrackKind, Codec, DeviceType, ConnectionState, DisconnectReason, and the composite stream constants.

All info classes are immutable `dataclass(frozen=True)` objects. What you get is a snapshot, and modifying it doesn't affect the SDK's internal state. For media frame types (`AudioFrame` / `VideoFrame` / `AudioFormat`), see [Audio and video data](/en/rtc/python/api-reference/audio).

***

## Info classes

### UserInfo

| Field | Type | Description |
| - | - | - |
| `uid` | `str` | User ID |
| `name` | `str` | User name |
| `device_id` | `str` | Device ID |
| `version` | `str` | Client SDK version |
| `channel` | `str` | Name of the channel the user is in |
| `sid` | `str` | Session ID; different each time the same uid joins |
| `device_type` | `int` | Client type, a `DeviceType` enum value |
| `is_audience` | `bool` | Whether the user is in audience mode |
| `join_at` / `leave_at` / `updated_at` | `int` | Join / leave / update timestamps |
| `props` | `dict` | Custom user properties |
| `stream_tracks` | `tuple[TrackInfo, ...]` | Tracks the user has published |

### TrackInfo

| Field | Type | Description |
| - | - | - |
| `id` | `str` | Track ID |
| `uid` | `str` | Publisher's uid |
| `desc` | `str` | Track description (specified by your app when publishing, such as `"mic"` or `"camera"`) |
| `kind` | `TrackKind` | `AUDIO` / `VIDEO` |
| `codec` | `int` | Encoding format, a `Codec` enum value |
| `width` / `height` / `fps` / `angle` | `int` | Video parameters |
| `bitrate` | `int` | Bitrate |
| `sample_rate` / `channel_count` | `int` | Audio parameters |
| `props` | `dict` | Custom track properties |

### ChannelInfo

| Field | Type | Description |
| - | - | - |
| `app_id` | `str` | App ID |
| `channel` | `str` | Channel name |
| `created_at` / `updated_at` | `int` | Creation / update timestamps |
| `props` | `dict` | Custom channel properties |

### ConnectionQuality

Uplink and downlink network quality, updated about once per second.

| Field | Type | Description |
| - | - | - |
| `ts` | `int` | When the report was generated (Unix milliseconds) |
| `pub` | `QualitySample` | Uplink (local → server) |
| `sub` | `QualitySample` | Downlink (server → local) |

`QualitySample`:

| Field | Type | Description |
| - | - | - |
| `score` | `float` | Quality score, 0–100 |
| `level` | `str` | `excellent` / `good` / `poor` / `lost` |
| `mos` | `float` | 1.0–4.5 |
| `loss` | `float` | Packet loss rate, 0–1 |
| `rtt` / `jitter` | `float` | Round-trip time / jitter (milliseconds) |
| `bitrate` | `float` | Average bitrate (kbps) |
| `packets` / `bytes` | `int` | Packets / bytes in this statistics window |

### ActiveSpeaker

| Field | Type | Description |
| - | - | - |
| `uid` | `str` | The speaker |
| `track_id` | `str` | Audio track ID |
| `level` | `float` | Volume, 0.0–1.0 |

### LayerSwitched

| Field | Type | Description |
| - | - | - |
| `sub_key` | `str` | Subscription handle, in the form `"pub_uid:track_id"` |
| `from_track_id` / `to_track_id` | `str` | The layer served before / after the switch; `from_track_id` is empty on initial playback |
| `reason` | `str` | `bwe_down` / `bwe_up` / `track_refresh` / `track_upgrade` / `track_ended` / `client` |
| `latency_ms` | `int` | Time from initiation to completion of the switch |

### CustomMsg

An in-channel custom message, sent by your backend through [Server API · Send a custom message](/en/rtc/server-api/channel). The client SDK only receives messages and doesn't send them.

| Field | Type | Description |
| - | - | - |
| `action` | `str` | Business action identifier |
| `uid` / `sid` | `str` | Sender |
| `channel` | `str` | Channel name |
| `is_private` | `bool` | `True` = sent to you point-to-point, `False` = channel broadcast |
| `content` | `Any` | Message content (parsed JSON) |

***

## Enums

### TrackKind

`AUDIO` = 0, `VIDEO` = 1.

### Codec

`H264`, `H265`, `VP8`, `VP9`, `AV1`, `OPUS`, `AAC`.

### DeviceType

`WINDOWS`(1), `ANDROID`(2), `IOS`(3), `LINUX`(4), `MACOS`(5), `WEBRTC`(6), `XCX`(7, WeChat Mini Program), `AGENTS`(80, server-side agent—the identity this SDK joins with). Other values are kept as-is as `int`.

### ConnectionState

`CONNECTING`(0), `CONNECTED`(1), `DISCONNECTED`(2), `RECONNECTING`(3).

### DisconnectReason

| Value | Meaning | Should you rejoin automatically? |
| - | - | - |
| `SELF`(1) | Left voluntarily | — |
| `KICKED`(2) | Removed from the channel | No |
| `REPLACE`(3) | Replaced by another session with the same uid that joined elsewhere | No |
| `TIMEOUT`(4) | Heartbeat timed out | Yes, with a new token |
| `DESTROY`(5) | The channel was destroyed | No |
| `ERROR`(-1) | Left due to an error; see `error` in `on_disconnected` for details | Depends on the error |

***

## Constants

Used when subscribing to the channel's composite stream:

| Constant | Value | Purpose |
| - | - | - |
| `MCU_PUBLISHER_UID` | `"__mcu__"` | Publisher uid of the composite stream |
| `TRACK_AMCU_ID` | `"__amcu__"` | track\_id of the audio composite stream |
| `TRACK_MCU_ID` | `"__mcu__"` | track\_id of the video composite stream |
