Files
rtsp-video-analysis-system/INSPECTION-WORKFLOW.md
2025-09-30 14:23:33 +08:00

12 KiB
Raw Permalink Blame History

巡检任务工作流程说明

📋 功能概述

本文档说明巡检任务的完整执行流程包括视频录制、保存、AI识别和告警创建。

🔄 完整工作流程

1. 任务启动

当巡检任务启动时:

InspectionTaskServiceImpl.executeInspectionTask(taskId)
  ├── 创建 InspectionTaskRecord记录ID
  ├── 更新任务状态为"执行中"
  └── 调用 performVideoAnalysisWithRecord()

2. 视频录制和保存

performVideoAnalysisWithRecord()
  ├── 从RTSP流抓取视频
  ├── 录制指定时长的视频
  ├── 保存为临时文件
  ├── 上传视频到MinIO
  ├── 更新InspectionTaskRecord.accessory视频URL
  └── 调用Python服务进行分析

3. AI识别处理

VideoAnalysisService.analyzeVideoWithRecord()
  ├── 创建HttpYoloDetector连接Python服务
  ├── 逐帧分析视频
  ├── 每10帧调用一次Python API检测
  ├── 绘制检测框
  ├── 去重检测结果(避免重复告警)
  ├── 创建告警记录
  ├── 上传处理后的视频
  ├── 生成检测结果摘要
  └── 更新InspectionTaskRecord.result识别结果

4. 告警创建(去重)

createAlarmRecordForRecord()
  ├── 提取检测区域图像
  ├── 上传告警图片到MinIO
  ├── 创建AlarmRecord
  │   ├── 设备ID
  │   ├── 告警类型
  │   ├── 告警内容(检测类别+置信度)
  │   ├── 关联的任务ID
  │   ├── 图片URL
  │   └── 帧位置
  └── 保存到数据库(仅新检测的对象)

📊 数据表关系

InspectionTask (巡检任务)
  ↓ 1:N
InspectionTaskRecord (巡检记录)
  ├── accessory: 原始视频URL + 处理后视频URL
  ├── result: AI识别结果摘要
  ├── duration: 执行时长
  └── status: 0=成功, 1=失败, 2=部分成功
  
InspectionTaskRecord → AlarmRecord (1:N)
  ├── 同一个record可以有多个告警
  └── 告警自动去重(相同位置的相同对象只记录一次)

🎯 关键字段说明

InspectionTaskRecord

字段 说明 示例
recordId 记录ID 自增主键
taskId 关联的任务ID 1001
executeTime 执行时间 2025-09-30 14:30:00
duration 执行时长(秒) 30
accessory 附件URL video1.mp4;video2.mp4
result 识别结果 共检测到3个问题详情垃圾(2) 烟雾(1)
status 执行状态 0=成功, 1=失败, 2=部分成功

AlarmRecord

字段 说明 示例
alarmId 告警ID 自增主键
deviceId 设备ID 1001
taskId 任务ID 1001
alarmType 告警类型 detection
alarmContent 告警内容 垃圾 - 置信度: 0.95
imageOssId 告警图片ID MinIO对象ID
framePosition 视频帧位置 150
confidence 置信度 0.95
status 处理状态 0=未处理, 1=已处理

🔧 关键实现细节

1. 去重机制

使用generateDetectionKey生成唯一键:

private String generateDetectionKey(Detection detection) {
    Rect rect = detection.getRect();
    // 取10的倍数允许小范围波动
    int x = rect.x() / 10 * 10;
    int y = rect.y() / 10 * 10;
    int w = rect.width() / 10 * 10;
    int h = rect.height() / 10 * 10;
    return String.format("%s_%d_%d_%d_%d", detection.getLabel(), x, y, w, h);
}

原理

  • 相同类别 + 相似位置 → 认为是同一个对象
  • 允许10像素的波动
  • 超过60秒未检测到自动清除

2. Python服务调用

使用容器名调用:

private static final String PYTHON_API_URL = "http://rtsp-python-service:8000/api/detect/file";
private static final String MODEL_NAME = "yolov8_detector";

3. 视频处理流程

RTSP流 → FFmpegFrameGrabber → 录制 → 临时文件 
  → 上传MinIO → 保存URL到record.accessory
  → 逐帧分析 → 调用Python API → 绘制检测框
  → 保存处理后视频 → 追加URL到record.accessory
  → 更新record.result

4. 附件字段格式

accessory字段使用分号分隔多个URL

