# 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 | 码率 | 丢包 | 抖动 | |---|---|---|---|---|---|---| | 静止桌面 | | | | | | | | 视频播放 | | | | | | | | 拖动窗口 | | | | | | |