172 lines
6.8 KiB
Python
172 lines
6.8 KiB
Python
import unittest
|
|
|
|
from video_ai_analysis_poc.result_parser import build_clip_result, extract_json_payload
|
|
|
|
|
|
class ResultParserTests(unittest.TestCase):
|
|
def test_extract_json_payload_handles_markdown_and_prose(self):
|
|
payload = extract_json_payload(
|
|
"analysis follows\n```json\n{\"screen_time\":\"12:31:20\",\"events\":[]}\n```"
|
|
)
|
|
|
|
self.assertEqual(payload, {"screen_time": "12:31:20", "events": []})
|
|
|
|
def test_build_clip_result_preserves_timeline_screen_time_and_events(self):
|
|
clip_record = {
|
|
"video_id": "video-abc",
|
|
"clip_id": "video-abc_c000001",
|
|
"clip_start_seconds": 120.0,
|
|
"clip_end_seconds": 130.0,
|
|
"clip_start_timecode": "00:02:00",
|
|
"clip_end_timecode": "00:02:10",
|
|
"clip_start_beijing_time": "2026-06-15 07:02:00",
|
|
"clip_end_beijing_time": "2026-06-15 07:02:10",
|
|
"frame_times": [
|
|
{
|
|
"frame_path": "frames/video-abc/000120.jpg",
|
|
"offset_seconds": 120.0,
|
|
"timecode": "00:02:00",
|
|
"beijing_time": "2026-06-15 07:02:00",
|
|
}
|
|
],
|
|
}
|
|
raw_response = (
|
|
"Here is the result: "
|
|
"{\"画面时间\":\"2026-06-14 12:31:20\","
|
|
"\"events\":[{\"event_type\":\"queue_detected\",\"confidence\":0.86}]}"
|
|
)
|
|
|
|
result = build_clip_result(
|
|
raw_response,
|
|
clip_record,
|
|
{"path": "/videos/a.mp4"},
|
|
{
|
|
"schema": {"version": "local-batch-v1"},
|
|
"runtime": {"timezone": "Asia/Shanghai"},
|
|
},
|
|
processing={"latency_ms": 1800},
|
|
)
|
|
|
|
self.assertEqual(result["schema_version"], "local-batch-v1")
|
|
self.assertEqual(result["video_id"], "video-abc")
|
|
self.assertEqual(result["video_path"], "/videos/a.mp4")
|
|
self.assertEqual(result["clip_id"], "video-abc_c000001")
|
|
self.assertEqual(result["status"], "ok")
|
|
self.assertEqual(result["monitoring_timeline"]["timezone"], "Asia/Shanghai")
|
|
self.assertIsNone(result["monitoring_timeline"]["video_start_time"])
|
|
self.assertEqual(
|
|
result["monitoring_timeline"]["clip_start_beijing_time"],
|
|
"2026-06-15 07:02:00",
|
|
)
|
|
self.assertEqual(
|
|
result["monitoring_timeline"]["clip_end_beijing_time"],
|
|
"2026-06-15 07:02:10",
|
|
)
|
|
self.assertEqual(result["monitoring_timeline"]["frame_times"], clip_record["frame_times"])
|
|
self.assertEqual(
|
|
result["monitoring_timeline"]["screen_time"],
|
|
"2026-06-14 12:31:20",
|
|
)
|
|
self.assertEqual(result["events"][0]["event_type"], "queue_detected")
|
|
self.assertEqual(result["events"][0]["start_offset_seconds"], 120.0)
|
|
self.assertEqual(result["events"][0]["end_offset_seconds"], 130.0)
|
|
self.assertEqual(result["raw_response"], raw_response)
|
|
self.assertEqual(result["processing"]["latency_ms"], 1800)
|
|
self.assertIsNone(result["error"])
|
|
|
|
def test_build_clip_result_reads_zhengxin_time_key(self):
|
|
result = build_clip_result(
|
|
(
|
|
'{"Action":"Action_Idle","quality_status":"qualified",'
|
|
'"error_type":"","安全隐患":"","人物位置":"","总结":"无",'
|
|
'"时间":"2026-06-14 12:31:20","employees":[],"guests":[]}'
|
|
),
|
|
{
|
|
"video_id": "video-abc",
|
|
"clip_id": "video-abc_c000001",
|
|
"clip_start_seconds": 0.0,
|
|
"clip_end_seconds": 10.0,
|
|
"clip_start_timecode": "00:00:00",
|
|
"clip_end_timecode": "00:00:10",
|
|
"frame_times": [],
|
|
},
|
|
{"path": "/videos/a.mp4"},
|
|
{
|
|
"schema": {"version": "local-batch-v1"},
|
|
"runtime": {"timezone": "Asia/Shanghai"},
|
|
},
|
|
processing={},
|
|
)
|
|
|
|
self.assertEqual(result["status"], "ok")
|
|
self.assertEqual(
|
|
result["monitoring_timeline"]["screen_time"],
|
|
"2026-06-14 12:31:20",
|
|
)
|
|
|
|
def test_build_clip_result_preserves_qsc_events(self):
|
|
result = build_clip_result(
|
|
(
|
|
'{"Action":"Action_Idle","quality_status":"","error_type":"",'
|
|
'"安全隐患":"","人物位置":"员工在操作台边","总结":"画面中有1人",'
|
|
'"时间":"2026-06-16 05:00:03","employees":[],"guests":[],'
|
|
'"qsc_events":[{"violation_code":"WGSJ0001",'
|
|
'"violation_type":"工作状态未戴口罩","is_violation":true,'
|
|
'"working_state":"working","reason":"员工在操作台处理食物时未见口罩",'
|
|
'"confidence":0.92,"evidence_frame_count":3,'
|
|
'"visible_target":"操作台边员工","evidence_checklist":{},'
|
|
'"suggested_action":"warning"}]}'
|
|
),
|
|
{
|
|
"video_id": "video-abc",
|
|
"clip_id": "video-abc_c000001",
|
|
"clip_start_seconds": 0.0,
|
|
"clip_end_seconds": 10.0,
|
|
"clip_start_timecode": "00:00:00",
|
|
"clip_end_timecode": "00:00:10",
|
|
"frame_times": [],
|
|
},
|
|
{"path": "/videos/a.mp4"},
|
|
{
|
|
"schema": {"version": "local-batch-v1"},
|
|
"runtime": {"timezone": "Asia/Shanghai"},
|
|
},
|
|
processing={},
|
|
)
|
|
|
|
self.assertEqual(result["status"], "ok")
|
|
self.assertEqual(len(result["qsc_events"]), 1)
|
|
self.assertEqual(result["qsc_events"][0]["violation_code"], "WGSJ0001")
|
|
self.assertEqual(result["qsc_events"][0]["suggested_action"], "warning")
|
|
|
|
def test_build_clip_result_records_parse_failure_without_crashing(self):
|
|
result = build_clip_result(
|
|
"not json",
|
|
{
|
|
"video_id": "video-abc",
|
|
"clip_id": "video-abc_c000001",
|
|
"clip_start_seconds": 0.0,
|
|
"clip_end_seconds": 10.0,
|
|
"clip_start_timecode": "00:00:00",
|
|
"clip_end_timecode": "00:00:10",
|
|
"frame_times": [],
|
|
},
|
|
{"path": "/videos/a.mp4"},
|
|
{
|
|
"schema": {"version": "local-batch-v1"},
|
|
"runtime": {"timezone": "Asia/Shanghai"},
|
|
},
|
|
processing={},
|
|
)
|
|
|
|
self.assertEqual(result["status"], "parse_failed")
|
|
self.assertEqual(result["events"], [])
|
|
self.assertEqual(result["qsc_events"], [])
|
|
self.assertEqual(result["monitoring_timeline"]["screen_time"], "")
|
|
self.assertEqual(result["raw_response"], "not json")
|
|
self.assertIn("JSON", result["error"])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|