原始视频URL;处理后视频URL

示例:

http://minio.com/inspection-videos/inspection_1001_1234567890.mp4;http://minio.com/inspection-videos/processed_1234567891.mp4

🚀 使用方法

1. 创建巡检任务

InspectionTask task = new InspectionTask();
task.setDeviceId(deviceId);
task.setDuration(30); // 录制30秒
task.setStatus(0); // 待执行

inspectionTaskService.insertInspectionTask(task);

2. 启动任务

// 异步执行
inspectionTaskService.executeInspectionTask(taskId);

3. 查看执行记录

-- 查询某任务的所有执行记录
SELECT * FROM v_inspection_task_record WHERE task_id = 1001 ORDER BY execute_time DESC;

-- 查询成功的记录
SELECT * FROM v_inspection_task_record WHERE status = 0;

-- 查询某记录的所有告警
SELECT * FROM v_alarm_record WHERE task_id = 1001;

4. 查看告警

-- 查询某任务的所有告警
SELECT * FROM v_alarm_record WHERE task_id = 1001 ORDER BY create_time DESC;

-- 查询未处理的告警
SELECT * FROM v_alarm_record WHERE status = 0;

📝 执行示例

执行流程

  1. 任务创建

    Task ID: 1001
    Device ID: 5001
    Duration: 30秒
    
  2. 记录创建

    Record ID: 2001
    Task ID: 1001
    Execute Time: 2025-09-30 14:30:00
    Status: 1 (执行中)
    
  3. 视频录制

    录制30秒视频
    保存到MinIO: inspection_1001_1234567890.mp4
    更新Record.accessory: http://minio.com/.../inspection_1001_1234567890.mp4
    
  4. AI识别

    调用Python服务
    检测到: 垃圾(2个), 烟雾(1个)
    
  5. 告警创建(去重)

    Alarm 1: 垃圾 - 位置(100,200) - 置信度0.95
    Alarm 2: 垃圾 - 位置(300,400) - 置信度0.87
    Alarm 3: 烟雾 - 位置(500,100) - 置信度0.92
    
  6. 处理后视频

    带检测框的视频上传
    保存到MinIO: processed_1234567891.mp4
    更新Record.accessory: 原始URL;处理后URL
    
  7. 更新记录

    Record.result: "共检测到 3 个问题,详情:垃圾(2) 烟雾(1)"
    Record.status: 0 (成功)
    Record.duration: 32秒
    

⚙️ 配置说明

Python服务配置

在Docker环境中Python服务地址为

http://rtsp-python-service:8000

模型配置

确保Python服务使用正确的模型名称

{
  "name": "yolov8_detector",
  "path": "models/yolov8_model.py",
  "size": [640, 640]
}

检测参数

VideoAnalysisService中可调整:

// 检测频率每N帧检测一次
if (frameCount % 10 == 0) { ... }

// 去重时间窗口(秒)
detectedGarbageCache.entrySet().removeIf(entry -> 
    (currentId - entry.getValue()) > grabber.getFrameRate() * 60);

🐛 故障排查

问题1: 视频未保存

检查

-- 查看record的accessory字段
SELECT record_id, accessory FROM v_inspection_task_record WHERE task_id = ?;

-- 查看MinIO对象
SELECT * FROM v_minio_object WHERE bucket_name = 'inspection-videos' ORDER BY create_time DESC;

解决

  • 检查MinIO服务是否可用
  • 检查网络连接
  • 查看后端日志

问题2: Python识别未执行

检查

# 查看Python服务日志
docker-compose logs python-service

# 测试Python服务
curl http://rtsp-python-service:8000/health
curl http://rtsp-python-service:8000/api/models

解决

  • 确认Python服务运行正常
  • 确认模型文件存在
  • 检查网络连通性

问题3: 告警未创建

检查

-- 查看告警记录
SELECT * FROM v_alarm_record WHERE task_id = ? ORDER BY create_time DESC;

-- 查看检测结果
SELECT result FROM v_inspection_task_record WHERE record_id = ?;

解决

  • 检查检测置信度阈值
  • 查看视频内容是否有检测对象
  • 检查Python服务返回结果

问题4: 重复告警

检查

  • 去重机制是否正常工作
  • generateDetectionKey逻辑是否合理

调整

// 调整去重的位置容差
int x = rect.x() / 20 * 20;  // 从10改为20更宽松的去重

📊 性能优化

1. 检测频率

// 降低检测频率以提升性能CPU模式
if (frameCount % 30 == 0) { // 从10改为30
    // 每30帧检测一次
}

