118 lines
5.4 KiB
Markdown
118 lines
5.4 KiB
Markdown
|
|
# B 侧设计文档(主控端 + 协议 + 网络)
|
|||
|
|
|
|||
|
|
> 负责人:成员 B | 主责 crate:`viewer/`、`common/` | 配合:A(agent/)
|
|||
|
|
> 按里程碑推进,每个里程碑独立 feature 分支,合入即打 tag。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## B1 · 联调基线(1-2 天,和 A 合作完成)
|
|||
|
|
|
|||
|
|
目标:拿到 H.264 版双机实测数据,作为一切优化的对照基线。
|
|||
|
|
|
|||
|
|
1. **HUD 扩展**:新增 丢包率(估算)/抖动(jitter)/帧间隔 p95 三项读数
|
|||
|
|
- 抖动 = 相邻帧 E2E 差值的绝对值 EMA;帧间隔 p95 用环形缓冲取 95 分位;
|
|||
|
|
- 码流异常计数(解码失败次数)也上 HUD,验证关键帧自愈是否生效。
|
|||
|
|
2. **测试脚本** `tools/bench.md`:固定三个场景各测 60s —— 静止桌面 / 播放视频 / 拖动窗口,记录 HUD 截图。
|
|||
|
|
3. **产出**:基线数据表填入本文件末尾。
|
|||
|
|
|
|||
|
|
## B2 · 码率自适应(3-4 天)
|
|||
|
|
|
|||
|
|
目标:弱网自动降码率保流畅,好网缓慢升码率提画质。
|
|||
|
|
|
|||
|
|
### 协议扩展(common/)
|
|||
|
|
|
|||
|
|
```rust
|
|||
|
|
/// B2 新增控制消息(流 2)
|
|||
|
|
RateReport {
|
|||
|
|
loss_permille: u16, // 接收端估算丢包率 ‰
|
|||
|
|
rtt_ms: u32, // 最近 RTT
|
|||
|
|
e2e_ms: u32, // 平滑后端到端延迟
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
viewer 每 2s 汇总一次发送(流 2 复用,无新增握手)。
|
|||
|
|
|
|||
|
|
### 控制算法(先简后精,AIMD 风格)
|
|||
|
|
|
|||
|
|
| 网络状态(连续 3 个周期) | 动作 |
|
|||
|
|
|---|---|
|
|||
|
|
| 丢包 > 8% 或 E2E > 400ms | 码率 ×0.6(下限 1Mbps),同时通知编码器降帧率到 20fps |
|
|||
|
|
| 丢包 3-8% | 码率 ×0.9 |
|
|||
|
|
| 丢包 < 1% 且 E2E < 150ms 持续 10s | 码率 +500Kbps 步进上探(上限 15Mbps) |
|
|||
|
|
|
|||
|
|
### agent 侧配合点(给 A 的接口需求)
|
|||
|
|
|
|||
|
|
- 需要运行时改码率的入口:优先查 openh264 crate 是否暴露 `SetOption(RC_PARAM)`;
|
|||
|
|
- 若 crate 不支持 → 方案 B:保留 encoder 实例但按新码率重建(重建成本 ~50ms,降码率不频繁,可接受);
|
|||
|
|
- 降级到极限(1Mbps 仍丢包 >15%)→ 主动降分辨率 1080p→720p(A 实现,协议传 `ResChange` 通知,viewer 重配解码器与窗口尺寸)。
|
|||
|
|
|
|||
|
|
## B3 · P2P 打洞 + 信令 + 中继(1.5-2 周,核心里程碑)
|
|||
|
|
|
|||
|
|
目标:跨公网可用。三层结构:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────┐ ①注册/交换地址(WebSocket) ┌──────────┐
|
|||
|
|
│ viewer │ ───────────────────────────→ │ 信令服务器 │
|
|||
|
|
└────┬────┘ └──────────┘
|
|||
|
|
│ ②拿到对方候选地址(IP:port×N) ↑
|
|||
|
|
│ ③a 直连(打洞) ──────────────────── agent 注册
|
|||
|
|
│ ③b 失败 → 走 TURN 中继
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 信令服务器(B 主建,A 参与评审)
|
|||
|
|
|
|||
|
|
- 最小实现:单二进制 Rust + WebSocket(tokio-tungstenite),无数据库;
|
|||
|
|
- 消息:`Register{agent_id}` / `Connect{agent_id}` / `Answer{candidates, auth_code_hint}`;
|
|||
|
|
- agent 开机注册自身 ID(设备码),viewer 输对方 ID 发起;
|
|||
|
|
- 中立服务器,不碰媒体数据,带宽成本 ≈ 0。
|
|||
|
|
|
|||
|
|
### 候选地址与打洞
|
|||
|
|
|
|||
|
|
1. agent 侧收集候选:本机局域网地址、路由器公网映射(STUN 探测,自建 coturn 的 stun 或公共 stun);
|
|||
|
|
2. 双方经信令交换候选后**同时**向对方发探测包(UDP 打洞,锥形 NAT 成功率高;对称 NAT 基本打不通);
|
|||
|
|
3. 打通 → 直连(QUIC 直接到该地址);打不通 → TURN 中继兜底。
|
|||
|
|
|
|||
|
|
### 中继方案(务实路线)
|
|||
|
|
|
|||
|
|
QUIC 本身没有标准 TURN 集成,两条路:
|
|||
|
|
- **路线一(推荐先做)**:自建中继服务 `relay` —— viewer 把 QUIC 包封装转发给 relay,relay 转给 agent(本质是应用层 TURN,复用信令服务器的部署);
|
|||
|
|
- **路线二(二期)**:coturn + 手写 ICE-lite,仅在路线一性能不足时投入。
|
|||
|
|
|
|||
|
|
### 安全(随 B3 一起做,替代现在的跳过校验)
|
|||
|
|
|
|||
|
|
- 预共享验证码升级为 **PAKE(SPAKE2)**:验证码不落服务器、不落网络,双方推导会话密钥;
|
|||
|
|
- 信令只传地址候选,媒体端到端加密保持 QUIC TLS 不变。
|
|||
|
|
|
|||
|
|
## B4 · 多屏 + 文件传输(各 2-3 天,穿插做)
|
|||
|
|
|
|||
|
|
**多屏**:
|
|||
|
|
- 协议:`ScreenList{screens: Vec<{id, w, h}>}`(AuthOk 里带)、`SelectScreen{id}`;
|
|||
|
|
- agent 枚举 DXGI outputs(A 实现),viewer 加屏幕切换下拉;
|
|||
|
|
- 第二期再做"多屏同显"。
|
|||
|
|
|
|||
|
|
**文件传输**:
|
|||
|
|
- 首选走已有 QUIC 连接开独立双向流(不引入 aria2 依赖,部署简单);
|
|||
|
|
- 协议:`FileOffer{name, size}` → `FileAccept` → 原始分块流(1MB 块 + 校验);
|
|||
|
|
- viewer 做拖拽发送 + 保存对话框。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 里程碑与分支规划
|
|||
|
|
|
|||
|
|
| 里程碑 | 分支 | 预估 | 验收标准 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| B1 联调基线 | feature/hud-baseline | 1-2 天 | 三场景基线数据入库 |
|
|||
|
|
| B2 码率自适应 | feature/rate-adapt | 3-4 天 | 模拟弱网(clumsy/丢包工具)下自动降码率,画面不断流 |
|
|||
|
|
| B3 打洞+中继 | feature/p2p-relay | 1.5-2 周 | 两台跨公网机器通过 ID 互联;打洞失败自动走中继 |
|
|||
|
|
| B4 多屏/文件 | feature/screens-files | 3-5 天 | 多屏切换、拖拽传文件可用 |
|
|||
|
|
|
|||
|
|
顺序建议:B1 → B2 → B3 → B4(B3 是价值最大项,B4 可穿插)。
|
|||
|
|
|
|||
|
|
## 基线数据表(B1 完成后填写)
|
|||
|
|
|
|||
|
|
| 场景 | FPS | RTT | E2E | 码率 | 丢包 | 抖动 |
|
|||
|
|
|---|---|---|---|---|---|---|
|
|||
|
|
| 静止桌面 | | | | | | |
|
|||
|
|
| 视频播放 | | | | | | |
|
|||
|
|
| 拖动窗口 | | | | | | |
|