238 lines
8.2 KiB
Markdown
238 lines
8.2 KiB
Markdown
# fpv-relay (C++)
|
||
|
||
OpenIPC / wfb-ng 数字图传的地面端程序。单个进程完成无线采集、解密、转发、录制、RTSP 输出
|
||
和遥测中继,并提供 Qt 图形界面。
|
||
|
||
天空端固定参数(PixelPilot / DigitalFPV):`link_id=7669206`,视频 `radio_port=0`,
|
||
mavlink 下行 `radio_port=0x10`,上行 `radio_port=160`,`epoch=0`,密钥 `gs.key`。
|
||
|
||
## 功能
|
||
|
||
- 采集:内嵌 wfb-ng。Linux 用 pcap + monitor 网卡,Windows 用 devourer(用户态 USB 驱动)。
|
||
解密后的 RTP 直接回调到转发层,不经过外部 `wfb_rx` 进程和本地 UDP 回环。
|
||
- 转发:每路可配多个 `forward` 目标,裸 RTP/UDP 原样直推。
|
||
- 录制:把 H265 还原成 Annex-B 裸流,按时间或大小分片。
|
||
- RTSP:TCP interleaved 与 UDP 两种传输,H265 单轨,支持多客户端。
|
||
- 遥测:接收天空端 mavlink 下行(`radio_port 0x10`)转发给本机 QGC;
|
||
上行 mavlink/遥控经 wfb_tx 注入无线。
|
||
- 状态页:HTTP `/`、`/status`、`/metrics`。
|
||
- 图形界面:Qt Quick + FluentUI,多路状态卡片、实时预览、设置、录像回放。
|
||
|
||
## 平台支持
|
||
|
||
| 功能 | Linux | Windows |
|
||
|---|---|---|
|
||
| 无线采集 | pcap + monitor 网卡 | devourer(USB,需 WinUSB 驱动) |
|
||
| 上行 wfb_tx | AF_PACKET 注入 | devourer(USB) |
|
||
| 转发 / 录制 / RTSP / 状态页 | 支持 | 支持 |
|
||
| GUI 预览 | ffmpeg | ffmpeg |
|
||
|
||
Windows 上的无线采集和上行需要先用 [Zadig](https://zadig.akeo.ie/) 把 RTL8812AU 的驱动
|
||
替换为 WinUSB(一次性操作),之后该网卡专供本程序使用。
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
CMakeLists.txt / CMakePresets.json
|
||
3rd/ 第三方库(yaml-cpp / spdlog / CLI11 / FluentUI / wfb-ng / devourer)
|
||
以及 Windows 运行依赖(win-deps = libusb+sodium,ffmpeg)
|
||
src/
|
||
common/ 日志、跨平台网络兼容层
|
||
config/ YAML 配置解析
|
||
capture/ 采集抽象、wfb(pcap/USB)、udp 采集、射频设置、USB 上行
|
||
relay/ 数据流、UDP 转发、DVR、H265 解包
|
||
rtsp/ status/ RTSP 输出、HTTP 状态页
|
||
gui/ Qt Quick + FluentUI 界面、ffmpeg 预览
|
||
config.example.yaml Linux 示例配置
|
||
config.windows.example.yaml Windows 示例配置
|
||
packaging/ 打包脚本
|
||
```
|
||
|
||
## 依赖
|
||
|
||
编译需要 CMake ≥ 3.16、C++20 编译器、pkg-config。
|
||
|
||
Linux:
|
||
- `libsodium-dev`、`libpcap-dev`
|
||
- 运行期 `iw`、`nmcli`、`ffmpeg`;采集需要 root,或对程序执行
|
||
`setcap cap_net_raw,cap_net_admin+eip`
|
||
|
||
```bash
|
||
sudo apt install build-essential cmake pkg-config libsodium-dev libpcap-dev ffmpeg
|
||
```
|
||
|
||
Windows(MinGW):
|
||
- Qt6、Ninja
|
||
- 无线采集与预览所需的 `libusb-1.0`、`libsodium`、`ffmpeg.exe` 已随仓库 vendored
|
||
(`3rd/win-deps`、`3rd/ffmpeg`),无需额外安装
|
||
- devourer(用户态 USB 驱动)已 vendored 在 `3rd/devourer`
|
||
- Qt 安装路径写在 `CMakePresets.json` 的 `windows-base`(默认 `E:/QT6.6.3/6.6.3/mingw_64`),按需修改
|
||
|
||
## 构建
|
||
|
||
Linux(Qt 路径通过环境变量 `QT_PREFIX` 指定):
|
||
|
||
```bash
|
||
export QT_PREFIX=$HOME/Qt6.3/6.6.3/gcc_64
|
||
cmake --preset linux-cli && cmake --build --preset linux-cli -j$(nproc)
|
||
cmake --preset linux-gui && cmake --build --preset linux-gui -j$(nproc)
|
||
```
|
||
|
||
Windows(PowerShell,Qt 路径已在 `CMakePresets.json` 里配置好,直接构建即可):
|
||
|
||
```powershell
|
||
cmake --preset windows-cli ; cmake --build --preset windows-cli
|
||
cmake --preset windows-gui ; cmake --build --preset windows-gui
|
||
```
|
||
|
||
> Qt 不在默认位置时,改 `CMakePresets.json` 里 `windows-base` 的 `FPC_QT_PREFIX`,
|
||
> 或直接传 `-DFPC_QT_PREFIX=<你的 Qt 路径>`。
|
||
|
||
可执行文件和运行期依赖(DLL、ffmpeg、Qt 运行库、示例配置、`gs.key`)会统一汇总到
|
||
`<build>/dist/`。Windows 打包可用 `.\packaging\build-win.ps1 -Gui`。
|
||
|
||
> Windows 上构建目录路径不能包含空格,否则 FluentUI 的版本资源编译会失败。
|
||
|
||
## 运行
|
||
|
||
```bash
|
||
# wfb 无线采集需要 root(设置 monitor 模式 / 打开 pcap)
|
||
sudo ./build/dist/fpv-relay -c config.yaml -v
|
||
```
|
||
|
||
每 5 秒打印一次各路统计。wfb 采集输出 `收包/数据/会话/解密错误/丢包/转发`。
|
||
|
||
## 配置
|
||
|
||
```yaml
|
||
captures:
|
||
- name: drone1
|
||
type: wfb # wfb 无线采集,或 udp 输入
|
||
iface: wfb0
|
||
key: /path/to/gs.key
|
||
link_id: 7669206 # channel_id = (link_id << 8) + radio_port
|
||
radio_port: 0
|
||
epoch: 0
|
||
channel: 161
|
||
bandwidth: HT20
|
||
region: BO
|
||
codec: h265
|
||
forward:
|
||
- "127.0.0.1:5700" # 本机低延迟播放口
|
||
- "192.168.1.50:5600" # 局域网接收端
|
||
```
|
||
|
||
Windows 用 `usb_vid` / `usb_pid` 指定网卡(见 `config.windows.example.yaml`),`iface` 可省略。
|
||
|
||
### 多卡
|
||
|
||
`captures` 里写多个 `type: wfb` 条目,每块卡用不同的 `iface`,即可同时收多路,各自的
|
||
`key` / `link_id` / `channel` / `forward` 相互独立。
|
||
|
||
多张同型号卡建议固定网卡名,否则开机时可能互换。可用 systemd `.link` 按 USB 物理端口
|
||
命名为 `wfb0` / `wfb1`(见 `tools/udev/README.md`)。
|
||
|
||
## 图形界面
|
||
|
||
界面基于 FluentUI + Qt 6.6。功能包括配置加载、启动/停止、多路状态卡片、实时日志、
|
||
深浅色切换、单路/多路实时预览、录像列表与回放。
|
||
|
||
预览由内置 RTSP 输出配合 ffmpeg 实现:程序始终在本地启动 RTSP 服务,预览窗口调用
|
||
`ffmpeg` 拉取 `rtsp://127.0.0.1:<port>/<name>` 并解码绘制,H264/H265 均可。预览需要先“启动”。
|
||
|
||
```bash
|
||
export QT_PREFIX=$HOME/Qt6.3/6.6.3/gcc_64
|
||
cmake --preset linux-gui && cmake --build --preset linux-gui -j$(nproc)
|
||
sudo ./build-gui/dist/fpv-relay-gui
|
||
```
|
||
|
||
接收端播放(低延迟 UDP 直推):
|
||
|
||
```bash
|
||
tools/play-udp.sh 5700 h265
|
||
```
|
||
|
||
## 上行链路
|
||
|
||
在配置里加 `uplink` 段,程序会内嵌 wfb-ng 的 wfb_tx,把本地收到的 mavlink/遥控经同一张
|
||
网卡注入无线发给天空端:
|
||
|
||
```yaml
|
||
uplink:
|
||
- enabled: true
|
||
iface: wfb0
|
||
key: /path/to/gs.key
|
||
link_id: 7669206
|
||
radio_port: 160 # 需与天空端 wfb_rx 一致
|
||
channel: 161
|
||
bandwidth: 20
|
||
mcs_index: 1
|
||
fec_k: 2
|
||
fec_n: 4
|
||
udp_port: 14551 # QGC/MAVProxy 把 mavlink 发到这里
|
||
```
|
||
|
||
然后让 QGroundControl / MAVProxy 把上行 mavlink 发到 `udp://127.0.0.1:14551`。
|
||
`radio_port` / `link_id` / 信道 / key 必须与天空端一致。
|
||
|
||
### 遥测下行
|
||
|
||
在采集路里加 `mavlink` 段,程序会另开一个接收流并把解出的 mavlink 转发给本机 QGC:
|
||
|
||
```yaml
|
||
mavlink:
|
||
enabled: true
|
||
radio_port: 16 # 0x10
|
||
target: "127.0.0.1:14550" # QGC 监听
|
||
```
|
||
|
||
需要天空端确实在发该流的 mavlink 数据。日志里出现 `SESSION` 表示会话已建立。
|
||
|
||
## 状态监控
|
||
|
||
```yaml
|
||
status:
|
||
enabled: true
|
||
address: ":8080"
|
||
```
|
||
|
||
- `http://<本机>:8080/` 状态面板
|
||
- `http://<本机>:8080/status` JSON
|
||
- `http://<本机>:8080/metrics` Prometheus 指标
|
||
|
||
字段:`online`、`recv`、`forwarded`、`session`(≥1 表示密钥配对成功)、`decErr`、`lost`。
|
||
也可用 `-s :8080` 临时开启。
|
||
|
||
## DVR 录制
|
||
|
||
```yaml
|
||
record:
|
||
enabled: true
|
||
dir: records # 录制根目录,其下按路名建子目录
|
||
segment_seconds: 300 # 分片时长
|
||
segment_mb: 0 # 分片大小上限(MB,0 不限)
|
||
```
|
||
|
||
文件形如 `records/drone1/drone1_20260910_210000.h265`。GUI 里可列出录像、回放,
|
||
并调用 ffmpeg 转封装为 MP4;录制也可通过卡片右键菜单动态开关。
|
||
|
||
## RTSP 输出
|
||
|
||
```yaml
|
||
rtsp:
|
||
enabled: true
|
||
address: ":8554"
|
||
udp_base: 8000
|
||
```
|
||
|
||
拉流地址:`rtsp://<本机>:8554/<name>`。支持 TCP interleaved 与 UDP、H265 单轨、多客户端,
|
||
SDP 带 sprop-vps/sps/pps,并发送 RTCP SR。低延迟场景仍建议用 `forward` 的 UDP 直推。
|
||
|
||
## 说明
|
||
|
||
- 采集端按 radiotap 的正确偏移过滤,只放行本路 `WB` + channel_id 的帧,并抑制会话建立前
|
||
的解密失败日志;正常运行时 `解密错误` 应为 0 或极少。
|
||
- 预览的延迟以 `forward` 的 UDP 直推为准。GUI 预览走 RTSP + ffmpeg,已做低延迟调参,
|
||
但不显示“延迟 ms”数值。
|
||
- Windows 不支持内核 monitor 驱动,无线采集/上行由 devourer 在用户态完成,需 WinUSB 驱动。
|