📱 你的实时视觉系统,已替你拆解好
用大白话说:这一页帮你搞懂「我这套系统到底在干嘛、为什么会卡、我之前调的那些参数有没有用」。
这一页是我替你做好的功课:把你那套 cpu_model_stream.py 系统,用大白话加图,从头讲到尾。
你出门在外,看这一页就够了,不用打开任何源码文件。
等你回家坐在电脑前,想对着代码看的时候,再去翻原文件也不迟。
你的系统其实就干一件事:
从网上接一路视频进来(比如无人机直播过来的画面),实时用 YOLO(说人话:一个专门认东西的 AI 模型)扫一遍,把认出来的东西用框圈起来,再把画面推回去给观众看。
同时它还会拉一个大模型来复核一下:「这个人到底戴没戴安全帽?」
下面我把整条链路、5 个同时在跑的线程、还有你最头疼的三个毛病(画面延迟 / 通道堵住 / 多路一起跑就卡),一次给你讲清楚。
这一页会冒出 NVENC / NVDEC / TensorRT / INT8 / FP16 这些吓人的词。
别慌,去 术语表 + 官方文档链接 那一页,每个词都有一句话的人话解释,还能直接跳去官方文档。
等你回家想改代码了,那一页也能帮你快速把概念捡回来。
一、一张图看懂整条链路
先看全景。一段视频从「网络那头」跑到「观众的屏幕上」,中间要过 7 道关。
图里的颜色是有讲究的:蓝色=正常干活的环节;黄色=最容易堵车的地方,你要盯紧它俩;绿色=在后台自己忙活、不挡道的分支。
把这 7 段配上人话,就是下面这样:
- ① 网络流:视频从摄像头或无人机那边,顺着网线过来了。
- ② 拉流 + 解码:把压缩过的视频包拆开,还原成一张张能看的图片。
现在这活是 CPU 干的,很费劲——这是第一个堵点。 - ③ 主线程读帧:程序伸手去拿这一张图。
拿不到就干等着,谁也别想动。 - ④ GPU 推理:把图交给显卡上的模型,让它认里面有什么。
不是每张都认,是每隔 N 张认一次。 - ⑤ 原始帧入队:图片排队等着被送出去。
队伍排满了就直接扔掉几张。 - ⑥ 推流线程编码:把图片重新压缩成视频,准备发出去。
这活也是 CPU 干的,更费劲——这是第二个堵点。 - ⑦ 观众看到视频:画面到达观众屏幕。
最下面那个绿色的分支,是画框、判断安全帽、叫大模型复核这些活。它们在旁边自己忙,不会挡住主流程。
二、其实是 5 个线程在同时跑
你可能以为程序是「一条线从头跑到尾」。其实不是。
它是 5 拨人在同时干活。线程(说人话:一个能独立干活的「小工」,几个小工可以同时开工)。
主线程是工头,负责拉视频和喊模型干活;剩下 4 个小工是它派出去的,各忙各的。
这 5 个小工分别干什么,看下面这张表:
| 哪个小工 | 它负责干啥 | 用的是 CPU 还是显卡 |
|---|---|---|
| 主线程 | 把视频拉进来、每隔 N 帧喊一次 YOLO、再把画面分给别人 | 读画面用 CPU,认东西用显卡 |
| 推流线程 | 把画面压缩成视频,发回去给观众看 | CPU 硬扛(很吃 CPU) |
| 绘制线程 | 把认出来的框画到画面上 | CPU |
| 富化线程 | 按几何位置判断「这人戴没戴安全帽」,顺便数人数 | CPU |
| 大模型线程池 | 把框里那一小块抠出来,拿给大模型问「这真的是个人吗」 | 显卡(最多同时问 2 个) |
三、你跑的到底是 TensorRT 还是 PyTorch?
这就是你之前一直纠结的量化(说人话:给模型「减肥」,让显卡跑得更快,代价是可能看得没那么准)问题。
结论我直接给你,你不用翻代码:
- 系统写得挺聪明,做了两手准备:机器上装了 TensorRT(说人话:英伟达出的加速工具,能把模型改造得跑更快)就用
.engine文件;没装就退回去用.pt文件跑 PyTorch。
这个设计本身没毛病。 - 但有个关键点你得记住:装了 TensorRT ≠ 就自动变快了。
你得真的把模型导出成.engine,并且在任务配置里指向它,才会真的走加速这条路。
要是你只给了.pt,那哪怕机器上装了 TensorRT,跑的照样是 PyTorch FP16,一点没提速。 .engine文件的精度(FP16 还是 INT8)在导出的那一刻就定死了,改不了。
后面推理时再传个「half=True」是没用的。
这就是为什么想换 INT8,必须从头重新导出一遍。- 还有个隐形的坑:开多个任务时,每个任务都会单独造一个模型塞进显存,它们之间没有共用。
你想扩到多路的时候,显存会被这么吃光。
你之前折腾的「量化成 .engine 提速 / 换 INT8」到底生没生效,只取决于一件事:任务配置里存的那个模型路径,结尾是
.pt 还是 .engine。想知道答案很简单,回家打开数据库看一眼那个任务的模型路径后缀就行了。
四、你三个痛点的真正根因
你一直说「延迟高、通道堵、多路卡」。
我查下来,根子不在模型慢,而在整个结构的搭法上。
下面四条,每条我都标出了真相是什么。
1. 通道堵塞:真源在读帧,不在推流
问题出在第 ③ 步——读画面这一步是会干等的。
ffmpeg 那边一张画面没给过来,主线程就只能杵在那儿等着。它一等,后面的模型推理也跟着停摆。
你之前在推流那一端做的「队伍满了就丢几张」,其实只是治标。
因为源头没有拆开:只要解码一慢,整条主线程就得跟着卡。
2. 延迟高:大概率不是模型,是 CPU 软编码
看第 ⑥ 步,推流编码用的是 libx264,这是让 CPU 硬扛的软件编码。
打个比方:这就像让一个会计用算盘去算一整个工厂的账。
多路视频一起跑的时候,CPU 会先被压垮,而且它比模型推理慢得多。
所以你要真想降延迟,该做的是把编码这活搬到显卡上去(NVENC,说人话:显卡里专门管压缩视频的小硬件),而不是去调 imgsz 那个参数。
3. 多任务「并行」是假象
推理那里写死了 device=0 和 batch=1。
这意味着:多路任务在显卡上其实是排队一个一个来的,根本不是同时跑。
再加上每个任务都新建一份模型、各占一块显存,显存很快就见底了。
想要真正的并行,得靠「把多路画面凑成一批一起算 + 大家共用同一个模型」。
4. 「增加推理间隔」的真相
你之前用「隔几帧才检测一次」来提速,这招确实能快。
但有个事你可能没意识到:那些被跳过的画面上,显示的不是「没检测到」,而是上一次检测的旧框。
所以画面看起来会「慢半拍」——框跟不上人。
这不是漏检,是在拿旧结果凑数。本质上,你是用「不够及时」换来了「跑得更快」。
五、旋钮分类:治标 vs 治本
你之前调过的那一堆参数,其实分两类。
这一节最重要,因为它决定了你到底是在绕开问题,还是在解决问题。
| 属于哪一类 | 具体做法 | 要付出什么代价 |
|---|---|---|
| 牺牲质量换速度(治标) | 把图缩小(降 imgsz)、隔几帧才检测一次、把判定门槛调高(提 conf 阈值) | 会漏看东西 / 框慢半拍 / 小的东西直接没了 |
| 改架构(治本) | 让解码单独开一个小工去做、用 NVDEC 让显卡来解码、用 NVENC 让显卡来编码、把图片预处理也搬到显卡上、把多路画面凑成一批一起算 | 得动代码,麻烦一点,但精度一点不丢 |
你之前干的那些事——「把 .pt 量化成 .engine、把图缩小、隔帧检测、把置信度门槛提高」——全都是在拿准确度换速度。
换句话说:你不是让它变强了,你是让它变得又快又马虎。
想要又快又不丢东西,就得动结构:把解码和编码搬到显卡上去,让各段活儿能同时干、互相不等。
这才叫治本。
六、手机上怎么用这一页
出门不用带源码,带手机就行。
第一步,看「图 1」,把 7 段链路记住。
第二步,看「第四节」,把三个痛点的真正原因记住。
第三步,看「第五节」,分清哪些是治标、哪些是治本。
什么时候算吃透了?
当你能不看任何东西,张嘴就说出「视频从网络到观众要过哪几段、哪一段最容易卡、我之前调的那些参数属于治标还是治本」——这一页你就学完了。