Orin 上用 DeepStream 跑多路检测
文章目录
- 1. 多路难点在哪
- 2. 多路的最小链路
- 3. 建议顺序:2 路 → 4 路,别直接 8 路
- 4. 开始前再确认一遍
- 5. 建议先做 2 路,再复制成 4 路
- 6. 四路最小配置示例
- 6.1 主配置:`ds_rtsp_multi4.txt`
- 6.2 推理配置:`pgie_config_multi.txt`
- 7. 跑起来后先看什么
- 8. 容量预估
- 9. 最常见的坑
- 10. 没桌面时怎么看多路结果
- 11. 多路通了以后再做什么
- 12. 跑通后可以对照这几条
- 13. 小结
摘要:单路 RTSP 检测通了之后,下一步通常是多路。很多人一上来就开 8 路,结果掉帧、花屏、OOM 一起来,最后分不清是网络、解码还是模型的问题。本文从 2 路扩到 4 路,把
source怎么加、batch-size怎么对齐、tiled-display怎么看、容量怎么估、常见坑怎么查说清楚。适合已经跑通单路 DeepStream 的人。
1. 多路难点在哪
单路通了,不等于多路只是“复制粘贴 source”。多路真正叠加的是这几件事:
- 每路都要解码
- streammux 要把多路合成 batch
- 推理要按 batch 吃进去
- OSD / 拼屏 / 编码出口也会跟着变重
- 网络带宽和摄像头抖动会互相拖累
所以多路不是“把 FPS 乘以路数”,而是整条链路的容量问题。DeepStream 的价值也在这里:它把多路合批这件事做成默认路径,而不是你自己用 OpenCV 开 N 个线程硬拼。
官方对deepstream-app多源和 streammux 的说明见:
- DeepStream Reference Application
- Gst-nvstreammux
一句话记住官方建议:streammux和primary-gie的batch-size,尽量等于输入路数。
2. 多路的最小链路
可以先这样理解:
多路 RTSP → 硬解码 → streammux 合批 → primary-gie 推理 → OSD → tiled-display / 落盘 / 推流
和单路相比,配置上多出来的核心只有三块:
| 变化点 | 单路 | 多路 |
|---|---|---|
| source | 只有[source0] | [source0]…[sourceN] |
| batch-size | 通常是 1 | 等于路数 |
| tiled-display | 可关 | 调试时建议开,方便一眼看齐 |
别的东西,比如模型路径、标签、OSD、功耗档,思路和单路一样。先别同时换模型、换分辨率、换推流,否则定位成本会翻倍。
3. 建议顺序:2 路 → 4 路,别直接 8 路
| 阶段 | 目标 | 先别做 |
|---|---|---|
| 2 路 | 证明合批和拼屏没问题 | 一上来改业务模型 |
| 4 路 | 看内存、温度、掉帧边界 | 同时开跟踪、二次网络、推流 |
| 再加路 | 按板型容量推进 | 掉帧还没定位就继续加 |
经验上:
- Orin Nano:先把 2~4 路 720p 稳住,再谈更高路数
- Orin NX:4~8 路比较常见,看模型和分辨率
- AGX Orin:路数余量更大,但网络和散热仍然会先卡你
具体上限别背“某型号一定能跑 N 路”。输入分辨率、编码格式、模型大小、interval、是否拼屏编码,都会改结论。
4. 开始前再确认一遍
单路那篇的前置条件这里都还成立。多路额外再确认:
cat/etc/nv_tegra_releasesudonvpmodel-qdeepstream-app--versiontegrastats然后:
- 每一路 RTSP 都能单独打开
不要在 DeepStream 里才发现第 3 路密码错了。 - 分辨率尽量先统一
例如都先按 1280×720 进 streammux,少留一个变量。 - 板子上别同时挂着重推理脚本
多路一开,资源争用会立刻放大。
单路验证命令还是先用:
gst-launch-1.0 rtspsrclocation="rtsp://相机地址"latency=200!rtph264depay!h264parse!avdec_h264!videoconvert!autovideosink每一路都过一遍,再进 DeepStream。
网络侧也建议先心里有个数。四路 1080p、每路大概 4~8 Mbps,交换机和 Orin 网口都未必是瓶颈,但 Wi-Fi 摄像头、跨网段录像机、共享带宽的交换机,经常会先把某一路拖死。多路掉帧时,先问一句:是四路一起慢,还是某一路先挂。
5. 建议先做 2 路,再复制成 4 路
如果你手里只有单路配置,最小改法是:
- 复制出
[source1],改 URI - 把
streammux.batch-size改成2 - 把
primary-gie.batch-size改成2 pgie里的batch-size同步改成2tiled-display开成rows=1 columns=2
2 路画面齐、perf 稳之后,再复制成 4 路。这一步看起来笨,但能把“合批逻辑错了”和“板子容量不够”分开。很多人直接从 1 跳到 8,最后日志一长串,不知道从哪一行看起。
batched-push-timeout也不要乱拧。直播源通常保留一个相对合理的超时(示意里是40000微秒量级),让 muxer 在等不满 batch 时也能往下推。设得太大,某一路卡住时整批更慢;设得太激进,又容易出现不完整 batch。第一次多路,先用 sample/单路附近的默认值,确认链路通了再微调。
6. 四路最小配置示例
下面给一个4 路 RTSP + 拼屏显示的最小思路。路径按你自己的环境改。
6.1 主配置:ds_rtsp_multi4.txt
[application] enable-perf-measurement=1 perf-measurement-interval-sec=5 [tiled-display] enable=1 rows=2 columns=2 width=1280 height=720 gpu-id=0 nvbuf-memory-type=0 [source0] enable=1 type=4 uri=rtsp://相机1地址 gpu-id=0 latency=200 cudadec-memtype=0 [source1] enable=1 type=4 uri=rtsp://相机2地址 gpu-id=0 latency=200 cudadec-memtype=0 [source2] enable=1 type=4 uri=rtsp://相机3地址 gpu-id=0 latency=200 cudadec-memtype=0 [source3] enable=1 type=4 uri=rtsp://相机4地址 gpu-id=0 latency=200 cudadec-memtype=0 [streammux] gpu-id=0 live-source=1 batch-size=4 batched-push-timeout=40000 width=1280 height=720 enable-padding=0 nvbuf-memory-type=0 [primary-gie] enable=1 gpu-id=0 batch-size=4 gie-unique-id=1 config-file=pgie_config_multi.txt nvbuf-memory-type=0 [osd] enable=1 gpu-id=0 border-width=2 text-size=12 text-color=1;1;1;1 text-bg-color=0.3;0.3;0.3;1 font=Serif show-clock=0 clock-x-offset=800 clock-y-offset=820 clock-text-size=12 clock-color=1;0;0;0 nvbuf-memory-type=0 [sink0] enable=1 type=2 sync=0 source-id=0 gpu-id=0 nvbuf-memory-type=0这里最容易写错的是:
source开了 4 路,但batch-size还停在 1streammux.batch-size和primary-gie.batch-size不一致tiled-display的rows * columns小于路数,看起来像少了一路live-source忘了开成 1
官方也明确说过:batch 设得比路数大或小,都可能把延迟搞怪。多路第一次,先对齐,再谈“优化”。
6.2 推理配置:pgie_config_multi.txt
[property] gpu-id=0 net-scale-factor=0.003921568627451 model-color-format=0 onnx-file=/home/ubuntu/models/yolov8n.onnx model-engine-file=/home/ubuntu/models/yolov8n_b4_fp16.engine labelfile-path=/home/ubuntu/models/labels.txt batch-size=4 network-mode=2 num-detected-classes=80 interval=0 gie-unique-id=1 process-mode=1 network-type=0 cluster-mode=2 maintain-aspect-ratio=1 symmetric-padding=1 [class-attrs-all] pre-cluster-threshold=0.25 nms-iou-threshold=0.45注意两点:
- engine 的 batch 最好和运行 batch 对齐
单路建出来的batch=1engine,拿去硬跑batch=4,轻则重建、重则报错或性能很差。多路第一次,建议在目标板上按目标 batch 重新建 engine。 interval是多路保命开关interval=0表示每帧都推推理。路数一多,先把它改成1或2(隔帧推理),往往比盲目换更大板子更快止血。
7. 跑起来后先看什么
deepstream-app-cds_rtsp_multi4.txt第一遍只盯四件事:
- 四路是不是都有画面
- 框是不是都在
- perf 打印是否大致平稳
tegrastats里内存和温度有没有顶满
建议另开一个终端:
tegrastats重点看:
| 观察项 | 正常时大概感觉 | 危险信号 |
|---|---|---|
| GPU | 有稳定占用 | 忽高忽低且画面卡 |
| RAM | 有余量 | 持续顶满、开始杀进程 |
| 温度 | 可控 | 持续高温后 FPS 明显掉 |
| 网络 | 各路延迟差不多 | 某一路长期拖后腿 |
多路场景里,最慢的那一路,常常决定整条链路的体感。所以别只看平均 FPS,也要看是不是某一路经常卡住。
8. 容量预估
现场一般按这个顺序压测:
- 单路 720p 稳住
- 2 路同配置
- 4 路同配置
- 再决定要不要升分辨率、加跟踪、开编码推流
每加一档,记一张表:
| 路数 | 输入 | 模型 | interval | 端到端 FPS 感觉 | 内存 | 温度 | 结论 |
|---|---|---|---|---|---|---|---|
| 1 | 720p | yolov8n | 0 | … | … | … | 基线 |
| 2 | 720p | yolov8n | 0 | … | … | … | … |
| 4 | 720p | yolov8n | 0 | … | … | … | … |
| 4 | 720p | yolov8n | 1 | … | … | … | … |
如果你发现:
- 2 路很好,4 路开始掉帧
先降分辨率、加interval,再怀疑板型不够 - 画面都在,但某一路长期黑屏
先查那路相机和网络,不要先改模型 - 一开拼屏编码推流就崩
先关输出编码,只保留检测链路,把瓶颈拆开
选型上可以粗看:
| 板型 | 多路检测常见起步 | 备注 |
|---|---|---|
| Orin Nano | 2~4 路轻量检测 | 内存和散热先卡你 |
| Orin NX | 4~8 路较常见 | 看模型和分辨率 |
| AGX Orin | 更高路数更从容 | 仍要算解码和出口 |
这是经验区间,不是承诺值。合同里的“支持 N 路”,一定要写清分辨率、码率、模型和是否实时编码。
还有一个实用取舍:业务不要求每帧都检时,优先加interval,而不是先换更大模型再硬扛。隔帧检测对很多门禁、通道、仓库巡检场景足够用,却能明显降低 GPU 和温度压力。真要“每路每帧”,再回头压分辨率、换更小模型,或者上更大内存的板型。
9. 最常见的坑
| 现象 | 多见原因 | 先查什么 |
|---|---|---|
| 只显示一路 | source 没全开,或 tile 行列不够 | enable、rows/columns |
| 起得来但很卡 | batch 不对、分辨率太大、interval=0 | batch-size、输入尺寸、interval |
| 某几路黑屏 | 那几路 RTSP 本身有问题 | 单独gst-launch |
| engine 报错/重建很久 | batch 和 engine 不匹配 | 按目标 batch 重建 |
| 跑一会内存涨 | 输出编码、泄漏、分辨率过大 | 先简化 sink,看tegrastats |
| 换板后全挂 | engine 不是本板生成 | 目标板重建 |
| 拼屏看着花 | 宽高和源不一致、padding 乱 | 统一 streammux 尺寸 |
还有一个很典型:单路 sample 很好,多路换成自己模型后全军覆没。这时优先查:
- parser 是否适配
num-detected-classes/ labels 是否对齐- 预处理是否和训练一致
- batch engine 是否在本机构建
DeepStream 不会替你自动修好 YOLO 适配问题。
排障时我习惯按层剥:
- 源:每路单独
gst-launch - 合批:
batch-size、live-source、tile 行列 - 推理:engine、labels、parser、
interval - 出口:显示 / 落盘 / 推流是否把整机拖垮
不要一上来同时改四层。多路日志本来就密,一次只动一个变量,定位会快很多。
10. 没桌面时怎么看多路结果
SSH 上去、没有显示器时,sink type=2往往不合适。多路调试可以先:
- 写文件
先确认四路都有框,再谈实时看。 - 只看 perf + 日志
先验证链路稳不稳,不急着盯画面。 - 后面再上 RTSP 出口
多路检测 + 多路再编码推流,是另一层复杂度。
第一次多路,我更建议:先拼屏本地看,或先落盘回看。一上来就“四路进、四路出再推平台”,出问题会很难拆。
11. 多路通了以后再做什么
到这一步,后面通常才有资格谈:
- 跟踪(tracker)
- 二次分类 / 属性网络
- 区域告警、落图、推消息
- Docker 固化与开机自启
- 评估要不要从 Nano/NX 升到 AGX,或以后看 Thor
顺序别反。业务逻辑堆上去之前,至少先证明:
- N 路能稳定进
- batch 推理能稳住
- 你知道掉帧时该降哪一档参数
12. 跑通后可以对照这几条
按上面从 2 路扩到 4 路之后,可以自己核对:
- 单路配置能不能平稳扩到多路,而不是靠重写一整套
batch-size是否和路数对齐,engine 是否按目标 batch 重建- 拼屏里各路画面、检测框是否都能一眼看清
- 掉帧时会不会先动
interval、分辨率、功耗档,而不是先怪模型 - 出问题时能不能按「源 → 合批 → 推理 → 出口」分层排查
这几条都过得去,多路就不再只是演示,而是可以拿去估板型、估容量了。
13. 小结
Orin 上多路 DeepStream,难点通常不在“再复制几个 source”,而在合批、容量和短板定位。先把 2 路、4 路按同一套配置跑稳,把batch-size、拼屏和tegrastats看懂,后面加跟踪和告警才没有问题。
