Files
im_server/docs/third/IM-声网音视频通话完整调用流程.md
T

9.8 KiB
Raw Blame History

IM 声网音视频通话完整调用流程

更新时间:2026-09-01

1. 流程目标

本文用于说明 IM 系统接入声网 RTC 后,一次音视频通话从后台配置、客户端发起、服务端校验、声网入会到挂断结束的完整调用链路。

首期调试环境只使用声网 app_id,客户端入会时 token 为空。正式环境启用 App 证书后,由 IM Server 使用 app_certificate 生成 RTC Token,再返回给客户端。

2. 整体链路

后台配置声网参数
-> 客户端 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 token 正式模式,服务端生成 RTC Token。
agora_app_id xxxxxxxx 声网项目 App ID,允许返回给客户端。
agora_channel_prefix call_ 服务端生成声网频道名前缀。
agora_uid_mode string 建议使用 usr... 作为声网 user account,避免 BIGINT 用户 ID 超过声网数字 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:

Authorization: Basic base64(customer_id + ":" + customer_secret)
Content-Type: application/json

5. 前端和后端对接流程

5.1 发起方流程

用户 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 发起通话示例:

{
  "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 被叫方流程

客户端 B 收到 IM WebSocket 来电消息
-> 展示来电页面
-> 用户 B 点击接听
-> 客户端 B 调用入会接口获取声网参数
-> IM Server 校验 B 是否为本次通话参与人
-> IM Server 返回同一个 channel_name 和 B 自己的 uid/token
-> 客户端 B 使用声网 SDK 加入频道
-> 客户端 B 通过 IM WebSocket 发送 call accept
-> 双方开始音视频通话

5.3 获取声网入会参数

建议接口:

POST /v1/im/calls/rtc-join
Authorization: Bearer <IM token>
X-MeetingIM-APIKey: <api_key>
X-IM-Schema: 1
X-Request-ID: <request_id>
Idempotency-Key: <idempotency_key>
Content-Type: application/json

请求 Body:

{
  "topic": "p2p...",
  "call_id": "call_01K...",
  "seq": 30,
  "call_type": "video",
  "role": "caller"
}

成功响应:

{
  "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:

初始化 RTC SDK: app_id
加入频道: channel_name
用户标识: uid
入会凭证: token

调试模式下 token 为空。正式环境下 token 必须由后端生成并返回。

音视频媒体流不经过 IM Server,客户端加入声网频道后由声网 RTC 负责音视频传输、音频路由、摄像头采集、网络切换和断线重连等能力。

6. 通话结束流程

6.1 主动挂断

任意一方点击挂断
-> 客户端离开声网频道
-> 客户端通过 IM WebSocket 发送 hang-up
-> IM Server 更新通话记录状态和通话时长
-> IM Server 推送通话结束消息给另一方
-> 另一方客户端关闭通话页面并离开声网频道

挂断信令示例:

{
  "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 即将过期或已过期回调。

声网 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=token、agora_app_id、agora_app_certificate。
  2. 客户端集成声网 RTC SDK,并使用后端返回的 RTC Token 入会。
  3. A 发起语音通话,确认 B 能收到 IM 来电信令。
  4. A、B 分别调用 /v1/im/calls/rtc-join,确认返回同一个 channel_name。
  5. A、B 使用各自 uid 加入声网频道,确认音频可通。
  6. 切换视频通话,确认视频流可通。
  7. 测试取消、拒接、挂断、超时、网络断开。
  8. 验证 Token 入会和 Token 续期。
  9. 后续再接入声网控制台 REST API 的项目管理能力。