
1. 项目概述1.1 核心需求解析做边缘AI的朋友应该都有同感模型在服务器上跑得好好的一搬到Jetson这种小卡上就各种翻车。视频异常检测系统更是如此它不像图像分类那样丢一张图进去出个结果就完事而是要连续处理视频流对每一帧做推理还要跨帧做时序判断计算量和内存占用都比普通视觉任务高一个量级。我这次实测的项目就是在Jetson系列设备上完整部署一套视频异常检测系统覆盖从视频流接入、目标检测、行为判断到告警输出的全链路。标题里写了“开篇”也确实如此——边缘AI的视频类应用市面上讲原理的多给出一手实测数据的少我打算用这个系列把Jetson上跑视频任务的真实情况完整记录下来哪些环节吃算力哪些环节是隐形瓶颈不同型号的Jetson到底能跑到什么水平用什么手段能压出性能余量。这篇文章是系列开篇先把系统搭建、模型选型、性能实测这三块核心内容讲透。不管你手里是Jetson Nano还是AGX Orin这篇文章的思路和结论都能直接用。1.2 为什么选择边缘端而不是云端这个项目启动时第一个被问到的就是为什么不用云服务器视频传上去后端分析结果推回来不是更省事吗答案是省事但不可行。视频异常检测的场景比如工厂车间安全监测、园区周界防护、机房设备巡检摄像头数量多、数据量大一条1080p视频流按H.264编码大约是4Mbps码率100路就是400Mbps这个带宽压力先不说光传输成本和时间延迟就够受的。更重要的是异常事件的处置往往讲究即时性——人员闯入、设备冒烟、跌倒摔倒这类事件从发生到响应窗口期可能就几秒钟。视频传云端来回一圈延迟轻松超过500毫秒再加上云端GPU实例的成本一个月下来比买几块Jetson贵得多。边缘AI的核心思路是把推理能力下沉到数据产生的地方摄像头附近放一块小算力板卡视频流本地解析只把告警信息和关键截图传出去。延迟从秒级压到百毫秒级带宽占用从几百Mbps降到几Kbps数据不出内网隐私安全也有保障。这个逻辑搞安防和工业视觉的同行应该深有体会。当然边缘方案不是没有代价最直接的就是算力受限、存储有限、环境复杂这恰恰是Jetson系列存在的意义也是这篇文章要解决的核心问题。1.3 边缘AI落地的核心矛盾真正上手之后你会发现边缘AI落地最大的矛盾就一句话算法要吃算力设备只有那么多功耗和散热余量。Jetson Nano的模组功耗只有5到10瓦算力大约472 GFLOPSFP16听起来够用但跑一个轻量级检测模型加上预处理后处理720p分辨率的视频流也就勉强跑到十几帧。Jetson Orin系列好很多但功耗也水涨船高AGX Orin满血模式能到60瓦性能翻了几倍代价是散热方案、电源规格、整机成本全部上去了。这个矛盾决定了边缘AI系统的每个环节都不能稀里糊涂。模型选型要考虑参数量和算力匹配推理框架必须做TensorRT加速数据管线要避免CPU和GPU空转等待供电散热要控制在高负载下的温度降频拐点。这篇文章的实测数据本质上就是在回答一个问题在给定功耗预算下这套系统能把性能榨到什么程度。2. 硬件平台选型与算力评估2.1 Jetson系列选型对比先把市面上主流的Jetson型号拉出来对比一下。选型这件事很多人上来就看算力峰值实际上要综合考虑算力、功耗、价格、接口资源四个维度。型号算力FP16功耗范围典型价格区间内存适用场景Jetson Nano472 GFLOPS5-10W千元级4GB LPDDR4轻量单路任务、算法原型验证Jetson Orin Nano8GB版约20 TOPS稀疏/10 TOPS稠密7-15W3000元左右8GB LPDDR5多路轻量检测、中等模型推理Jetson Orin NX16GB版约100 TOPS稀疏/50 TOPS稠密15-25W6000元左右16GB LPDDR5多路视频流、Transformer类模型Jetson AGX Orin64GB版约275 TOPS稀疏/137 TOPS稠密15-60W15000元以上64GB LPDDR5高帧率多路视频、大模型端侧部署说几个容易被忽略的点。第一稠密算力才是真算力TensorRT加速时如果不用稀疏性优化2:4稀疏裁剪实际跑的是稠密算力Nano和Orin系列在这个口径下差距没有宣传的那么夸张但依然是指数级的提升。第二内存带宽往往比算力更早成为瓶颈Orin NX的LPDDR5带宽约102GB/s比Nano的25.6GB/s提升了3倍这个指标直接影响视频多路并发时的帧率。第三同型号不同功耗模式下性能差异巨大Orin NX在15瓦和25瓦模式下跑同一个模型帧率能差50%以上。我这次实测用了Orin Nano 8GB和AGX Orin 64GB两块板子分别代表消费级和工业级两个梯队中间档位的Orin NX基于参数推算给出参考值。2.2 理论算力怎么折算成实际帧率很多刚接触Jetson的朋友会直接拿算力峰值除以模型计算量来估算帧率这是典型的第一层误判。模型的计算量通常用FLOPs浮点运算次数表示比如YOLOv5s的输入640x640分辨率FP16下一次推理大约需要16.5 GFLOPS。用Orin Nano的稠密算力10 TOPS来算理论上每秒能跑600次推理但实际只能跑到25到30 FPS差了20倍以上。差距来自哪里首先是利用率GPU推理不是单纯做矩阵乘还有内存搬运、算子调度、CPU和GPU间的数据同步实测TensorRT优化良好的模型GPU利用率能到70%到80%已经算优秀。其次是输入输出开销视频帧从解码到送入TensorRT引擎再到后处理输出这个管线的耗时往往和推理本身一样长。再次是时序任务带来的额外计算异常检测不只是每一帧跑一次目标检测还需要跨帧做特征聚合比如轨迹分析、姿态判断、行为分类这部分单独吃算力。所以我的建议是选型时用“理论算力乘0.1到0.15”来粗估可用帧率比如Orin Nano跑到25到30 FPS的YOLOv5s不夸张但也没法再高。想确认准确的数字只能做实测下面第5章会有完整的测试数据。2.3 供电、散热与部署环境这节内容可能看起来不“AI”但踩过坑的朋友都知道很多系统跑崩了根本不是算法问题而是供电和散热没做好。Jetson Nano建议用5V/4A的电源市面上很多充电头标称5V/2A接上之后高负载直接黑屏重启。Orin Nano和Orin NX需要DC电源官方适配器是19V第三方电源要特别注意纹波和峰值电流电源品质不好GPU降频会非常严重。AGX Orin更夸张满血模式60瓦功耗推荐用官方电源适配器或者高品质DC电源我遇到过用劣质电源导致系统在高负载下反复重启换电源后问题消失。散热方面被动散热只适合低功耗模式跑视频推理建议直接上主动散热。机箱风扇直吹散热片的效果远好于小涡轮风扇。环境温度超过35度时即使有风扇Jetson也会在长时间高负载后触发温度降频Orin系列从85度开始降频性能会逐步跌到峰值的60%左右。部署环境的建议工业场景务必用带风扇的金属机箱预留通风口实验桌场景可以裸板加散热片户外场景必须做防水防尘散热方案要重新设计。3. 异常检测模型选型与TensorRT加速3.1 视频异常检测的常见技术路线视频异常检测的技术路线大致分三类我分别说一下在Jetson上的可行性和坑。第一类是重建类方法核心思路是用自动编码器学习正常画面的分布推理时如果重建误差大说明出现了模型没见过的东西判定为异常。典型代表是ConvLSTM-AE、记忆增强自编码器。这类方法的好处是不需要异常样本标注缺陷是对光线变化、相机抖动太敏感误报率高而且自编码器的计算量不低在Jetson上跑720p视频也就勉强实时。第二类是预测类方法用过去的帧预测未来的帧预测误差大的区域判为异常典型代表是PredNet、FramePred。效果比重建类好一些但模型结构更复杂时序依赖长延迟高不适合做实时告警系统。第三类是检测加分类的组合方法先用目标检测模型提取画面中的人或物体再用轻量级的分类网络或行为识别模块判断其状态是否异常。这是目前工业落地的主流路线好处是误报率可控计算量集中在检测模型上便于用TensorRT优化坏处是需要针对特定场景标注数据可迁移性差一些。我的项目选择的是第三条路线主体是一个轻量目标检测模型辅助一个行为分类头。具体展开在下一节。3.2 模型选型轻量化与精度的平衡目标检测模型的选择直接影响系统性能。我在这个项目里实测对比了YOLOv5s、YOLOv6s、YOLOv8s以及轻量级的YOLOv5n和YOLOv8n分别在Jetson Orin Nano上做了TensorRT FP16加速后的帧率测试。实测结果640x640输入下YOLOv5n约45 FPSYOLOv8n约40 FPSYOLOv5s约28 FPSYOLOv8s约24 FPS。精度上COCO验证集mAP依次是45.7%、37.3%、55.4%、44.9%。从性价比看YOLOv8s精度最高但帧率偏低YOLOv5n帧率最友好但小目标检测能力偏弱。最终选了YOLOv5s。它在Orin Nano上能稳定跑到28 FPS配合抽帧策略每秒分析10帧覆盖4到6路视频流是够用的。精度比YOLOv8s差一些但结合异常检测的需求检测出目标后还会过行为分类模块整体误报率可控。有一个细节值得注意Jetson上有TensorRT的插件层支持YOLOv系列很多自定义算子但YOLOv6早期版本的某些算子TensorRT不支持需要自己写插件。YOLOv5和YOLOv8的TensorRT生态最成熟优先推荐。3.3 TensorRT转换与INT8量化实操TensorRT是Jetson性能的核心不会用TensorRT就等于浪费硬件。转换流程看着简单实操中细节很多我完整走一遍。首先是导出ONNX模型。PyTorch训练好的模型用torch.onnx.export导出时要固定输入尺寸、设置opset_version11以上、把推理模式切到eval同时关闭梯度计算。YOLOv5为例还需要把检测头的decode逻辑一起导出方便在TensorRT里直接输出最终检测结果这个步骤很多人漏掉结果导出来的模型只有特征图输出后处理在端侧没法做。然后是trtexec工具转换。在Jetson上安装TensorRT之后官方提供了trtexec这个命令行工具转换命令如下trtexec --onnxyolov5s.onnx \ --saveEngineyolov5s_fp16.engine \ --fp16 \ --workspace2048 \ --minShapesimages:1x3x640x640 \ --optShapesimages:1x3x640x640 \ --maxShapesimages:4x3x640x640加粗的几个参数解释一下--fp16开启半精度推理Jetson GPU对FP16的支持非常好精度损失可以忽略--workspace指定转换时的最大工作空间--minShapes、--optShapes、--maxShapes要配套设置这样TensorRT会为动态batch做tactic选择保证不同batch下都有较优性能。转换完成后建议用trtexec --loadEngineyolov5s_fp16.engine --shapesimages:1x3x640x640测试一下引擎是否正确、延迟是否达标。如果还想进一步压性能可以试INT8量化。TensorRT的INT8量化需要校准数据集YOLOv5官方给了一套VOC或COCO的校准图片命令如下trtexec --onnxyolov5s.onnx \ --saveEngineyolov5s_int8.engine \ --int8 \ --calib/path/to/calibration_imagesINT8量化的精度损失通常能控制在2到3个mAP点以内帧率能比FP16再提升30%到50%。但校准数据集要和实际场景分布一致否则会出现某些类别的目标完全检测不到的情况。我实测的工厂场景用COCO校准的效果不好换了现场采集的500张图之后明显改善。这一点必须亲自做实验不要依赖默认配置。4. 系统架构与部署实操4.1 整体软件架构这套视频异常检测系统的软件架构我用一句话概括GStreamer负责取流和推流TensorRT负责推理Python胶水层做控制和业务逻辑。选GStreamer而不是OpenCV的VideoCapture是因为GStreamer底层利用Jetson的硬件编解码器CPU占用率低延迟小还支持rtsp流、本地文件、USB摄像头、CSI摄像头等多种输入源。实测同样的1080p视频流OpenCV解码CPU占用能到40%GStreamer硬解只有8%左右。TensorRT负责模型推理用Python的pycuda和tensorrt包加载engine推理时需要注意输入输出的内存管理尽量用cuda.mem_alloc分配显存减少CPU和GPU间的数据拷贝。Python胶水层负责任务调度、告警逻辑、状态上报。性能要求极高的场景可以用C重写核心管线但开发效率低很多我先用Python跑通全流程性能瓶颈后续再逐段用C替换。完整流程图简化成这样[RTSP/USB/本地视频源] | v [GStreamer硬件解码 - BGR图像] | v [预处理resize normalize] | v [TensorRT推理引擎(检测 行为分类)] | v [后处理NMS 异常规则判断] | v [告警模块(截图保存 消息推送)]这个架构的好处是每层都可以独立替换比如换一个检测模型只需要改推理层换视频源不需要动业务逻辑。4.2 视频流接入与预处理视频流接入看似简单实际上最容易出问题。我踩过的坑包括RTSP流断线重连、GStreamer管道缓冲延迟、CSI和USB摄像头在Jetson上的不同行为。RTSP断线是摄像头场景最常见的问题网络抖动、摄像头重启都可能导致流中断。我的处理方案是用GStreamer的udpsrc替代rtspsrc在摄像头端有些网络摄像头支持RTSP over UDP或者用ffmpeg拉流转推然后在应用层加心跳检测和自动重启逻辑。代码层面用GStreamer的about-to-finish信号重新拉起管道def on_eos(bus, msg): print(Stream ended, restarting...) pipeline.set_state(Gst.State.NULL) pipeline.set_state(Gst.State.PLAYING)预处理需要注意的点是分辨率建议先resize到640x640模型输入尺寸resize的算法选择上用OpenCV的INTER_LINEAR就够追求质量可以上INTER_CUBIC但对检测结果影响很小。归一化要记得除255并且注意通道顺序是BGR还是RGB——PyTorch训练时一般用RGBOpenCV读出来是BGR搞反了会导致检测结果一塌糊涂。4.3 推理管线与后处理推理管线的性能优化是整个项目的重头戏我分三块说异步推理、batch推理、后处理优化。异步推理是必须做的。TensorRT的execute_v2是同步接口调用时CPU会阻塞等待GPU计算完成这段时间CPU利用率是0管线效率极低。正确做法是用多线程一个线程负责取帧和预处理一个线程负责推理一个线程负责后处理线程之间用队列通信。实测用双缓冲队列加异步推理整体吞吐能提升60%以上。batch推理适合多路视频流场景。如果同时分析4路视频可以等4帧到齐后一次性送入TensorRT用定义的动态shapesbatch4的推理时间大约只比batch1多30%等于把总吞吐提升了3倍。但batch不能无限加大一是显存有限二是帧对齐的时间成本会暴涨。后处理中的NMS非极大值抑制是CPU计算的大头一张图检测出几十个目标时Python写的NMS循环会吃掉大量时间。我的做法是先用简单的confidence阈值过滤掉大部分低置信度框再做NMS并且用numpy向量化实现def nms_fast(boxes, scores, iou_threshold0.5): x1 boxes[:, 0]; y1 boxes[:, 1] x2 boxes[:, 2]; y2 boxes[:, 3] areas (x2 - x1) * (y2 - y1) order scores.argsort()[::-1] keep [] while order.size 0: i order[0] keep.append(i) xx1 np.maximum(x1[i], x1[order[1:]]) yy1 np.maximum(y1[i], y1[order[1:]]) xx2 np.minimum(x2[i], x2[order[1:]]) yy2 np.minimum(y2[i], y2[order[1:]]) w np.maximum(0.0, xx2 - xx1) h np.maximum(0.0, yy2 - yy1) inter w * h iou inter / (areas[i] areas[order[1:]] - inter) inds np.where(iou iou_threshold)[0] order order[inds 1] return keep这段代码比纯Python循环快20倍以上几乎可以忽略不计。5. 性能实测与数据对比5.1 测试方法与指标性能测试最怕的是测不准我统一所有测试条件保证数据可复现。测试输入一段5分钟1080p/30fps的仓库监控视频包含人员走动、叉车运行、静止场景三种片段码率4Mbps。测试时截取中段2分钟避免首帧解码波动影响数据。软件环境JetPack 5.1.2TensorRT 8.5.3CUDA 11.4Python 3.8模型为YOLOv5s TensorRT FP16引擎输入尺寸640x640。测试指标端到端延迟从视频帧进入系统到告警输出、推理帧率每秒处理帧数、CPU占用率、GPU占用率、内存占用、核心温度、功耗。统一用系统自带工具采集数据CPU和GPU占用率用tegrastats功耗用Jetson的电源管理接口。5.2 实测数据先看Orin Nano 8GB在15瓦功耗模式的单路视频流结果。指标数值端到端延迟112ms推理帧率28 FPSCPU占用率32%GPU利用率71%内存占用3.2GB / 8GB核心温度稳定在72度功耗14.2W再看AGX Orin 64GB在40瓦功耗模式的单路视频流结果。指标数值端到端延迟68ms推理帧率63 FPSCPU占用率18%GPU利用率66%内存占用4.1GB / 64GB核心温度稳定在64度功耗38.5W两组数据对比AGX Orin的帧率是Orin Nano的2.25倍延迟降低44%。这里有个有意思的现象GPU利用率反而比Orin Nano低说明AGX Orin的性能余量很大单路视频流吃不满它的算力。这就意味着AGX Orin适合做多路并发场景。多路视频流的实测我用Orin Nano跑4路720p视频流每路帧率8到12 FPS总吞吐约40 FPSAGX Orin跑4路1080p视频流每路帧率22到30 FPS总吞吐约100 FPS。坑点在于Orin Nano跑4路时内存带宽接近饱和CPU占用率飙升到80%以上GPU利用率反而下降瓶颈已经从算力转移到了数据搬运。5.3 瓶颈定位与调优实测之后用NVIDIA的Nsight Systems做了一次瓶颈分析发现一个被很多人忽略的问题预处理和后处理占用了大量CPU时间这部分时间在tecgr时根本看不出来但通过Nsight的timeline可以清楚看到CPU线程的忙等。定位到瓶颈后做了三处优化。预处理方面把resize和归一化放到GPU上做用TensorRT的预处理层代替OpenCV的CPU操作后处理方面把NMS的置信度阈值从0.25提高到0.4减少进入NMS的候选框数量推理方面使用了更大的batch。优化之后Orin Nano单路帧率从28提升到33 FPS延迟从112ms降到95msCPU占用率从32%降到21%。这个优化幅度说明一个道理Jetson上的性能优化算法层面只占一半工程层面的数据搬运、代码效率、资源调度是另一半不能只盯着模型改。6. 常见问题与排查技巧实录6.1 长时间运行后性能衰减如果你发现系统刚启动时帧率正常跑半小时后性能越来越差八成是温度降频导致的。Jetson设备有动态调频机制核心温度达到85度以后会主动降低GPU频率来保护硬件。处理方案分两步。第一步是看温度曲线用以下命令实时监控sudo tegrastats --interval 1000 | grep GPU第二步是改善散热。如果是裸板加装散热风扇是最直接有效的方案散热片的面积和风道设计比风扇转速更重要。如果是机箱内部署确保进风口和出风口通畅不要把设备放在密闭弱电箱里。我实测的环境下Orin Nano在良好的主动散热条件下可以长期稳定在72度左右性能不衰减散热不良的封闭环境中30分钟后帧率掉到初始值的70%。6.2 多路视频流的掉帧问题多路视频流的掉帧问题排查思路要分层先看视频源是不是不稳定再看解码环节是不是CPU过载最后看推理batch是不是配置不当。如果是RTSP来源优先检查网络延迟和丢包率差网络环境下用UDP传流要启用重传机制。如果是本地USB摄像头检查带宽是否被占满Jetson的USB控制器带宽有限4路1080p USB摄像头就可能跑满。解码环节的典型问题是GStreamer管道没有启用硬解。确认方法是在管道字符串中加入nvdec插件比如rtspsrc rtph264depay h264parse nvv4l2decoder这样解码会走GPUCPU占用大幅降低。推理环节要注意batch设置不要过大。Orin Nano上推荐batch4超过8之后显存占用剧增反而降低整体吞吐。6.3 TensorRT引擎构建慢与序列化TensorRT引擎构建过程非常耗时一个YOLOv5s模型在Orin Nano上构建可能花5到10分钟每次重启都要等一遍显然不可接受。解决办法是把构建好的engine序列化到磁盘启动时直接load。import tensorrt as trt def load_or_build_engine(onnx_path, engine_path): if os.path.exists(engine_path): with open(engine_path, rb) as f: return trt.Runtime(trt.Logger()).deserialize_cuda_engine(f.read()) # 构建引擎... with open(engine_path, wb) as f: f.write(engine.serialize()) return engine需要提醒的是序列化的engine文件是和特定TensorRT版本、GPU型号绑定的。JetPack升级后旧engine可能无法加载重建即可。构建时的tactic选择也依赖GPU型号不要在PC上构建引擎然后拷贝到Jetson上直接用大概率会报错。6.4 实测心得与避坑清单最后把这些天实测踩坑的经验整理成清单每一条都是真金白银换来的。供电永远是第一位。Jetson设备对电源质量比普通PC敏感得多电源不足会导致GPU降频、USB外设掉线、系统随机重启排查各种诡异问题之前先确认供电是否达标。散热不要省。Jetson长时间高负载运行散热是性能稳定的前提。建议直接用带风扇的主动散热套件不要依赖被动散热。TensorRT的版本必须和JetPack配套。手动升级TensorRT可能会导致引擎构建失败出现奇怪的CUDA错误优先用JetPack自带版本。INT8量化一定要做校准。直接转INT8而不做校准或者校准数据不符合实际场景分布精度损失可能超过10个mAP模型形同虚设。监控指标要多维度采集。只看帧率会掩盖很多问题CPU占用率、GPU利用率、内存带宽、温度、功耗这些指标要一起看才能定位真正的瓶颈在哪里。不要过度优化。系统跑通了、延迟在可接受范围内就先用着把精力放在提高检测精度和告警稳定性上。边缘AI项目的核心还是业务效果为了多几帧FPS把系统搞复杂得不偿失。