diff --git a/docs/third/IM-声网音视频通话完整调用流程.md b/docs/third/IM-声网音视频通话完整调用流程.md new file mode 100644 index 0000000..caff0de --- /dev/null +++ b/docs/third/IM-声网音视频通话完整调用流程.md @@ -0,0 +1,318 @@ +# IM 声网音视频通话完整调用流程 + +更新时间:2026-09-01 + +## 1. 流程目标 + +本文用于说明 IM 系统接入声网 RTC 后,一次音视频通话从后台配置、客户端发起、服务端校验、声网入会到挂断结束的完整调用链路。 + +首期调试环境只使用声网 `app_id`,客户端入会时 `token` 为空。正式环境启用 App 证书后,由 IM Server 使用 `app_certificate` 生成 RTC Token,再返回给客户端。 + +## 2. 整体链路 + +```text +后台配置声网参数 +-> 客户端 A 发起通话 +-> IM Server 校验业务权限并生成 call_id/channel/uid +-> IM WebSocket 通知客户端 B +-> A、B 分别向 IM Server 获取声网入会参数 +-> A、B 使用声网 SDK 加入同一频道 +-> 音视频媒体流走声网 RTC +-> 挂断/拒接/超时通过 IM 信令结束 +-> IM Server 记录通话状态和通话记录 +``` + +## 3. 后台配置流程 + +### 3.1 调试模式 + +调试模式只需要准备声网项目的 `app_id`。 + +后台配置建议: + +| 配置项 | 示例 | 说明 | +| --- | --- | --- | +| `agora_enabled` | `true` | 是否启用声网音视频。 | +| `agora_auth_mode` | `app_id` | 调试模式,客户端入会不需要 Token。 | +| `agora_app_id` | `xxxxxxxx` | 声网项目 App ID,允许返回给客户端。 | +| `agora_channel_prefix` | `call_` | 服务端生成声网频道名前缀。 | +| `agora_uid_mode` | `int` | 首期建议使用数字 UID。 | + +### 3.2 正式模式 + +正式模式需要启用 App 证书,由后端生成 RTC Token。 + +后台配置建议: + +| 配置项 | 说明 | +| --- | --- | +| `agora_auth_mode=token` | 开启 Token 鉴权模式。 | +| `agora_app_certificate` | 声网 App 证书,只能后端保存和使用。 | +| `agora_token_ttl_seconds` | Token 有效期,建议 3600 秒。 | + +### 3.3 声网控制台 REST API 配置 + +声网 REST API 的 `customer_id/customer_secret` 只用于后端调用声网控制台 API,例如创建项目、查询项目、启用/禁用项目、启用/重置证书。它不是客户端入会参数,也不是每次通话必须调用的接口。 + +后台配置建议: + +| 配置项 | 说明 | +| --- | --- | +| `agora_rest_customer_id` | 声网 REST API 客户 ID。 | +| `agora_rest_customer_secret` | 声网 REST API 客户密钥,必须脱敏展示。 | +| `agora_rest_primary_domain` | 国内建议 `https://api.sd-rtn.com`。 | +| `agora_rest_backup_domain` | 备用建议 `https://api.agora.io`。 | + +## 4. 后端和声网 API 对接流程 + +### 4.1 调试阶段 + +调试阶段后端不需要请求声网服务端 API。IM Server 只负责读取后台配置,并把客户端入会需要的参数返回给当前登录用户。 + +返回给客户端的字段: + +| 字段 | 说明 | +| --- | --- | +| `provider` | 固定 `agora`。 | +| `auth_mode` | 调试模式为 `app_id`。 | +| `app_id` | 声网 App ID。 | +| `channel_name` | 服务端生成的频道名。 | +| `uid` | 当前 IM 用户映射到声网的 UID。 | +| `token` | 调试模式为空字符串。 | +| `token_expires_at` | 调试模式为 `null`。 | + +### 4.2 正式 Token 阶段 + +正式阶段后端仍然不需要每次请求声网 REST API。IM Server 使用本地保存的 `app_id`、`app_certificate`、`channel_name`、`uid` 和有效期生成 RTC Token。 + +生成完成后只把 Token 返回给当前通话参与人。`app_certificate` 不允许返回客户端,不允许写入普通日志。 + +### 4.3 控制台 REST API 阶段 + +只有后台需要自动管理声网项目时,才调用声网控制台 REST API。 + +常用接口: + +| 场景 | 声网 API | +| --- | --- | +| 创建项目 | `POST /dev/v1/project` | +| 查询指定项目 | `GET /dev/v1/project?id=&name=` | +| 查询全部项目 | `GET /dev/v1/projects` | +| 启用/禁用项目 | `POST /dev/v1/project_status` | +| 启用/禁用主要 App 证书 | `POST /dev/v1/signkey` | +| 重置主要 App 证书 | `POST /dev/v1/reset_signkey` | + +声网 REST API 使用 Basic Auth: + +```text +Authorization: Basic base64(customer_id + ":" + customer_secret) +Content-Type: application/json +``` + +## 5. 前端和后端对接流程 + +### 5.1 发起方流程 + +```text +用户 A 点击语音/视频通话 +-> 客户端 A 生成 call_id +-> 客户端 A 通过 IM WebSocket 发送 call started +-> IM Server 校验 A 和 B 的关系、黑名单、账号状态、租户状态 +-> IM Server 写入或更新通话记录 +-> IM Server 返回 Topic seq +-> 客户端 A 调用入会接口获取声网参数 +-> 客户端 A 使用声网 SDK 加入频道 +-> IM Server 通过 WebSocket 把来电消息推送给客户端 B +``` + +WebSocket 发起通话示例: + +```json +{ + "pub": { + "id": "call-pub-1", + "topic": "p2p...", + "head": { + "mime": "application/json", + "webrtc": "started", + "x-im-type": "call", + "x-im-client-mid": "mid_call_1" + }, + "content": { + "callId": "call_01K...", + "callType": "video", + "audio": true, + "video": true, + "provider": "agora" + } + } +} +``` + +### 5.2 被叫方流程 + +```text +客户端 B 收到 IM WebSocket 来电消息 +-> 展示来电页面 +-> 用户 B 点击接听 +-> 客户端 B 调用入会接口获取声网参数 +-> IM Server 校验 B 是否为本次通话参与人 +-> IM Server 返回同一个 channel_name 和 B 自己的 uid/token +-> 客户端 B 使用声网 SDK 加入频道 +-> 客户端 B 通过 IM WebSocket 发送 call accept +-> 双方开始音视频通话 +``` + +### 5.3 获取声网入会参数 + +建议接口: + +```http +POST /v1/im/calls/rtc-join +Authorization: Bearer +X-MeetingIM-APIKey: +X-IM-Schema: 1 +X-Request-ID: +Idempotency-Key: +Content-Type: application/json +``` + +请求 Body: + +```json +{ + "topic": "p2p...", + "call_id": "call_01K...", + "seq": 30, + "call_type": "video", + "role": "caller" +} +``` + +成功响应: + +```json +{ + "code": 0, + "data": { + "provider": "agora", + "auth_mode": "app_id", + "app_id": "声网 App ID", + "channel_name": "call_call_01K...", + "uid": 1565659909440147456, + "token": "", + "token_expires_at": null, + "call_id": "call_01K...", + "topic": "p2p...", + "seq": 30 + }, + "request_id": "req_01K...", + "server_time": "2026-09-01T16:00:00+08:00" +} +``` + +正式 Token 模式下,`auth_mode` 返回 `token`,`token` 不为空,`token_expires_at` 返回具体过期时间。 + +### 5.4 客户端加入声网频道 + +客户端拿到后端返回参数后调用声网 RTC SDK: + +```text +初始化 RTC SDK: app_id +加入频道: channel_name +用户标识: uid +入会凭证: token +``` + +调试模式下 `token` 为空。正式环境下 `token` 必须由后端生成并返回。 + +音视频媒体流不经过 IM Server,客户端加入声网频道后由声网 RTC 负责音视频传输、音频路由、摄像头采集、网络切换和断线重连等能力。 + +## 6. 通话结束流程 + +### 6.1 主动挂断 + +```text +任意一方点击挂断 +-> 客户端离开声网频道 +-> 客户端通过 IM WebSocket 发送 hang-up +-> IM Server 更新通话记录状态和通话时长 +-> IM Server 推送通话结束消息给另一方 +-> 另一方客户端关闭通话页面并离开声网频道 +``` + +挂断信令示例: + +```json +{ + "note": { + "topic": "p2p...", + "what": "call", + "event": "hang-up", + "seq": 30, + "payload": { + "callId": "call_01K...", + "reason": "finished" + } + } +} +``` + +### 6.2 取消、拒接和超时 + +| 场景 | 处理 | +| --- | --- | +| 发起方取消 | IM Server 标记为 `cancelled` 或 `missed`,被叫端关闭来电页面。 | +| 被叫方拒接 | IM Server 标记为 `declined`,发起方关闭等待页面。 | +| 被叫方超时未接 | IM Server 标记为 `missed`,双方客户端退出通话状态。 | +| 网络异常断开 | 客户端根据声网 SDK 回调提示重连;业务最终状态以 IM Server 的结束事件为准。 | + +## 7. Token 续期流程 + +正式环境启用 Token 后,客户端需要监听声网 SDK 的 Token 即将过期或已过期回调。 + +```text +声网 SDK 提示 Token 即将过期 +-> 客户端调用 /v1/im/calls/rtc-join 或续期接口 +-> IM Server 校验当前通话仍有效 +-> IM Server 重新生成 RTC Token +-> 客户端调用声网 SDK renewToken +``` + +调试模式不涉及 Token 续期。 + +## 8. 安全边界 + +| 数据 | 是否返回客户端 | 说明 | +| --- | --- | --- | +| `app_id` | 是 | 客户端初始化声网 SDK 必须使用。 | +| `channel_name` | 是 | 服务端生成,客户端不能自定义任意频道。 | +| `uid` | 是 | 当前用户对应的声网 UID。 | +| `token` | 是 | 正式环境返回,仅当前通话参与人可获取。 | +| `app_certificate` | 否 | 后端生成 RTC Token 使用。 | +| `customer_id` | 否 | 后端调用声网控制台 REST API 使用。 | +| `customer_secret` | 否 | 后端调用声网控制台 REST API 使用。 | + +## 9. 异常处理 + +| reason | 场景 | +| --- | --- | +| `AGORA_DISABLED` | 后台未启用声网通话。 | +| `AGORA_CONFIG_MISSING` | 缺少 `app_id`,或 Token 模式缺少 `app_certificate`。 | +| `CALL_NOT_FOUND` | `call_id/topic/seq` 不匹配或通话不存在。 | +| `CALL_NOT_ALLOWED` | 当前用户不是通话参与人,或被权限策略拦截。 | +| `CALL_STATE_INVALID` | 通话已结束、已超时或当前状态不允许入会。 | +| `VALIDATION_FAILED` | 请求参数非法。 | + +## 10. 联调顺序建议 + +1. 后台配置 `agora_enabled=true`、`agora_auth_mode=app_id`、`agora_app_id`。 +2. 客户端集成声网 RTC SDK,并支持后端返回的空 Token 入会。 +3. A 发起语音通话,确认 B 能收到 IM 来电信令。 +4. A、B 分别调用 `/v1/im/calls/rtc-join`,确认返回同一个 `channel_name`。 +5. A、B 使用各自 `uid` 加入声网频道,确认音频可通。 +6. 切换视频通话,确认视频流可通。 +7. 测试取消、拒接、挂断、超时、网络断开。 +8. 正式环境启用 App 证书,切换 `agora_auth_mode=token`。 +9. 验证 Token 入会和 Token 续期。 +10. 后续再接入声网控制台 REST API 的项目管理能力。 diff --git a/docs/third/IM-声网音视频通话接入文档.md b/docs/third/IM-声网音视频通话接入文档.md new file mode 100644 index 0000000..1f394f5 --- /dev/null +++ b/docs/third/IM-声网音视频通话接入文档.md @@ -0,0 +1,320 @@ +# IM 声网音视频通话接入文档 + +更新时间:2026-09-01 + +## 1. 接入目标 + +本次接入目标是把 IM 的一对一语音/视频通话媒体能力从原 WebRTC 直连方案切到声网 RTC。IM Server 继续负责账号、租户、好友/黑名单、通话状态、WebSocket 信令和通话记录;声网只负责音视频媒体频道、音视频流传输和后续可选的媒体质量能力。 + +首期按声网调试账号接入,只使用 `app_id`,不生成 RTC Token。正式上线时再启用 App 证书,由 IM Server 按频道和用户生成 RTC Token。 + +## 2. 系统边界 + +| 模块 | 责任 | +| --- | --- | +| IM Server | 校验登录态、租户、好友/黑名单和通话权限;生成 `call_id`、声网频道名、声网 UID;维护通话状态和通话记录;通过 WebSocket 下发邀请、接听、挂断等信令。 | +| 前端客户端 | 集成声网 RTC SDK;从 IM Server 获取声网入会配置;使用 `app_id/channel_name/uid/token` 加入声网频道;通过 IM WebSocket 发送通话业务事件。 | +| HotGo/Admin | 保存声网第三方配置;后续可提供项目、证书、开关等管理入口。 | +| 声网 RTC | 提供音视频实时媒体通道。 | +| 声网控制台 REST API | 可选,用于服务端创建项目、查询项目、启停项目、启停或重置主要 App 证书。首期不强依赖。 | + +## 3. 声网账号与配置准备 + +### 3.1 调试模式必须准备 + +| 配置 | 说明 | +| --- | --- | +| `agora_app_id` | 声网项目 App ID,客户端初始化 RTC SDK 使用。 | +| `agora_auth_mode` | 首期填 `app_id`,表示仅 App ID 鉴权。 | +| `agora_enabled` | 是否启用声网通话,建议测试环境先设为 `true`。 | +| `agora_uid_mode` | 建议先用 `int`,客户端加入频道时使用数字 UID。 | +| `agora_channel_prefix` | 建议 `call_`,最终频道名为 `call_{call_id}`。 | + +### 3.2 正式模式后续准备 + +| 配置 | 说明 | +| --- | --- | +| `agora_app_certificate` | 声网 App 证书,服务端生成 RTC Token 使用,禁止下发客户端。 | +| `agora_token_ttl_seconds` | RTC Token 有效期,建议 3600 秒。 | +| `agora_rest_customer_id` | 声网 RESTful API 客户 ID,用于控制台 API。 | +| `agora_rest_customer_secret` | 声网 RESTful API 客户密钥,用于控制台 API,必须脱敏保存和展示。 | +| `agora_rest_primary_domain` | 国内建议 `https://api.sd-rtn.com`。 | +| `agora_rest_backup_domain` | 备用建议 `https://api.agora.io`。 | + +配置建议继续存放在 HotGo `hg_sys_config` 的 `im_third_party` 分组,IM Server 通过现有 `store.ThirdPartyConfig.Get("im_third_party", ...)` 读取,并受 Kafka `third_party.updated` 或 `cache.third_party.invalidate` 事件清理进程内缓存。 + +## 4. 后端与声网 API 对接 + +### 4.1 首期不调用声网 REST API + +只使用 `app_id` 的调试模式下,IM Server 不需要向声网发起服务端请求。后端只需要读取后台配置,把 `app_id`、频道名、UID 和空 Token 返回给客户端。 + +首期后端返回: + +```json +{ + "provider": "agora", + "auth_mode": "app_id", + "app_id": "声网 App ID", + "channel_name": "call_call_01K...", + "uid": 1565659909440147456, + "token": "", + "token_expires_at": null +} +``` + +### 4.2 正式 Token 模式 + +正式模式启用 App 证书后,IM Server 使用 `agora_app_id + agora_app_certificate + channel_name + uid + ttl` 在本地生成 RTC Token。Token 只返回给当前登录用户,不能存日志,不能返回给非通话参与人。 + +正式后端返回: + +```json +{ + "provider": "agora", + "auth_mode": "token", + "app_id": "声网 App ID", + "channel_name": "call_call_01K...", + "uid": 1565659909440147456, + "token": "007eJx...", + "token_expires_at": "2026-09-01T17:00:00+08:00" +} +``` + +客户端收到声网 SDK 的 Token 即将过期回调后,重新调用 IM Server 获取新 Token,再调用声网 SDK 的 `renewToken` 或等价接口更新。 + +### 4.3 声网控制台 REST API + +控制台 REST API 是后台运维能力,不是每通电话的实时链路。需要自动化管理声网项目时再接入。 + +声网 REST API 鉴权: + +```text +Authorization: Basic base64(customer_id + ":" + customer_secret) +Content-Type: application/json +``` + +常用接口: + +| 能力 | 方法与路径 | 说明 | +| --- | --- | --- | +| 创建项目 | `POST /dev/v1/project` | Body `name, enable_sign_key`;返回 `vendor_key`,即 App ID。 | +| 查询指定项目 | `GET /dev/v1/project?id=&name=` | 按项目 ID 和名称查询。 | +| 查询全部项目 | `GET /dev/v1/projects` | 获取当前声网账号下项目列表。 | +| 启用/禁用项目 | `POST /dev/v1/project_status` | Body `id, status`,`1` 启用,`0` 禁用。 | +| 启用/禁用主要 App 证书 | `POST /dev/v1/signkey` | Body `id, enable`。 | +| 重置主要 App 证书 | `POST /dev/v1/reset_signkey` | Body `id`;证书未启用时会启用主要证书。 | + +调用约束: + +- 成功 HTTP 状态码为 `200` 或 `201`。 +- 失败响应通常包含 `statusCode/error/message`。 +- 每个声网账号 REST API QPS 默认 10 次/秒。 +- 请求失败时日志记录声网响应 Header `X-Request-ID`、`X-Resource-ID`,但不能记录客户密钥、App 证书或 RTC Token。 +- 国内服务优先 `api.sd-rtn.com`,失败时按退避策略切换 `api.agora.io` 或区域域名。 + +## 5. 前端与后端对接 + +### 5.1 WebSocket 通话信令 + +现有 IM WebSocket 仍是通话业务信令主链路。客户端发起通话时发布一条 `x-im-type=call` 的 Topic 消息: + +```json +{ + "pub": { + "id": "call-pub-1", + "topic": "p2p...", + "head": { + "mime": "application/json", + "webrtc": "started", + "x-im-type": "call", + "x-im-client-mid": "mid_call_1" + }, + "content": { + "callId": "call_01K...", + "callType": "audio", + "audio": true, + "video": false, + "provider": "agora" + } + } +} +``` + +服务端返回: + +```json +{ + "ctrl": { + "id": "call-pub-1", + "code": 202, + "text": "accepted", + "params": { + "seq": 30 + } + } +} +``` + +后续 `ringing/accept/hang-up` 继续走 `{note what="call"}`。切到声网后,`offer/answer/ice-candidate` 不再需要由客户端发送给 IM Server;媒体协商由声网 SDK 自己完成。为了兼容旧客户端,服务端可以继续接受这些事件,但新客户端应忽略旧 WebRTC SDP/ICE 流程。 + +### 5.2 获取声网入会配置 + +建议新增产品接口: + +```http +POST /v1/im/calls/rtc-join +Authorization: Bearer +X-MeetingIM-APIKey: +X-IM-Schema: 1 +X-Request-ID: +Idempotency-Key: +Content-Type: application/json +``` + +请求 Body: + +```json +{ + "topic": "p2p...", + "call_id": "call_01K...", + "seq": 30, + "call_type": "audio", + "role": "caller" +} +``` + +字段说明: + +| 字段 | 必填 | 说明 | +| --- | --- | --- | +| `topic` | 是 | P2P Topic。首期只支持一对一通话。 | +| `call_id` | 是 | 通话 ID,必须和 WebSocket call 消息一致。 | +| `seq` | 建议 | 通话消息 seq。发起方可在 `{pub}` 返回后传入;接听方从收到的 call 消息中取得。 | +| `call_type` | 是 | `audio` 或 `video`。 | +| `role` | 是 | `caller` 或 `callee`,用于审计和风控。 | + +成功响应: + +```json +{ + "code": 0, + "data": { + "provider": "agora", + "auth_mode": "app_id", + "app_id": "声网 App ID", + "channel_name": "call_call_01K...", + "uid": 1565659909440147456, + "token": "", + "token_expires_at": null, + "call_id": "call_01K...", + "topic": "p2p...", + "seq": 30 + }, + "request_id": "req_01K...", + "server_time": "2026-09-01T16:00:00+08:00" +} +``` + +失败原因建议: + +| reason | 场景 | +| --- | --- | +| `AGORA_DISABLED` | 后台未开启声网。 | +| `AGORA_CONFIG_MISSING` | 缺少 App ID,或正式模式缺少 App 证书。 | +| `CALL_NOT_FOUND` | `call_id/topic/seq` 不存在或不匹配。 | +| `CALL_NOT_ALLOWED` | 用户不是通话参与人,或被好友/黑名单/租户策略限制。 | +| `CALL_STATE_INVALID` | 通话已结束、已超时或状态不允许入会。 | +| `VALIDATION_FAILED` | 请求字段非法。 | + +### 5.3 客户端发起通话流程 + +```text +用户点击语音/视频通话 +-> 客户端生成 call_id +-> WS pub call started +-> 收到 ctrl 202 和 seq +-> 调 POST /v1/im/calls/rtc-join 获取声网入会参数 +-> 使用声网 SDK joinChannel +-> 等待对方 ringing/accept +-> 通话中通过 IM note hang-up 结束业务状态 +``` + +### 5.4 客户端接听通话流程 + +```text +收到 Topic call started data +-> 展示来电 UI +-> 用户点击接听 +-> 调 POST /v1/im/calls/rtc-join 获取声网入会参数 +-> 使用声网 SDK joinChannel +-> WS note call accept +-> 通话中通过 IM note hang-up 结束业务状态 +``` + +### 5.5 客户端挂断/取消/拒接 + +客户端通过 IM WebSocket 发送: + +```json +{ + "note": { + "topic": "p2p...", + "what": "call", + "event": "hang-up", + "seq": 30, + "payload": { + "callId": "call_01K...", + "reason": "cancelled" + } + } +} +``` + +服务端按当前状态把原通话消息替换为 `finished/missed/declined/disconnected`,并更新 `im_call_records`。客户端以服务端下发的替换消息为准,不相信本地计算的最终时长。 + +## 6. 数据与安全要求 + +1. `agora_app_certificate`、`agora_rest_customer_secret`、RTC Token 都是敏感信息,不写普通日志、不下发给无关用户、不进入埋点。 +2. 调试模式可以只用 App ID,但生产环境建议启用 App 证书和 RTC Token。 +3. `channel_name` 必须由服务端规则生成,建议 `call_{call_id}`,客户端不能自定义任意声网频道。 +4. `uid` 必须稳定,首期建议使用当前 IM 用户数据库 BIGINT ID;如果客户端 SDK 使用字符串 UID,后端和客户端必须同时切到 string 模式。 +5. 入会接口必须校验当前用户属于该 P2P 通话双方之一。 +6. 被拉黑、非好友、账号禁用、租户禁用、青少年模式限制等场景必须拒绝发起或接听。 + +## 7. 联调清单 + +| 编号 | 场景 | 预期 | +| --- | --- | --- | +| AGORA-01 | 后台只配置 `agora_app_id` 和 `agora_auth_mode=app_id` | `/v1/im/calls/rtc-join` 返回 App ID、频道名、UID,Token 为空。 | +| AGORA-02 | A 发起语音通话,B 接听 | 双方使用同一 `channel_name` 加入声网频道,IM 通话状态变为 `accepted`。 | +| AGORA-03 | A 发起视频通话,B 接听 | 双方可看到/听到媒体流,IM 通话记录为 `video`。 | +| AGORA-04 | B 拒接 | IM 替换原通话消息为 `declined`,双方退出声网频道。 | +| AGORA-05 | A 取消 | IM 替换原通话消息为 `missed` 或取消态,B 来电 UI 关闭。 | +| AGORA-06 | 通话中任一方挂断 | IM 以服务端计时生成 `finished` 和 `duration_ms`。 | +| AGORA-07 | 非参与人请求入会配置 | 返回 `CALL_NOT_ALLOWED`。 | +| AGORA-08 | 关闭 `agora_enabled` | 入会接口返回 `AGORA_DISABLED`。 | +| AGORA-09 | 正式 Token 模式缺少 App 证书 | 入会接口返回 `AGORA_CONFIG_MISSING`。 | +| AGORA-10 | Token 即将过期刷新 | 正式模式下客户端重新获取 Token 并成功 `renewToken`。 | + +## 8. 后续增强 + +1. 接入 RTC Token 生成器,支持 App 证书正式模式。 +2. 后台增加声网配置页和敏感字段脱敏。 +3. 接入声网控制台 REST API,实现项目查询、证书启停和重置。 +4. 记录声网频道、UID、入会时间、离会时间和错误码,便于排障。 +5. 采集通话质量指标:建连耗时、首帧耗时、丢包、延迟、卡顿、断线重连。 +6. 后续如需多人通话,单独设计会议房间和 SFU/RTC 房间状态,不复用 P2P `call_id` 状态机。 + +## 9. 参考文档 + +- 声网创建项目:https://doc.shengwang.cn/doc/console/general/console/operations/post-dev-v1-project +- 声网获取指定项目信息:https://doc.shengwang.cn/doc/console/general/console/operations/get-dev-v1-project +- 声网获取所有项目信息:https://doc.shengwang.cn/doc/console/general/console/operations/get-dev-v1-projects +- 声网启用或禁用项目:https://doc.shengwang.cn/doc/console/general/console/operations/post-dev-v1-project_status +- 声网启用或禁用主要 App 证书:https://doc.shengwang.cn/doc/console/general/console/operations/post-dev-v1-signkey +- 声网重置主要 App 证书:https://doc.shengwang.cn/doc/console/general/console/operations/post-dev-v1-reset_signkey +- 声网响应状态码:https://doc.shengwang.cn/doc/console/general/api/response-code +- 声网配额限制:https://doc.shengwang.cn/doc/console/general/api/quota +- 声网 REST 高可用:https://doc.shengwang.cn/doc/console/general/api/guarantee-rest +- 声网 RTC Token 鉴权:https://doc.shengwang.cn/doc/rtc/android/basic-features/token-authentication