声网视频接入说明
This commit is contained in:
6
.workbuddy/memory/2026-09-14.md
Normal file
6
.workbuddy/memory/2026-09-14.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# 2026-09-14
|
||||
|
||||
- 编写 `docs/DOC-10-声网视频接入说明-V1.0.md`:声网(Agora)视频接入说明文档。
|
||||
- 梳理了项目中声网相关代码:`src/components/AgoraRtc.tsx`(通用观看组件,URL 传参 app_id/channel/token/uid,mode rtc/vp8)、`src/components/AgrtcRoomRobot.tsx`(机器人上位机组件,CHANNEL=serialNumber,mode live/h264,硬编码 AppID 7887b4db... 与临时 Token,含 2s 自动重连)、`DroneVideoPlayer.tsx` 按 `url_type`(volc/agora)分流到火山/声网播放器。
|
||||
- 注意:本仓库 Read 工具将 src 下部分 tsx/md 误判为二进制,需用 python 读取;docs/ 文档规范为 DOC-XX-名称-V1.0.md + 元数据表。
|
||||
- 文档中标出了安全风险:Token 硬编码在前端、无 renewToken、UID 随机生成,上线前需改为后端动态生成 Token。
|
||||
198
docs/DOC-10-声网视频接入说明-V1.0.md
Normal file
198
docs/DOC-10-声网视频接入说明-V1.0.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# 声网视频接入说明 V1.0
|
||||
|
||||
| 项目 | 内容 |
|
||||
|------|------|
|
||||
| 文档编号 | DOC-10 |
|
||||
| 文档名称 | 声网视频接入说明 |
|
||||
| 版本 | V1.0 |
|
||||
| 状态 | 草案(Draft) |
|
||||
| 适用系统 | 机器人智慧服务系统(Web 前端) |
|
||||
| 编写日期 | 2026-09-14 |
|
||||
| 关联文档 | DOC-08 设备数据字典、DOC-09 控制命令字典、机器人能力模型(`cap.video`) |
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本系统使用声网(Agora)WebRTC SDK 实现设备(机器人上位机 / 无人机)视频画面在 Web 端的实时观看。
|
||||
|
||||
- **SDK**:`agora-rtc-sdk-ng`(WebRTC NG SDK),版本 `^4.24.3`(见 `package.json`)
|
||||
- **角色模型**:设备端(上位机 / 无人机)为推流方(Host/Broadcaster),Web 前端为**纯观看方(Audience)**,只订阅远端流,不本地推流
|
||||
- **与火山 RTC 的关系**:系统同时接入了火山引擎 RTC(`@volcengine/rtc`)作为主视频通道,声网为第二通道。前端根据后端返回的 `url_type` 字段自动选择播放器(见 §5.2)
|
||||
|
||||
### 1.1 涉及代码
|
||||
|
||||
| 文件 | 组件 | 用途 |
|
||||
|------|------|------|
|
||||
| `src/components/AgoraRtc.tsx` | `AgoraRtcRoom` | 通用观看组件,从后端返回的 URL 中解析 RTC 参数加入频道 |
|
||||
| `src/components/AgrtcRoomRobot.tsx` | `AgrtcRoomRobot` | 机器人上位机专用观看组件,含自动重连与状态显示 |
|
||||
| `src/components/devices/DroneVideoPlayer.tsx` | — | 无人机/机场视频组件,按 `url_type` 分流到火山或声网播放器 |
|
||||
| `src/components/devices/DeviceOverviewPage.tsx` | — | 设备总览页,`hasHost` 设备使用 `AgrtcRoomRobot` |
|
||||
|
||||
> 注:`services/` 后端目录中**没有**声网 Token 生成逻辑,当前使用的是声网控制台生成的**临时 Token**(硬编码在前端),详见 §7 安全建议。
|
||||
|
||||
## 2. 接入架构
|
||||
|
||||
```
|
||||
┌──────────────┐ 推流(RTC/H264) ┌──────────────┐ 订阅/播放 ┌──────────────────┐
|
||||
│ 设备端 │ ─────────────────> │ 声网 SD-RTN │ ───────────> │ Web 前端(浏览器) │
|
||||
│ 上位机/无人机 │ (Host) │ 云网络 │ (Audience) │ AgoraRtc 组件 │
|
||||
└──────────────┘ └──────────────┘ └──────────────────┘
|
||||
```
|
||||
|
||||
- 设备端按 `App ID + Channel + Token + UID` 加入频道并推流(设备侧实现,不在本仓库内)
|
||||
- Web 端以 Audience 角色加入**同一频道**,通过 `user-published` 事件自动订阅远端视频/音频
|
||||
|
||||
### 2.1 关键参数
|
||||
|
||||
| 参数 | 说明 | 来源 |
|
||||
|------|------|------|
|
||||
| `appId` | 声网项目 App ID,当前 `7887b4db6033410d9ac3264b40ca9c1a` | 声网控制台 |
|
||||
| `channel` | 频道名。机器人场景 = 设备 `serialNumber`;无人机场景由后端下发 | 双方约定 |
|
||||
| `token` | 加入频道的鉴权 Token,有效期有限 | 声网控制台(临时)/ 后端生成(正式) |
|
||||
| `uid` | 用户 ID。前端随机生成 `Math.floor(Math.random() * 100000)` | 前端 |
|
||||
|
||||
## 3. 前置条件
|
||||
|
||||
1. 声网账号已注册,并创建项目(鉴权机制建议:**App ID + Token(安全模式)**)
|
||||
2. `package.json` 已包含依赖(无需额外安装):
|
||||
|
||||
```json
|
||||
"agora-rtc-sdk-ng": "^4.24.3"
|
||||
```
|
||||
|
||||
3. 设备端(上位机)已实现推流,频道名与平台约定一致
|
||||
4. 浏览器环境要求:Chrome/Edge 等现代浏览器,允许摄像头/自动播放策略(纯观看场景一般无需授权弹窗,但需允许自动播放)
|
||||
|
||||
## 4. 组件说明
|
||||
|
||||
### 4.1 `AgoraRtcRoom`(通用观看组件)
|
||||
|
||||
**文件**:`src/components/AgoraRtc.tsx`
|
||||
|
||||
| Props | 类型 | 说明 |
|
||||
|-------|------|------|
|
||||
| `url` | `string` | 后端返回的 RTC 播放地址,Query 参数中携带 `app_id` / `channel` / `token` / `uid` |
|
||||
|
||||
**URL 参数协议**(由后端拼装返回):
|
||||
|
||||
```
|
||||
https://<任意域名>/?app_id=<AppID>&channel=<频道名>&token=<Token>&uid=<UID>
|
||||
```
|
||||
|
||||
- 四个参数缺任一则组件不发起连接(仅打印日志 `RTC参数不全,无法播放`)
|
||||
- `uid` 缺省时前端随机生成
|
||||
|
||||
**内部行为**:
|
||||
- `mode: "rtc"`、`codec: "vp8"` 创建客户端
|
||||
- 监听 `user-published` 自动订阅并播放远端视频(渲染到内部容器),音频直接 `play()`
|
||||
- 监听 `user-left` 清空画面
|
||||
- **不推流**(纯观看,未创建本地轨道)
|
||||
- URL 任一参数变化时**销毁旧实例并整体重连**(调用侧配合 `key={url}` 强制重建组件,避免复用旧 client 导致黑屏)
|
||||
- 组件卸载时 `removeAllListeners()` + `leave()` 彻底清理
|
||||
|
||||
### 4.2 `AgrtcRoomRobot`(机器人上位机专用组件)
|
||||
|
||||
**文件**:`src/components/AgrtcRoomRobot.tsx`
|
||||
|
||||
| Props | 类型 | 说明 |
|
||||
|-------|------|------|
|
||||
| `CHANNEL` | `string` | 频道名,调用处传入 `selectedDevice.serialNumber`(设备序列号) |
|
||||
|
||||
**内部行为**:
|
||||
- `mode: "live"`、`codec: "h264"`,`setClientRole("audience")`
|
||||
- App ID / Token **硬编码**在组件内(当前为控制台临时 Token)
|
||||
- **加入频道后主动补订**:遍历 `client.remoteUsers`,对已推流的远端用户手动 `subscribe`(覆盖"观看端后于设备端入会"的场景)
|
||||
- **自动重连**:监听 `connection-state-change`,状态变为 `DISCONNECTED` 后清空画面并延迟 2 秒重连
|
||||
- **Token 过期预警**:监听 `token-privilege-will-expire`,弹 `message.warning` 提示(正式环境应调用 `client.renewToken(newToken)`,见 §7)
|
||||
- 顶部状态栏显示连接状态(RTC 已连接/未连接、已加入/未加入频道、当前频道名)
|
||||
- 无远端流时显示"视频加载中,等待远端推流..."占位
|
||||
- 卸载时逐个 `off()` 解绑事件 + `leave()`
|
||||
- 使用 `joiningRef` 防止并发 join,`OPERATION_ABORTED` 错误(React StrictMode / 快速卸载)静默忽略
|
||||
|
||||
### 4.3 使用示例
|
||||
|
||||
```tsx
|
||||
// ① 机器人上位机视频(设备 hasHost 时)
|
||||
<AgrtcRoomRobot CHANNEL={selectedDevice?.serialNumber || ''} />
|
||||
|
||||
// ② 无人机/机场视频(后端返回 streamData.url,按 url_type 分流)
|
||||
streamData?.url_type === 'volc' ? (
|
||||
<DroneLivePlayer key={streamData.url} streamData={streamData} />
|
||||
) : (
|
||||
<AgoraRtcRoom key={streamData.url} url={streamData.url} />
|
||||
)
|
||||
```
|
||||
|
||||
## 5. 关键流程
|
||||
|
||||
### 5.1 机器人观看时序
|
||||
|
||||
```
|
||||
Web前端 声网SD-RTN 机器人上位机
|
||||
│ createClient(live/h264) │ │
|
||||
│ setClientRole(audience) │ │
|
||||
│──── join(appId,channel,token,uid) ────────┐ │
|
||||
│ │<────────────┤ │
|
||||
│ │ (上位机此前已 join + publish)
|
||||
│──── 遍历 remoteUsers ─────>│ │
|
||||
│──── subscribe(remoteUser, "video") ───────┤ │
|
||||
│<─── user-published 事件 ───│ │
|
||||
│ videoTrack.play(container) │
|
||||
│ (画面渲染完成) │
|
||||
```
|
||||
|
||||
### 5.2 无人机/机场视频流程(含分流)
|
||||
|
||||
1. 前端调用设备接口切换镜头/摄像头:
|
||||
- `changeCameraPlane({ sn, lensType, cameraIndex, qualityType: "adaptive", videoExpire })` —— 无人机镜头(wide/zoom/ir)
|
||||
- `changeCameragateway({ sn, cameraIndex, cameraPosition, qualityType, videoExpire })` —— 机场摄像头(indoor/outdoor)
|
||||
2. 后端返回 `res.data`(`streamData`),包含 `url`、`url_type`
|
||||
3. `url_type === "volc"` → 火山播放器 `DroneLivePlayer`;否则 → 声网 `AgoraRtcRoom`
|
||||
4. `AgoraRtcRoom` 解析 `url` 中的 Query 参数,走 §5.1 流程加入并订阅
|
||||
|
||||
### 5.3 断线重连(AgrtcRoomRobot)
|
||||
|
||||
```
|
||||
connection-state-change: CONNECTED → DISCONNECTED
|
||||
│
|
||||
▼
|
||||
清空远端画面(setHasRemoteVideo=false) → 2s 延迟 → 重新 join → 补订 remoteUsers
|
||||
```
|
||||
|
||||
## 6. 事件与状态参考
|
||||
|
||||
| 事件 | 触发时机 | 前端处理 |
|
||||
|------|----------|----------|
|
||||
| `connection-state-change` | 连接状态变化(DISCONNECTED/CONNECTING/CONNECTED/RECONNECTING) | 更新状态徽标;DISCONNECTED 触发重连 |
|
||||
| `user-published` | 远端用户发布媒体流 | `subscribe` 后 `videoTrack.play()` / `audioTrack.play()` |
|
||||
| `user-unpublished` | 远端停止推流(如上位机停止推流) | 停止轨道并清空画面 |
|
||||
| `user-left` | 远端用户离开频道 | 清空画面,显示占位 |
|
||||
| `user-joined` | 远端用户进入频道 | 仅日志 |
|
||||
| `token-privilege-will-expire` | Token 即将过期(提前约 30s) | 警告提示;正式环境应 `client.renewToken()` |
|
||||
|
||||
## 7. 安全建议(重要)
|
||||
|
||||
当前实现存在以下与生产环境的差距,**上线前必须整改**:
|
||||
|
||||
1. **Token 硬编码在前端**(`AgrtcRoomRobot.tsx`)。声网临时 Token 有效期短(默认 24 小时内),过期后视频不可用且密钥暴露在浏览器端。应在后端(`services/`)集成声网服务端 SDK,按频道动态生成 Token 并通过接口下发(`AgoraRtcRoom` 的 URL 传参模式即为此设计,建议统一)。
|
||||
2. **App 证书**:确认声网项目已开启 App Certificate(Token 鉴权),关闭"App ID 鉴权"裸奔模式。
|
||||
3. **Token 续期**:在 `token-privilege-will-expire` 回调中请求后端换发新 Token 并调用 `client.renewToken(newToken)`,而非仅弹窗提示。
|
||||
4. **UID 碰撞**:前端 `Math.random()` 生成 UID 有小概率与设备端 UID 或多开页面冲突,建议由后端分配唯一 UID。
|
||||
|
||||
## 8. 常见问题排查
|
||||
|
||||
| 现象 | 可能原因 | 处理建议 |
|
||||
|------|----------|----------|
|
||||
| 黑屏 / 无画面 | client 复用旧实例 | 已通过"每次新建 client + `key` 强制重建组件"规避,新增调用处务必沿用该模式 |
|
||||
| 加入频道失败 | appId/token/channel 不匹配,或 Token 过期 | 核对三元组;临时 Token 需在声网控制台重新生成 |
|
||||
| `OPERATION_ABORTED` 报错 | React StrictMode 双执行 / 组件快速卸载 | 代码已静默忽略,属预期行为 |
|
||||
| 加入成功但无视频 | 设备端未推流,或观看端先于设备端入会 | 已实现 `remoteUsers` 补订;确认设备端 publish 正常 |
|
||||
| 频繁重连 | 网络波动或 Token 过期 | 查看控制台 `连接状态变更` 日志;Token 过期会周期性 DISCONNECTED |
|
||||
| 视频卡顿 | 编码/网络质量 | 检查 `qualityType: "adaptive"` 自适应档位;确认上行带宽 |
|
||||
|
||||
## 9. 版本记录
|
||||
|
||||
| 版本 | 日期 | 说明 |
|
||||
|------|------|------|
|
||||
| V1.0 | 2026-09-14 | 初稿:梳理现有 AgoraRtc / AgrtcRoomRobot 组件、参数协议、重连机制与安全建议 |
|
||||
Reference in New Issue
Block a user