新增内容: - 项目概述(边缘 AI 推理服务功能说明) - 常用命令(本地开发、测试、工具脚本、Docker 部署) - 架构概览(核心模块详细说明) - 配置同步、视频流、推理引擎、告警上报 - 算法模块(离岗、入侵检测) - 数据流说明(配置下发、视频推理、告警上报、截图请求) - Redis Key 设计(云端 + 本地) - 配置文件说明(.env 环境变量、YAML 配置) - 告警上报数据格式(触发和结束) - 开发工作流(添加算法、修改推理流程、优化性能) - 常见问题排查(引擎加载、告警失败、配置更新、GPU 内存) - Git 提交规范 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
9.0 KiB
9.0 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
项目概述
边缘 AI 推理服务,部署在客户现场边缘端。通过 TensorRT GPU 加速实时分析视频流,检测离岗、入侵等异常行为,上报告警到云端。支持配置热更新、截图上传、告警去重等功能。
部署位置: 边缘端(客户现场) 运行方式: 裸机部署或 Docker(需要 GPU 支持) 主要功能:
- RTSP 视频流接入(从 WVP 平台拉流)
- TensorRT GPU 推理(批量处理,8 帧/批次)
- 多算法支持(leave_post 离岗、intrusion 入侵)
- 告警去重(ROI 级 + 摄像头级冷却)
- 配置热更新(Redis Stream 订阅)
- 截图上传(腾讯云 COS)
- 告警上报(HTTP POST 到云端)
常用命令
本地开发
# 安装依赖(Python 3.8+)
pip install -r requirements.txt
# 配置环境
cp .env.example .env
# 编辑 .env:
# DEVICE_ID=edge_device_001
# CLOUD_REDIS_HOST=腾讯云Redis地址
# CLOUD_REDIS_PORT=6379
# CLOUD_REDIS_PASSWORD=密码
# LOCAL_REDIS_HOST=localhost
# LOCAL_REDIS_PORT=6379
# COS_SECRET_ID=腾讯云COS密钥ID
# COS_SECRET_KEY=腾讯云COS密钥KEY
# COS_BUCKET=your-bucket
# COS_REGION=ap-beijing
# CLOUD_API_URL=http://云端IP:8000
# 运行推理服务
python main.py
测试
# 运行完整工作流测试
python test_leave_post_full_workflow.py
# 运行无持续时长测试
python test_leave_post_no_duration.py
# 运行单元测试
pytest tests/
pytest -v tests/test_config_sync.py
工具脚本
# 诊断缺失摄像头配置
python diagnose_missing_cameras.py
# 清理旧的 ROI 配置
python cleanup_old_rois.py
# 恢复摄像头配置
python restore_cameras.py
Docker 部署(生产环境)
# 构建镜像(需要 CUDA 12.1 + TensorRT 8.6 基础镜像)
docker build -t edge-inference:latest .
# 运行容器(需要 GPU 支持)
docker run -d \
--name edge-inference \
--gpus all \
--restart=always \
-v /path/to/models:/app/models \
-v /path/to/.env:/app/.env \
-v /path/to/data:/app/data \
edge-inference:latest
# 查看日志
docker logs -f edge-inference
# 重启容器
docker restart edge-inference
# 进入容器调试
docker exec -it edge-inference /bin/bash
# 检查 GPU 使用情况
nvidia-smi
架构概览
核心模块(core/)
-
config_sync.py — 配置同步管理器
- 订阅云端 Redis Stream:
device_config_stream - 拉取配置:
GET device:{device_id}:config - 版本控制、自动回滚、离线可用
- 热更新视频流(启停摄像头)
- 订阅云端 Redis Stream:
-
video_stream.py — 多流管理器
- RTSP 拉流、解码、帧缓存
- 多路并发处理
- 流状态监控、自动重连
-
preprocessor.py — 图像预处理
- Resize、Normalize、NCHW 转换
- 批量预处理(8 帧/批次)
-
tensorrt_engine.py — TensorRT 推理引擎
- Engine 缓存管理
- 批量推理(提升吞吐量)
- GPU 内存优化
-
postprocessor.py — 后处理器
- NMS(非极大值抑制)
- ROI 区域过滤(point-in-polygon)
- 算法分发(根据 algorithm_code)
-
result_reporter.py — 结果上报器
- 生成 alarm_id:
edge_{device_id}_{timestamp}_{uuid6} - LPUSH 到本地 Redis:
local:alarm:pending - 零阻塞(立即返回)
- 生成 alarm_id:
-
alarm_upload_worker.py — 告警上传 Worker
- 独立线程,BRPOP 消费队列
- 上传截图到腾讯云 COS
- HTTP POST 到云端:
/api/ai/alert/edge/report - 失败重试(3 次)→ 死信队列
-
screenshot_handler.py — 截图处理器
- XREADGROUP 订阅云端 Redis Stream:
edge_snap_request - 从视频流获取最新帧
- 上传 COS,HTTP 回调 WVP
- XREADGROUP 订阅云端 Redis Stream:
算法模块(algorithms.py)
已实现算法:
-
LeavePostAlgorithm — 离岗检测
- 检测 ROI 内是否有人
- 持续无人触发告警
- 人员回归发送 resolve 通知
-
IntrusionAlgorithm — 入侵检测
- 检测 ROI 内是否有人入侵
- 立即触发告警
算法接口:
class AlgorithmBase:
def process(self, detections, roi_info, camera_id, bind_info):
"""
处理检测结果
Args:
detections: 检测框列表 [{class_id, confidence, bbox}]
roi_info: ROI 配置 {roi_id, polygon, ...}
camera_id: 摄像头 ID
bind_info: 算法绑定配置 {threshold, cooldown, ...}
Returns:
告警信息或 None
"""
pass
数据流
配置下发:
WVP → XADD device_config_stream → Edge XREADGROUP
→ 拉取 Redis config → 版本校验 → 热更新视频流
视频推理:
RTSP 拉流 → 解码 → 预处理 → TensorRT 推理
→ NMS → ROI 过滤 → 算法处理 → 告警去重
→ LPUSH local:alarm:pending
告警上报:
BRPOP 队列 → 上传 COS 截图 → HTTP POST 云端
→ 失败重试 → 死信队列
截图请求:
WVP → XADD edge_snap_request → Edge XREADGROUP
→ 获取帧 → 上传 COS → HTTP 回调 WVP
Redis Key 设计
云端 Redis
device:{device_id}:config— 设备最新配置 JSONdevice:{device_id}:version— 配置版本号device_config_stream— 配置变更 Streamedge_snap_request— 截图请求 Stream
本地 Redis
local:device:config:current— 当前生效配置local:device:config:backup— 上次成功配置(回滚用)local:device:config:version— 当前版本号local:alarm:pending— 待上报告警队列local:alarm:retry— 重试队列local:alarm:dead— 死信队列
配置文件
.env 环境变量(关键配置)
# 设备标识
DEVICE_ID=edge_device_001
# 云端 Redis(配置同步)
CLOUD_REDIS_HOST=腾讯云Redis地址
CLOUD_REDIS_PORT=6379
CLOUD_REDIS_PASSWORD=密码
# 本地 Redis(告警队列、配置缓存)
LOCAL_REDIS_HOST=localhost
LOCAL_REDIS_PORT=6379
# 腾讯云 COS(截图上传)
COS_SECRET_ID=your_secret_id
COS_SECRET_KEY=your_secret_key
COS_BUCKET=your-bucket-1234567890
COS_REGION=ap-beijing
# 云端 API(告警上报)
CLOUD_API_URL=http://云端IP:8000
config/ 目录(YAML 配置)
settings.py— 配置加载器(读取 .env)database.py— SQLite 管理器(本地配置持久化)config_models.py— 配置数据模型
告警上报数据格式
告警触发(POST /api/ai/alert/edge/report)
{
"alarm_id": "edge_device001_20260305120000_a1b2c3",
"alarm_type": "leave_post",
"device_id": "camera_001",
"scene_id": "roi_001",
"event_time": "2026-03-05T12:00:00Z",
"alarm_level": 2,
"snapshot_url": "https://cos.ap-beijing.myqcloud.com/...",
"confidence_score": 0.92,
"algorithm_code": "YOLO",
"ext_data": {
"bind_id": "bind_123",
"bbox": [100, 100, 300, 400],
"first_frame_time": "2026-03-05T12:00:00Z"
}
}
告警结束(POST /api/ai/alert/edge/resolve)
{
"alarm_id": "edge_device001_20260305120000_a1b2c3",
"duration_ms": 120000,
"last_frame_time": "2026-03-05T12:02:00Z",
"resolve_type": "PERSON_RETURN"
}
开发工作流
添加新算法
- 在
algorithms.py创建新的算法类,继承AlgorithmBase - 实现
process()方法 - 在
AlgorithmManager注册算法 - 更新 WVP 后端的算法配置表
修改推理流程
- 修改
main.py中的EdgeInferenceService - 调整批量大小:
self._max_batch_size - 调整冷却时间:
self._camera_cooldown_seconds
调整告警去重策略
- ROI 级冷却:每个 ROI 独立冷却
- 摄像头级冷却:同摄像头同类型告警冷却
- 修改:
main.py中的_camera_alert_cooldown逻辑
优化性能
- 批量推理:调整
_max_batch_size(默认 8) - GPU 内存:减少视频流并发数
- 告警队列:监控 Redis 队列长度
- TensorRT 引擎:确保引擎缓存命中
常见问题
TensorRT 引擎加载慢
首次运行会构建引擎(5-10 分钟),之后会缓存。
检查 models/ 目录下是否有 .engine 文件。
告警上报失败
检查云端 API 是否可达:
curl http://云端IP:8000/health
检查 COS 配置:
# 查看 .env 中的 COS 配置
cat .env | grep COS
配置不更新
检查云端 Redis 连接:
redis-cli -h 云端Redis地址 -p 6379 -a 密码 ping
检查配置版本:
redis-cli GET device:edge_device_001:version
redis-cli GET local:device:config:version
视频流断开
检查 RTSP 地址是否可访问:
ffprobe rtsp://云端IP:10002/...
检查 WVP 流媒体服务:
docker logs vsp-zlmedia
GPU 内存不足
降低批量大小或减少并发流数量。 检查 GPU 使用情况:
nvidia-smi
Git 提交规范
在修改代码后,使用中文提交信息:
git add .
git commit -m "功能:添加XXX功能
详细说明...
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
不要立即 push,等待用户指示再推送到远程。