1324 lines
30 KiB
Markdown
1324 lines
30 KiB
Markdown
这份是**“智能锁新实时系统方案”模块开发周期、技术栈、难点和注意事项**。
|
||
|
||
> 预估前提:
|
||
> - `starcloud`、`starlock`、`app-starlock`、现有设备端已有基础能力。
|
||
> - 新项目重点是实时控制面、BifroMQ、WebRTC/TURN/ZLMediaKit、事件链路、AI 旁路。
|
||
> - 团队配置按:后端 2 人、APP 1 人、设备端 1 人、运维 1 人、测试 1 人估算。
|
||
|
||
---
|
||
|
||
# 一、整体开发阶段建议
|
||
|
||
## 阶段划分
|
||
|
||
| 阶段 | 目标 | 周期预估 |
|
||
|---|---|---|
|
||
| 阶段 0:方案细化与协议设计 | 确定 topic、状态机、API、媒体选路策略 | 1 - 2 周 |
|
||
| 阶段 1:实时控制面 MVP | 完成 `session-orchestrator`、`device-bootstrap`、BifroMQ 基础接入 | 3 - 5 周 |
|
||
| 阶段 2:WebRTC / TURN / ZLM 媒体链路 | 完成 P2P、TURN、ZLMediaKit 基础切换 | 4 - 8 周 |
|
||
| 阶段 3:APP 与设备端联调 | APP、WiFi 锁、后台完整跑通呼叫、接听、挂断、切路 | 4 - 6 周 |
|
||
| 阶段 4:事件、日志、可观测、弱网优化 | 完成事件消费、质量上报、链路追踪、告警 | 2 - 4 周 |
|
||
| 阶段 5:AI 旁路接入 | 接入 `ai-gateway`、`xiaozhi_server` | 2 - 4 周 |
|
||
| 阶段 6:灰度上线与稳定性优化 | 压测、弱网测试、灰度、回滚方案 | 2 - 4 周 |
|
||
|
||
## 总周期预估
|
||
|
||
| 范围 | 周期 |
|
||
|---|---|
|
||
| 最小可用版本 MVP | 8 - 12 周 |
|
||
| 可灰度上线版本 | 12 - 16 周 |
|
||
| 含 AI、完整动态选路、完整可观测版本 | 16 - 24 周 |
|
||
|
||
---
|
||
|
||
# 二、模块开发周期、技术栈、难点与注意事项
|
||
|
||
## 1. `starlock` 租户应用层改造
|
||
|
||
### 模块定位
|
||
|
||
`starlock` 是 APP 的统一业务入口,负责:
|
||
|
||
- APP 登录鉴权
|
||
- 家庭 / 门锁归属判断
|
||
- 调用 `starcloud` 共享能力
|
||
- 调用 `session-orchestrator` 创建实时会话
|
||
- 下发短期会话权限
|
||
- 处理事件回调和业务通知
|
||
|
||
### 开发周期
|
||
|
||
**2 - 4 周**
|
||
|
||
如果现有 PHP 代码结构清晰,只做 API 编排,约 2 周。
|
||
如果需要整理权限、设备归属、租户模型,可能 4 周以上。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 后端语言 | PHP |
|
||
| 框架 | Laravel / ThinkPHP / Yii / 原有框架,按现状 |
|
||
| API | RESTful API |
|
||
| 认证 | JWT / Session / OAuth2 内部 token |
|
||
| 数据库 | MySQL / PostgreSQL |
|
||
| 缓存 | Redis |
|
||
| 内部调用 | HTTP / gRPC,可先 HTTP |
|
||
| 日志 | Monolog / ELK / Loki |
|
||
|
||
### 主要开发内容
|
||
|
||
- 新增“创建视频会话”接口
|
||
- 调用 `session-orchestrator` 创建 `sessionId`
|
||
- 根据用户、家庭、门锁关系做权限校验
|
||
- 返回 APP 所需短期 token、MQTT topic、媒体策略
|
||
- 处理 `MQTT event worker` 回调
|
||
- 处理 AI 会话状态回调
|
||
- 保留对 `starcloud` 的共享能力调用
|
||
|
||
### 难点
|
||
|
||
1. **权限边界**
|
||
- APP 用户是否有权访问某把锁
|
||
- 家庭成员、租户、渠道、套餐规则是否影响通话权限
|
||
|
||
2. **短期会话权限设计**
|
||
- APP 不能直接拿长期业务 token 去访问实时系统
|
||
- 需要生成短期、单会话、可过期的 token
|
||
|
||
3. **业务状态与实时状态解耦**
|
||
- `starlock` 不应该维护完整通话状态机
|
||
- 它只关心会话结果、事件回调和业务通知
|
||
|
||
4. **兼容旧链路**
|
||
- 旧 UDP 控制、旧 `scd/scrd/rpcd` 可能仍有设备在用
|
||
- 需要新旧能力并存一段时间
|
||
|
||
### 注意事项
|
||
|
||
- `starlock` 不要直接搬运 WebRTC signaling。
|
||
- APP 不应直接访问 `session-orchestrator` 的内部管理接口。
|
||
- 所有会话创建都必须经过设备归属和家庭权限校验。
|
||
- 短期 token 要绑定:
|
||
- `userId`
|
||
- `deviceId`
|
||
- `sessionId`
|
||
- 过期时间
|
||
- 权限范围
|
||
- 事件回调要做幂等处理,防止重复消费。
|
||
- 所有敏感操作要写审计日志。
|
||
|
||
---
|
||
|
||
## 2. `starcloud` 共享业务能力对接
|
||
|
||
### 模块定位
|
||
|
||
`starcloud` 是共享业务平台,主要提供:
|
||
|
||
- 用户 / 权限策略
|
||
- 家庭 / 设备关系
|
||
- 套餐 / 计费
|
||
- 审计 / 风控
|
||
- 通用业务规则
|
||
|
||
### 开发周期
|
||
|
||
**1 - 3 周**
|
||
|
||
如果现有 API 完备,只需对接和字段适配,约 1 周。
|
||
如果需要补充共享能力 API,则需要 2 - 3 周。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 后端 | 现有 `starcloud` 技术栈 |
|
||
| API | REST / RPC |
|
||
| 鉴权 | 内部服务 token / AK-SK / OAuth2 |
|
||
| 数据库 | 现有数据库 |
|
||
| 缓存 | Redis |
|
||
| 审计 | 日志服务 / 审计表 |
|
||
|
||
### 主要开发内容
|
||
|
||
- 提供设备归属查询能力
|
||
- 提供用户权限策略查询能力
|
||
- 提供风控和审计接口
|
||
- 给 `starlock` 提供标准化业务 API
|
||
|
||
### 难点
|
||
|
||
- 多租户和跨项目能力边界容易混乱
|
||
- 共享模型与 `starlock` 定制逻辑可能重复
|
||
- 权限策略需要兼容现有用户体系
|
||
|
||
### 注意事项
|
||
|
||
- `starcloud` 不直接参与实时会话状态机。
|
||
- `starcloud` 只输出通用业务判断,不关心 WebRTC、BifroMQ、ZLM 细节。
|
||
- 通用能力和租户定制能力要分清。
|
||
- 不要把实时系统的 topic、signaling、media route 等细节侵入 `starcloud`。
|
||
|
||
---
|
||
|
||
## 3. `session-orchestrator` 会话编排服务
|
||
|
||
### 模块定位
|
||
|
||
这是新实时系统的核心模块,负责:
|
||
|
||
- 创建会话
|
||
- 管理会话状态机
|
||
- 下发控制指令
|
||
- 处理 ACK / 超时 / 重试
|
||
- 编排 signaling topic
|
||
- 控制媒体选路
|
||
- 记录会话状态和质量数据
|
||
|
||
### 开发周期
|
||
|
||
**4 - 8 周**
|
||
|
||
MVP 版本 4 周左右。
|
||
完整支持状态机、切路、追踪、重试、幂等,建议预留 6 - 8 周。
|
||
|
||
### 技术栈
|
||
|
||
推荐技术栈:
|
||
|
||
| 类型 | 推荐 |
|
||
|---|---|
|
||
| 后端语言 | Go / Java / Node.js |
|
||
| 推荐优先级 | Go 或 Java 更适合长连接、并发和状态机 |
|
||
| Web 框架 | Go Fiber / Gin,Java Spring Boot |
|
||
| 内部 API | REST / gRPC |
|
||
| MQTT Client | Eclipse Paho / gmqtt / HiveMQ Client |
|
||
| 状态缓存 | Redis |
|
||
| 持久化 | MySQL / PostgreSQL |
|
||
| 消息序列 | Redis Stream / Kafka,可顺续引入 |
|
||
| 日志追踪 | OpenTelemetry |
|
||
| 指标 | Prometheus |
|
||
| 配置 | YAML / ENV / Nacos / Consul |
|
||
|
||
### 主要开发内容
|
||
|
||
- `CreateSession`
|
||
- `InviteDevice`
|
||
- `AcceptSession`
|
||
- `RejectSession`
|
||
- `StartSignaling`
|
||
- `ReportQuality`
|
||
- `SwitchRoute`
|
||
- `Hangup`
|
||
- `Timeout`
|
||
- `Terminate`
|
||
- 会话状态机
|
||
- MQTT topic 分配
|
||
- 短期 token 校验
|
||
- ACK / seq / retry
|
||
- 会话日志落库
|
||
- 媒体策略下发
|
||
|
||
### 推荐状态机
|
||
|
||
```text
|
||
pending
|
||
-> ringing
|
||
-> accepted
|
||
-> connecting
|
||
-> connected
|
||
-> degraded
|
||
-> switching_route
|
||
-> recovered
|
||
-> ended
|
||
|
||
异常结束:
|
||
-> rejected
|
||
-> timeout
|
||
-> failed
|
||
```
|
||
|
||
### 难点
|
||
|
||
1. **状态一致性**
|
||
- APP、设备、云端三方状态容易不一致。
|
||
- 必须通过状态机和事件序列统一收敛。
|
||
|
||
2. **ACK 与超时控制**
|
||
- `invite` 发出后,设备可能离线、延迟、重复 ACK。
|
||
- 所有控制指令要有 `seq`、`ack`、`timeout`。
|
||
|
||
3. **动态选路**
|
||
- 什么时候从 P2P 切 TURN?
|
||
- 什么时候从 TURN 切 ZLM?
|
||
- 切路过程中如何不中断或少中断?
|
||
|
||
4. **幂等性**
|
||
- APP 重试创建会话
|
||
- 设备重复上报 accept
|
||
- MQTT 重复投递
|
||
- 都必须能安全处理
|
||
|
||
5. **分布式扩容**
|
||
- 多个 `session-orchestrator` 实例时,会话归属、锁、状态更新要处理好。
|
||
|
||
### 注意事项
|
||
|
||
- 会话 ID 必须全局唯一。
|
||
- 所有指令都要带:
|
||
- `sessionId`
|
||
- `eventId`
|
||
- `seq`
|
||
- `timestamp`
|
||
- `expireAt`
|
||
- `from`
|
||
- `to`
|
||
- 状态变更必须有合法状态迁移校验。
|
||
- 会话状态建议短期放 Redis,终态落 MySQL。
|
||
- 不建议在 MQTT retained message 中保存敏感 signaling。
|
||
- `session-orchestrator` 不搬运大媒体流。
|
||
- `session-orchestrator` 应只管控制面,不直接承载视频数据。
|
||
|
||
---
|
||
|
||
## 4. `device-bootstrap` 设备接入服务
|
||
|
||
### 模块定位
|
||
|
||
设备首次或周期性接入时,通过该服务获取:
|
||
|
||
- 设备认证
|
||
- MQTT 连接参数
|
||
- 短期 MQTT 凭证
|
||
- 设备 topic 权限
|
||
- 设备能力配置
|
||
- 固件能力声明
|
||
|
||
### 开发周期
|
||
|
||
**2 - 4 周**
|
||
|
||
如果设备认证机制已存在,2 周左右。
|
||
如果需要重新设计设备证书、密钥、签名,3 - 4 周。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 后端语言 | Go / Java / PHP 均可 |
|
||
| API | HTTPS |
|
||
| 鉴权 | 设备证书 / 设备密钥 / HMAC 签名 |
|
||
| 存储 | MySQL |
|
||
| 缓存 | Redis |
|
||
| MQTT 权限 | BifroMQ Auth Provider / 自定义鉴权 |
|
||
|
||
### 主要开发内容
|
||
|
||
- 设备身份校验
|
||
- 颁发 MQTT username/password/token
|
||
- 生成设备 topic ACL
|
||
- 返回 BifroMQ 连接地址
|
||
- 返回心跳周期
|
||
- 返回设备配置
|
||
- 支持设备能力声明:
|
||
- 是否支持 WebRTC
|
||
- 是否支持 ZLM
|
||
- 是否支持 AI 音频旁路
|
||
- 是否支持 BLE 透传
|
||
|
||
### 难点
|
||
|
||
- 设备端时间不准导致签名过期判断失败
|
||
- 设备密钥泄露风险
|
||
- MQTT ACL 粒度设计
|
||
- 新旧设备兼容
|
||
|
||
### 注意事项
|
||
|
||
- 不要给设备长期固定 MQTT 密码。
|
||
- MQTT 凭证建议短期有效,可刷新。
|
||
- topic 权限必须最小化。
|
||
- 设备只能发布和订阅自己的 topic。
|
||
- 设备 capability 要版本化,方便后续灰度。
|
||
|
||
---
|
||
|
||
## 5. Apache BifroMQ 模块
|
||
|
||
### 模块定位
|
||
|
||
BifroMQ 承担:
|
||
|
||
- 设备在线状态
|
||
- 发现
|
||
- MQTT signaling
|
||
- 事件总线
|
||
- APP 与设备信令通道
|
||
|
||
### 开发周期
|
||
|
||
**2 - 4 周**
|
||
|
||
部署和基础联调 1 - 2 周。
|
||
完整 ACL、认证、监控、压测,建议 3 - 4 周。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| MQTT Broker | Apache BifroMQ |
|
||
| 协议 | MQTT 3.1.1 / MQTT 5 |
|
||
| APP 连接 | MQTT over WSS |
|
||
| 设备连接 | MQTT over TLS |
|
||
| 鉴权 | 自定义 Auth Provider |
|
||
| 监控 | Prometheus / Grafana |
|
||
| 日志 | Loki / ELK |
|
||
|
||
### Topic 设计建议
|
||
|
||
```text
|
||
tenant/{tenantId}/device/{deviceId}/status
|
||
tenant/{tenantId}/device/{deviceId}/event
|
||
tenant/{tenantId}/session/{sessionId}/signal/app
|
||
tenant/{tenantId}/session/{sessionId}/signal/device
|
||
tenant/{tenantId}/session/{sessionId}/control
|
||
tenant/{tenantId}/session/{sessionId}/quality
|
||
```
|
||
|
||
### 难点
|
||
|
||
1. **topic 权限控制**
|
||
- APP 只能访问自己本次会话相关 topic。
|
||
- 设备只能访问自己所属 topic。
|
||
|
||
2. **在线状态判断**
|
||
- MQTT connected 不等于设备业务可用。
|
||
- 需要结合心跳、lastWill、设备能力状态。
|
||
|
||
3. **QoS 选择**
|
||
- signaling 可用 QoS 1。
|
||
- 质量上报可用 QoS 0。
|
||
- 控制指令建议 QoS 1 + 应用层 ACK。
|
||
|
||
4. **消息顺序**
|
||
- MQTT 不能替代完整状态机。
|
||
- 状态一致性仍应由 `session-orchestrator` 控制。
|
||
|
||
### 注意事项
|
||
|
||
- 不要通过 MQTT 传大视频流。
|
||
- 不要把长期敏感 token 放在 topic 或 payload 里。
|
||
- topic 命名要预留租户维度。
|
||
- MQTT payload 要版本化。
|
||
- retained message 谨慎使用,尤其是 signaling 类消息。
|
||
- LWT 遗嘱消息要设计好,用于设备离线通知。
|
||
|
||
---
|
||
|
||
## 6. APP 端 `app-starlock` 改造
|
||
|
||
### 模块定位
|
||
|
||
APP 需要支持:
|
||
|
||
- 调用 `starlock` 创建会话
|
||
- 连接 BifroMQ
|
||
- 订阅 session topic
|
||
- WebRTC offer/answer/candidate
|
||
- 媒体链路质量上报
|
||
- 动态切路响应
|
||
- 弱网提示
|
||
- AI 辅助入口
|
||
|
||
### 开发周期
|
||
|
||
**4 - 8 周**
|
||
|
||
如果现有 Flutter 已有实时对讲能力,约 4 - 5 周。
|
||
如果 WebRTC 从零接入,建议 6 - 8 周。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| APP 框架 | Flutter |
|
||
| WebRTC | flutter_webrtc |
|
||
| MQTT | mqtt_client / 其他 Flutter MQTT SDK |
|
||
| 网络 | Dio |
|
||
| 状态管理 | Riverpod / Bloc / Provider |
|
||
| 本地存储 | shared_preferences / hive |
|
||
| 日志 | Sentry / 自建日志上报 |
|
||
| 推送 | FCM / APNs / 厂商推送 |
|
||
|
||
### 主要开发内容
|
||
|
||
- 会话创建 API
|
||
- MQTT over WSS 连接
|
||
- WebRTC PeerConnection
|
||
- ICE candidate 处理
|
||
- offer/answer 交换
|
||
- TURN 配置
|
||
- ZLM 播放 / 推流能力接入
|
||
- route switch 指令处理
|
||
- 通话 UI 状态机
|
||
- 通话质量上报
|
||
- 异常提示和重连
|
||
|
||
### 难点
|
||
|
||
1. **Flutter WebRTC 稳定性**
|
||
- Android 和 iOS 行为不同。
|
||
- 后台、锁屏、权限、音频路由复杂。
|
||
|
||
2. **弱网处理**
|
||
- 网络切换 WiFi/4G
|
||
- ICE reconnect
|
||
- MQTT 断线重连
|
||
- 媒体重连
|
||
|
||
3. **状态同步**
|
||
- APP UI 状态必须跟云端会话状态保持一致。
|
||
- 不能只靠本地 WebRTC 状态判断。
|
||
|
||
4. **音频权限和回声消除**
|
||
- 双向语音容易出现回声、啸叫、音量问题。
|
||
|
||
### 注意事项
|
||
|
||
- APP 不要保存长期 MQTT 密钥。
|
||
- APP 进入后台时要处理 MQTT 和 WebRTC 生命周期。
|
||
- 会话失败要区分:
|
||
- 设备离线
|
||
- 权限不足
|
||
- signaling 超时
|
||
- ICE 失败
|
||
- ZLM 失败
|
||
- 所有通话状态变化都要上报。
|
||
- iOS 需要特别注意后台音视频权限和推送唤醒策略。
|
||
- Android 需要注意不同厂商后台保活限制。
|
||
|
||
---
|
||
|
||
## 7. WiFi 网关锁 / 设备端改造
|
||
|
||
### 模块定位
|
||
|
||
WiFi 锁作为网关设备,需要支持:
|
||
|
||
- HTTPS bootstrap
|
||
- MQTT/TLS 连接
|
||
- 在线状态上报
|
||
- 会话 invite/accept/reject/hangup
|
||
- WebRTC 采集、编码、推流
|
||
- TURN / ZLM / relay 切换
|
||
- AI 音频旁路
|
||
- BLE 锁透传
|
||
|
||
### 开发周期
|
||
|
||
**6 - 12 周**
|
||
|
||
如果设备端已有音视频 SDK 和 WebRTC 能力,6 - 8 周。
|
||
如果从零接入 WebRTC,尤其是嵌入式平台,可能 12 周以上。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 语言 | C / C++ |
|
||
| MQTT | Eclipse Paho Embedded / mosquitto client / 自研 |
|
||
| TLS | mbedTLS / OpenSSL |
|
||
| WebRTC | libwebrtc / Pion 设备适配 / vendor SDK |
|
||
| 编码 | H.264 / H.265 / AAC / Opus |
|
||
| 媒体 | GStreamer / FFmpeg / 设备厂商 SDK |
|
||
| 存储 | Flash / 本地配置 |
|
||
| 日志 | 本地环形日志 + 云端上报 |
|
||
|
||
### 主要开发内容
|
||
|
||
- bootstrap 接入
|
||
- MQTT topic 订阅和发布
|
||
- 设备能力声明
|
||
- 接收 `invite`
|
||
- 发送 `ringing/accept/reject`
|
||
- signaling 处理
|
||
- WebRTC 建链
|
||
- TURN 支持
|
||
- ZLM 推流或 WebRTC 接入
|
||
- 质量指标采集
|
||
- route switch 响应
|
||
- 会话结束清理
|
||
- AI旁路转发
|
||
|
||
### 难点
|
||
|
||
1. **设备性能限制**
|
||
- CPU、内存、编码能力有限。
|
||
- WebRTC 对资源要求高。
|
||
|
||
2. **嵌入式 WebRTC 集成难**
|
||
- ICE、DTLS、SRTP、NAT 穿透复杂。
|
||
- SDK 移植成本高。
|
||
|
||
3. **音视频编码兼容**
|
||
- APP、ZLM、WebRTC 对 codec 支持要统一。
|
||
- H.264 profile、packetization mode 要注意。
|
||
|
||
4. **切路过程中资源释放**
|
||
- P2P 切 ZLM 时要释放旧连接。
|
||
- 防止摄像头、麦克风、编码器被占用。
|
||
|
||
5. **断网恢复**
|
||
- 设备重连后要恢复 MQTT 状态。
|
||
- 旧会话要能被云端清理。
|
||
|
||
### 注意事项
|
||
|
||
- 设备端必须实现控制指令 ACK。
|
||
- 设备端所有消息要带 `sessionId` 和 `seq`。
|
||
- 设备端不能信任任意 MQTT 消息,必须校验 token 或签名。
|
||
- 摄像头、麦克风只能被一个会话独占,除非明确支持多路。
|
||
- 本地日志非常重要,否则现场问题很难定位。
|
||
- 如果设备端 WebRTC 难度过高,可以第一阶段优先走 ZLMediaKit 或厂商 SDK,再逐步补 P2P。
|
||
|
||
---
|
||
|
||
## 8. WebRTC / TURN 媒体链路模块
|
||
|
||
### 模块定位
|
||
|
||
负责 APP 与设备之间的实时音视频链路:
|
||
|
||
- 优先 P2P
|
||
- P2P 不通走 TURN
|
||
- 弱网时可切 ZLM
|
||
- 最终兜底走中心转发
|
||
|
||
### 开发周期
|
||
|
||
**4 - 8 周**
|
||
|
||
APP、设备、服务端三方联调复杂,建议至少预留 1 个月。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| WebRTC | libwebrtc / flutter_webrtc |
|
||
| STUN/TURN | coturn |
|
||
| 加密 | DTLS-SRTP |
|
||
| NAT 穿透 | ICE |
|
||
| 编码 | H.264 / Opus |
|
||
| 质量监控 | getStats / 自定义质量上报 |
|
||
|
||
### 主要开发内容
|
||
|
||
- ICE server 配置
|
||
- offer/answer
|
||
- candidate 收集和交换
|
||
- TURN credential
|
||
- 质量上报
|
||
- P2P / TURN 判定
|
||
- ICE restart
|
||
- 通话异常恢复
|
||
|
||
### 难点
|
||
|
||
- NAT 类型复杂
|
||
- 对称 NAT 下 P2P 失败率高
|
||
- TURN 成本高,带宽压力大
|
||
- ICE 状态和业务状态不完全一致
|
||
- 移动网络切换容易断流
|
||
|
||
### 注意事项
|
||
|
||
- TURN 账号必须短期有效。
|
||
- TURN 带宽成本要评估。
|
||
- 不要把 TURN 当成无限免费兜底。
|
||
- WebRTC 质量指标要持续上报:
|
||
- RTT
|
||
- packet loss
|
||
- jitter
|
||
- bitrate
|
||
- candidate type
|
||
- frame drop
|
||
- 首版可以先实现“失败后重建到 ZLM”,不要一开始追求无感切换。
|
||
|
||
---
|
||
|
||
## 9. `ZLMediaKit` 中心转发模块
|
||
|
||
### 模块定位
|
||
|
||
ZLMediaKit 用于:
|
||
|
||
- 弱网优先转发
|
||
- P2P/TURN 失败后的媒体兜底
|
||
- 标准化流媒体接入
|
||
- 后续录像、截图、事件视频处理
|
||
|
||
### 开发周期
|
||
|
||
**3 - 6 周**
|
||
|
||
基础部署和推拉流 1 - 2 周。
|
||
与 APP、设备、鉴权、会话状态打通,约 3 - 6 周。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 流媒体服务 | ZLMediaKit |
|
||
| 协议 | WebRTC / RTSP / RTMP / HLS / HTTP-FLV |
|
||
| 编码 | H.264 / AAC / Opus |
|
||
| 鉴权 | ZLM hook + 业务鉴权 |
|
||
| 部署 | Docker / systemd |
|
||
| 负载均衡 | Nginx / SLB |
|
||
| 监控 | Prometheus exporter / 日志采集 |
|
||
|
||
### 主要开发内容
|
||
|
||
- ZLM 部署
|
||
- 推流地址生成
|
||
- 播放地址生成
|
||
- Hook 鉴权
|
||
- 流开始 / 结束事件回调
|
||
- 与 `session-orchestrator` 对接
|
||
- APP 播放适配
|
||
- 设备推流适配
|
||
- 异常断流重试
|
||
|
||
### 难点
|
||
|
||
1. **协议选择**
|
||
- 设备推什么协议?
|
||
- APP 拉什么协议?
|
||
- 是否都走 WebRTC?
|
||
|
||
2. **延迟控制**
|
||
- HLS 延迟高,不适合实时对讲。
|
||
- WebRTC / RTMP / HTTP-FLV 要按实际需求选。
|
||
|
||
3. **双向语音**
|
||
- 只看视频容易,双向对讲更复杂。
|
||
- 要确认 ZLM 在当前方案中如何承载上行音频。
|
||
|
||
4. **鉴权和防盗链**
|
||
- 推流 / 播放 URL 必须短期有效。
|
||
- 不能裸露固定流地址。
|
||
|
||
### 注意事项
|
||
|
||
- 弱网优先 ZLM 是合理的,但要明确“实时对讲”的延迟指标。
|
||
- 首版建议只做一套主协议,避免 RTMP、RTSP、WebRTC、FLV 全部都上。
|
||
- ZLM 的 hook 回调要和 `session-orchestrator` 状态机打通。
|
||
- 流 ID 要绑定 `sessionId`。
|
||
- 推流和播放权限必须过期。
|
||
- 要有自动清理僵尸流机制。
|
||
|
||
---
|
||
|
||
## 10. `media-relay` 中心转发兜底模块
|
||
|
||
### 模块定位
|
||
|
||
`media-relay` 是最终兜底。
|
||
但你文档里已经明确:**优先采用 ZLMediaKit 落地,通常不需要长期维护自研 relay。**
|
||
|
||
### 开发周期
|
||
|
||
| 方案 | 周期 |
|
||
|---|---|
|
||
| 不自研,直接用 ZLMediaKit 承担 | 0 - 1 周设计适配 |
|
||
| 轻量封装 ZLM relay API | 2 - 3 周 |
|
||
| 自研完整音视频 relay | 8 - 16 周,不建议第一阶段做 |
|
||
|
||
### 技术栈
|
||
|
||
如果不自研:
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| Relay 实现 | ZLMediaKit |
|
||
| 控制层 | `session-orchestrator` |
|
||
| 鉴权 | ZLM hook |
|
||
| 监控 | Prometheus / 日志 |
|
||
|
||
如果自研:
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 语言 | C++ / Go |
|
||
| 媒体协议 | RTP / SRTP / WebRTC |
|
||
| 编码处理 | FFmpeg / GStreamer |
|
||
| NAT | ICE / TURN |
|
||
| 难度 | 高 |
|
||
|
||
### 难点
|
||
|
||
- 自研媒体转发成本极高
|
||
- 音视频同步、抖动缓冲、拥塞控制都复杂
|
||
- 稳定性和性能验证成本高
|
||
|
||
### 注意事项
|
||
|
||
- 第一阶段不建议自研 `media-relay`。
|
||
- 先让 `media-relay` 成为逻辑模块,由 ZLMediaKit 实现。
|
||
- 后续只有在 ZLM 无法满足业务需求时再考虑自研。
|
||
|
||
---
|
||
|
||
## 11. `MQTT event worker` / 原 `event_listener` 演进
|
||
|
||
### 模块定位
|
||
|
||
负责消费设备事件和实时事件:
|
||
|
||
- 门锁事件
|
||
- 设备上下线
|
||
- 通话事件
|
||
- 媒体事件
|
||
- AI 事件
|
||
- 图片 / 视频后处理
|
||
- 回调 `starlock`
|
||
|
||
### 开发周期
|
||
|
||
**2 - 4 周**
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 后端语言 | Go / Java / PHP Worker / Node.js |
|
||
| 消息来源 | BifroMQ MQTT |
|
||
| 队列 | Redis Stream / Kafka / RabbitMQ,可选 |
|
||
| 存储 | MySQL / Redis |
|
||
| 回调 | HTTP |
|
||
| 重试 | 延迟队列 / 定时任务 |
|
||
|
||
### 主要开发内容
|
||
|
||
- MQTT 事件订阅
|
||
- 事件解析
|
||
- 事件幂等
|
||
- 回调 `starlock`
|
||
- 失败重试
|
||
- 死信队列
|
||
- 事件日志落库
|
||
- 媒体后处理触发
|
||
|
||
### 难点
|
||
|
||
- MQTT 事件可能重复
|
||
- 设备事件顺序可能乱
|
||
- 回调失败后要重试
|
||
- 事件消费不能阻塞主实时链路
|
||
|
||
### 注意事项
|
||
|
||
- 每个事件必须有唯一 `eventId`。
|
||
- 回调 `starlock` 要支持幂等。
|
||
- 不要在 worker 中做耗时媒体处理,应该异步化。
|
||
- 事件处理失败要可追踪、可重放。
|
||
- 事件 schema 要版本化。
|
||
|
||
---
|
||
|
||
## 12. `realtime-store` 实时状态与日志缓存
|
||
|
||
### 模块定位
|
||
|
||
用于保存:
|
||
|
||
- 会话临时状态
|
||
- 会话质量指标
|
||
- signaling 摘要
|
||
- route 切换记录
|
||
- 调试日志
|
||
- 会话终态
|
||
|
||
### 开发周期
|
||
|
||
**1 - 3 周**
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 热状态 | Redis |
|
||
| 持久化 | MySQL / PostgreSQL |
|
||
| 日志 | Loki / Elasticsearch |
|
||
| 指标 | Prometheus |
|
||
| 链路追踪 | OpenTelemetry |
|
||
|
||
### 数据建议
|
||
|
||
#### Redis
|
||
|
||
```text
|
||
session:{sessionId}:state
|
||
session:{sessionId}:participants
|
||
session:{sessionId}:route
|
||
session:{sessionId}:quality
|
||
device:{deviceId}:online
|
||
device:{deviceId}:capability
|
||
```
|
||
|
||
#### MySQL
|
||
|
||
- `realtime_session`
|
||
- `realtime_session_event`
|
||
- `realtime_quality_report`
|
||
- `realtime_route_switch`
|
||
- `device_online_log`
|
||
|
||
### 难点
|
||
|
||
- 热状态和持久化状态一致性
|
||
- 会话结束后的资源清理
|
||
- 日志量较大
|
||
- 敏感数据脱敏
|
||
|
||
### 注意事项
|
||
|
||
- Redis key 必须设置 TTL。
|
||
- signaling 内容不建议完整长期保存,只保存必要摘要。
|
||
- 质量数据可以采样,不要无限写入。
|
||
- 终态必须落库,便于审计和问题排查。
|
||
- 需要按 `sessionId` 能快速查完整链路。
|
||
|
||
---
|
||
|
||
## 13. `ai-gateway` 与 `xiaozhi_server` AI 旁路模块
|
||
|
||
### 模块定位
|
||
|
||
AI 不进入主通话状态机,而是旁路能力:
|
||
|
||
- 设备音频旁路到 AI
|
||
- APP AI 辅助模式
|
||
- AI 结果回传 `starlock`
|
||
- 不影响主对讲链路
|
||
|
||
### 开发周期
|
||
|
||
**2 - 4 周**
|
||
|
||
如果只是接入已有 `xiaozhi_server`,2 周左右。
|
||
如果需要实时音频流、唤醒词、语音识别、语音合成,4 周以上。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 网关语言 | Go / Python / Node.js |
|
||
| AI 服务 | xiaozhi_server |
|
||
| 音频协议 | WebSocket / RTP / HTTP streaming |
|
||
| 编码 | PCM / Opus / AAC |
|
||
| 鉴权 | 短期 token |
|
||
| 回调 | HTTP 到 `starlock` |
|
||
|
||
### 主要开发内容
|
||
|
||
- AI 会话创建
|
||
- 音频旁路接入
|
||
- AI 服务转发
|
||
- AI 结果回调
|
||
- 会话结束清理
|
||
- AI 异常不影响主通话
|
||
|
||
### 难点
|
||
|
||
- 音频格式转换
|
||
- 实时性要求
|
||
- AI 服务异常隔离
|
||
- 主通话和 AI 旁路资源竞争
|
||
- 隐私和权限控制
|
||
|
||
### 注意事项
|
||
|
||
- AI 不要阻塞主对讲链路。
|
||
- AI 失败不能导致视频通话失败。
|
||
- AI 音频采集要经过用户授权。
|
||
- AI 数据要做隐私合规处理。
|
||
- AI 事件要独立状态机,不能混入主通话状态机。
|
||
|
||
---
|
||
|
||
## 14. 运维部署与基础设施模块
|
||
|
||
### 模块定位
|
||
|
||
负责部署:
|
||
|
||
- BifroMQ
|
||
- `session-orchestrator`
|
||
- `device-bootstrap`
|
||
- coturn
|
||
- ZLMediaKit
|
||
- MQTT event worker
|
||
- Redis
|
||
- MySQL
|
||
- 日志、监控、告警
|
||
|
||
### 开发周期
|
||
|
||
**3 - 6 周**
|
||
|
||
MVP Docker Compose 1 - 2 周。
|
||
生产高可用部署 4 - 6 周。
|
||
|
||
### 技术栈
|
||
|
||
| 类型 | 技术 |
|
||
|---|---|
|
||
| 容器 | Docker |
|
||
| 编排 | Docker Compose / Kubernetes |
|
||
| 网关 | Nginx / Ingress |
|
||
| 证书 | Let's Encrypt / 企业证书 |
|
||
| 监控 | Prometheus + Grafana |
|
||
| 日志 | Loki / ELK |
|
||
| 追踪 | Jaeger / Tempo |
|
||
| CI/CD | GitLab CI / GitHub Actions |
|
||
| 配置 | ENV / Secret / ConfigMap |
|
||
|
||
### 难点
|
||
|
||
- BifroMQ 集群部署
|
||
- TURN 公网 IP 和端口规划
|
||
- ZLM 带宽和并发压力
|
||
- 日志量控制
|
||
- 多服务之间配置复杂
|
||
- 灰度和回滚
|
||
|
||
### 注意事项
|
||
|
||
- coturn 必须部署在公网可达节点。
|
||
- TURN UDP 端口范围要提前开放。
|
||
- ZLM 和 TURN 带宽要按峰值计算。
|
||
- 所有服务要有健康检查。
|
||
- 生产环境密钥不能写在配置文件仓库中。
|
||
- 日志要设置保留周期,避免磁盘被打满。
|
||
- 要准备一键回滚方案。
|
||
|
||
---
|
||
|
||
# 三、模块优先级建议
|
||
|
||
## P0:第一阶段必须完成
|
||
|
||
| 模块 | 说明 |
|
||
|---|---|
|
||
| `starlock` 会话入口 | APP 创建会话必须依赖 |
|
||
| `session-orchestrator` | 新实时系统核心 |
|
||
| `device-bootstrap` | 设备拿 MQTT 凭证 |
|
||
| BifroMQ | 发现、在线、信令 |
|
||
| APP MQTT + WebRTC 基础 | APP 端通话能力 |
|
||
| 设备 MQTT + WebRTC/ZLM 基础 | 设备端通话能力 |
|
||
| coturn | P2P 失败补位 |
|
||
| ZLMediaKit 基础转发 | 弱网和失败兜底 |
|
||
| `MQTT event worker` | 事件回调 |
|
||
| 基础监控日志 | 联调和上线必需 |
|
||
|
||
## P1:灰度上线前建议完成
|
||
|
||
| 模块 | 说明 |
|
||
|---|---|
|
||
| 完整 ACK / 超时 / 重试 | 提升状态一致性 |
|
||
| 质量指标上报 | 支撑动态选路 |
|
||
| 动态 route switch | P2P / TURN / ZLM 切换 |
|
||
| 会话追踪 | 定位问题 |
|
||
| ZLM hook 鉴权 | 防止盗流 |
|
||
| TURN 临时凭证 | 安全必需 |
|
||
| 异常恢复 | 网络切换、断线重连 |
|
||
| 压测和弱网测试 | 上线前必需 |
|
||
|
||
## P2:后续增强
|
||
|
||
| 模块 | 说明 |
|
||
|---|---|
|
||
| AI 旁路 | 不影响主链路,可后置 |
|
||
| 自研 media-relay | 如 ZLM 不满足再考虑 |
|
||
| 高级网络评分模型 | 根据数据逐步优化 |
|
||
| 多区域接入 | 用户量上来后再做 |
|
||
| 完整录像 / 云存储 | 按业务套餐推进 |
|
||
|
||
---
|
||
|
||
# 四、关键技术难点总结
|
||
|
||
## 1. 控制面和媒体面解耦
|
||
|
||
难点不是画架构,而是实现时防止耦合:
|
||
|
||
- `session-orchestrator` 不能直接处理视频流
|
||
- BifroMQ 不能传大媒体
|
||
- `starlock` 不能变成实时状态机
|
||
- ZLM 不能承载业务权限判断
|
||
|
||
正确边界是:
|
||
|
||
```text
|
||
starlock:业务权限
|
||
session-orchestrator:会话状态机
|
||
BifroMQ:信令和事件通道
|
||
WebRTC/ZLM/TURN:媒体链路
|
||
event worker:异步事件处理
|
||
```
|
||
|
||
---
|
||
|
||
## 2. 会话状态一致性
|
||
|
||
这是整个方案最大的工程难点之一。
|
||
|
||
必须解决:
|
||
|
||
- APP 发起了但设备没收到
|
||
- 设备 accept 了但 APP 已取消
|
||
- MQTT 重连导致重复消息
|
||
- WebRTC 连上但云端状态还是 connecting
|
||
- P2P 断了但双方状态不一致
|
||
- 会话结束后资源没释放
|
||
|
||
建议所有状态变化都通过 `session-orchestrator` 收敛。
|
||
|
||
---
|
||
|
||
## 3. 媒体动态选路
|
||
|
||
动态选路不要一开始做得太复杂。
|
||
|
||
建议第一版策略:
|
||
|
||
```text
|
||
默认尝试 P2P
|
||
-> ICE 失败或超时,切 TURN
|
||
-> TURN 仍失败,切 ZLMediaKit
|
||
-> ZLMediaKit 失败,提示通话失败或走旧 relay
|
||
```
|
||
|
||
弱网优化版再做:
|
||
|
||
```text
|
||
根据 RTT、丢包、jitter、candidate type、带宽评估是否提前切 ZLM
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 设备端复杂度
|
||
|
||
设备端是高风险点。
|
||
|
||
尤其要确认:
|
||
|
||
- 芯片性能是否支撑 WebRTC
|
||
- 是否有硬编 H.264
|
||
- 是否支持 Opus / AAC
|
||
- 是否支持 TLS
|
||
- 是否支持 MQTT 长连接
|
||
- 摄像头和麦克风资源是否可同时给 WebRTC 和 AI
|
||
- 固件 OTA 是否方便灰度
|
||
|
||
如果设备 WebRTC 成本过高,建议:
|
||
|
||
```text
|
||
第一阶段:设备 -> ZLMediaKit,APP -> ZLMediaKit
|
||
第二阶段:中高端设备支持 WebRTC P2P
|
||
```
|
||
|
||
---
|
||
|
||
## 5. BifroMQ 权限和 topic 设计
|
||
|
||
MQTT topic 一旦上线后修改成本较高。
|
||
|
||
建议提前确定:
|
||
|
||
- topic 命名规范
|
||
- tenant 隔离
|
||
- device 隔离
|
||
- session 隔离
|
||
- QoS 策略
|
||
- retained 使用策略
|
||
- LWT 设备离线策略
|
||
- ACL 权限模型
|
||
|
||
---
|
||
|
||
# 五、上线前必须注意的点
|
||
|
||
## 1. 安全
|
||
|
||
必须做好:
|
||
|
||
- MQTT TLS
|
||
- MQTT ACL
|
||
- 短期 token
|
||
- TURN 临时账号
|
||
- ZLM 播放 / 推流鉴权
|
||
- 设备密钥不能明文泄露
|
||
- 日志脱敏
|
||
|
||
---
|
||
|
||
## 2. 可观测性
|
||
|
||
至少要能按 `sessionId` 查到:
|
||
|
||
- 谁发起
|
||
- 哪个设备
|
||
- 哪个 APP
|
||
- 设备是否在线
|
||
- invite 是否送达
|
||
- accept 是否收到
|
||
- offer/answer 是否完成
|
||
- ICE 是否成功
|
||
- 使用了 P2P / TURN / ZLM / relay 哪条链路
|
||
- 失败原因是什么
|
||
- 最终状态是什么
|
||
|
||
否则后期排查会非常痛苦。
|
||
|
||
---
|
||
|
||
## 3. 弱网和异常测试
|
||
|
||
必须覆盖:
|
||
|
||
- APP 4G / WiFi 切换
|
||
- 设备断网重连
|
||
- MQTT 断线重连
|
||
- TURN 不可用
|
||
- ZLM 不可用
|
||
- BifroMQ 重启
|
||
- `session-orchestrator` 重启
|
||
- APP 杀进程
|
||
- 设备重复上线
|
||
- 双端同时挂断
|
||
- 多个 APP 同时呼叫同一把锁
|
||
|
||
---
|
||
|
||
## 4. 资源和成本
|
||
|
||
需要重点评估:
|
||
|
||
| 资源 | 风险 |
|
||
|---|---|
|
||
| TURN | 带宽成本高 |
|
||
| ZLMediaKit | 中心转发带宽和 CPU 压力 |
|
||
| BifroMQ | 长连接数量 |
|
||
| Redis | 会话状态和 TTL 清理 |
|
||
| 日志系统 | signaling 和质量上报可能量很大 |
|
||
| MySQL | 会话事件写入频率 |
|
||
|
||
---
|
||
|
||
# 六、推荐的第一阶段 MVP 范围
|
||
|
||
第一阶段不要一次性做太满,建议 MVP 范围如下:
|
||
|
||
## 必做
|
||
|
||
- `starlock` 创建会话 API
|
||
- `session-orchestrator` 独立服务
|
||
- BifroMQ 接入
|
||
- APP MQTT over WSS
|
||
- 设备 MQTT/TLS
|
||
- 基础 invite / accept / reject / hangup
|
||
- WebRTC P2P 基础链路
|
||
- coturn 兜底
|
||
- ZLMediaKit 兜底链路
|
||
- 基础质量上报
|
||
- 基础会话日志
|
||
- 事件 worker 回调 `starlock`
|
||
|
||
## 暂缓
|
||
|
||
- AI 深度集成
|
||
- 自研 media-relay
|
||
- 复杂无感切路
|
||
- 多区域部署
|
||
- 高级网络评分模型
|
||
- 全量录像和云存储
|
||
- 复杂套餐计费联动
|
||
|
||
---
|
||
|
||
# 七、建议的里程碑排期
|
||
|
||
## 第 1 - 2 周:协议和架构落地
|
||
|
||
- 确定 API 文档
|
||
- 确定 MQTT topic
|
||
- 确定状态机
|
||
- 确定 route 策略
|
||
- 确定设备 capability schema
|
||
- 搭建 BifroMQ、coturn、ZLM 测试环境
|
||
|
||
## 第 3 - 6 周:控制面 MVP
|
||
|
||
- `session-orchestrator`
|
||
- `device-bootstrap`
|
||
- `starlock` 会话入口
|
||
- APP MQTT
|
||
- 设备 MQTT
|
||
- invite / accept / hangup 跑通
|
||
|
||
## 第 7 - 10 周:媒体链路 MVP
|
||
|
||
- WebRTC P2P
|
||
- TURN
|
||
- ZLM 推拉流
|
||
- APP 与设备完整通话
|
||
- 失败后切换到 ZLM
|
||
|
||
## 第 11 - 14 周:稳定性和可观测
|
||
|
||
- ACK / retry / timeout 完善
|
||
- 质量上报
|
||
- 会话追踪
|
||
- 事件 worker
|
||
- 日志和监控
|
||
- 弱网测试
|
||
|
||
## 第 15 - 16 周:灰度上线
|
||
|
||
- 小范围设备灰度
|
||
- 问题收集
|
||
- 性能压测
|
||
- 回滚方案
|
||
- 运维文档
|
||
|
||
---
|
||
|
||
# 八、最终建议
|
||
|
||
这个架构方向是合理的,关键是第一阶段要控制范围。
|
||
|
||
我建议优先落地这条主链路:
|
||
|
||
```text
|
||
APP
|
||
-> starlock
|
||
-> session-orchestrator
|
||
-> BifroMQ signaling
|
||
-> 设备
|
||
-> WebRTC P2P / TURN
|
||
-> 失败后 ZLMediaKit
|
||
```
|
||
|
||
同时把 AI、自研 relay、高级动态选路放到第二阶段。
|
||
|
||
最需要重点投入的模块是:
|
||
|
||
1. `session-orchestrator` 状态机
|
||
2. BifroMQ topic / ACL / token 设计
|
||
3. APP 与设备端 WebRTC 联调
|
||
4. ZLMediaKit 弱网兜底
|
||
5. 会话日志与问题追踪
|
||
|
||
如果这 5 个点做好,后续 AI、录像、套餐、计费、多区域扩容都可以逐步叠加。 |