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 把 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
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 指定):
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 里配置好,直接构建即可):
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 的版本资源编译会失败。
运行
# wfb 无线采集需要 root(设置 monitor 模式 / 打开 pcap)
sudo ./build/dist/fpv-relay -c config.yaml -v
每 5 秒打印一次各路统计。wfb 采集输出 收包/数据/会话/解密错误/丢包/转发。
配置
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 均可。预览需要先“启动”。
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 直推):
tools/play-udp.sh 5700 h265
上行链路
在配置里加 uplink 段,程序会内嵌 wfb-ng 的 wfb_tx,把本地收到的 mavlink/遥控经同一张
网卡注入无线发给天空端:
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:
mavlink:
enabled: true
radio_port: 16 # 0x10
target: "127.0.0.1:14550" # QGC 监听
需要天空端确实在发该流的 mavlink 数据。日志里出现 SESSION 表示会话已建立。
状态监控
status:
enabled: true
address: ":8080"
http://<本机>:8080/状态面板http://<本机>:8080/statusJSONhttp://<本机>:8080/metricsPrometheus 指标
字段:online、recv、forwarded、session(≥1 表示密钥配对成功)、decErr、lost。
也可用 -s :8080 临时开启。
DVR 录制
record:
enabled: true
dir: records # 录制根目录,其下按路名建子目录
segment_seconds: 300 # 分片时长
segment_mb: 0 # 分片大小上限(MB,0 不限)
文件形如 records/drone1/drone1_20260910_210000.h265。GUI 里可列出录像、回放,
并调用 ffmpeg 转封装为 MP4;录制也可通过卡片右键菜单动态开关。
RTSP 输出
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 驱动。