2. 视频质量

// 降低视频比特率节省存储
recorder.setVideoBitrate(500000); // 降低比特率

3. 去重时间窗口

// 缩短去重时间窗口
(currentId - entry.getValue()) > grabber.getFrameRate() * 30  // 从60秒改为30秒

🔍 调试方法

查看执行日志

# 查看后端日志
docker-compose logs -f backend | grep "inspection"

# 查看Python服务日志
docker-compose logs -f python-service

# 查看特定记录的处理过程
docker-compose logs backend | grep "recordId=2001"

数据库查询

-- 查看最新的执行记录
SELECT 
    r.record_id,
    r.task_id,
    r.execute_time,
    r.duration,
    r.status,
    r.result,
    LENGTH(r.accessory) as accessory_length
FROM v_inspection_task_record r
ORDER BY r.create_time DESC
LIMIT 10;

-- 查看记录对应的告警
SELECT 
    a.alarm_id,
    a.alarm_content,
    a.confidence,
    a.frame_position,
    a.create_time
FROM v_alarm_record a
WHERE a.task_id = ?
ORDER BY a.create_time DESC;

-- 统计告警数量
SELECT 
    r.record_id,
    r.execute_time,
    COUNT(a.alarm_id) as alarm_count
FROM v_inspection_task_record r
LEFT JOIN v_alarm_record a ON r.task_id = a.task_id
    AND a.create_time >= r.execute_time
    AND a.create_time <= DATE_ADD(r.execute_time, INTERVAL r.duration SECOND)
GROUP BY r.record_id
ORDER BY r.create_time DESC;

💡 扩展建议

1. 添加检测类型过滤

createAlarmRecordForRecord中:

// 只对特定类型创建告警
List<String> alarmTypes = Arrays.asList("垃圾", "烟雾", "火焰");
if (!alarmTypes.contains(detection.getLabel())) {
    return; // 忽略其他类型
}

2. 添加置信度阈值

// 只对高置信度的检测创建告警
if (detection.getConfidence() < 0.7) {
    return; // 忽略低置信度检测
}

3. 添加区域过滤

// 只对特定区域的检测创建告警
Rect rect = detection.getRect();
if (!isInMonitorArea(rect, task)) {
    return; // 忽略监控区域外的检测
}

4. 添加告警级别

// 根据检测类型设置告警级别
String alarmLevel = "medium";
if (detection.getLabel().contains("火焰")) {
    alarmLevel = "high";
} else if (detection.getLabel().contains("垃圾")) {
    alarmLevel = "low";
}
alarmRecord.setAlarmLevel(alarmLevel);

🔒 安全考虑

1. 异常处理

所有方法都包含完整的异常处理:

  • 视频录制失败 → 更新record状态为失败
  • Python服务调用失败 → 记录错误但不影响整体流程
  • MinIO上传失败 → 记录错误并回滚

2. 资源清理

使用try-finally确保资源释放

  • FFmpegFrameGrabber自动关闭
  • FFmpegFrameRecorder自动关闭
  • 临时文件自动删除

3. 并发控制

使用@Async异步执行,避免阻塞:

  • 任务执行不阻塞API响应
  • 多个任务可并发执行
  • 通过runningTasks避免重复执行

📈 监控指标

建议监控的指标

  1. 执行成功率

    SELECT 
        COUNT(CASE WHEN status = 0 THEN 1 END) * 100.0 / COUNT(*) as success_rate
    FROM v_inspection_task_record
    WHERE execute_time >= DATE_SUB(NOW(), INTERVAL 1 DAY);
    
  2. 平均执行时长

    SELECT AVG(duration) as avg_duration
    FROM v_inspection_task_record
    WHERE status = 0 AND execute_time >= DATE_SUB(NOW(), INTERVAL 1 DAY);
    
  3. 告警统计

    SELECT 
        alarm_type,
        COUNT(*) as count
    FROM v_alarm_record
    WHERE create_time >= DATE_SUB(NOW(), INTERVAL 1 DAY)
    GROUP BY alarm_type;
    

📞 技术支持

如有问题,请查看:

  1. 后端日志:docker-compose logs backend
  2. Python服务日志docker-compose logs python-service
  3. 数据库记录:查询v_inspection_task_recordv_alarm_record
  4. MinIO对象查询v_minio_object

文档版本: 1.0 最后更新: 2025-09-30 适用版本: YOLOv8, Docker Compose部署