简介LntonAIServer视频智能分析服务v1.0.01是一套面向安防与安全生产场景的AI视频分析解决方案支持行人入侵、烟火识别、车型检测、玩手机/打电话检测、厨帽识别及抽烟检测等常见算法且不限定GPU平台可广泛部署于森林防火、明厨亮灶、安全生产防范等领域适合算法集成人员、智能安防开发者及项目负责人快速搭建视频分析能力。压缩包共152个文件约306.43MB。文件类型以78个dll动态库、37个js前端逻辑、11个css样式、6个weights模型权重、6个proto协议文件为主同时包含启动脚本、exe及配置文件各类型分工明确dll提供核心推理能力weights和proto承载算法模型与网络结构js/css构成可视化管理界面便于开发者在已有环境中集成和调试。目前已有247人学习说明该服务在中小项目中有一定实用参考价值。资源配有完整的前端页面、运行脚本与参数文件不仅可以直接启动体验检测效果还可参考其算法调用流程、模型组织方式及多算法并行工作的工程实现为二次开发或同类视频智能分析项目提供压缩包级参考。1. LntonAIServer 视频智能分析服务为什么烟火识别和抽烟检测这类实时算法反而更适合 CPU某个化工厂的安环部负责人找我说他们监控系统有 200 路摄像头想在重点区域加烟火识别和抽烟检测但预算只够买一台普通 X86 服务器买不起带 GPU 的机器。我当时的判断是这类视频智能分析任务反而用 CPU 算法部署更容易落地。LntonAIServer v1.0.01 就是把这套思路做成服务的一个实例——它把烟火识别、抽烟检测等算法封装成可直接拉流、分析、告警的软件服务跑在 Intel、AMD 甚至 ARM 服务器上不依赖显卡。这个资源解决的是“既有监控系统升级为智能报警系统”的场景你不用换摄像头、不用改网络在现有局域网里加一台服务器配置好 RTSP 视频源就能让烟火识别和抽烟检测跑起来。适合两类人一类是安防集成商工程师需要快速给客户交付并减少硬件成本另一类是自己维护监控系统的甲方 IT想用最少的钱做最关键的报警功能。下面我会从架构、部署、调参、排错到压测把这套服务完整的拆开讲。2. 从视频流到报警事件服务架构与 CPU 算法的选型逻辑2.1 拉流-分析-告警三段式架构LntonAIServer 这类视频分析服务内部很少是单体“一帧进模型出”的流程尤其跑 CPU 时必须把拉流、解码、推断、事件判定拆开。常见做法是三个独立模块接入层负责从 RTSP/RTMP/GB28181 拉流并按需解码分析层按抽帧策略取图交给检测模型推理业务层拿推理结果做去抖、持续帧判定、产生报警并回调给上层平台。我一般会提醒接手项目的同事不要试图让每一路视频每一秒都做全帧检测。CPU 算法能不能稳定跑核心在“怎么少算但不错报”。把架构拆开之后拉流解码可以独占线程推理线程只处理真正需要判定的图像报警回调又单独走队列这样一路摄像头的抽搐不会拖垮全局。LntonAIServer 在 v1.0.01 里把这三段封装成了常驻服务对使用方暴露的是配置文件和告警接口你不用关心内部队列怎么搭但理解这个架构对你调参数有直接帮助。在实际项目中RTSP 源的分辨率往往被误配成 4K 或者 1080P 超高码率解码就已经把 CPU 吃满了。即使模型很小也没有余量做分析。所以接入层有一个非常实用的设计拉流后先在解码环节强制缩放常见做法是统一缩放到 1280×720甚至 960×540后续推理只处理缩放后的帧。烟火识别这类目标比较大720P 足够抽烟检测看的是手部区域720P 也能满足。这个缩放策略直接决定你能同时跑多少路。2.2 烟火识别与抽烟检测的模型选型体积、输入尺寸、算力消耗烟火识别和抽烟检测在 CPU 上能跑不等于随便拿一个大模型就能跑。LntonAIServer 在算法打包时会强制用轻量检测模型目标检测部分采用单阶段小网络输入尺寸通常控制在 320×320 到 416×416 之间模型体积在 5MB 到 20MB 左右。这套服务用 ONNX 格式作为推理中间格式因为 ONNX Runtime 的 CPU 优化比较成熟也方便在 x86 和 arm 之间切换。烟火识别有它的特殊性烟雾边缘模糊火苗目标又小模型不能只靠语义分类必须给检测头加小目标分支。常见做法是把输入图切成 320×320 分块检测对视频画面里疑似烟雾的区域做 RoI 放大后再判一次这个二次确认逻辑会显著降低昼夜误报代价是推理次数从 1 变 2。LntonAIServer 里把这种策略参数化配置默认开启“分块小目标增强”你可以根据现场关闭。抽烟检测则完全不一样。它要检测的是“人手里有没有烟”不是直接在大图上搜一个烟头而是先做人/手关键点检测再截取手部附近区域交给一个专门的烟支分类模型。这种“检测分类”串联的结构在 CPU 上比直接端到端检测更稳因为烟目标一般小于 20×20 像素单阶段模型很难在小目标上同时区分烟支和手指。资源包里已经内置了这两个串联模型也都转成了 ONNX你不需要再训练拿起来就能用。下表是我常用的参数参考算法任务模型输入单帧推理耗时4核i5实测部署侧关注点烟火识别416×416约 70ms ~ 120ms分块小目标增强是否开启抽烟检测320×320 人手RoI约 50ms ~ 100ms先检测人体再检测手需配置检测置信度车辆/人员基础跟踪640×416约 30ms ~ 60ms与烟火/抽烟分析共用抽帧锁避免争抢2.3 抽帧策略与多路调度CPU 算法的真正瓶颈不在算力而在帧同步CPU 推理再快也没办法把一路 25fps 的实时视频每帧都过一遍烟火模型25 帧全跑意味着每秒要推理 25 次任何普通服务器都扛不住多路。实际部署中LntonAIServer 对每路视频采用“基础帧率 动态触发”的抽帧策略。所谓基础帧率就是正常情况下每秒只取 1 到 2 帧做全画面分析动态触发则是当前帧里面出现了目标框或目标候选后立刻把抽帧间隔缩短到每秒 5 到 10 帧持续确认这个目标是不是真的火苗或烟头。这个策略我喜欢叫它“慢看全图快看重点”。它对 CPU 算法有两个好处一是大部分空画面时间不耗算力服务器可以把 CPU 让给解码和多路接入二是真的发生紧急事件时服务的分析频率会自动翻倍不会漏掉火苗从出现到蔓延的过程。LntonAIServer 的调度模块还会对所有分析请求打时间戳如果上一帧推理还没返回新帧直接丢弃而不是排队堆积。这也是一条非常关键的防踩坑设计——如果每一帧都在排队延时会越来越大最终事件发生几十秒之后才报警意义就没了。3. 部署与配置把 LntonAIServer 跑在裸机服务器上3.1 目录结构与启动脚本拿到 v1.0.01 的资源包后解压出来通常是一个带固定目录的服务骨架。我第一次部署时习惯先把目录结构看清楚避免之后改配置找不到文件。常见目录如下lntonai-server/ ├── bin/ │ ├── lntonai_server # 服务主程序 │ └── model_convert.py # 模型精度转换/检查脚本 ├── config/ │ └── config.yaml # 核心配置文件 ├── models/ │ ├── fire_smoke.onnx │ └── smoke_action.onnx ├── logs/ │ └── runtime.log # 运行日志 ├── scripts/ │ ├── start.sh │ └── stop.sh └── web/ └── dashboard # 内置管理页面静态文件启动脚本里一般只做两件事设置环境变量和后台拉起主程序。vim 打开scripts/start.sh核心部分是这样#!/bin/bash export LD_LIBRARY_PATH./lib:$LD_LIBRARY_PATH export OMP_NUM_THREADS4 # 控制 OpenMP 线程数 nohup ./bin/lntonai_server -c ./config/config.yaml ./logs/runtime.log 21 echo $! ./logs/server.pid设置OMP_NUM_THREADS4非常关键。如果你在 8 核机器上不限制这个参数ONNX Runtime 会自动开启所有核导致多路视频解码线程和推理线程互相抢 CPU。我一般会预留 2 个核给拉流解码和系统自身所以 8 核机器配OMP_NUM_THREADS616 核机器配OMP_NUM_THREADS10具体还要看路数。server.pid用来停止服务时读取进程号避免误杀。3.2 修改 config.yaml视频源、算法开关、阈值config.yaml 是这套服务的核心也是你花最多时间调整的地方。首次部署我建议只配置一路视频源跑通后再往上加。下面是一个最小可运行的配置片段server: port: 8260 workers: 4 streams: - id: cam_yard_01 url: rtsp://192.168.1.100:554/Streaming/Channels/101 width: 1280 height: 720 fps: 8 algorithms: fire_smoke: enabled: true model_path: ./models/fire_smoke.onnx input_size: [416, 416] conf_threshold: 0.45 iou_threshold: 0.5 enhancement: true smoking_act: enabled: true model_path: ./models/smoke_action.onnx input_size: [320, 320] conf_threshold: 0.55 callback: url: http://192.168.1.50:9000/event interval: 3 retry_count: 3streams下面的fps不是拉流帧率而是最大分析帧率。示例里设置 8代表正常情况下每秒最多取 8 帧做推理就算摄像头是 25fps服务也不会全接。conf_threshold是置信度阈值烟火识别默认 0.45 偏低适合远距离小目标抽烟检测默认 0.55 偏高因为烟支形态容易和手指混淆阈值低了误报特别多。enhancement就是 2.2 里说的分块小目标增强开关。callback.interval表示同一目标连续触发事件时最少间隔多少秒才再次回调防止同一片烟雾三秒钟推十几条报警。3.3 接入 RTSP 与 ONVIF 摄像机接入摄像头这一步最耗时的往往不是服务配置而是先确认摄像头 RTSP 地址是否稳定。很多海康、大华摄像头会有多个码流地址一个主码流一个子码流。CPU 视频分析尽量用子码流分辨率和码率都更低。接入前我习惯用 ffmpeg 验证ffmpeg -rtsp_transport tcp -i rtsp://192.168.1.100:554/Streaming/Channels/102 -frames:v 1 /tmp/test.jpg如果这条命令能快速落一张图说明摄像头地址和网络都没问题。如果卡住不动就要检查摄像头编码格式是不是 H.265。LntonAIServer 的解码模块一般依赖 FFmpeg 的软解能力H.265 在低端 CPU 上软解很吃力。遇到这种情况我建议把摄像头主码流编码改成 H.264或者直接在摄像头后台把子码流改成 H.264解码占用能下降 40% 以上。配置好视频源后启动服务用一行命令sh scripts/start.sh sleep 2 tail -f logs/runtime.log看到类似stream cam_yard_01 connected和inference worker started的日志说明已经跑起来了。服务内置的 Web 管理页面会监听 8260 端口浏览器打开http://服务器IP:8260可以直接看到每路视频的分析结果和实时报警列表。4. 烟火识别与抽烟检测的报警联动把识别结果变成真正有用的事件4.1 报警状态机持续时间与置信度双重确认跑通视频流只是第一步。很多新手会在界面上看到检测框就算“上线了”但一到现场就被误报折磨。正确的做法是把识别结果先交给报警状态机由状态机决定最终是否推送事件。状态机的核心参数是“连续触发帧数”和“确认延时”。举例来说烟火识别单帧检测到烟雾的置信度是 0.7但这可能只是镜头前飘过一道阴影。状态机会要求连续 3 到 5 帧都满足置信度并且在 1 秒持续时间内判定有效才会产生报警。LntonAIServer 中这个逻辑通过配置里的confirm_frames和confirm_time_ms决定。我常用的一组值烟火识别confirm_frames3抽烟检测confirm_frames5。抽烟检测要比烟火更严格因为人手部动作太快单帧的烟支目标很容易误检多等几帧反而能滤掉大部分假阳性。4.2 回调 WebhookJSON 结构与重试机制报警事件最终是通过 HTTP 回调送出。在楼宇对讲、门禁、安防平台对接时回调格式是谁方便谁来定但我见过大量项目因为回调失败导致报警丢失。LntonAIServer 的 callback 模块会把事件先写入本地内存队列再异步发送到callback.url发送失败自动重试。下面是实际发出到业务平台的 JSON 结构{ event_id: 8f3a2c1d-4d0a-4f9e-9b7e-2a3d4e5f6a7b, stream_id: cam_yard_01, type: fire_smoke, label: smoke, confidence: 0.82, bbox: [1080, 420, 1185, 600], snapshot: /data/capture/8f3a2c1d.jpg, timestamp: 1737362400 }bbox是检测框在 1280×720 原图上的坐标snapshot是服务自动保存的报警截图路径。接入方拿到这个 JSON 后至少要做两件事用event_id做去重防止重试导致重复工单校验bbox是否在合理范围内比如画面顶部高亮区域出现的“火苗”大多是车灯反射。如果回调地址不可达服务会按retry_count重试重试间隔随次数递增这个细节能保命。4.3 特殊场景调参白天烟囱、晚上车灯、空调外机现场环境的干扰项比模型训练时的负样本丰富得多。我实际部署中总结过三组常踩的调参场景场景现象有效调参配置工厂烟囱白天冒白汽持续把水蒸汽识别成烟雾把conf_threshold提到 0.65并开启烟雾纹理二次过滤夜间车辆灯光车灯在画面剧烈运动被当作火苗开启报警状态机的区域屏蔽把道路区域拉黑空调外机/白色外墙高温气流引起画面抖动报烟火误报加大confirm_frames到 6并降低抽帧率到 2fps调参不是一次到位的。我自己的流程是先跑 24 小时统计日志里的 false positive再针对高频误报区域在配置里加zones排除列表。LntonAIServer 在 v1.0.01 里支持多边形屏蔽区定义可以把烟囱、路灯、车棚入口等容易干扰的位置圈出去比只调阈值更直接。5. 常见问题与避坑指南CPU 视频分析里我踩过的四个坑5.1 服务器 CPU 瞬间占满所有视频源同时断流现象启动 LntonAIServer 之后刚开始能正常分析大约 10 分钟后整机 CPU 冲到 100%日志里出现大量decoder timeout。原因这是典型的解码线程被阻塞。大多数视频分析服务默认会对所有配置的摄像头同时建立 RTSP 连接如果某一路摄像头网络质量差重连机制会反复发起 TCP 连接FFmpeg 解码器在等待 I 帧时长期占用线程资源最终拖垮整个进程。解决给每个视频源单独配置lazy_connect: true服务启动时不立即拉流等第一个分析请求到来时才建流。同时把connect_timeout设置为 5000ms重试间隔设置为 30s。这样断流的摄像头不会影响其他正常视频源。5.2 烟火识别没有任何报警日志却不报错现象视频画面里明明有燃烧的纸箱服务也显示了检测框但报警系统始终没收到事件。原因事件被报警状态机拦下了。现场有两类原因一是confirm_frames设置得太大目标只在画面出现 2 帧就被风吹走了状态机认为未达到持续确认二是回调地址返回 200 但响应体不是合法 JSON服务按失败重试多次后把事件丢弃。解决把confirm_frames从 5 临时降为 1再用真实火源测试一次。如果仍然不报警用 curl 模拟回调接口检查响应状态码和Content-Type是否规范。我后来养成的习惯是让回调接口直接返回{code:0}简单可靠不引入多余的判断逻辑。5.3 抽烟检测误报率奇高画面里手指、笔都被当成烟现象部署后一天收到上千条抽烟报警翻看截图发现全是手拿手机、笔或者嘴唇阴影。原因关键点在“检测分类”串联结构中的第一环——人手检测框不准确。手部检测框比实际区域大分类模型会把框内错位的物体当作烟支。另外conf_threshold设置到 0.35 太低手机反光在手部区域里极其像白烟。解决把抽烟检测的conf_threshold调到 0.6 之上并开启手部关键点对齐功能。该功能会先检测手腕、虎口、指尖将分类区域裁剪到食指和中指之间再送去推理。裁剪正确之后误报率通常能下降到原先的三分之一。5.4 多路视频并发时检测框和画面位置错位现象16 路摄像头接入后部分画面报出位置完全错误的目标框比如画面左侧的人触发了一个位于右侧的烟雾框。原因CPU 推理线程是并发的但报警回调没有绑定视频帧的时间戳。A 路摄像头的推理结果被延迟到 B 路的回调线程里发送。这类问题多出在把workers配置得过大比如 4 核机器设置workers8线程切换加剧了结果错位。解决严格按物理核心数重新分配workers4 核机器设 28 核机器设 4。同时确认每路视频分析结果里带stream_id在报警推送前做校验一旦发现回调 JSON 里stream_id和当前处理队列不一致就丢弃并重算。这样问题基本就能消失。6. 进阶玩法跑通闭环验收给服务端做一次“真刀真枪”的压力测试部署完成后强烈建议不要直接接入生产视频。我会先构造一段模拟视频流用 FFmpeg 循环推送到 LntonAIServer再人工触发火源和抽烟动作做完整闭环验收。这样既能验证算法阈值是否合适又能顺便压一压服务器的多路并发能力。第一步准备验收素材。把一段包含烟雾发生器的测试视频存成test_fire.mp4用 ffmpeg 的-stream_loop -1参数循环推 RTSP 流。如果没有现成的 RTSP 服务器可以用mediamtx快速起一个ffmpeg -stream_loop -1 -re -i test_fire.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/fire然后把这个地址填到 config.yaml 里服务立刻就能拉到流。这样做的好处是测试视频的每一帧都能被服务反复分析你可以用固定画面反复调节置信度阈值直到找到一个最稳定的值。这个过程属于“可控压测”用真实场景片段去调参比直接看监控大屏省心得多。第二步观察服务内部统计接口。LntonAIServer 在 v1.0.01 版本默认暴露/api/v1/statscurl 一下就能拿到 CPU 占用和每路视频的平均推理耗时curl http://127.0.0.1:8260/api/v1/stats返回结果里重点看avg_infer_ms和queue_depth。如果avg_infer_ms超过 200ms说明模型在当前机器上太吃力如果queue_depth持续增长说明抽帧节流没有生效。前面 2.3 节里说的动态触发抽帧在这里可以对照验证空画面时queue_depth应该稳定在 0有人物或烟雾目标出现时才短暂波动。第三步做多路并发测试。复制多个相同的转发串流地址改不同cam_id从 4 路开始加每加一路压测 10 分钟观察 CPU 和报警延迟。我通常在 8 路并发时要求每路报警延迟不超过 3 秒。达到这个指标再继续加路数然后找到 CPU 剩余 15% 的临界点。记住这个配置和路数作为生产环境上限。最后说一个我自己的教训曾经有一台 128 核大机器部署我贪心开了 48 路分析结果日志不报错CPU 也只用了 60%但报警延迟到了 20 秒。原因就是解码线程和网络连接数把进程文件描述符吃满了线程上下文切换成本极高。从那以后我每次压测都强制先跑一遍ulimit -n 65535并用脚本记录每路视频的connect_time与infer_ms的关联曲线宁可少接 4 路也要把单路报警延迟压进 2 秒内。希望这份资料里的部署经验能帮你在 CPU 算法落地上少走弯路。本文还有配套的精品资源点击获取