diff --git a/fam-core/src/fam_core/db_layer.py b/fam-core/src/fam_core/db_layer.py index 856d591..af00032 100644 --- a/fam-core/src/fam_core/db_layer.py +++ b/fam-core/src/fam_core/db_layer.py @@ -187,12 +187,21 @@ def insert_event(task_id: int, event_start_time: str, event_end_time: str, conn = get_conn() try: cursor = conn.cursor() + # event_start/end_time 为 NOT NULL 列: 空值兜底 + # end 缺失 → 用 start;start 也缺失 → 用当前时间 + dt_start = _dt_or_none(event_start_time) + dt_end = _dt_or_none(event_end_time) + if not dt_end: + dt_end = dt_start + if not dt_start: + from datetime import datetime as _dt + dt_start = dt_end = _dt.now().strftime('%Y-%m-%d %H:%M:%S') cursor.execute( """INSERT INTO monitor_events (task_id, event_start_time, event_end_time, camera_name, global_summary, entities_json, compute_provider) VALUES (%s, %s, %s, %s, %s, %s, %s)""", - (task_id, _dt_or_none(event_start_time), _dt_or_none(event_end_time), camera_name, + (task_id, dt_start, dt_end, camera_name, global_summary, json.dumps(entities_json, ensure_ascii=False), json.dumps(compute_provider, ensure_ascii=False)) ) @@ -214,12 +223,17 @@ def insert_event_detail(event_id: int, task_id: int, frame_index: int, conn = get_conn() try: cursor = conn.cursor() + # frame_timestamp 为 NOT NULL 列: 空值兜底为当前时间 + dt_ts = _dt_or_none(frame_timestamp) + if not dt_ts: + from datetime import datetime as _dt + dt_ts = _dt.now().strftime('%Y-%m-%d %H:%M:%S') cursor.execute( """INSERT INTO event_details (event_id, task_id, frame_index, frame_timestamp, camera_name, person, action, clothing, is_attention_event, source_providers) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", - (event_id, task_id, frame_index, _dt_or_none(frame_timestamp), camera_name, + (event_id, task_id, frame_index, dt_ts, camera_name, person, action, clothing, is_attention_event, json.dumps(source_providers, ensure_ascii=False)) ) diff --git a/fam-edge/src/fam_edge/ai_orchestrator/orchestrator.py b/fam-edge/src/fam_edge/ai_orchestrator/orchestrator.py index 58c8a80..df4ad3c 100644 --- a/fam-edge/src/fam_edge/ai_orchestrator/orchestrator.py +++ b/fam-edge/src/fam_edge/ai_orchestrator/orchestrator.py @@ -14,6 +14,7 @@ import time import json import base64 import requests +from datetime import datetime, timedelta from concurrent.futures import ThreadPoolExecutor, as_completed, TimeoutError as FuturesTimeout from typing import Dict, List, Optional @@ -366,6 +367,17 @@ class AIOrchestrator: video_path, len(compressed_frames), event_start_time ) + # event_end_time 未提供时,用 start + 视频时长推算(DB 列 NOT NULL) + event_end_time = task_data.get('event_end_time', '') + if not event_end_time and event_start_time and preprocessor.video_duration > 0: + try: + start_dt = datetime.strptime(event_start_time, '%Y-%m-%d %H:%M:%S') + event_end_time = ( + start_dt + timedelta(seconds=int(preprocessor.video_duration)) + ).strftime('%Y-%m-%d %H:%M:%S') + except ValueError: + pass + # 3. 并行视觉分析 model_outputs = self.run_visual_analysis( healthy_adapters, compressed_frames, frame_timestamps, known_members @@ -383,7 +395,7 @@ class AIOrchestrator: "task_id": task_id, "status": "success", "event_start_time": event_start_time, - "event_end_time": task_data.get('event_end_time', ''), + "event_end_time": event_end_time, "camera_name": task_data.get('camera_name', ''), "global_summary": fusion_result.get('global_summary', ''), "entities_json": fusion_result.get('entities_json', []),