# DroneScrewServer RTSP 推流方案 - MediaMTX 部署指南
## 背景
FFmpeg 的 RTSP muxer 在 `listen` 模式下无法作为 RTSP 服务器供 VLC 等客户端主动拉流(`listen` 是等 TCP 连接,而 RTSP 协议需要服务器先监听 RTSP 握手)。因此采用 **mediamtx** 作为中转服务器。
## 架构
```
DroneScrewServer --推流--> mediamtx --拉流--> VLC/CtrlApp
(本地推送) (RTSP服务器) (局域网拉流)
rtsp://127.0.0.1:8554 监听 :8554 rtsp://板子IP:8554
```
## 部署步骤
### 1. 准备文件
将以下文件复制到板子上的 `/opt/dronescrew/` 目录(或你选择的目录):
```bash
SDK/mediamtx/arm64/mediamtx # mediamtx 可执行文件
GrabBagPrj/mediamtx_dronescrew.yml # mediamtx 配置文件
GrabBagPrj/start_mediamtx.sh # 手动启动脚本
```
### 2. 方法 A:手动启动(测试用)
```bash
cd /opt/dronescrew
chmod +x mediamtx start_mediamtx.sh
./start_mediamtx.sh
```
看到类似输出表示启动成功:
```
启动 mediamtx RTSP 服务器...
配置文件: /opt/dronescrew/mediamtx_dronescrew.yml
RTSP 端口: 8554
推流地址: rtsp://127.0.0.1:8554/live/dronescrew (DroneScrewServer 内部推流)
拉流地址: rtsp://<板子IP>:8554/live/dronescrew (VLC/CtrlApp 从外部拉流)
按 Ctrl+C 停止服务
[INFO] mediamtx v1.x.x
[INFO] RTSP server listening on :8554
```
### 3. 方法 B:systemd 开机自启(生产环境)
```bash
# 1. 复制文件
sudo mkdir -p /opt/dronescrew
sudo cp mediamtx mediamtx_dronescrew.yml /opt/dronescrew/
sudo chmod +x /opt/dronescrew/mediamtx
# 2. 安装 systemd service
sudo cp GrabBagPrj/mediamtx-dronescrew.service /etc/systemd/system/
# 3. 启用并启动服务
sudo systemctl daemon-reload
sudo systemctl enable mediamtx-dronescrew.service
sudo systemctl start mediamtx-dronescrew.service
# 4. 查看状态
sudo systemctl status mediamtx-dronescrew.service
# 5. 查看实时日志
sudo journalctl -u mediamtx-dronescrew.service -f
```
### 4. 验证
#### 启动 DroneScrewServer
```bash
cd /opt/dronescrewserver
./DroneScrewServer
```
DroneScrewServer 启动后会自动推流到 `rtsp://127.0.0.1:8554/live/dronescrew`。
#### 用 VLC 拉流测试
在 PC 上打开 VLC,媒体 → 打开网络串流,输入:
```
rtsp://192.168.10.30:8554/live/dronescrew
```
(将 `192.168.10.30` 替换为板子的实际 IP)
应该能看到实时视频流(1920×1080, 30fps, H.264)。
#### 用 ffplay 测试
```bash
ffplay -rtsp_transport tcp rtsp://192.168.10.30:8554/live/dronescrew
```
## 配置说明
### mediamtx_dronescrew.yml
- **端口**:8554(RTSP 标准端口)
- **认证**:无(局域网内部使用,允许任何 IP 推流/拉流)
- **传输方式**:TCP(更稳定,适合工业环境)
- **路径**:`/live/dronescrew`
如需修改端口或路径:
1. 修改 `mediamtx_dronescrew.yml` 中的 `rtspAddress`
2. 同步修改 DroneScrewServer 配置文件中的 RTSP 端口和路径
### DroneScrewServer 配置
`config/config.xml` 中的 RTSP 相关配置:
```xml
8554
/live/dronescrew
```
代码已经硬编码 `rtspHost = "127.0.0.1"`(推到本地 mediamtx),无需额外配置。
## 故障排查
### 1. mediamtx 启动失败
**现象**:`./start_mediamtx.sh` 报错或立即退出
**检查**:
```bash
# 端口被占用?
sudo netstat -tulnp | grep 8554
# 如果有其他进程占用,kill 它或换个端口
# 权限问题?
ls -l mediamtx
chmod +x mediamtx
```
### 2. DroneScrewServer 推流失败
**现象**:日志显示 `avformat_write_header fail -111 (连接被拒绝)`
**检查**:
```bash
# mediamtx 是否在运行?
ps aux | grep mediamtx
sudo systemctl status mediamtx-dronescrew.service
# 端口是否监听?
sudo netstat -tulnp | grep 8554
```
### 3. VLC 拉流失败
**现象**:VLC 显示"无法打开 rtsp://..."
**检查**:
```bash
# DroneScrewServer 是否在推流?
# 查看 mediamtx 日志,应该有类似输出:
# [INFO] [rtsp] [conn 127.0.0.1:xxxxx] opened
# [INFO] [rtsp] [session ...] created by 127.0.0.1:xxxxx
# 防火墙是否阻止了 8554?
sudo iptables -L -n | grep 8554
# 如需开放:
sudo iptables -I INPUT -p tcp --dport 8554 -j ACCEPT
# 网络是否通?
ping 192.168.10.30
```
## 性能
- **延迟**:<100ms(mediamtx 中转延迟极低)
- **带宽**:~4Mbps(H.264 CBR,1920×1080@30fps)
- **CPU**:mediamtx 本身几乎不占 CPU(纯转发,不解码)
- **多客户端**:支持多个 VLC/CtrlApp 同时拉流(mediamtx 自动复制流)
## 后续优化(可选)
### 1. 开启 HTTPS(RTSPS)
修改 `mediamtx_dronescrew.yml`:
```yaml
rtspEncryption: optional # 或 strict
rtspServerCert: /opt/dronescrew/server.crt
rtspServerKey: /opt/dronescrew/server.key
```
生成自签名证书:
```bash
openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -days 365 -nodes
```
### 2. 添加认证
修改 `mediamtx_dronescrew.yml`:
```yaml
authInternalUsers:
- user: admin
pass: your_password_here
permissions:
- action: publish
- action: read
```
同时修改 DroneScrewServer 代码,在 `VrFFPushConfig` 中设置:
```cpp
pc.authUser = "admin";
pc.authPass = "your_password_here";
```
(当前 FFmpeg RTSP muxer 暂不支持 auth,需修改 `initRtspOutput` 添加 `av_dict_set(&opts, "rtsp_user", ...)` 等)
### 3. 录像
修改 `mediamtx_dronescrew.yml`:
```yaml
paths:
live_dronescrew:
record: true
recordPath: /opt/dronescrew/recordings/%Y-%m-%d_%H-%M-%S.mp4
```
## 代码改动总结
| 文件 | 改动 |
|------|------|
| `IVrFFMediaPusher.h` | `VrFFPushConfig` 增加 `rtspHost` 字段 |
| `CVrFFMediaPusher.h` | 去掉 `m_acceptThread` 和 `m_bStopAccept` |
| `CVrFFMediaPusher.cpp` | `initRtspOutput`: URL 改为 `rtsp://{host}:{port}{path}`
`Start`: 去掉线程,直接调用 `avformat_write_header`
`Stop`: 去掉 `join()`
`PushFrame`: 去掉等客户端逻辑 |
| `DroneScrewServerPresenter.cpp` | 配置中加 `pc.rtspHost = "127.0.0.1"` |
| `DroneScrewCtrlApp/main.cpp` | 增加 FFmpeg stub (`querystring` / `ff_log_level`) |
## 测试清单
- [x] mediamtx 单独启动成功
- [ ] DroneScrewServer 推流成功(日志无 -111 错误)
- [ ] VLC 从局域网拉流成功
- [ ] DroneScrewCtrlApp 拉流显示成功
- [ ] 停止推流后 mediamtx 正常释放连接
- [ ] 重启 DroneScrewServer 后能自动重连
## 参考
- MediaMTX 官方文档: https://github.com/bluenviron/mediamtx
- FFmpeg RTSP muxer: https://ffmpeg.org/ffmpeg-formats.html#rtsp