feat: 链路控制、延迟校准与长测工具,补全文档
- 固件:新增 link_control / stream_control,覆盖运行中 Wi-Fi 断线恢复、取帧节拍、 温控与质量/帧率减载;UDP 发送增加有界重试预算与帧期限,PSRAM JPEG 直发减少拷贝。 - 协议:重组器严格校验分片布局,统计未收齐、超时与完全缺失的帧,处理帧号回绕与设备重启。 - 桌面端:视频改 latest-value 通道并前置帧时间标记,拒绝积压和慢解码的过期画面;新增 延迟标记页与 --latency-report 校准,完善录制、服务端与退出流程。 - 文档与脚本:新增硬件、开发、延迟、功耗、实时性、稳定性文档和改动记录,重写根 README; 新增构建、性能、延迟与串口长测脚本,以及长测客户端脚本。 - 构建:固定 esp-1.97.0.0 工具链,分区表随构建复制,更新 sdkconfig 与忽略规则。
This commit is contained in:
+47
-12
@@ -12,8 +12,8 @@
|
||||
|
||||
```text
|
||||
desktop/
|
||||
core/ cam-core:不含任何界面与 Tauri 的东西(80 个测试)
|
||||
src-tauri/ Tauri 后端:推流、命令、录制(30 个测试)
|
||||
core/ cam-core:不含任何界面与 Tauri 的东西(83 个测试)
|
||||
src-tauri/ Tauri 后端:推流、命令、录制(32 个测试)
|
||||
src/ React 前端:两套页面 + HUD
|
||||
src/lib/ IPC 封装、WebSocket 客户端、状态存储、格式化
|
||||
src/components/ 视频窗格、血条、胜负横幅、瞄准器、装甲板表、队名编辑、录制面板、设置抽屉
|
||||
@@ -27,16 +27,37 @@ cd desktop
|
||||
pnpm install
|
||||
pnpm app # = tauri dev:起 vite + 编 Rust + 开窗口
|
||||
pnpm build # 只构建前端(tsc --noEmit && vite build)
|
||||
pnpm tauri build # 出 .app 与 .dmg
|
||||
pnpm tauri build # 默认打包 macOS 的 .app 与 .dmg;Windows 见下文
|
||||
```
|
||||
|
||||
下面两条是 Rust 侧,用它验证不依赖窗口的部分:
|
||||
|
||||
```sh
|
||||
cd desktop/core && cargo test # 80
|
||||
cd desktop/src-tauri && cargo test # 30,其中几条真的会起 ffmpeg
|
||||
cd desktop/core && cargo test # 83
|
||||
cd desktop/src-tauri && cargo test # 32,其中几条真的会起 ffmpeg
|
||||
```
|
||||
|
||||
### Windows x64 构建
|
||||
|
||||
需要 Node.js 22.12+(或 24)、pnpm 12、Rust stable MSVC,以及 Visual Studio Build Tools 的 C++ 桌面开发组件和 Windows SDK。应用窗口使用 WebView2 Runtime。
|
||||
|
||||
在 `desktop/` 中执行:
|
||||
|
||||
```powershell
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm tauri build --target x86_64-pc-windows-msvc --bundles nsis --ci -- --locked --config 'unstable.build-std=[]'
|
||||
```
|
||||
|
||||
`--target` 覆盖本目录原来的 macOS target,`--bundles nsis` 选择 Windows 安装包;末尾的 Cargo 参数清空从根固件项目继承的 `build-std`。
|
||||
|
||||
- 程序:`src-tauri/target/x86_64-pc-windows-msvc/release/cam-desktop.exe`。
|
||||
- 安装包:同一 release 目录下的 `bundle/nsis/*-setup.exe`。
|
||||
- 核心测试:进入 `core/` 后运行 `cargo +stable test --locked --target x86_64-pc-windows-msvc --config 'unstable.build-std=[]'`。
|
||||
|
||||
视频录制另需可从 `PATH` 找到的 `ffmpeg`,也可以在配置的 `[recording] ffmpeg` 中指定路径;基础图传显示不依赖它。
|
||||
|
||||
设备发现使用板卡的 Hello 广播;客户端除广播订阅外,还会按已发现设备的 IP 定向续订。Windows 开启 VPN / 虚拟网卡时,全局广播可能走虚拟接口;定向续订可避免“能发现并绑定,但始终等待画面”的情况。队伍端的绑定和画面过滤仍然生效。
|
||||
|
||||
### 演示模式:没有板子也能把整条链路跑起来
|
||||
|
||||
```sh
|
||||
@@ -410,11 +431,13 @@ open 'http://127.0.0.1:1420/?preview=referee' # 裁判端(密码 1234)
|
||||
## 测试
|
||||
|
||||
```sh
|
||||
cd desktop/core && cargo test # 80:重组、发现、两道闸门、帧率窗口、槽位、配置、密码、胜负判定
|
||||
cd desktop/src-tauri && cargo test # 30:帧头布局、录制、截图、演示画面、命令行
|
||||
cd protocol && cargo test # 15
|
||||
cd desktop/core && cargo test # 83:重组、发现、两道闸门、帧率窗口、槽位、配置、密码、胜负判定
|
||||
cd desktop/src-tauri && cargo test # 32:帧头布局、录制、截图、演示画面、命令行
|
||||
cd protocol && cargo test # 20
|
||||
```
|
||||
|
||||
前端解码队列测试:在 `desktop/` 运行 `pnpm test:stream`,5 项测试覆盖慢解码时保留最新帧、多路独立处理、关闭清理、坏帧恢复与设备重启。它不替代实际 WebView 的画面验证。
|
||||
|
||||
三条值得单独说的:
|
||||
|
||||
- **录制**那条真的起 ffmpeg、喂 20 帧、停,然后用 `ffprobe` 读回帧数与分辨率。只断言"文件
|
||||
@@ -444,8 +467,11 @@ RUST_LOG=debug ./target/aarch64-apple-darwin/debug/cam-desktop | grep 'stream:'
|
||||
| `demo-*`(仅演示) | 合成协议数据报 | 走同一条真实路径 |
|
||||
| tokio 任务 | WebSocket 服务、5 Hz 快照 | 异步 IO |
|
||||
|
||||
跨线程只有两样东西:`Arc` 与广播通道。帧在接收线程里编码一次(16 字节头 + JPEG),
|
||||
所有界面共用同一份 `Bytes`。
|
||||
帧在接收线程里编码一次(16 字节头 + JPEG),所有界面共用同一份 `Bytes`。
|
||||
视频使用每路只保留最新帧的 watch 通道;状态与控制消息使用有序广播通道。
|
||||
前端每路最多保留一次正在进行的解码和一张最新待解码帧。
|
||||
|
||||
每张本地 JPEG 前增加 `frameTiming` 文本消息,包含同机后端发布时刻;JPEG 二进制头仍为 16 字节。前端在解码前后检查本机队列年龄,超过 100 ms 的待解码帧或解码结果直接释放,恢复后优先显示最新画面。后端不重放超过 100 ms 的缓存帧,本地视频 socket 写入超时后重连。旧版没有时间标记时仍支持 JPEG,但只能按 JS 收到时刻判断本地年龄。这些时间不能用于测量 ESP 到电脑的无线传输延迟。
|
||||
|
||||
## 已知限制与没做的
|
||||
|
||||
@@ -459,11 +485,20 @@ RUST_LOG=debug ./target/aarch64-apple-darwin/debug/cam-desktop | grep 'stream:'
|
||||
`ws://127.0.0.1:*`(端口是启动时随机分配的,写不死)。验证方式是"前端能不能连上后端"
|
||||
——见下面"测试"一节最后一条。
|
||||
- **证书与公证**没做,`.dmg` 只在本机可用。
|
||||
- 前端没有自动化测试。界面这一侧的验证手段是浏览器预览 + 真机运行;逻辑都在 `core/` 里
|
||||
有测试。
|
||||
- 前端已有解码队列测试;布局、实际 WebView 解码和画面显示仍需浏览器预览及真机运行验证。
|
||||
|
||||
## 排查
|
||||
|
||||
需要测量相机到客户端的整条链路时,使用裁判配置启动校准模式:
|
||||
|
||||
```powershell
|
||||
.\cam-desktop.exe --config .\referee.toml --latency-report .\latency-run.ndjson
|
||||
```
|
||||
|
||||
报告路径必须是新文件。让相机完整拍到左侧四个彩色角块,避开右侧回显,固定相机和窗口位置。标记每 50 ms 更新;程序沿正常接收、解码和 `VideoSurface` 绘制路径记录每个标记的首次有效回显,拒绝曝光混合而无法可靠解码的帧。NDJSON 包含相邻 rAF 夹定的时间、解码完成到画布绘制时间和标记分析耗时,不保存图像或配置。面板扫描和像素响应未测量,精确物理光学延迟需用高速相机复核。正常启动不运行标记识别;校准模式不会额外订阅一份 UDP 视频。
|
||||
|
||||
`pnpm test:latency` 验证标记边界、旋转/镜像、混合曝光拒绝及屏幕原色泛白情形。
|
||||
|
||||
| 现象 | 原因 |
|
||||
|---|---|
|
||||
| 起不来,提示绑不上 UDP 5600 | 同一端口上已经跑着另一个客户端(旧的 Slint 版或另一份本程序)。看 `~/.config/cam-desktop/startup-error.txt` |
|
||||
|
||||
Reference in New Issue
Block a user