From ef0047af6d28e9d99df40dde28c3ea7f1977b01a Mon Sep 17 00:00:00 2001 From: yangyl Date: Wed, 17 Jun 2026 11:33:54 +0800 Subject: [PATCH] Initial video AI analysis project --- .gitignore | 37 + agent.md | 250 ++++ config/local_batch.yaml | 173 +++ docs/project.md | 719 ++++++++++ .../2026-06-16-hik-cloud-download-analysis.md | 190 +++ ...6-16-hik-cloud-download-analysis-design.md | 151 ++ tests/test_aggregator.py | 309 ++++ tests/test_cli.py | 1275 +++++++++++++++++ tests/test_clips.py | 167 +++ tests/test_config.py | 240 ++++ tests/test_discovery.py | 41 + tests/test_ffmpeg_sampler.py | 357 +++++ tests/test_frames.py | 61 + tests/test_hik_cloud.py | 554 +++++++ tests/test_manifest.py | 30 + tests/test_probe.py | 51 + tests/test_result_parser.py | 135 ++ tests/test_vlm_client.py | 85 ++ video_ai_analysis_poc/__init__.py | 9 + video_ai_analysis_poc/aggregator.py | 403 ++++++ video_ai_analysis_poc/cli.py | 424 ++++++ video_ai_analysis_poc/clips.py | 158 ++ video_ai_analysis_poc/config.py | 278 ++++ video_ai_analysis_poc/discovery.py | 27 + video_ai_analysis_poc/ffmpeg_sampler.py | 243 ++++ video_ai_analysis_poc/frames.py | 59 + video_ai_analysis_poc/hik_cloud.py | 450 ++++++ video_ai_analysis_poc/manifest.py | 35 + video_ai_analysis_poc/paths.py | 71 + video_ai_analysis_poc/probe.py | 99 ++ video_ai_analysis_poc/result_parser.py | 138 ++ video_ai_analysis_poc/timeline.py | 67 + video_ai_analysis_poc/vlm_client.py | 134 ++ video_ai_analysis_system_plan.md | 1193 +++++++++++++++ 录像下载流程_1.pdf | Bin 0 -> 477499 bytes 35 files changed, 8613 insertions(+) create mode 100644 .gitignore create mode 100644 agent.md create mode 100644 config/local_batch.yaml create mode 100644 docs/project.md create mode 100644 docs/superpowers/plans/2026-06-16-hik-cloud-download-analysis.md create mode 100644 docs/superpowers/specs/2026-06-16-hik-cloud-download-analysis-design.md create mode 100644 tests/test_aggregator.py create mode 100644 tests/test_cli.py create mode 100644 tests/test_clips.py create mode 100644 tests/test_config.py create mode 100644 tests/test_discovery.py create mode 100644 tests/test_ffmpeg_sampler.py create mode 100644 tests/test_frames.py create mode 100644 tests/test_hik_cloud.py create mode 100644 tests/test_manifest.py create mode 100644 tests/test_probe.py create mode 100644 tests/test_result_parser.py create mode 100644 tests/test_vlm_client.py create mode 100644 video_ai_analysis_poc/__init__.py create mode 100644 video_ai_analysis_poc/aggregator.py create mode 100644 video_ai_analysis_poc/cli.py create mode 100644 video_ai_analysis_poc/clips.py create mode 100644 video_ai_analysis_poc/config.py create mode 100644 video_ai_analysis_poc/discovery.py create mode 100644 video_ai_analysis_poc/ffmpeg_sampler.py create mode 100644 video_ai_analysis_poc/frames.py create mode 100644 video_ai_analysis_poc/hik_cloud.py create mode 100644 video_ai_analysis_poc/manifest.py create mode 100644 video_ai_analysis_poc/paths.py create mode 100644 video_ai_analysis_poc/probe.py create mode 100644 video_ai_analysis_poc/result_parser.py create mode 100644 video_ai_analysis_poc/timeline.py create mode 100644 video_ai_analysis_poc/vlm_client.py create mode 100644 video_ai_analysis_system_plan.md create mode 100644 录像下载流程_1.pdf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..064557c --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +# Secrets and local credentials +access_token.md +.env +.env.* +*.pem +*.key + +# Runtime inputs and generated outputs +outputs/ +videos/ +downloads/ +frames/ +codex_records/ + +# Agent working notes, not project source +findings.md +memories.md +progress.md +task_plan.md + +# Python caches and test artifacts +__pycache__/ +*.py[cod] +.pytest_cache/ +.coverage +htmlcov/ + +# Local indexes, editor, and OS files +.codegraph/ +.DS_Store +.idea/ +.vscode/ + +# Logs and temporary files +*.log +*.pid +*.tmp diff --git a/agent.md b/agent.md new file mode 100644 index 0000000..6308b48 --- /dev/null +++ b/agent.md @@ -0,0 +1,250 @@ +# Video AI Analysis PoC Agent Instructions + +本文件约束后续 AI 在 `/Users/yoilun/AI-train/video-ai-analysis-poc` 中的开发、审查、测试和文档维护行为。任何业务代码修改前必须先阅读并遵守本文件。 + +## Repository Snapshot + +- 项目名称:`video-ai-analysis-poc`。 +- 项目目录:`/Users/yoilun/AI-train/video-ai-analysis-poc`。 +- 项目目标:实现本地视频文件夹离线批处理分析 PoC。 +- 外部模型/参考实现目录:`/Users/yoilun/AI-train/zhengxin-vlm-0413`。 +- 参考 VLM 模型:`/Users/yoilun/AI-train/zhengxin-vlm-0413/models/memai-zhengxin-v3-20260413`。 +- 测试环境:`ssh xiaozheng@192.168.5.100`,用户说明该环境已有模型。 +- 运行目标:Ubuntu 24,单机 NVIDIA RTX 3080 20GB,离线批处理优先吞吐而非低延迟。 + +## Hard Directory Boundary + +`video-ai-analysis-poc` 是本次项目目录。后续代码、配置、计划、文档、测试和输出模板都必须放在这里。 + +`zhengxin-vlm-0413` 不是本次项目目录,只能作为: + +- 已有模型目录。 +- 参考实现目录。 +- VLM API、prompt、输出解析、部署方式的参考。 + +默认禁止在 `zhengxin-vlm-0413` 中创建本项目文件或修改业务代码。特别禁止改动、移动、删除或复制: + +- `zhengxin-vlm-0413/models/**` +- `zhengxin-vlm-0413/service/config.yaml` +- `zhengxin-vlm-0413/service/config.yaml-bk` +- `zhengxin-vlm-0413/docker/.env` + +如果后续确实需要从参考项目复制逻辑,必须复制到本项目目录内,并注明来源和差异。 + +## Repository Map + +当前项目文件: + +- `video_ai_analysis_system_plan.md`:前期系统实施方案。 +- `agent.md`:本文件,约束后续 AI 工作。 +- `task_plan.md`:本次 goal 的阶段计划。 +- `findings.md`:代码阅读、约束、关键发现。 +- `progress.md`:执行记录、测试结果、bug 循环。 +- `docs/project.md`:项目目标、架构、配置、运行方式和风险。 +- `memories.md`:主 agent 对用户要求和关键决策的长期记忆。 + +参考目录关键文件: + +- `/Users/yoilun/AI-train/zhengxin-vlm-0413/service/rtsp_service.py`:实时 RTSP 服务入口。 +- `/Users/yoilun/AI-train/zhengxin-vlm-0413/service/config.yaml`:现有推理、摄像头、prompt、服务、YOLO 配置,包含敏感信息。 +- `/Users/yoilun/AI-train/zhengxin-vlm-0413/shared/vlm_client.py`:VLM 请求构建、OpenAI-compatible API 调用、Action 解析。 +- `/Users/yoilun/AI-train/zhengxin-vlm-0413/shared/frame_utils.py`:已有本地视频抽帧辅助函数,但不满足本次完整离线批处理需求。 +- `/Users/yoilun/AI-train/zhengxin-vlm-0413/docker/docker-compose.yml`:vLLM 与 RTSP 服务容器编排。 + +## Current Workflow Batch + +```text +[项目: /Users/yoilun/AI-train/video-ai-analysis-poc] +[工作流批次: v1.0 本地视频批处理PoC] +``` + +派发任何子 agent 时,任务首段必须包含: + +```text +[项目: /Users/yoilun/AI-train/video-ai-analysis-poc] +[工作流批次: v1.0 本地视频批处理PoC] +[阶段: 阶段 x <阶段名>] +[角色: <角色名>] +[子agent名称: <从指定名单中选择>] +``` + +子 agent 名称必须从以下列表选择: + +```text +huzenan, jiangzhiyou, linjiayu, hujiarui, wangchiheng, niwenhao, +caiziquan, yepeijun, lizheng, zhengchenda, chenruihao, yangyilun, donglele +``` + +## Required Workflow + +### 1. Agent Rules Before Code + +在 `agent.md` 未确定前,不允许修改业务代码。 + +阶段 0 允许修改: + +- `agent.md` +- `task_plan.md` +- `findings.md` +- `progress.md` +- `docs/project.md` +- `memories.md` + +### 2. File-Based Planning Is Mandatory + +非简单任务必须维护: + +- `task_plan.md` +- `findings.md` +- `progress.md` +- `docs/project.md` +- `memories.md` + +每个阶段开始前,主 agent 必须读取这些文件,确认当前目标和下一步。每个阶段完成后,必须更新阶段状态、验证记录、关键文件和剩余风险。 + +### 3. Sub Agent Workflow + +每个实现阶段至少使用: + +- coding agent:只实现当前阶段,不处理未来阶段,不做无关重构。 +- testing/review agent:只测试、审查、复现问题和报告 bug,不直接修改代码。 + +如果 testing/review agent 发现 bug: + +1. 主 agent 将 bug report 记录到 `progress.md`。 +2. 主 agent 将 bug report 转发给当前阶段 coding agent。 +3. coding agent 只修复报告中的问题。 +4. testing/review agent 复测。 +5. 同一问题最多 3 轮,仍失败则暂停并向用户报告。 + +### 4. TDD And Verification + +新增功能或 bugfix 必须优先写测试或最小可复现验证,再写实现。无法自动化测试的 GPU/视频/环境行为,必须写清楚 smoke test 命令、输入样例和人工判定标准。 + +完成任何阶段前,必须有新鲜验证证据: + +- 单元测试。 +- CLI smoke test。 +- FFmpeg 命令检查。 +- vLLM health check。 +- 输出 JSON schema/字段检查。 + +不能只根据代码阅读声称完成。 + +## Local Batch PoC Requirements + +### 1. Input + +本次 PoC 优先支持本地视频文件夹: + +- 通过 CLI 参数或 config 选择输入目录。 +- 递归或非递归行为必须可配置。 +- 支持常见视频格式,例如 `.mp4`、`.mov`、`.mkv`、`.avi`、`.flv`、`.ts`、`.m4v`。 +- 不支持或损坏的视频要记录失败原因,不能阻塞整个文件夹。 + +### 2. Video Processing + +- 必须优先使用 FFmpeg + NVDEC GPU 解码。 +- 默认 1 FPS 抽帧。 +- 默认 clip 长度 10 秒,允许配置 10-20 秒。 +- 禁止逐帧 LLM 推理,必须 clip 级推理。 +- Clip 输入帧数要小,默认 8-10 帧,避免 RTX 3080 20GB OOM。 +- 输出目录保存 manifest、抽帧中间结果、clip 结果和汇总 JSON。 + +### 3. Prompt Configuration + +- prompt 必须从 config 读取,不能硬编码在业务逻辑中。 +- 支持 `prompt.system` 和 `prompt.user`。 +- Prompt 必须要求模型输出严格 JSON。 +- Prompt 必须要求输出画面时间字段;如果画面时间不可读,要保留 clip 的视频相对时间。 + +### 4. Timeline Output + +输出结果必须包含监控画面的时间轴。至少包含: + +- `video_id` 或视频文件路径。 +- `video_start_time`:如果文件或画面可识别则填写,否则为 `null`。 +- `clip_start_seconds`。 +- `clip_end_seconds`。 +- `clip_start_timecode`,格式如 `HH:MM:SS`。 +- `clip_end_timecode`,格式如 `HH:MM:SS`。 +- `frame_times`:clip 内参与推理帧的相对秒数或 timecode。 +- `screen_time` 或 `画面时间`:模型从监控画面 OCR 到的时间,无法读取则为空。 +- 事件级 `start_time` / `end_time` 或对应 clip 范围。 + +不能只输出 `datetime.now()` 这种服务处理时间。 + +### 5. Model Inference + +- 优先兼容 OpenAI-compatible `/v1/chat/completions`。 +- 默认模型名:`memai-zhengxin-v3-20260413`。 +- 默认配置使用 `api_base_url: http://localhost:8679` 和 `chat_completions_path: /v1/chat/completions`,由代码拼接为完整请求 URL。 +- RTX 3080 20GB 上 batch 保守起步,先 batch size 1,再逐步尝试 2-4。 +- vLLM dtype 和显存参数要在测试环境验证;如 BF16 不稳定,优先 FP16。 + +## Security And Data Rules + +- 不要在新文档、测试夹具或输出示例中复制真实 RTSP 密码、token、Webhook 密钥、Cookie。 +- 参考项目 `service/config.yaml` 包含真实内网 RTSP URL 和密码,阅读可以,传播要脱敏。 +- 本地视频、抽帧图片、模型输出可能包含门店画面,默认视为敏感数据。 +- 不要把视频帧、日志、输出样例批量复制到仓库外部。 +- 不要删除用户已有视频或模型文件。 + +## Implementation Rules + +- 所有新增代码放在本项目目录内。 +- 不修改参考项目实时 RTSP 主链路。 +- 可参考 `shared/vlm_client.py` 的接口设计,但新实现应位于本项目。 +- 不引入不必要的分布式系统。 +- 不引入大型依赖解决小问题。 +- 保持配置、运行命令、文档一致。 +- 所有输出文件命名要稳定,支持断点续跑。 +- JSON 输出必须可被机器解析;模型 raw response 可以保留,但不能作为唯一结构化结果。 + +## Validation Matrix + +阶段 0 文档/agent 规则: + +- 检查文件存在: + - `agent.md` + - `task_plan.md` + - `findings.md` + - `progress.md` + - `docs/project.md` + - `memories.md` +- 检查 `zhengxin-vlm-0413` 下没有本次误放的工作流文件。 + +本地批处理代码变更后: + +- Python 语法检查: + - `python3 -m py_compile ` +- 单元测试: + - 如新增 tests,运行对应 `python3 -m unittest ...` 或 `pytest ...` +- FFmpeg/NVDEC 检查: + - `ffmpeg -hwaccels` + - `ffmpeg -decoders | grep cuvid` +- vLLM health check: + - `curl http://localhost:8679/v1/models` +- 最小视频 smoke test: + - 使用一个短视频目录运行本地批处理入口。 + - 检查输出包含 clip 级时间轴和汇总 JSON。 + +测试环境验证: + +- 通过 `ssh xiaozheng@192.168.5.100` 执行前,先确认路径、依赖和 GPU 状态。 +- 远端命令要尽量只读或写入明确输出目录。 +- 不要覆盖远端已有模型和配置。 + +## Definition Of Done + +本次 PoC 完成必须满足: + +1. 支持本地文件夹所有视频分析。 +2. 不依赖海康云眸云存储。 +3. 模型提示词可通过 config 调整。 +4. 输出包含视频、clip、事件的监控时间轴。 +5. 4B VLM 使用现有模型路径或测试环境已有模型。 +6. 断点续跑和失败记录有基本支持。 +7. 文档更新,包含运行命令、配置项和输出结构。 +8. 必要验证命令已运行并记录。 +9. 每个阶段的子 agent 审查结论记录在 `progress.md`。 diff --git a/config/local_batch.yaml b/config/local_batch.yaml new file mode 100644 index 0000000..05c70e6 --- /dev/null +++ b/config/local_batch.yaml @@ -0,0 +1,173 @@ +input: + dir: ./videos + recursive: true + extensions: [".mp4", ".mov", ".mkv", ".avi", ".flv", ".ts", ".m4v"] + +source: + mode: local + +output: + dir: ./outputs/local-batch + overwrite: false + resume: true + keep_frames: true + +hik_cloud: + api_base_url: https://api2.hik-cloud.com + download_path: /v1/carrier/cstorage/open/play/download + access_token: null + access_token_env: HIK_CLOUD_ACCESS_TOKEN + chunk_seconds: 600 + timeout_seconds: 60 + download_timeout_seconds: 600 + devices: + - device_serial: EXAMPLE_DEVICE_SERIAL + channel_no: 1 + name: example-device + time_ranges: + - begin: "2026-02-03 09:00:00" + end: "2026-02-03 10:00:00" + +ffprobe: + timeout_seconds: 30 + +ffmpeg: + prefer_nvdec: true + allow_cpu_fallback: false + hwaccel: cuda + codec_decoders: + h264: h264_cuvid + hevc: hevc_cuvid + frame_fps: 1 + frame_width: 640 + jpeg_quality: 4 + timeout_seconds_per_video: 3600 + +clip: + length_seconds: 10 + stride_seconds: 10 + frames_per_clip: 8 + min_frames_per_clip: 4 + +vlm: + api_base_url: http://localhost:8679 + chat_completions_path: /v1/chat/completions + model: memai-zhengxin-v3-20260413 + timeout_seconds: 120 + max_tokens: 512 + temperature: 0 + batch_size: 1 + image_transport: data_uri + retries: 1 + +prompt: + system: >- + You are an AI quality inspector and store monitoring assistant for a fried chicken cutlet (鸡排) production line and storefront. + Your task is to analyze a short video clip and output a structured JSON describing actions, quality statuses, errors, safety hazards, personnel (employees/guests), and the frame timestamp. + + + All 9 top-level keys below are REQUIRED in every response. Use the specified empty-value convention when a field does not apply — never omit a key. + + + ### 1. Action (REQUIRED) + + Identify the primary action. Use the "Action_" prefix on every label except End_Frying. If no action is detected, output "Action_Idle". + + Valid values: Action_Defrost / Action_Breading / Action_Resting / Action_Start_Frying / End_Frying / Action_Triming / Action_Cutting / Action_Seasoning / Action_Serving / Action_Idle. + + + ### 2. quality_status (REQUIRED — "" if not applicable) + + Choose based on the action: + + - Action_Breading → fully_covered | uneven + + - Action_Resting → stacked | qualified + + - Action_Start_Frying / End_Frying → standard_time | early_retrieval | overcooked | double_fried + + - Action_Cutting → complete_cut | linked | dusted_before_cut + + - Action_Seasoning → coverage_high | missed | single_side_dusted + + - Other actions → qualified + + If no ingredient is visible or the action has no applicable status, output "". + + + ### 3. error_type (REQUIRED — "" if no error) + + Short description of any anomaly. Examples: "smoking", "dusted_before_cut", "single_side_dusted", "double_fried". If the operation is normal, output "". + + + ### 4. 安全隐患 (REQUIRED — "" if no hazard) + + Chinese description of any safety hazard visible in the scene (e.g., "油锅附近有易燃物"). If none, output "". + + + ### 5. 人物位置 (REQUIRED — "" if no people) + + Descriptive Chinese sentence of where people are and how they are moving. Example: "员工在油锅边". If no one is in the frame, output "". + + + ### 6. 总结 (REQUIRED — "无" if no people) + + Descriptive Chinese sentence summarizing the scene with the exact person count. Example: "员工在油锅边炸鸡,顾客在收银台前等待". If no one is in the frame, output "无". + + + ### 7. 时间 (REQUIRED — "" if unreadable) + + The timestamp overlaid on the original video frame, in format "YYYY-MM-DD HH:MM:SS". If the timestamp is not visible or cannot be read, output "". + + + ### 8. employees (REQUIRED — [] if none) + + Array of employee objects. Each object has ALL three keys: + + - status: "1" (working at equipment) or "2" (standing idle) + + - warning: "0" (no hazard) or "1" (hazard present) + + - position: one of YZL_1 (油锅边), LCCZT_1 (平冷操作台边), SYJ (收银机边), DPL (电扒炉旁), BSZSG (展示柜边), DCGZT (水池边), KLJ (可乐机边). + + If no employees are in the frame, output []. + + + ### 9. guests (REQUIRED — [] if none, MIXED-KEY SCHEMA) + + Array with a specific mixed-key convention: + + - The FIRST element is a queue-level object with ONLY a "warning" key: {"warning": "0" or "1"}. "1" means the queue has ≥ 3 people; "0" means < 3. + + - Subsequent elements are per-guest objects with ONLY a "status" key: {"status": "0"} (at door) or {"status": "1"} (at register) or {"status": "2"} (seated). One such object per visible guest. + + If there are no guests at all, output []. If only the queue header is known, output [{"warning": "0 or 1"}]. + + Example: [{"warning": "0"}, {"status": "1"}, {"status": "2"}] + + + ### Output format (strict JSON, all 9 keys REQUIRED) + + {"Action": "", "quality_status": "", "error_type": "", "安全隐患": "", "人物位置": "", "总结": "", "时间": "", "employees": [{"status": "<1 or 2>", "warning": "<0 or 1>", "position": ""}], "guests": [{"warning": "<0 or 1>"}, {"status": "<0, 1, or 2>"}]} + + Do not wrap the JSON in markdown fences. Do not add any prose before or after the JSON. + user: 'Analyze the video clip and return the required JSON with all 9 keys. Read the timestamp from the frame overlay into "时间".' + +schema: + version: local-batch-v1 + event_types: + - customer_enter + - customer_leave + - queue_detected + - staff_absent + - staff_present + - area_crowded + - abnormal_behavior + - unknown + require_strict_json: true + parse_retry: 1 + merge_gap_seconds: 30 + +runtime: + timezone: Asia/Shanghai + log_level: INFO diff --git a/docs/project.md b/docs/project.md new file mode 100644 index 0000000..7bebd4a --- /dev/null +++ b/docs/project.md @@ -0,0 +1,719 @@ +# Project Documentation + +## Goal + +本项目是在 `/Users/yoilun/AI-train/video-ai-analysis-poc` 中实现视频离线批处理分析 PoC。`v1.0` 已支持本地视频文件夹;`v1.1` 新增海康云存储录像下载作为视频来源,下载完成后复用现有抽帧、clip、VLM 推理和聚合流程。 + +必须支持: + +- 选择一个本地视频文件夹。 +- 直接调用海康云存储录像下载 API 获取录像下载地址并下载视频。 +- AccessToken 通过 config 或环境变量配置,不写入测试夹具和文档样例。 +- 设备序列号和通道可配置,并支持多设备。 +- 分析时间段包含年月日,支持 `YYYY-MM-DD HH:MM:SS` 配置。 +- 海康 API 单次最多下载 1 小时,超过 1 小时的时间段必须拆成多个不超过 3600 秒的请求;默认示例使用 600 秒分片,真实 smoke 中比 3600 秒更稳定。 +- 自动发现文件夹内所有常见视频文件。 +- 对每个视频按 1 FPS 抽帧,按 10-20 秒 clip 组织输入。 +- 使用已有 4B VLM 模型能力,兼容 `memai-zhengxin-v3-20260413` 的 OpenAI-compatible vLLM 接口。 +- prompt 通过 config 调整。 +- 输出结构化 JSON/JSONL。 +- 输出中必须包含监控画面的时间轴,包括视频、clip、frame 和事件的时间定位。 + +## v1.1 Hik Cloud Storage Source + +海康文档 `录像下载流程_1.pdf` 的“2、获取录像下载地址”定义: + +```text +POST https://api2.hik-cloud.com/v1/carrier/cstorage/open/play/download +Authorization: bearer +Content-Type: application/json +``` + +请求 body: + +```json +{ + "deviceSerial": "EXAMPLE_DEVICE_SERIAL", + "channelNo": 1, + "timeBegin": 1764856787, + "timeEnd": 1764856978 +} +``` + +成功返回 `data.url`、`actualBeginTime`、`actualEndTime`。错误码 `80430002` 包含起止时间大于 3600 秒的参数错误,错误码 `80438027` 表示起始时间内没有录像。 + +配置示例: + +```yaml +source: + mode: hik_cloud # local | hik_cloud + +hik_cloud: + api_base_url: https://api2.hik-cloud.com + download_path: /v1/carrier/cstorage/open/play/download + access_token: null + access_token_env: HIK_CLOUD_ACCESS_TOKEN + chunk_seconds: 600 + timeout_seconds: 60 + download_timeout_seconds: 600 + devices: + - device_serial: EXAMPLE_DEVICE_SERIAL + channel_no: 1 + name: store-front + time_ranges: + - begin: "2026-02-03 09:00:00" + end: "2026-02-03 11:30:00" +``` + +云下载输出: + +- `hik_cloud_download_manifest.jsonl`:每个设备/通道/时间分片的请求、实际时间、状态和错误。`--dry-run` 云模式只请求下载地址并写入 `address_ok` / failure 状态,不下载 mp4,不 probe。 +- `downloads/hik_cloud//ch/*.mp4`:下载后供现有分析链路消费的视频文件。 +- `video_manifest.jsonl`:保留现有契约,并附加云来源元数据。 + +运行本地文件夹模式: + +```bash +python3 -B -m video_ai_analysis_poc.cli \ + --config config/local_batch.yaml \ + --input-dir /path/to/local/videos \ + --output-dir ./outputs/local-batch +``` + +运行海康云存储模式时,复制配置文件并设置 `source.mode: hik_cloud`,AccessToken 优先通过环境变量提供: + +```bash +export HIK_CLOUD_ACCESS_TOKEN='' +python3 -B -m video_ai_analysis_poc.cli \ + --config /path/to/hik-cloud.yaml \ + --output-dir ./outputs/hik-cloud +``` + +`--dry-run` 会请求海康下载地址并写 `hik_cloud_download_manifest.jsonl`,但不会下载视频文件、probe、抽帧、推理或聚合。`--until clips` 会在下载、探测、抽帧和 clip manifest 后停止;`--until inference` 会继续运行模型推理并写入 `clip_results.jsonl`。 + +真实远端 smoke 观察到同一 1 小时时间段直接按 3600 秒下载时,云端返回的 MP4 缺少 `moov` atom,`ffprobe` 无法解析;改用 600 秒分片后 6 个分片均可探测并进入抽帧。抽帧阶段会根据云下载记录的 `actual_begin/actual_end` 或 `requested_begin/requested_end` 给 FFmpeg 加输出帧数上限,避免海康 MP4 异常时间戳导致 `fps=1` 复制出过量帧。 + +海康云存储安全规则: + +- 不提交真实 AccessToken。 +- 优先使用 `hik_cloud.access_token_env: HIK_CLOUD_ACCESS_TOKEN`。 +- 不记录 Authorization header。 +- 不持久化签名下载 URL query,例如 `sign`、`sig`、`token`、`access_token`。 +- `access_token.md` 是敏感验证文件,只能用于远端真实 smoke,不复制进文档、测试或输出样例。 + +## Directory Boundaries + +```text +/Users/yoilun/AI-train/video-ai-analysis-poc + 本次 PoC 项目目录,后续代码、配置、计划、文档都放这里。 + +/Users/yoilun/AI-train/zhengxin-vlm-0413 + 外部模型和参考实现目录,不是本次项目目录。 +``` + +硬性边界: + +- 不在 `zhengxin-vlm-0413` 中创建本项目文件。 +- 不修改 `zhengxin-vlm-0413/models/**`。 +- 不修改 `zhengxin-vlm-0413/service/config.yaml`、`service/config.yaml-bk`、`docker/.env`。 +- 不把参考项目真实 RTSP、Webhook、token、Cookie、密码写入本项目示例配置、测试夹具、文档或输出样例。 +- 输出目录只能是用户显式传入目录,或本项目内 `outputs/`。 +- 不覆盖用户原始视频文件。 + +## Inference Architecture Decision + +本 PoC 明确选择: + +```text +OpenAI-compatible vLLM API +``` + +不在 PoC 第一版中直接加载 PyTorch + Transformers + PEFT。原因: + +- 用户说明测试环境已有模型。 +- 参考项目已经使用 vLLM OpenAI-compatible API。 +- 本地视频批处理的主要目标是打通工程链路,而不是重新实现模型服务。 + +配置字段固定为: + +```yaml +vlm: + api_base_url: http://localhost:8679 + chat_completions_path: /v1/chat/completions +``` + +代码拼接规则: + +```text +chat_url = api_base_url.rstrip("/") + chat_completions_path +``` + +不要在配置中同时传完整 endpoint 和 base URL,避免出现 `/v1/chat/completions/v1/chat/completions` 之类的双拼路径。 + +## Target File Structure + +```text +video-ai-analysis-poc/ + agent.md + task_plan.md + findings.md + progress.md + memories.md + video_ai_analysis_system_plan.md + config/ + local_batch.yaml + video_ai_analysis_poc/ + __init__.py + cli.py + config.py + paths.py + discovery.py + probe.py + ffmpeg_sampler.py + frames.py + clips.py + vlm_client.py + result_parser.py + aggregator.py + manifest.py + logging_utils.py + schemas/ + clip_result.schema.json + video_result.schema.json + folder_summary.schema.json + tests/ + test_config.py + test_discovery.py + test_probe.py + test_clips.py + test_result_parser.py + test_aggregator.py + outputs/ + .gitkeep +``` + +## Module Boundaries + +### `config.py` + +- 加载 `config/local_batch.yaml`。 +- 合并 CLI 参数覆盖项。 +- 校验必填字段、数值范围、路径安全。 +- 不访问视频、不调用 FFmpeg、不调用模型。 + +### `paths.py` + +- 生成稳定 `video_id`、`clip_id`。 +- 生成输出目录结构。 +- 防止输出目录指向参考模型目录或覆盖输入视频目录。 + +### `discovery.py` + +- 只负责按 `input.dir`、`recursive`、`extensions` 发现视频。 +- 输出 `video_manifest.jsonl`。 +- 不做 ffprobe,不做抽帧,不调用模型。 + +### `probe.py` + +- 包装 `ffprobe`。 +- 输出 `duration_seconds`、`codec_name`、`width`、`height`、`fps`、`format_name`、`start_time`。 +- 损坏或不支持视频标记 `probe_failed`,记录 `last_error`,不阻塞其他视频。 + +### `ffmpeg_sampler.py` + +- 使用 FFmpeg + NVDEC 做 1 FPS 抽帧。 +- 根据 codec 选择 `h264_cuvid` / `hevc_cuvid`。 +- 默认 `allow_cpu_fallback: false`。 +- 输出 JPEG 和 `frame_manifest.jsonl`。 +- 保存 FFmpeg stderr 摘要,作为实际使用 GPU 解码的证据。 + +### `frames.py` + +- 计算 frame 的相对秒数和 timecode。 +- 维护 frame 文件路径、offset、timecode。 +- 优先使用可获得的 `pts_time`,否则使用抽帧序号按 FPS 推导相对时间。 + +### `clips.py` + +- 读取 `frame_manifest.jsonl`。 +- 按 `clip.length_seconds` 和 `clip.stride_seconds` 构建 clip。 +- 从 1 FPS 帧中均匀采样 `frames_per_clip`。 +- 输出 `clip_manifest.jsonl`,必须包含参与推理的实际帧时间。 + +### `vlm_client.py` + +- 调用 OpenAI-compatible `/v1/chat/completions`。 +- 多帧使用 `image_url`,默认 `data:image/jpeg;base64`。 +- prompt 来自 config,不硬编码。 +- 不解析业务事件,只返回 raw response、latency 和 HTTP 状态。 +- 阶段 4 实现使用 Python 标准库 `urllib`,并暴露可注入 HTTP 函数以便测试 mock;默认 URL 拼接为 `vlm.api_base_url.rstrip("/") + vlm.chat_completions_path`。 + +### `result_parser.py` + +- 从 raw response 中提取严格 JSON。 +- 校验 `schema_version`、`events`、`screen_time`、事件枚举等字段。 +- 解析失败触发一次严格 prompt 重试。 +- 仍失败写 `parse_failed`,保留 `raw_response`。 +- 阶段 4 实现支持 raw JSON、markdown/prose 中嵌入 JSON,输出 clip 级 `monitoring_timeline`、`events`、`raw_response`、`processing` 和 `error` 字段。 + +### `aggregator.py` + +- 消费 `video_manifest.jsonl`、`clip_manifest.jsonl` 和 `clip_results.jsonl`。 +- 聚合为 `videos//video_result.json` 和输出根目录下的 `folder_summary.json`。 +- 按 `merge_gap_seconds` 合并同视频、同类型、相邻时间范围接近的事件。 +- 保留事件相对时间轴、screen_time、clip evidence 和 frame evidence。 +- 统计 `parse_failed` / `inference_failed` clip 数量。 + +### `manifest.py` + +- 负责 JSONL 读写和状态字段。 +- 支持断点续跑。 +- 每条记录包含 `status`、`retry_count`、`last_error`。 + +## Config Schema + +`config/local_batch.yaml` 建议字段: + +```yaml +input: + dir: /path/to/videos + recursive: true + extensions: [".mp4", ".mov", ".mkv", ".avi", ".flv", ".ts", ".m4v"] + +source: + mode: local + +output: + dir: ./outputs/local-batch + overwrite: false + resume: true + keep_frames: true + +hik_cloud: + api_base_url: https://api2.hik-cloud.com + download_path: /v1/carrier/cstorage/open/play/download + access_token: null + access_token_env: HIK_CLOUD_ACCESS_TOKEN + chunk_seconds: 600 + timeout_seconds: 60 + download_timeout_seconds: 600 + devices: + - device_serial: EXAMPLE_DEVICE_SERIAL + channel_no: 1 + name: example-device + time_ranges: + - begin: "2026-02-03 09:00:00" + end: "2026-02-03 10:00:00" + +ffprobe: + timeout_seconds: 30 + +ffmpeg: + prefer_nvdec: true + allow_cpu_fallback: false + hwaccel: cuda + codec_decoders: + h264: h264_cuvid + hevc: hevc_cuvid + frame_fps: 1 + frame_width: 640 + jpeg_quality: 4 + timeout_seconds_per_video: 3600 + +clip: + length_seconds: 10 + stride_seconds: 10 + frames_per_clip: 8 + min_frames_per_clip: 4 + +vlm: + api_base_url: http://localhost:8679 + chat_completions_path: /v1/chat/completions + model: memai-zhengxin-v3-20260413 + timeout_seconds: 120 + max_tokens: 512 + temperature: 0 + batch_size: 1 + image_transport: data_uri + retries: 1 + +prompt: + system: "You are a store video analysis assistant. Return strict JSON only." + user: "Analyze this clip. Return events and screen_time. If no event, return events: []." + +schema: + version: local-batch-v1 + event_types: + - customer_enter + - customer_leave + - queue_detected + - staff_absent + - staff_present + - area_crowded + - abnormal_behavior + - unknown + require_strict_json: true + parse_retry: 1 + merge_gap_seconds: 30 + +runtime: + timezone: Asia/Shanghai + log_level: INFO +``` + +## File Contracts + +### `video_manifest.jsonl` + +One line per discovered video: + +```json +{ + "video_id": "stable_hash_or_slug", + "source_path": "/path/to/video.mp4", + "status": "pending", + "probe": null, + "retry_count": 0, + "last_error": null +} +``` + +### `frame_manifest.jsonl` + +One line per sampled frame: + +```json +{ + "video_id": "stable_hash_or_slug", + "frame_id": "stable_hash_or_slug_f000120", + "frame_path": "frames/stable_hash_or_slug/000120.jpg", + "offset_seconds": 120.0, + "timecode": "00:02:00", + "pts_time": 120.0, + "status": "sampled" +} +``` + +### `clip_manifest.jsonl` + +One line per clip: + +```json +{ + "video_id": "stable_hash_or_slug", + "clip_id": "stable_hash_or_slug_c000012", + "clip_start_seconds": 120.0, + "clip_end_seconds": 130.0, + "clip_start_timecode": "00:02:00", + "clip_end_timecode": "00:02:10", + "frame_times": [ + { + "frame_path": "frames/stable_hash_or_slug/000120.jpg", + "offset_seconds": 120.0, + "timecode": "00:02:00" + } + ], + "status": "pending", + "retry_count": 0, + "last_error": null +} +``` + +### `clip_results.jsonl` + +One line per inferred clip: + +```json +{ + "schema_version": "local-batch-v1", + "video_id": "stable_hash_or_slug", + "video_path": "/path/to/video.mp4", + "clip_id": "stable_hash_or_slug_c000012", + "status": "ok", + "monitoring_timeline": { + "timezone": "Asia/Shanghai", + "video_start_time": null, + "clip_start_seconds": 120.0, + "clip_end_seconds": 130.0, + "clip_start_timecode": "00:02:00", + "clip_end_timecode": "00:02:10", + "frame_times": [ + { + "frame_path": "frames/stable_hash_or_slug/000120.jpg", + "offset_seconds": 120.0, + "timecode": "00:02:00" + } + ], + "screen_time": "2026-06-14 12:31:20" + }, + "events": [ + { + "event_type": "queue_detected", + "start_time": null, + "end_time": null, + "start_offset_seconds": 120.0, + "end_offset_seconds": 130.0, + "confidence": 0.86, + "severity": "medium", + "attributes": {}, + "evidence": { + "clip_id": "stable_hash_or_slug_c000012", + "frame_paths": ["frames/stable_hash_or_slug/000120.jpg"] + } + } + ], + "raw_response": null, + "processing": { + "started_at": "2026-06-15T10:00:00+08:00", + "finished_at": "2026-06-15T10:00:02+08:00", + "latency_ms": 1800 + }, + "error": null +} +``` + +### `video_result.json` + +Written to: + +```text +videos//video_result.json +``` + +Required top-level fields: + +```text +schema_version +video_id +video_path +probe +monitoring_timeline.video_start_time +monitoring_timeline.video_duration_seconds +clip_count +failed_clip_count +event_counts +events +outputs.clip_results_jsonl +processing +``` + +### `folder_summary.json` + +Required top-level fields: + +```text +schema_version +input_dir +video_count +processed_video_count +failed_video_count +event_counts +videos +processing +``` + +## Timeline Rules + +时间轴必须区分三类时间: + +- 视频相对时间:`offset_seconds`、`timecode`。 +- 画面 OCR 时间:`screen_time` 或模型输出里的 `画面时间`。 +- 处理时间:`processing.started_at`、`processing.finished_at`。 + +本地视频没有可靠业务开始时间时: + +- `video_start_time` 必须为 `null`。 +- 不允许伪造绝对时间。 +- 事件必须保留 `start_offset_seconds` 和 `end_offset_seconds`。 + +参与推理的实际帧时间必须写入 `frame_times`。不能只写 clip 起止时间。 + +## Reference Code Usage + +可以参考: + +- `zhengxin-vlm-0413/shared/vlm_client.py` 的 OpenAI-compatible payload 结构。 +- `zhengxin-vlm-0413/shared/frame_utils.py` 的 base64 data URI 处理方式。 +- `zhengxin-vlm-0413/service/config.yaml` 的 prompt 配置风格。 + +不能直接复用为核心实现: + +- `frame_utils.extract_frames_from_video`,因为它是整段均匀抽 8 帧,不满足 1 FPS、clip manifest、时间轴要求。 +- `vlm_client.extract_action`,因为它只解析 `Action`,不能覆盖本项目完整事件和时间轴 schema。 +- `rtsp_service.py` 主循环,因为它服务实时 RTSP,不适合离线文件夹批处理。 + +## Validation Matrix + +### Phase 1 Architecture Validation + +阶段 1 complete 条件: + +- `docs/project.md` 固化模块边界、文件输出契约、config schema、时间轴 schema、安全边界和验证矩阵。 +- 推理接口选择已明确为 OpenAI-compatible vLLM。 +- API URL 字段语义已固定为 `api_base_url` + `chat_completions_path`。 +- 已声明参考 `frame_utils.py` / `vlm_client.py` 哪些可借鉴、哪些不能直接复用。 +- 已列出阶段 2-6 的 smoke test 输入、命令、期望输出字段和失败判定标准。 +- 子 agent 审查结论记录到 `progress.md`。 + +### Phase 2 Validation + +目标:本地视频发现、ffprobe、manifest、CLI 骨架。 + +命令: + +```bash +python3 -m py_compile video_ai_analysis_poc/*.py +python3 -m video_ai_analysis_poc.cli --config config/local_batch.yaml --input-dir /path/to/videos --output-dir ./outputs/local-batch --dry-run +``` + +期望: + +- 生成 `video_manifest.jsonl`。 +- 损坏/不支持视频被标记失败,不阻塞其他视频。 +- 不读取或写入参考模型目录。 + +### Phase 3 Validation + +目标:FFmpeg/NVDEC 1 FPS 抽帧和 clip 构建。 + +命令: + +```bash +ffmpeg -hwaccels +ffmpeg -decoders | grep cuvid +python3 -m video_ai_analysis_poc.cli --config config/local_batch.yaml --input-dir /path/to/short-videos --output-dir ./outputs/local-batch --until clips +``` + +期望: + +- 对一个样例视频实际运行带 `-hwaccel cuda` 和 `h264_cuvid` 或 `hevc_cuvid` 的抽帧命令。 +- 保存 FFmpeg stderr 或日志中的解码器证据。 +- 生成 `frame_manifest.jsonl` 和 `clip_manifest.jsonl`。 +- `clip_manifest.jsonl` 包含 `frame_times`。 + +### Phase 4 Validation + +目标:vLLM OpenAI-compatible API、prompt 配置、JSON 解析重试。 + +命令: + +```bash +curl http://localhost:8679/v1/models +python3 -m video_ai_analysis_poc.cli --config config/local_batch.yaml --input-dir /path/to/short-videos --output-dir ./outputs/local-batch --until inference --limit-clips 3 +``` + +期望: + +- prompt 从 config 读取。 +- 请求 URL 使用 `api_base_url + chat_completions_path`。 +- 生成 `clip_results.jsonl`。 +- 每条结果包含 `monitoring_timeline.frame_times` 和 `screen_time` 字段。 + +### Phase 5 Validation + +目标:clip/video/folder 聚合和 schema 校验。 + +命令: + +```bash +python3 -m video_ai_analysis_poc.cli --config config/local_batch.yaml --input-dir /path/to/short-videos --output-dir ./outputs/local-batch +python3 -m json.tool ./outputs/local-batch/folder_summary.json >/dev/null +``` + +期望: + +- 默认 CLI 运行不传 `--dry-run` 或 `--until` 时,会执行到 inference 并继续 aggregation。 +- `--until clips` 和 `--until inference` 仍停在各自阶段,不写聚合输出。 +- 生成 `videos//video_result.json`。 +- 生成 `folder_summary.json`。 +- 事件聚合保留相对时间轴。 +- JSON 可被标准工具解析。 + +### Phase 6 Validation + +目标:测试环境 smoke test 与文档更新。 + +远端环境: + +```text +ssh xiaozheng@192.168.5.100 +/home/xiaozheng/video-ai-analysis-poc +``` + +模型服务: + +```bash +ssh xiaozheng@192.168.5.100 'curl http://localhost:8679/v1/models' +``` + +当前服务状态: + +- 容器:`zhengxin-vllm` +- 镜像:`vllm/vllm-openai:v0.14.1` +- 端口:`8679` +- 模型:`memai-zhengxin-v3-20260413` +- 模型目录挂载:`/home/xiaozheng/zhengxin-vlm-0413/models:/models:ro` + +远端能力验证命令: + +```bash +ssh xiaozheng@192.168.5.100 'nvidia-smi --query-gpu=name,memory.total,driver_version --format=csv,noheader' +ssh xiaozheng@192.168.5.100 'ffmpeg -hwaccels' +ssh xiaozheng@192.168.5.100 'ffmpeg -decoders' +``` + +已验证: + +- GPU: `NVIDIA GeForce RTX 3080`, `20480 MiB`, driver `595.71.05`。 +- FFmpeg 6.1.1 支持 `cuda` hwaccel。 +- FFmpeg decoders 包含 `h264_cuvid` 和 `hevc_cuvid`。 +- `/v1/models` 返回模型 id `memai-zhengxin-v3-20260413`。 +- `/v1/chat/completions` 安全 quoted health check 返回 `OK`。 + +远端 smoke 输入: + +```text +/tmp/video-ai-analysis-poc-smoke.h1cZUR/input/sample_h264.mp4 +``` + +远端 smoke 输出: + +```text +/tmp/video-ai-analysis-poc-smoke.h1cZUR/output +``` + +远端批处理命令: + +```bash +ssh xiaozheng@192.168.5.100 'PYTHONPATH=/home/xiaozheng/video-ai-analysis-poc python3 -B -m unittest discover -s /home/xiaozheng/video-ai-analysis-poc/tests -v' +ssh xiaozheng@192.168.5.100 'python3 -B -m compileall -q /home/xiaozheng/video-ai-analysis-poc/video_ai_analysis_poc' +ssh xiaozheng@192.168.5.100 'PYTHONPATH=/home/xiaozheng/video-ai-analysis-poc python3 -B -m video_ai_analysis_poc.cli --config /home/xiaozheng/video-ai-analysis-poc/config/local_batch.yaml --input-dir /tmp/video-ai-analysis-poc-smoke.h1cZUR/input --output-dir /tmp/video-ai-analysis-poc-smoke.h1cZUR/output --until clips' +ssh xiaozheng@192.168.5.100 'PYTHONPATH=/home/xiaozheng/video-ai-analysis-poc python3 -B -m video_ai_analysis_poc.cli --config /home/xiaozheng/video-ai-analysis-poc/config/local_batch.yaml --input-dir /tmp/video-ai-analysis-poc-smoke.h1cZUR/input --output-dir /tmp/video-ai-analysis-poc-smoke.h1cZUR/output --until inference --limit-clips 1' +ssh xiaozheng@192.168.5.100 'PYTHONPATH=/home/xiaozheng/video-ai-analysis-poc python3 -B -m video_ai_analysis_poc.cli --config /home/xiaozheng/video-ai-analysis-poc/config/local_batch.yaml --input-dir /tmp/video-ai-analysis-poc-smoke.h1cZUR/input --output-dir /tmp/video-ai-analysis-poc-smoke.h1cZUR/output' +``` + +已验证输出: + +- `video_manifest.jsonl`: 1 条视频记录。 +- `frame_manifest.jsonl`: 12 条 sampled frame 记录。 +- `clip_manifest.jsonl`: 1 条 clip 记录。 +- frame manifest 中持久化 `hwaccel: cuda`、`decoder: h264_cuvid`、`ffmpeg_command` 和 FFmpeg stderr 摘要。 +- `clip_results.jsonl`: 1 条记录,`status: ok`,包含 `monitoring_timeline.frame_times`。 +- `videos//video_result.json`: JSON 可解析,`failed_clip_count: 0`。 +- `folder_summary.json`: JSON 可解析,`video_count: 1`、`processed_video_count: 1`。 +- 本地视频没有可靠业务开始时间时,`monitoring_timeline.video_start_time` 输出 `null`;ffprobe 的 `start_time: 0.0` 只保留在 `probe`。 + +远端验证约束: + +- 只写入明确输出目录。 +- 不覆盖远端已有模型、配置和视频。 +- 不复制真实凭据到日志或文档。 + +## Known Risks + +- HEVC decoder 可用性已验证,但实际 smoke 只覆盖 H.264 样例视频。 +- 24 小时真实门店视频吞吐量尚未压测。 +- 海康云眸云录像/RTSP 接入仍在当前本地文件夹 PoC 范围之外。 +- 本地视频可能没有画面内时间戳,必须同时保留相对时间。 +- 模型事件质量尚未用真实门店素材验收;合成测试图没有业务事件,输出空事件是合理结果。 +- 远端 vLLM 容器当前为手工启动,不是生产级 systemd/compose 托管。 diff --git a/docs/superpowers/plans/2026-06-16-hik-cloud-download-analysis.md b/docs/superpowers/plans/2026-06-16-hik-cloud-download-analysis.md new file mode 100644 index 0000000..19b9f6d --- /dev/null +++ b/docs/superpowers/plans/2026-06-16-hik-cloud-download-analysis.md @@ -0,0 +1,190 @@ +# Hik Cloud Download Analysis Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add Hik Cloud Storage recording download as a configurable multi-device source, then feed downloaded videos into the existing model analysis pipeline. + +**Architecture:** Keep the current local-folder pipeline intact. Add a cloud acquisition module that plans one-hour chunks, calls the Hik download-address API, downloads videos to local output storage, records a download manifest, and returns local file records for the existing probe/frame/clip/inference/aggregate stages. + +**Tech Stack:** Python standard library, existing `unittest` suite, existing JSONL manifest helpers, FFmpeg/vLLM pipeline already in `video_ai_analysis_poc`. + +--- + +### Task 1: Config Schema And Time Chunking + +**Files:** +- Modify: `video_ai_analysis_poc/config.py` +- Create: `video_ai_analysis_poc/hik_cloud.py` +- Modify: `tests/test_config.py` +- Create: `tests/test_hik_cloud.py` + +- [ ] **Step 1: Write failing config tests** + +Add tests that load: + +```yaml +source: + mode: hik_cloud +hik_cloud: + access_token_env: HIK_CLOUD_ACCESS_TOKEN + devices: + - device_serial: EXAMPLE_DEVICE_SERIAL + channel_no: 1 + name: front + time_ranges: + - begin: "2026-02-03 09:00:00" + end: "2026-02-03 10:30:00" +``` + +Expected: `source.mode == "hik_cloud"`, `devices` is a list of dicts, and `time_ranges` is a list of dicts. + +- [ ] **Step 2: Write failing chunk tests** + +Test that `build_download_chunks(...)` converts the range above into chunks with `timeEnd - timeBegin <= 3600`. + +- [ ] **Step 3: Run red tests** + +Run: + +```bash +python3 -B -m unittest tests.test_config tests.test_hik_cloud -v +``` + +Expected: fail because list-of-mapping parsing and `hik_cloud.py` do not exist yet. + +- [ ] **Step 4: Implement minimal parser/defaults/chunking** + +Extend the simple YAML parser only enough for list items shaped as mappings. Add defaults for `source` and `hik_cloud`. Implement date-time parsing with `zoneinfo.ZoneInfo`. + +- [ ] **Step 5: Run green tests** + +Run the same unittest command. Expected: pass. + +### Task 2: Hik Download Address API Client + +**Files:** +- Modify: `video_ai_analysis_poc/hik_cloud.py` +- Modify: `tests/test_hik_cloud.py` + +- [ ] **Step 1: Write failing API client tests** + +Mock the HTTP function and verify: + +- URL is `api_base_url.rstrip("/") + download_path`. +- Headers include `Authorization: bearer TOKEN`. +- JSON body includes `deviceSerial`, `channelNo`, `timeBegin`, `timeEnd`. +- Success returns URL and actual begin/end. +- Code `80438027` returns a structured `no_recording` result. +- Other non-zero codes return `address_failed`. + +- [ ] **Step 2: Run red tests** + +Run: + +```bash +python3 -B -m unittest tests.test_hik_cloud -v +``` + +Expected: fail because the client is missing. + +- [ ] **Step 3: Implement client** + +Use `urllib.request` and injectable callables for tests. Do not log or persist the token. + +- [ ] **Step 4: Run green tests** + +Run the same command. Expected: pass. + +### Task 3: Download Files And Manifest + +**Files:** +- Modify: `video_ai_analysis_poc/hik_cloud.py` +- Modify: `video_ai_analysis_poc/paths.py` +- Modify: `tests/test_hik_cloud.py` + +- [ ] **Step 1: Write failing downloader tests** + +Mock address results and download bytes. Verify downloaded files are written under `downloads/hik_cloud//ch/`, filenames contain requested timestamps, manifest rows are written, token/query signatures are not in filenames, and resume skips already downloaded files. + +- [ ] **Step 2: Run red tests** + +Run: + +```bash +python3 -B -m unittest tests.test_hik_cloud -v +``` + +Expected: fail because downloader/manifest behavior is missing. + +- [ ] **Step 3: Implement downloader** + +Write `download_hik_cloud_recordings(config, output_dir, *, address_client=None, download_url=None)` returning downloaded video records with cloud metadata. + +- [ ] **Step 4: Run green tests** + +Run the same command. Expected: pass. + +### Task 4: CLI Cloud Source Integration + +**Files:** +- Modify: `video_ai_analysis_poc/cli.py` +- Modify: `tests/test_cli.py` + +- [ ] **Step 1: Write failing CLI tests** + +Add tests that: + +- `source.mode: local` still uses `discover_videos`. +- `source.mode: hik_cloud` calls the cloud downloader and probes returned downloaded paths. +- `--dry-run` in cloud mode requests download addresses and writes the download manifest, but does not download video files, probe, call FFmpeg, call VLM, or aggregate. +- `--until clips` in cloud mode produces video/frame/clip manifests from mocked downloaded video records. + +- [ ] **Step 2: Run red tests** + +Run: + +```bash +python3 -B -m unittest tests.test_cli -v +``` + +Expected: fail because CLI has no source mode branch. + +- [ ] **Step 3: Implement CLI branch** + +Keep local behavior unchanged. In cloud mode, call downloader before probe and carry cloud metadata into `video_manifest.jsonl`. + +- [ ] **Step 4: Run green tests** + +Run the same command. Expected: pass. + +### Task 5: Docs, Example Config, And Full Verification + +**Files:** +- Modify: `config/local_batch.yaml` +- Modify: `docs/project.md` +- Modify: `findings.md` +- Modify: `progress.md` +- Modify: `memories.md` + +- [ ] **Step 1: Update docs/config** + +Add a commented or safe example for `source.mode: hik_cloud`, token env var, devices, and time ranges. Do not include a real token. + +- [ ] **Step 2: Run full tests** + +Run: + +```bash +python3 -B -m unittest discover -s tests -v +python3 -B -m py_compile video_ai_analysis_poc/*.py +``` + +Expected: all pass. + +- [ ] **Step 3: Run local mock smoke** + +Use test mocks or a temporary local HTTP fixture to verify cloud mode can produce downloaded files and continue to `--until clips` without a real Hik token. + +- [ ] **Step 4: Record results** + +Update `progress.md` with commands, results, files changed, and remaining risk. Real Hik API verification is skipped until a real AccessToken/device/time range is provided. diff --git a/docs/superpowers/specs/2026-06-16-hik-cloud-download-analysis-design.md b/docs/superpowers/specs/2026-06-16-hik-cloud-download-analysis-design.md new file mode 100644 index 0000000..31d1709 --- /dev/null +++ b/docs/superpowers/specs/2026-06-16-hik-cloud-download-analysis-design.md @@ -0,0 +1,151 @@ +# Hik Cloud Download Analysis Design + +## Goal + +Add Hik Cloud Storage recording download as a first-class video source for the existing video analysis pipeline. The implementation must support configurable AccessToken, multiple devices, configurable date-time ranges, one-hour API slicing, video downloads, and reuse the existing local analysis pipeline. + +## Source Model + +The pipeline keeps the existing local mode and adds a cloud mode: + +```yaml +source: + mode: local # local | hik_cloud +``` + +`local` keeps the current folder discovery behavior. `hik_cloud` runs a download stage first, then analyzes the downloaded files exactly like local files. + +## Hik Cloud Configuration + +The config should allow a literal token for controlled testing and an environment variable for normal use: + +```yaml +hik_cloud: + api_base_url: https://api2.hik-cloud.com + download_path: /v1/carrier/cstorage/open/play/download + access_token: null + access_token_env: HIK_CLOUD_ACCESS_TOKEN + chunk_seconds: 600 + timeout_seconds: 60 + download_timeout_seconds: 600 + devices: + - device_serial: EXAMPLE_DEVICE_SERIAL + channel_no: 1 + name: store-front + time_ranges: + - begin: "2026-02-03 09:00:00" + end: "2026-02-03 11:30:00" +``` + +The implementation must not print or persist the token. Manifest entries may record the API URL path, device serial, channel, requested times, actual times, and status, but not the Authorization header. + +## Time Handling + +The user-facing time range includes year, month, day, hour, minute, and second. The config supports both `YYYY-MM-DD HH:MM:SS` strings and integer epoch seconds. String parsing uses `runtime.timezone`, defaulting to `Asia/Shanghai`, and converts to Unix seconds for `timeBegin` and `timeEnd`. + +Ranges are split into chunks with `end - begin <= 3600` because the PDF documents error `80430002` when the requested interval exceeds 3600 seconds. The example default uses 600 seconds because real remote smoke found that shorter chunks produced valid, probeable MP4 files for the provided test range. + +## API Contract + +Use the PDF section “2、获取录像下载地址”: + +```text +POST https://api2.hik-cloud.com/v1/carrier/cstorage/open/play/download +Authorization: bearer +Content-Type: application/json +``` + +Request body: + +```json +{ + "deviceSerial": "EXAMPLE_DEVICE_SERIAL", + "channelNo": 1, + "timeBegin": 1764856787, + "timeEnd": 1764856978 +} +``` + +Successful response: + +```json +{ + "code": 0, + "data": { + "url": "https://...", + "actualBeginTime": "1764856787", + "actualEndTime": "1764856978" + }, + "success": true +} +``` + +Non-zero codes become structured failures. `80438027` is treated as `no_recording` so one empty chunk does not stop the batch. + +## Output Contract + +Cloud downloads write a dedicated manifest: + +```text +/hik_cloud_download_manifest.jsonl +``` + +Each row contains: + +- `source: hik_cloud` +- `device_serial` +- `channel_no` +- `requested_begin`, `requested_end` +- `actual_begin`, `actual_end` +- `download_url_host` or no URL at all if avoiding host persistence is preferred +- `path` for downloaded video +- `status`: `address_ok`, `downloaded`, `no_recording`, `address_failed`, `download_failed` +- `retry_count`, `last_error` + +Downloaded videos go under: + +```text +/downloads/hik_cloud//ch/ +``` + +Filenames use device/channel/requested timestamps and never include URL query signatures or tokens. + +## Pipeline Integration + +`cli.py` should branch only at source acquisition: + +```text +local mode: + discover local videos -> probe -> frames -> clips -> inference -> aggregate + +hik_cloud mode: + build chunks -> request download URLs -> download videos -> probe -> frames -> clips -> inference -> aggregate +``` + +After downloads complete, the rest of the pipeline should consume downloaded file paths and preserve cloud metadata in `video_manifest.jsonl`. + +FFmpeg sampling caps output frames from the requested/actual cloud chunk duration. This prevents malformed or irregular Hik MP4 timestamps from making the `fps=1` filter duplicate tens of thousands of frames for a 10-minute chunk. + +Cloud `--dry-run` stops at download-address planning: it requests addresses and writes `hik_cloud_download_manifest.jsonl`, but does not download video files, run ffprobe, sample frames, infer, or aggregate. + +## Error Handling + +- Missing token: fail fast with a clear config error in `hik_cloud` mode. +- Invalid range: fail fast if `end <= begin`. +- API code 80438027: record `no_recording`, continue. +- Other API non-zero code: record `address_failed`, continue other chunks. +- Download HTTP/IO failure: record `download_failed`, continue other chunks. +- Existing downloaded file with manifest status `downloaded`: skip on resume. + +## Testing + +Use TDD with standard-library mocks: + +- config parser loads `devices` as list of dicts. +- time parser accepts date-time strings and epoch integers. +- splitter produces max-3600-second chunks. +- API client builds correct URL, body, bearer header, and parses success/failure. +- downloader writes bytes and manifest without persisting token. +- CLI cloud mode uses downloaded files and keeps local mode unchanged. + +Real Hik API smoke uses the sensitive `access_token.md` file provided by the user on the remote test environment. Do not copy values from that file into docs, tests, logs, or final responses. diff --git a/tests/test_aggregator.py b/tests/test_aggregator.py new file mode 100644 index 0000000..f5446af --- /dev/null +++ b/tests/test_aggregator.py @@ -0,0 +1,309 @@ +import json +import tempfile +import unittest +from datetime import datetime, timedelta +from pathlib import Path + +from video_ai_analysis_poc.aggregator import aggregate_outputs + + +class AggregatorTests(unittest.TestCase): + def test_aggregates_video_results_folder_summary_and_merges_adjacent_events(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + video_a = { + "video_id": "video-a", + "path": "/videos/a.mp4", + "status": "probed", + "duration_seconds": 40.0, + "codec_name": "h264", + "width": 1920, + "height": 1080, + } + video_b = { + "video_id": "video-b", + "path": "/videos/b.mp4", + "status": "probe_failed", + "last_error": "bad file", + } + self._write_jsonl(output_dir / "video_manifest.jsonl", [video_a, video_b]) + clips = [ + self._clip("video-a", "video-a_c000001", 0.0, 10.0), + self._clip("video-a", "video-a_c000002", 12.0, 20.0), + self._clip("video-a", "video-a_c000003", 21.0, 30.0), + self._clip("video-b", "video-b_c000001", 0.0, 10.0), + ] + self._write_jsonl(output_dir / "clip_manifest.jsonl", clips) + results = [ + self._result( + "video-a", + "video-a_c000001", + "/videos/a.mp4", + 0.0, + 10.0, + "09:00:01", + [{"event_type": "queue_detected", "start_offset_seconds": 1.0, "end_offset_seconds": 10.0}], + ), + self._result( + "video-a", + "video-a_c000002", + "/videos/a.mp4", + 12.0, + 20.0, + "09:00:13", + [{"event_type": "queue_detected", "start_offset_seconds": 12.0, "end_offset_seconds": 16.0}], + ), + self._result( + "video-a", + "video-a_c000003", + "/videos/a.mp4", + 21.0, + 30.0, + "09:00:22", + [{"event_type": "staff_absent", "start_offset_seconds": 21.0, "end_offset_seconds": 25.0}], + ), + { + "schema_version": "local-batch-v1", + "video_id": "video-b", + "video_path": "/videos/b.mp4", + "clip_id": "video-b_c000001", + "status": "inference_failed", + "monitoring_timeline": { + "video_start_time": None, + "clip_start_seconds": 0.0, + "clip_end_seconds": 10.0, + "frame_times": [], + "screen_time": "", + }, + "events": [], + "raw_response": "", + "processing": {}, + "error": "offline", + }, + ] + self._write_jsonl(output_dir / "clip_results.jsonl", results) + + aggregate_outputs( + output_dir, + { + "input": {"dir": "/videos"}, + "schema": {"version": "local-batch-v1", "merge_gap_seconds": 3}, + "runtime": {"timezone": "Asia/Shanghai"}, + }, + ) + + video_result_path = output_dir / "videos" / "video-a" / "video_result.json" + self.assertTrue(video_result_path.exists()) + video_result = json.loads(video_result_path.read_text(encoding="utf-8")) + self.assertEqual(video_result["schema_version"], "local-batch-v1") + self.assertEqual(video_result["video_id"], "video-a") + self.assertEqual(video_result["video_path"], "/videos/a.mp4") + self.assertEqual(video_result["probe"]["codec_name"], "h264") + self.assertIsNone(video_result["monitoring_timeline"]["video_start_time"]) + self.assertEqual(video_result["monitoring_timeline"]["video_duration_seconds"], 40.0) + self.assertEqual(video_result["clip_count"], 3) + self.assertEqual(video_result["failed_clip_count"], 0) + self.assertEqual(video_result["event_counts"], {"queue_detected": 1, "staff_absent": 1}) + self.assertEqual(len(video_result["events"]), 2) + merged = video_result["events"][0] + self.assertEqual(merged["event_type"], "queue_detected") + self.assertEqual(merged["start_offset_seconds"], 1.0) + self.assertEqual(merged["end_offset_seconds"], 16.0) + self.assertEqual(merged["screen_times"], ["09:00:01", "09:00:13"]) + self.assertEqual(merged["evidence"]["clip_ids"], ["video-a_c000001", "video-a_c000002"]) + self.assertEqual( + [ + clip["clip_start_beijing_time"] + for clip in merged["evidence"]["clips"] + ], + ["2026-06-15 07:00:00", "2026-06-15 07:00:12"], + ) + self.assertEqual( + [ + clip["clip_end_beijing_time"] + for clip in merged["evidence"]["clips"] + ], + ["2026-06-15 07:00:10", "2026-06-15 07:00:20"], + ) + self.assertEqual(video_result["outputs"]["clip_results_jsonl"], "clip_results.jsonl") + self.assertIn("started_at", video_result["processing"]) + self.assertIn("finished_at", video_result["processing"]) + + failed_video_result = json.loads( + (output_dir / "videos" / "video-b" / "video_result.json").read_text( + encoding="utf-8" + ) + ) + self.assertEqual(failed_video_result["clip_count"], 1) + self.assertEqual(failed_video_result["failed_clip_count"], 1) + self.assertEqual(failed_video_result["event_counts"], {}) + + folder_summary = json.loads( + (output_dir / "folder_summary.json").read_text(encoding="utf-8") + ) + self.assertEqual(folder_summary["schema_version"], "local-batch-v1") + self.assertEqual(folder_summary["input_dir"], "/videos") + self.assertEqual(folder_summary["video_count"], 2) + self.assertEqual(folder_summary["processed_video_count"], 1) + self.assertEqual(folder_summary["failed_video_count"], 1) + self.assertEqual(folder_summary["event_counts"], {"queue_detected": 1, "staff_absent": 1}) + self.assertEqual( + [video["video_id"] for video in folder_summary["videos"]], + ["video-a", "video-b"], + ) + self.assertIn("processing", folder_summary) + + def test_ffprobe_start_time_is_not_treated_as_monitoring_timeline_start(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + self._write_jsonl( + output_dir / "video_manifest.jsonl", + [ + { + "video_id": "video-local", + "path": "/videos/local.mp4", + "status": "probed", + "duration_seconds": 12.0, + "start_time": 0.0, + } + ], + ) + self._write_jsonl( + output_dir / "clip_manifest.jsonl", + [self._clip("video-local", "video-local_c000001", 0.0, 10.0)], + ) + self._write_jsonl(output_dir / "clip_results.jsonl", []) + + aggregate_outputs( + output_dir, + { + "input": {"dir": "/videos"}, + "schema": {"version": "local-batch-v1", "merge_gap_seconds": 3}, + }, + ) + + video_result = json.loads( + (output_dir / "videos" / "video-local" / "video_result.json").read_text( + encoding="utf-8" + ) + ) + self.assertEqual(video_result["probe"]["start_time"], 0.0) + self.assertIsNone(video_result["monitoring_timeline"]["video_start_time"]) + + def test_does_not_merge_different_event_types_videos_or_large_gaps(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + self._write_jsonl( + output_dir / "video_manifest.jsonl", + [ + {"video_id": "video-a", "path": "/videos/a.mp4", "status": "probed"}, + {"video_id": "video-b", "path": "/videos/b.mp4", "status": "probed"}, + ], + ) + self._write_jsonl( + output_dir / "clip_manifest.jsonl", + [ + self._clip("video-a", "a1", 0.0, 10.0), + self._clip("video-a", "a2", 40.0, 50.0), + self._clip("video-a", "a3", 51.0, 60.0), + self._clip("video-b", "b1", 0.0, 10.0), + ], + ) + self._write_jsonl( + output_dir / "clip_results.jsonl", + [ + self._result("video-a", "a1", "/videos/a.mp4", 0.0, 10.0, "", [{"event_type": "queue_detected", "start_offset_seconds": 1.0, "end_offset_seconds": 5.0}]), + self._result("video-a", "a2", "/videos/a.mp4", 40.0, 50.0, "", [{"event_type": "queue_detected", "start_offset_seconds": 40.0, "end_offset_seconds": 45.0}]), + self._result("video-a", "a3", "/videos/a.mp4", 51.0, 60.0, "", [{"event_type": "staff_absent", "start_offset_seconds": 51.0, "end_offset_seconds": 55.0}]), + self._result("video-b", "b1", "/videos/b.mp4", 0.0, 10.0, "", [{"event_type": "queue_detected", "start_offset_seconds": 1.0, "end_offset_seconds": 5.0}]), + ], + ) + + aggregate_outputs( + output_dir, + { + "input": {"dir": "/videos"}, + "schema": {"version": "local-batch-v1", "merge_gap_seconds": 3}, + }, + ) + + video_a = json.loads( + (output_dir / "videos" / "video-a" / "video_result.json").read_text( + encoding="utf-8" + ) + ) + video_b = json.loads( + (output_dir / "videos" / "video-b" / "video_result.json").read_text( + encoding="utf-8" + ) + ) + self.assertEqual(len(video_a["events"]), 3) + self.assertEqual(video_a["event_counts"], {"queue_detected": 2, "staff_absent": 1}) + self.assertEqual(len(video_b["events"]), 1) + self.assertEqual(video_b["event_counts"], {"queue_detected": 1}) + + def _clip(self, video_id, clip_id, start, end): + return { + "video_id": video_id, + "clip_id": clip_id, + "clip_start_seconds": start, + "clip_end_seconds": end, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:10", + "frame_times": [ + { + "frame_path": f"frames/{video_id}/{clip_id}.jpg", + "offset_seconds": start, + "timecode": "00:00:00", + } + ], + "status": "pending", + } + + def _result(self, video_id, clip_id, video_path, start, end, screen_time, events): + base = datetime(2026, 6, 15, 7, 0, 0) + clip_start_beijing_time = (base + timedelta(seconds=start)).strftime( + "%Y-%m-%d %H:%M:%S" + ) + clip_end_beijing_time = (base + timedelta(seconds=end)).strftime( + "%Y-%m-%d %H:%M:%S" + ) + return { + "schema_version": "local-batch-v1", + "video_id": video_id, + "video_path": video_path, + "clip_id": clip_id, + "status": "ok", + "monitoring_timeline": { + "video_start_time": None, + "clip_start_seconds": start, + "clip_end_seconds": end, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:10", + "clip_start_beijing_time": clip_start_beijing_time, + "clip_end_beijing_time": clip_end_beijing_time, + "frame_times": [ + { + "frame_path": f"frames/{video_id}/{clip_id}.jpg", + "offset_seconds": start, + "timecode": "00:00:00", + "beijing_time": clip_start_beijing_time, + } + ], + "screen_time": screen_time, + }, + "events": events, + "raw_response": "{}", + "processing": {}, + "error": None, + } + + def _write_jsonl(self, path, records): + path.write_text( + "".join(json.dumps(record, sort_keys=True) + "\n" for record in records), + encoding="utf-8", + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_cli.py b/tests/test_cli.py new file mode 100644 index 0000000..501fba5 --- /dev/null +++ b/tests/test_cli.py @@ -0,0 +1,1275 @@ +import io +import json +import tempfile +import unittest +from contextlib import redirect_stderr +from pathlib import Path +from unittest.mock import ANY, patch + +from video_ai_analysis_poc.cli import main +from video_ai_analysis_poc.paths import stable_video_id + + +class CliTests(unittest.TestCase): + def test_unknown_source_mode_exits_with_cli_error_without_traceback(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + output_dir = root / "output" + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "source:", + " mode: bad_mode", + "output:", + f" dir: {output_dir}", + ] + ), + encoding="utf-8", + ) + stderr = io.StringIO() + + with redirect_stderr(stderr), self.assertRaises(SystemExit): + main(["--config", str(config_path), "--dry-run"]) + + stderr_text = stderr.getvalue() + self.assertIn("unsupported source.mode: bad_mode", stderr_text) + self.assertNotIn("Traceback", stderr_text) + + def test_local_source_dry_run_uses_discovery_and_not_hik_cloud_downloader(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "source:", + " mode: local", + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + ] + ), + encoding="utf-8", + ) + + with ( + patch("video_ai_analysis_poc.cli.discover_videos") as discover_videos, + patch( + "video_ai_analysis_poc.cli.download_hik_cloud_recordings" + ) as download_hik_cloud, + ): + discover_videos.return_value = [] + + exit_code = main(["--config", str(config_path), "--dry-run"]) + + self.assertEqual(exit_code, 0) + discover_videos.assert_called_once_with( + str(input_dir.resolve(strict=False)), + [".mp4"], + recursive=False, + ) + download_hik_cloud.assert_not_called() + + def test_hik_cloud_source_downloads_probes_and_preserves_cloud_metadata(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + output_dir = root / "output" + downloaded_path = output_dir / "downloads" / "hik_cloud" / "clip.mp4" + downloaded_path.parent.mkdir(parents=True) + downloaded_path.write_bytes(b"mp4") + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "source:", + " mode: hik_cloud", + "output:", + f" dir: {output_dir}", + "ffprobe:", + " timeout_seconds: 7", + ] + ), + encoding="utf-8", + ) + downloaded_record = { + "source": "hik_cloud", + "path": str(downloaded_path), + "source_path": "hik_cloud://DS-1/ch1/100-160", + "device_serial": "DS-1", + "channel_no": 1, + "requested_begin": 100, + "requested_end": 160, + "actual_begin": 101, + "actual_end": 159, + "status": "downloaded", + "retry_count": 0, + "last_error": None, + } + + with ( + patch( + "video_ai_analysis_poc.cli.download_hik_cloud_recordings" + ) as download_hik_cloud, + patch("video_ai_analysis_poc.cli.discover_videos") as discover_videos, + patch("video_ai_analysis_poc.cli.probe_video") as probe_video, + patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames, + ): + download_hik_cloud.return_value = [downloaded_record] + probe_video.return_value = { + "path": str(downloaded_path), + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 60.0, + "codec_name": "h264", + } + sample_frames.return_value = [] + + exit_code = main(["--config", str(config_path), "--until", "clips"]) + + self.assertEqual(exit_code, 0) + download_hik_cloud.assert_called_once_with( + ANY, output_dir.resolve(strict=False), download=True + ) + discover_videos.assert_not_called() + probe_video.assert_called_once_with(str(downloaded_path), timeout_seconds=7) + records = [ + json.loads(line) + for line in (output_dir / "video_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(len(records), 1) + record = records[0] + self.assertEqual(record["video_id"], stable_video_id(downloaded_path)) + self.assertEqual(record["status"], "probed") + self.assertEqual(record["source"], "hik_cloud") + self.assertEqual(record["source_path"], "hik_cloud://DS-1/ch1/100-160") + self.assertEqual(record["device_serial"], "DS-1") + self.assertEqual(record["channel_no"], 1) + self.assertEqual(record["requested_begin"], 100) + self.assertEqual(record["requested_end"], 160) + self.assertEqual(record["actual_begin"], 101) + self.assertEqual(record["actual_end"], 159) + self.assertEqual(record["duration_seconds"], 60.0) + self.assertEqual(record["codec_name"], "h264") + + def test_hik_cloud_dry_run_requests_addresses_without_download_probe_or_analysis(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + output_dir = root / "output" + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "source:", + " mode: hik_cloud", + "output:", + f" dir: {output_dir}", + ] + ), + encoding="utf-8", + ) + + with ( + patch( + "video_ai_analysis_poc.cli.download_hik_cloud_recordings" + ) as download_hik_cloud, + patch("video_ai_analysis_poc.cli.probe_video") as probe_video, + patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames, + patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip, + patch("video_ai_analysis_poc.cli.aggregate_outputs") as aggregate_outputs, + ): + download_hik_cloud.return_value = [] + + exit_code = main(["--config", str(config_path), "--dry-run"]) + + self.assertEqual(exit_code, 0) + download_hik_cloud.assert_called_once_with( + ANY, output_dir.resolve(strict=False), download=False + ) + probe_video.assert_not_called() + self.assertTrue((output_dir / "video_manifest.jsonl").exists()) + sample_frames.assert_not_called() + infer_clip.assert_not_called() + aggregate_outputs.assert_not_called() + + def test_hik_cloud_until_clips_generates_video_frame_and_clip_manifests(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + output_dir = root / "output" + downloaded_path = output_dir / "downloads" / "hik_cloud" / "clips.mp4" + downloaded_path.parent.mkdir(parents=True) + downloaded_path.write_bytes(b"mp4") + video_id = stable_video_id(downloaded_path) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "source:", + " mode: hik_cloud", + "output:", + f" dir: {output_dir}", + "ffprobe:", + " timeout_seconds: 5", + "ffmpeg:", + " prefer_nvdec: true", + " allow_cpu_fallback: false", + " hwaccel: cuda", + " codec_decoders:", + " h264: h264_cuvid", + "clip:", + " length_seconds: 10", + " stride_seconds: 10", + " frames_per_clip: 4", + " min_frames_per_clip: 2", + ] + ), + encoding="utf-8", + ) + downloaded_record = { + "source": "hik_cloud", + "path": str(downloaded_path), + "source_path": "hik_cloud://DS-3/ch1/300-360", + "device_serial": "DS-3", + "channel_no": 1, + "requested_begin": 300, + "requested_end": 360, + "actual_begin": 300, + "actual_end": 360, + "status": "downloaded", + } + frame_records = [ + { + "video_id": video_id, + "frame_id": f"{video_id}_f{index + 1:06d}", + "frame_path": f"frames/{video_id}/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + "retry_count": 0, + "last_error": None, + } + for index in range(4) + ] + + with ( + patch( + "video_ai_analysis_poc.cli.download_hik_cloud_recordings" + ) as download_hik_cloud, + patch("video_ai_analysis_poc.cli.probe_video") as probe_video, + patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames, + patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip, + patch("video_ai_analysis_poc.cli.aggregate_outputs") as aggregate_outputs, + ): + download_hik_cloud.return_value = [downloaded_record] + probe_video.return_value = { + "path": str(downloaded_path), + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 4.0, + "codec_name": "h264", + } + sample_frames.return_value = frame_records + + exit_code = main(["--config", str(config_path), "--until", "clips"]) + + self.assertEqual(exit_code, 0) + download_hik_cloud.assert_called_once_with( + ANY, output_dir.resolve(strict=False), download=True + ) + sample_frames.assert_called_once() + infer_clip.assert_not_called() + aggregate_outputs.assert_not_called() + video_records = [ + json.loads(line) + for line in (output_dir / "video_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + persisted_frames = [ + json.loads(line) + for line in (output_dir / "frame_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + clip_records = [ + json.loads(line) + for line in (output_dir / "clip_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(len(video_records), 1) + self.assertEqual(video_records[0]["video_id"], video_id) + self.assertEqual(video_records[0]["source"], "hik_cloud") + self.assertEqual(persisted_frames, frame_records) + self.assertEqual(len(clip_records), 1) + self.assertEqual(clip_records[0]["video_id"], video_id) + self.assertEqual(clip_records[0]["status"], "pending") + + def test_dry_run_discovers_probes_and_writes_manifest_without_crashing(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + (input_dir / "dummy.mp4").write_text("not a real video", encoding="utf-8") + (input_dir / "ignore.txt").write_text("ignore", encoding="utf-8") + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + "ffprobe:", + " timeout_seconds: 3", + ] + ), + encoding="utf-8", + ) + + exit_code = main(["--config", str(config_path), "--dry-run"]) + + self.assertEqual(exit_code, 0) + manifest_path = output_dir / "video_manifest.jsonl" + self.assertTrue(manifest_path.exists()) + records = [ + json.loads(line) + for line in manifest_path.read_text(encoding="utf-8").splitlines() + ] + self.assertEqual(len(records), 1) + self.assertEqual(records[0]["status"], "probe_failed") + self.assertEqual(records[0]["retry_count"], 0) + self.assertIn("dummy.mp4", records[0]["path"]) + + def test_dry_run_resume_preserves_existing_completed_manifest_record(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "done.mp4" + video_path.write_text("not a real video", encoding="utf-8") + existing_record = { + "path": str(video_path), + "video_id": stable_video_id(video_path), + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 12.5, + } + manifest_path = output_dir / "video_manifest.jsonl" + manifest_path.write_text( + json.dumps(existing_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "ffprobe:", + " timeout_seconds: 3", + ] + ), + encoding="utf-8", + ) + + with patch("video_ai_analysis_poc.cli.probe_video") as probe_video: + exit_code = main(["--config", str(config_path), "--dry-run"]) + + self.assertEqual(exit_code, 0) + probe_video.assert_not_called() + records = [ + json.loads(line) + for line in manifest_path.read_text(encoding="utf-8").splitlines() + ] + self.assertEqual(records, [existing_record]) + + def test_until_clips_writes_video_frame_and_clip_manifests_without_vlm(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + video_path = input_dir / "clip.mp4" + video_path.write_text("not a real video", encoding="utf-8") + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + "ffprobe:", + " timeout_seconds: 3", + "ffmpeg:", + " prefer_nvdec: true", + " allow_cpu_fallback: false", + " hwaccel: cuda", + " codec_decoders:", + " h264: h264_cuvid", + " frame_fps: 1", + " frame_width: 640", + " jpeg_quality: 4", + " timeout_seconds_per_video: 30", + "clip:", + " length_seconds: 10", + " stride_seconds: 10", + " frames_per_clip: 4", + " min_frames_per_clip: 2", + ] + ), + encoding="utf-8", + ) + frame_records = [ + { + "video_id": stable_video_id(video_path), + "frame_id": f"{stable_video_id(video_path)}_f{index + 1:06d}", + "frame_path": f"frames/{stable_video_id(video_path)}/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + } + for index in range(4) + ] + + with ( + patch("video_ai_analysis_poc.cli.probe_video") as probe_video, + patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames, + ): + probe_video.return_value = { + "path": str(video_path), + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 4.0, + "codec_name": "h264", + } + sample_frames.return_value = frame_records + + exit_code = main(["--config", str(config_path), "--until", "clips"]) + + self.assertEqual(exit_code, 0) + self.assertTrue((output_dir / "video_manifest.jsonl").exists()) + self.assertTrue((output_dir / "frame_manifest.jsonl").exists()) + self.assertTrue((output_dir / "clip_manifest.jsonl").exists()) + clip_records = [ + json.loads(line) + for line in (output_dir / "clip_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(len(clip_records), 1) + self.assertEqual(clip_records[0]["status"], "pending") + self.assertEqual(len(clip_records[0]["frame_times"]), 4) + + def test_until_clips_resume_preserves_existing_frame_and_clip_manifests(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "done.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + video_record = { + "path": str(video_path), + "video_id": video_id, + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 4.0, + "codec_name": "h264", + } + frame_record = { + "video_id": video_id, + "frame_id": f"{video_id}_f000001", + "frame_path": f"frames/{video_id}/000001.jpg", + "offset_seconds": 0.0, + "timecode": "00:00:00", + "pts_time": 0.0, + "status": "sampled", + "retry_count": 0, + "last_error": None, + } + clip_record = { + "video_id": video_id, + "clip_id": f"{video_id}_c000001", + "clip_start_seconds": 0.0, + "clip_end_seconds": 4.0, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:04", + "frame_times": [ + { + "frame_id": frame_record["frame_id"], + "frame_path": frame_record["frame_path"], + "offset_seconds": 0.0, + "timecode": "00:00:00", + "pts_time": 0.0, + } + ], + "status": "pending", + "retry_count": 0, + "last_error": None, + } + (output_dir / "video_manifest.jsonl").write_text( + json.dumps(video_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "frame_manifest.jsonl").write_text( + json.dumps(frame_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "clip_manifest.jsonl").write_text( + json.dumps(clip_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "ffprobe:", + " timeout_seconds: 3", + "ffmpeg:", + " prefer_nvdec: true", + " allow_cpu_fallback: false", + " codec_decoders:", + " h264: h264_cuvid", + "clip:", + " length_seconds: 10", + " stride_seconds: 10", + " frames_per_clip: 4", + " min_frames_per_clip: 1", + ] + ), + encoding="utf-8", + ) + + with patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames: + exit_code = main(["--config", str(config_path), "--until", "clips"]) + + self.assertEqual(exit_code, 0) + sample_frames.assert_not_called() + persisted_frames = [ + json.loads(line) + for line in (output_dir / "frame_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + persisted_clips = [ + json.loads(line) + for line in (output_dir / "clip_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(persisted_frames, [frame_record]) + self.assertEqual(persisted_clips, [clip_record]) + + def test_resume_backfills_beijing_times_without_reinference(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "done.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + video_record = { + "path": str(video_path), + "video_id": video_id, + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 10.0, + "codec_name": "h264", + "actual_begin": 1781478000, + "actual_end": 1781478010, + } + frame_records = [ + { + "video_id": video_id, + "frame_id": f"{video_id}_f{index + 1:06d}", + "frame_path": f"frames/{video_id}/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + "retry_count": 0, + "last_error": None, + } + for index in range(10) + ] + clip_id = f"{video_id}_c000001" + old_clip_record = { + "video_id": video_id, + "clip_id": clip_id, + "clip_start_seconds": 0.0, + "clip_end_seconds": 10.0, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:10", + "frame_times": [frame_records[0]], + "status": "pending", + "retry_count": 0, + "last_error": None, + } + old_result_record = { + "schema_version": "local-batch-v1", + "video_id": video_id, + "video_path": str(video_path), + "clip_id": clip_id, + "status": "ok", + "monitoring_timeline": { + "timezone": "Asia/Shanghai", + "clip_start_seconds": 0.0, + "clip_end_seconds": 10.0, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:10", + "frame_times": [frame_records[0]], + "screen_time": "2026-06-15 07:00:00", + }, + "events": [], + "raw_response": "{}", + "processing": {}, + "error": None, + } + (output_dir / "video_manifest.jsonl").write_text( + json.dumps(video_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "frame_manifest.jsonl").write_text( + "".join( + json.dumps(record, sort_keys=True) + "\n" + for record in frame_records + ), + encoding="utf-8", + ) + (output_dir / "clip_manifest.jsonl").write_text( + json.dumps(old_clip_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "clip_results.jsonl").write_text( + json.dumps(old_result_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "ffprobe:", + " timeout_seconds: 3", + "ffmpeg:", + " prefer_nvdec: true", + " allow_cpu_fallback: false", + " codec_decoders:", + " h264: h264_cuvid", + "clip:", + " length_seconds: 10", + " stride_seconds: 10", + " frames_per_clip: 4", + " min_frames_per_clip: 1", + "runtime:", + " timezone: Asia/Shanghai", + ] + ), + encoding="utf-8", + ) + + with ( + patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames, + patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip, + ): + exit_code = main(["--config", str(config_path), "--until", "inference"]) + + self.assertEqual(exit_code, 0) + sample_frames.assert_not_called() + infer_clip.assert_not_called() + persisted_frames = [ + json.loads(line) + for line in (output_dir / "frame_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + persisted_clips = [ + json.loads(line) + for line in (output_dir / "clip_manifest.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + result_records = [ + json.loads(line) + for line in (output_dir / "clip_results.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(persisted_frames[0]["beijing_time"], "2026-06-15 07:00:00") + self.assertEqual(persisted_frames[9]["beijing_time"], "2026-06-15 07:00:09") + self.assertEqual( + persisted_clips[0]["clip_start_beijing_time"], + "2026-06-15 07:00:00", + ) + self.assertEqual( + persisted_clips[0]["clip_end_beijing_time"], + "2026-06-15 07:00:10", + ) + self.assertEqual( + result_records[0]["monitoring_timeline"]["clip_start_beijing_time"], + "2026-06-15 07:00:00", + ) + self.assertEqual( + result_records[0]["monitoring_timeline"]["frame_times"][0][ + "beijing_time" + ], + "2026-06-15 07:00:00", + ) + + def test_until_inference_writes_clip_results_and_uses_limit(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "ready.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + video_record = { + "path": str(video_path), + "video_id": video_id, + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 20.0, + "codec_name": "h264", + } + clip_records = [ + { + "video_id": video_id, + "clip_id": f"{video_id}_c00000{index + 1}", + "clip_start_seconds": float(index * 10), + "clip_end_seconds": float((index + 1) * 10), + "clip_start_timecode": f"00:00:{index * 10:02d}", + "clip_end_timecode": f"00:00:{(index + 1) * 10:02d}", + "frame_times": [ + { + "frame_path": f"frames/{video_id}/00000{index + 1}.jpg", + "offset_seconds": float(index * 10), + "timecode": f"00:00:{index * 10:02d}", + } + ], + "status": "pending", + "retry_count": 0, + "last_error": None, + } + for index in range(2) + ] + for clip in clip_records: + frame_path = output_dir / clip["frame_times"][0]["frame_path"] + frame_path.parent.mkdir(parents=True, exist_ok=True) + frame_path.write_bytes(b"jpg") + (output_dir / "video_manifest.jsonl").write_text( + json.dumps(video_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "clip_manifest.jsonl").write_text( + "".join(json.dumps(record, sort_keys=True) + "\n" for record in clip_records), + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "ffprobe:", + " timeout_seconds: 3", + "vlm:", + " api_base_url: http://localhost:8679", + " chat_completions_path: /v1/chat/completions", + " model: memai-zhengxin-v3-20260413", + "prompt:", + " system: system from config", + " user: user from config", + "schema:", + " version: local-batch-v1", + "runtime:", + " timezone: Asia/Shanghai", + ] + ), + encoding="utf-8", + ) + + with patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip: + infer_clip.return_value = { + "raw_response": '{"screen_time":"10:00:01","events":[]}', + "latency_ms": 12, + "http_status": 200, + } + + exit_code = main( + [ + "--config", + str(config_path), + "--until", + "inference", + "--limit-clips", + "1", + ] + ) + + self.assertEqual(exit_code, 0) + self.assertEqual(infer_clip.call_count, 1) + result_records = [ + json.loads(line) + for line in (output_dir / "clip_results.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(len(result_records), 1) + self.assertEqual(result_records[0]["status"], "ok") + self.assertEqual(result_records[0]["monitoring_timeline"]["frame_times"], clip_records[0]["frame_times"]) + self.assertEqual(result_records[0]["monitoring_timeline"]["screen_time"], "10:00:01") + self.assertEqual(result_records[0]["events"], []) + self.assertFalse((output_dir / "video_result.json").exists()) + self.assertFalse((output_dir / "folder_summary.json").exists()) + + def test_until_inference_flushes_clip_results_after_each_clip(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "ready.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + video_record = { + "path": str(video_path), + "video_id": video_id, + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 20.0, + "codec_name": "h264", + } + clip_records = [ + { + "video_id": video_id, + "clip_id": f"{video_id}_c00000{index + 1}", + "clip_start_seconds": float(index * 10), + "clip_end_seconds": float((index + 1) * 10), + "clip_start_timecode": f"00:00:{index * 10:02d}", + "clip_end_timecode": f"00:00:{(index + 1) * 10:02d}", + "frame_times": [], + "status": "pending", + "retry_count": 0, + "last_error": None, + } + for index in range(2) + ] + (output_dir / "video_manifest.jsonl").write_text( + json.dumps(video_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "clip_manifest.jsonl").write_text( + "".join(json.dumps(record, sort_keys=True) + "\n" for record in clip_records), + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {output_dir}", + " resume: true", + "schema:", + " version: local-batch-v1", + ] + ), + encoding="utf-8", + ) + + flush_observations = [] + + def fake_infer_clip(clip_record, *args, **kwargs): + if clip_record["clip_id"] == clip_records[1]["clip_id"]: + results_path = output_dir / "clip_results.jsonl" + flushed = [] + if results_path.exists(): + flushed = [ + json.loads(line) + for line in results_path.read_text(encoding="utf-8").splitlines() + ] + flush_observations.append( + { + "exists": results_path.exists(), + "count": len(flushed), + "first_clip_id": flushed[0]["clip_id"] if flushed else None, + "first_status": flushed[0]["status"] if flushed else None, + } + ) + return { + "raw_response": '{"screen_time":"10:00:01","events":[]}', + "latency_ms": 12, + "http_status": 200, + } + + with patch("video_ai_analysis_poc.cli.infer_clip", side_effect=fake_infer_clip): + exit_code = main(["--config", str(config_path), "--until", "inference"]) + + self.assertEqual(exit_code, 0) + self.assertEqual( + flush_observations, + [ + { + "exists": True, + "count": 1, + "first_clip_id": clip_records[0]["clip_id"], + "first_status": "ok", + } + ], + ) + result_records = [ + json.loads(line) + for line in (output_dir / "clip_results.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(len(result_records), 2) + + def test_until_inference_preserves_existing_ok_result_and_records_parse_failure(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "ready.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + ok_clip_id = f"{video_id}_c000001" + retry_clip_id = f"{video_id}_c000002" + video_record = { + "path": str(video_path), + "video_id": video_id, + "status": "probed", + "retry_count": 0, + "last_error": None, + } + clip_records = [ + { + "video_id": video_id, + "clip_id": ok_clip_id, + "clip_start_seconds": 0.0, + "clip_end_seconds": 10.0, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:10", + "frame_times": [], + "status": "pending", + }, + { + "video_id": video_id, + "clip_id": retry_clip_id, + "clip_start_seconds": 10.0, + "clip_end_seconds": 20.0, + "clip_start_timecode": "00:00:10", + "clip_end_timecode": "00:00:20", + "frame_times": [], + "status": "pending", + }, + ] + existing_ok = { + "schema_version": "local-batch-v1", + "video_id": video_id, + "video_path": str(video_path), + "clip_id": ok_clip_id, + "status": "ok", + "monitoring_timeline": {"frame_times": [], "screen_time": ""}, + "events": [], + "raw_response": "{}", + "processing": {}, + "error": None, + } + (output_dir / "video_manifest.jsonl").write_text( + json.dumps(video_record, sort_keys=True) + "\n", + encoding="utf-8", + ) + (output_dir / "clip_manifest.jsonl").write_text( + "".join(json.dumps(record, sort_keys=True) + "\n" for record in clip_records), + encoding="utf-8", + ) + (output_dir / "clip_results.jsonl").write_text( + json.dumps(existing_ok, sort_keys=True) + "\n", + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "ffprobe:", + " timeout_seconds: 3", + ] + ), + encoding="utf-8", + ) + + with patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip: + infer_clip.return_value = { + "raw_response": "not-json", + "latency_ms": 12, + "http_status": 200, + } + + exit_code = main(["--config", str(config_path), "--until", "inference"]) + + self.assertEqual(exit_code, 0) + self.assertEqual(infer_clip.call_count, 2) + result_records = [ + json.loads(line) + for line in (output_dir / "clip_results.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(result_records[0], existing_ok) + self.assertEqual(result_records[1]["clip_id"], retry_clip_id) + self.assertEqual(result_records[1]["status"], "parse_failed") + self.assertIn("JSON", result_records[1]["error"]) + + def test_until_inference_retries_once_after_parse_failure(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + output_dir.mkdir() + video_path = input_dir / "ready.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + clip_id = f"{video_id}_c000001" + (output_dir / "video_manifest.jsonl").write_text( + json.dumps( + { + "path": str(video_path), + "video_id": video_id, + "status": "probed", + "retry_count": 0, + "last_error": None, + }, + sort_keys=True, + ) + + "\n", + encoding="utf-8", + ) + (output_dir / "clip_manifest.jsonl").write_text( + json.dumps( + { + "video_id": video_id, + "clip_id": clip_id, + "clip_start_seconds": 0.0, + "clip_end_seconds": 10.0, + "clip_start_timecode": "00:00:00", + "clip_end_timecode": "00:00:10", + "frame_times": [], + "status": "pending", + }, + sort_keys=True, + ) + + "\n", + encoding="utf-8", + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "schema:", + " version: local-batch-v1", + " parse_retry: 1", + ] + ), + encoding="utf-8", + ) + + with patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip: + infer_clip.side_effect = [ + { + "raw_response": "not-json", + "latency_ms": 10, + "http_status": 200, + }, + { + "raw_response": '{"screen_time":"10:00:02","events":[]}', + "latency_ms": 11, + "http_status": 200, + }, + ] + + exit_code = main(["--config", str(config_path), "--until", "inference"]) + + self.assertEqual(exit_code, 0) + self.assertEqual(infer_clip.call_count, 2) + result_records = [ + json.loads(line) + for line in (output_dir / "clip_results.jsonl") + .read_text(encoding="utf-8") + .splitlines() + ] + self.assertEqual(result_records[0]["status"], "ok") + self.assertEqual(result_records[0]["monitoring_timeline"]["screen_time"], "10:00:02") + + def test_default_full_run_writes_clip_video_and_folder_results(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "input" + output_dir = root / "output" + input_dir.mkdir() + video_path = input_dir / "full.mp4" + video_path.write_text("not a real video", encoding="utf-8") + video_id = stable_video_id(video_path) + frame_records = [ + { + "video_id": video_id, + "frame_id": f"{video_id}_f{index + 1:06d}", + "frame_path": f"frames/{video_id}/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + } + for index in range(4) + ] + for frame in frame_records: + frame_path = output_dir / frame["frame_path"] + frame_path.parent.mkdir(parents=True, exist_ok=True) + frame_path.write_bytes(b"jpg") + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4"]', + "output:", + f" dir: {output_dir}", + " resume: true", + "ffprobe:", + " timeout_seconds: 3", + "ffmpeg:", + " prefer_nvdec: true", + " allow_cpu_fallback: false", + " codec_decoders:", + " h264: h264_cuvid", + "clip:", + " length_seconds: 10", + " stride_seconds: 10", + " frames_per_clip: 4", + " min_frames_per_clip: 1", + "schema:", + " version: local-batch-v1", + " merge_gap_seconds: 30", + ] + ), + encoding="utf-8", + ) + + with ( + patch("video_ai_analysis_poc.cli.probe_video") as probe_video, + patch("video_ai_analysis_poc.cli.sample_video_frames") as sample_frames, + patch("video_ai_analysis_poc.cli.infer_clip") as infer_clip, + ): + probe_video.return_value = { + "path": str(video_path), + "status": "probed", + "retry_count": 0, + "last_error": None, + "duration_seconds": 4.0, + "codec_name": "h264", + } + sample_frames.return_value = frame_records + infer_clip.return_value = { + "raw_response": ( + '{"screen_time":"10:00:02",' + '"events":[{"event_type":"queue_detected","confidence":0.8}]}' + ), + "latency_ms": 12, + "http_status": 200, + } + + exit_code = main(["--config", str(config_path)]) + + self.assertEqual(exit_code, 0) + self.assertTrue((output_dir / "clip_results.jsonl").exists()) + self.assertTrue((output_dir / "videos" / video_id / "video_result.json").exists()) + self.assertTrue((output_dir / "folder_summary.json").exists()) + folder_summary = json.loads( + (output_dir / "folder_summary.json").read_text(encoding="utf-8") + ) + self.assertEqual(folder_summary["video_count"], 1) + self.assertEqual(folder_summary["processed_video_count"], 1) + self.assertEqual(folder_summary["failed_video_count"], 0) + self.assertEqual(folder_summary["event_counts"], {"queue_detected": 1}) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_clips.py b/tests/test_clips.py new file mode 100644 index 0000000..dd415d1 --- /dev/null +++ b/tests/test_clips.py @@ -0,0 +1,167 @@ +import json +import tempfile +import unittest +from pathlib import Path + +from video_ai_analysis_poc.clips import build_clip_records, build_clip_records_from_manifest + + +class ClipTests(unittest.TestCase): + def test_build_clip_records_uniformly_samples_frames_per_clip(self): + frames = [ + { + "video_id": "video-abc", + "frame_id": f"video-abc_f{index + 1:06d}", + "frame_path": f"frames/video-abc/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + } + for index in range(10) + ] + + clips = build_clip_records( + frames, + { + "length_seconds": 10, + "stride_seconds": 10, + "frames_per_clip": 4, + "min_frames_per_clip": 2, + }, + ) + + self.assertEqual(len(clips), 1) + self.assertEqual(clips[0]["clip_id"], "video-abc_c000001") + self.assertEqual(clips[0]["clip_start_seconds"], 0.0) + self.assertEqual(clips[0]["clip_end_seconds"], 10.0) + self.assertEqual( + [frame["offset_seconds"] for frame in clips[0]["frame_times"]], + [0.0, 3.0, 6.0, 9.0], + ) + self.assertEqual(clips[0]["status"], "pending") + self.assertEqual(clips[0]["retry_count"], 0) + self.assertIsNone(clips[0]["last_error"]) + + def test_tail_clip_end_is_truncated_to_last_frame_interval(self): + frames = [ + { + "video_id": "video-abc", + "frame_id": f"video-abc_f{index + 1:06d}", + "frame_path": f"frames/video-abc/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + } + for index in range(15) + ] + + clips = build_clip_records( + frames, + { + "length_seconds": 10, + "stride_seconds": 10, + "frames_per_clip": 8, + "min_frames_per_clip": 4, + }, + ) + + self.assertEqual(len(clips), 2) + self.assertEqual(clips[1]["clip_start_seconds"], 10.0) + self.assertEqual(clips[1]["clip_end_seconds"], 15.0) + self.assertEqual(clips[1]["clip_end_timecode"], "00:00:15") + + def test_build_clip_records_adds_beijing_time_range_and_frame_times(self): + frames = [ + { + "video_id": "video-abc", + "frame_id": f"video-abc_f{index + 1:06d}", + "frame_path": f"frames/video-abc/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "beijing_time": f"2026-06-15 07:00:{index:02d}", + "status": "sampled", + } + for index in range(10) + ] + + clips = build_clip_records( + frames, + { + "length_seconds": 10, + "stride_seconds": 10, + "frames_per_clip": 4, + "min_frames_per_clip": 2, + }, + ) + + self.assertEqual(clips[0]["clip_start_beijing_time"], "2026-06-15 07:00:00") + self.assertEqual(clips[0]["clip_end_beijing_time"], "2026-06-15 07:00:10") + self.assertEqual( + [frame["beijing_time"] for frame in clips[0]["frame_times"]], + [ + "2026-06-15 07:00:00", + "2026-06-15 07:00:03", + "2026-06-15 07:00:06", + "2026-06-15 07:00:09", + ], + ) + + def test_build_clip_records_from_manifest_skips_failed_frames_and_writes_jsonl(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + frame_manifest = root / "frame_manifest.jsonl" + clip_manifest = root / "clip_manifest.jsonl" + records = [ + { + "video_id": "video-abc", + "frame_id": f"video-abc_f{index + 1:06d}", + "frame_path": f"frames/video-abc/{index + 1:06d}.jpg", + "offset_seconds": float(index), + "timecode": f"00:00:{index:02d}", + "pts_time": float(index), + "status": "sampled", + } + for index in range(4) + ] + records.append( + { + "video_id": "video-abc", + "frame_id": None, + "frame_path": None, + "offset_seconds": None, + "timecode": None, + "pts_time": None, + "status": "sample_failed", + "last_error": "bad decode", + } + ) + frame_manifest.write_text( + "\n".join(json.dumps(record, sort_keys=True) for record in records) + "\n", + encoding="utf-8", + ) + + clips = build_clip_records_from_manifest( + frame_manifest, + clip_manifest, + { + "length_seconds": 10, + "stride_seconds": 10, + "frames_per_clip": 8, + "min_frames_per_clip": 4, + }, + ) + + self.assertEqual(len(clips), 1) + self.assertEqual(len(clips[0]["frame_times"]), 4) + persisted = [ + json.loads(line) + for line in clip_manifest.read_text(encoding="utf-8").splitlines() + ] + self.assertEqual(persisted, clips) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 0000000..83f682f --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,240 @@ +import tempfile +import unittest +from pathlib import Path + +from video_ai_analysis_poc.config import load_config + + +class ConfigTests(unittest.TestCase): + def test_loads_local_batch_yaml_and_applies_cli_overrides(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + output_dir = root / "out" + override_input = root / "override-videos" + override_output = root / "override-out" + input_dir.mkdir() + override_input.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + " recursive: false", + ' extensions: [".mp4", ".mov"]', + "output:", + f" dir: {output_dir}", + " overwrite: false", + "ffprobe:", + " timeout_seconds: 5", + ] + ), + encoding="utf-8", + ) + + config = load_config( + config_path, + input_dir=override_input, + output_dir=override_output, + ) + + self.assertEqual(config["input"]["dir"], str(override_input.resolve())) + self.assertEqual(config["output"]["dir"], str(override_output.resolve())) + self.assertFalse(config["input"]["recursive"]) + self.assertEqual(config["input"]["extensions"], [".mp4", ".mov"]) + self.assertEqual(config["ffprobe"]["timeout_seconds"], 5) + + def test_rejects_output_dir_equal_to_input_dir(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + input_dir.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {input_dir}", + ] + ), + encoding="utf-8", + ) + + with self.assertRaisesRegex(ValueError, "output dir must not equal input dir"): + load_config(config_path) + + def test_rejects_output_dir_inside_reference_project(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + input_dir.mkdir() + forbidden_output = ( + Path("/Users/yoilun/AI-train/zhengxin-vlm-0413") + / "outputs" + / "local-batch" + ) + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {forbidden_output}", + ] + ), + encoding="utf-8", + ) + + with self.assertRaisesRegex( + ValueError, "output dir must not be inside forbidden reference dir" + ): + load_config(config_path) + + def test_loads_nested_mapping_values(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + output_dir = root / "output" + input_dir.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {output_dir}", + "ffmpeg:", + " codec_decoders:", + " h264: h264_cuvid", + " hevc: hevc_cuvid", + ] + ), + encoding="utf-8", + ) + + config = load_config(config_path) + + self.assertEqual( + config["ffmpeg"]["codec_decoders"], + {"h264": "h264_cuvid", "hevc": "hevc_cuvid"}, + ) + + def test_loads_prompt_block_scalar_values(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + output_dir = root / "output" + input_dir.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {output_dir}", + "prompt:", + " system: >-", + " First instruction.", + " Second instruction.", + "", + " Final instruction.", + " user: 'Return strict JSON.'", + ] + ), + encoding="utf-8", + ) + + config = load_config(config_path) + + self.assertEqual( + config["prompt"]["system"], + "First instruction.\nSecond instruction.\n\nFinal instruction.", + ) + self.assertEqual(config["prompt"]["user"], "Return strict JSON.") + + def test_defaults_source_mode_to_local_and_hik_cloud_section(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + output_dir = root / "output" + input_dir.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {output_dir}", + ] + ), + encoding="utf-8", + ) + + config = load_config(config_path) + + self.assertEqual(config["source"]["mode"], "local") + self.assertIn("devices", config["hik_cloud"]) + self.assertIn("time_ranges", config["hik_cloud"]) + + def test_loads_hik_cloud_devices_and_time_ranges_as_list_of_mappings(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + input_dir = root / "videos" + output_dir = root / "output" + input_dir.mkdir() + config_path = root / "local_batch.yaml" + config_path.write_text( + "\n".join( + [ + "input:", + f" dir: {input_dir}", + "output:", + f" dir: {output_dir}", + "source:", + " mode: hik_cloud", + "hik_cloud:", + " devices:", + " - device_serial: EXAMPLE_DEVICE_SERIAL", + " channel_no: 1", + " name: front", + " time_ranges:", + ' - begin: "2026-02-03 09:00:00"', + ' end: "2026-02-03 10:30:00"', + ] + ), + encoding="utf-8", + ) + + config = load_config(config_path) + + self.assertEqual(config["source"]["mode"], "hik_cloud") + self.assertEqual( + config["hik_cloud"]["devices"], + [ + { + "device_serial": "EXAMPLE_DEVICE_SERIAL", + "channel_no": 1, + "name": "front", + } + ], + ) + self.assertEqual( + config["hik_cloud"]["time_ranges"], + [ + { + "begin": "2026-02-03 09:00:00", + "end": "2026-02-03 10:30:00", + } + ], + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_discovery.py b/tests/test_discovery.py new file mode 100644 index 0000000..1016644 --- /dev/null +++ b/tests/test_discovery.py @@ -0,0 +1,41 @@ +import tempfile +import unittest +from pathlib import Path + +from video_ai_analysis_poc.discovery import discover_videos + + +class DiscoveryTests(unittest.TestCase): + def test_discovers_supported_extensions_without_recursion(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + nested = root / "nested" + nested.mkdir() + supported = root / "a.MP4" + unsupported = root / "notes.txt" + nested_video = nested / "b.mov" + supported.write_text("not a real video", encoding="utf-8") + unsupported.write_text("ignore me", encoding="utf-8") + nested_video.write_text("not a real video", encoding="utf-8") + + videos = discover_videos(root, [".mp4", ".mov"], recursive=False) + + self.assertEqual(videos, [supported]) + + def test_discovers_supported_extensions_recursively_sorted(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + nested = root / "nested" + nested.mkdir() + first = root / "a.mp4" + second = nested / "b.mov" + first.write_text("x", encoding="utf-8") + second.write_text("x", encoding="utf-8") + + videos = discover_videos(root, [".mp4", ".mov"], recursive=True) + + self.assertEqual(videos, [first, second]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_ffmpeg_sampler.py b/tests/test_ffmpeg_sampler.py new file mode 100644 index 0000000..b671889 --- /dev/null +++ b/tests/test_ffmpeg_sampler.py @@ -0,0 +1,357 @@ +import json +import subprocess +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +from video_ai_analysis_poc.ffmpeg_sampler import ( + build_sample_command, + sample_video_frames, +) + + +class FfmpegSamplerTests(unittest.TestCase): + def test_build_sample_command_uses_nvdec_decoder_for_h264(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) / "output" + + command = build_sample_command( + Path("/tmp/input.mp4"), + output_dir, + "video-abc", + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"h264": "h264_cuvid", "hevc": "hevc_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + }, + codec_name="h264", + ) + + self.assertIn("-hwaccel", command) + self.assertIn("cuda", command) + self.assertIn("-c:v", command) + self.assertIn("h264_cuvid", command) + self.assertEqual(command[-1], str(output_dir / "frames" / "video-abc" / "%06d.jpg")) + + def test_build_sample_command_uses_nvdec_decoder_for_hevc(self): + with tempfile.TemporaryDirectory() as tmp: + command = build_sample_command( + Path("/tmp/input.mp4"), + Path(tmp) / "output", + "video-abc", + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"h264": "h264_cuvid", "hevc": "hevc_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + }, + codec_name="hevc", + ) + + self.assertIn("-hwaccel", command) + self.assertIn("cuda", command) + self.assertIn("-c:v", command) + self.assertIn("hevc_cuvid", command) + + def test_build_sample_command_refuses_cpu_fallback_by_default(self): + with tempfile.TemporaryDirectory() as tmp: + with self.assertRaisesRegex(ValueError, "NVDEC decoder is required"): + build_sample_command( + Path("/tmp/input.mp4"), + Path(tmp), + "video-abc", + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "codec_decoders": {"h264": "h264_cuvid", "hevc": "hevc_cuvid"}, + }, + codec_name="vp9", + ) + + def test_sample_video_frames_writes_structured_failure_record(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + manifest_path = root / "frame_manifest.jsonl" + failure = subprocess.CalledProcessError( + returncode=1, + cmd=["ffmpeg"], + stderr="No decoder h264_cuvid", + ) + + with patch("subprocess.run", side_effect=failure): + records = sample_video_frames( + { + "video_id": "video-abc", + "path": str(root / "input.mp4"), + "codec_name": "h264", + }, + root, + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"h264": "h264_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 30, + }, + manifest_path=manifest_path, + ) + + self.assertEqual(len(records), 1) + self.assertEqual(records[0]["video_id"], "video-abc") + self.assertEqual(records[0]["status"], "sample_failed") + self.assertIn("h264_cuvid", records[0]["last_error"]) + persisted = [ + json.loads(line) + for line in manifest_path.read_text(encoding="utf-8").splitlines() + ] + self.assertEqual(persisted, records) + + def test_sample_video_frames_persists_success_nvdec_evidence(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + manifest_path = root / "frame_manifest.jsonl" + video_id = "video-abc" + frame_dir = root / "frames" / video_id + + def run_success(*args, **kwargs): + frame_dir.mkdir(parents=True, exist_ok=True) + (frame_dir / "000001.jpg").write_bytes(b"jpg") + return subprocess.CompletedProcess( + args=args[0], + returncode=0, + stdout="", + stderr="Using decoder h264_cuvid with hwaccel cuda", + ) + + with patch("subprocess.run", side_effect=run_success): + records = sample_video_frames( + { + "video_id": video_id, + "path": str(root / "input.mp4"), + "codec_name": "h264", + }, + root, + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"h264": "h264_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 30, + }, + manifest_path=manifest_path, + ) + + self.assertEqual(records[0]["status"], "sampled") + self.assertEqual(records[0]["decoder"], "h264_cuvid") + self.assertEqual(records[0]["hwaccel"], "cuda") + self.assertIn("h264_cuvid", records[0]["ffmpeg_command"]) + self.assertIn("Using decoder h264_cuvid", records[0]["stderr_summary"]) + persisted = [ + json.loads(line) + for line in manifest_path.read_text(encoding="utf-8").splitlines() + ] + self.assertEqual(persisted, records) + + def test_sample_video_frames_adds_beijing_time_from_hik_actual_begin(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + video_id = "video-abc" + frame_dir = root / "frames" / video_id + + def run_success(command, *args, **kwargs): + frame_dir.mkdir(parents=True, exist_ok=True) + (frame_dir / "000001.jpg").write_bytes(b"jpg") + (frame_dir / "000002.jpg").write_bytes(b"jpg") + return subprocess.CompletedProcess( + args=command, + returncode=0, + stdout="", + stderr="", + ) + + with patch("subprocess.run", side_effect=run_success): + records = sample_video_frames( + { + "video_id": video_id, + "path": str(root / "input.mp4"), + "codec_name": "h264", + "actual_begin": 1781478000, + "actual_end": 1781478600, + }, + root, + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"h264": "h264_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 30, + "timezone": "Asia/Shanghai", + }, + ) + + self.assertEqual(records[0]["beijing_time"], "2026-06-15 07:00:00") + self.assertEqual(records[1]["beijing_time"], "2026-06-15 07:00:01") + + def test_sample_video_frames_caps_output_frames_to_requested_duration(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + video_id = "video-abc" + frame_dir = root / "frames" / video_id + captured_command = [] + + def run_success(command, *args, **kwargs): + captured_command.extend(command) + frame_dir.mkdir(parents=True, exist_ok=True) + (frame_dir / "000001.jpg").write_bytes(b"jpg") + return subprocess.CompletedProcess( + args=command, + returncode=0, + stdout="", + stderr="", + ) + + with patch("subprocess.run", side_effect=run_success): + sample_video_frames( + { + "video_id": video_id, + "path": str(root / "input.mp4"), + "codec_name": "hevc", + "requested_begin": 1000, + "requested_end": 1600, + }, + root, + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"hevc": "hevc_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 30, + }, + ) + + self.assertIn("-frames:v", captured_command) + frames_flag_index = captured_command.index("-frames:v") + self.assertEqual(captured_command[frames_flag_index + 1], "601") + + def test_sample_video_frames_limits_decode_window_to_requested_duration(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + video_id = "video-abc" + frame_dir = root / "frames" / video_id + captured_command = [] + + def run_success(command, *args, **kwargs): + captured_command.extend(command) + frame_dir.mkdir(parents=True, exist_ok=True) + (frame_dir / "000001.jpg").write_bytes(b"jpg") + return subprocess.CompletedProcess( + args=command, + returncode=0, + stdout="", + stderr="", + ) + + with patch("subprocess.run", side_effect=run_success): + sample_video_frames( + { + "video_id": video_id, + "path": str(root / "input.mp4"), + "codec_name": "hevc", + "requested_begin": 1000, + "requested_end": 1600, + "duration_seconds": 104259.921, + }, + root, + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"hevc": "hevc_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 30, + }, + ) + + self.assertIn("-t", captured_command) + input_index = captured_command.index("-i") + t_flag_index = captured_command.index("-t") + vf_index = captured_command.index("-vf") + self.assertLess(input_index, t_flag_index) + self.assertLess(t_flag_index, vf_index) + self.assertEqual(captured_command[t_flag_index + 1], "600") + + def test_sample_video_frames_uses_complete_frames_when_ffmpeg_exits_nonzero(self): + with tempfile.TemporaryDirectory() as tmp: + root = Path(tmp) + video_id = "video-abc" + frame_dir = root / "frames" / video_id + manifest_path = root / "frame_manifest.jsonl" + + def run_with_nonzero_exit(command, *args, **kwargs): + frame_dir.mkdir(parents=True, exist_ok=True) + for index in range(1, 602): + (frame_dir / f"{index:06d}.jpg").write_bytes(b"jpg") + raise subprocess.CalledProcessError( + returncode=1, + cmd=command, + stderr="trailing decoder error after requested frames", + ) + + with patch("subprocess.run", side_effect=run_with_nonzero_exit): + records = sample_video_frames( + { + "video_id": video_id, + "path": str(root / "input.mp4"), + "codec_name": "hevc", + "requested_begin": 1000, + "requested_end": 1600, + }, + root, + { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"hevc": "hevc_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 30, + }, + manifest_path=manifest_path, + ) + + self.assertEqual(len(records), 601) + self.assertEqual({record["status"] for record in records}, {"sampled"}) + self.assertIn("-t", records[0]["ffmpeg_command"]) + self.assertIn("trailing decoder error", records[0]["stderr_summary"]) + persisted = [ + json.loads(line) + for line in manifest_path.read_text(encoding="utf-8").splitlines() + ] + self.assertEqual(persisted, records) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_frames.py b/tests/test_frames.py new file mode 100644 index 0000000..85476ae --- /dev/null +++ b/tests/test_frames.py @@ -0,0 +1,61 @@ +import tempfile +import unittest +from pathlib import Path + +from video_ai_analysis_poc.frames import build_frame_records, seconds_to_timecode + + +class FrameTests(unittest.TestCase): + def test_seconds_to_timecode_formats_relative_offsets(self): + self.assertEqual(seconds_to_timecode(0), "00:00:00") + self.assertEqual(seconds_to_timecode(65.2), "00:01:05") + self.assertEqual(seconds_to_timecode(3661), "01:01:01") + + def test_build_frame_records_uses_stable_paths_and_offsets(self): + with tempfile.TemporaryDirectory() as tmp: + frame_dir = Path(tmp) / "frames" / "video-abc" + frame_dir.mkdir(parents=True) + first = frame_dir / "000001.jpg" + second = frame_dir / "000002.jpg" + first.write_bytes(b"jpg") + second.write_bytes(b"jpg") + + records = build_frame_records( + "video-abc", + Path(tmp), + [first, second], + frame_fps=1, + ) + + self.assertEqual(records[0]["frame_id"], "video-abc_f000001") + self.assertEqual(records[0]["frame_path"], "frames/video-abc/000001.jpg") + self.assertEqual(records[0]["offset_seconds"], 0.0) + self.assertEqual(records[0]["timecode"], "00:00:00") + self.assertEqual(records[0]["pts_time"], 0.0) + self.assertEqual(records[0]["status"], "sampled") + self.assertEqual(records[1]["offset_seconds"], 1.0) + + def test_build_frame_records_adds_beijing_time_from_timeline_epoch(self): + with tempfile.TemporaryDirectory() as tmp: + frame_dir = Path(tmp) / "frames" / "video-abc" + frame_dir.mkdir(parents=True) + first = frame_dir / "000001.jpg" + second = frame_dir / "000002.jpg" + first.write_bytes(b"jpg") + second.write_bytes(b"jpg") + + records = build_frame_records( + "video-abc", + Path(tmp), + [first, second], + frame_fps=1, + timeline_start_epoch=1781478000, + timezone_name="Asia/Shanghai", + ) + + self.assertEqual(records[0]["beijing_time"], "2026-06-15 07:00:00") + self.assertEqual(records[1]["beijing_time"], "2026-06-15 07:00:01") + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_hik_cloud.py b/tests/test_hik_cloud.py new file mode 100644 index 0000000..ef5395a --- /dev/null +++ b/tests/test_hik_cloud.py @@ -0,0 +1,554 @@ +import os +import tempfile +import unittest +from datetime import datetime +from pathlib import Path +from unittest.mock import patch +from zoneinfo import ZoneInfo + +from video_ai_analysis_poc import hik_cloud +from video_ai_analysis_poc.hik_cloud import ( + build_download_chunks, + request_download_address, + resolve_access_token, +) +from video_ai_analysis_poc.manifest import read_jsonl, write_manifest + + +class HikCloudTests(unittest.TestCase): + def test_build_download_chunks_defaults_to_600_second_chunks(self): + config = { + "runtime": {"timezone": "Asia/Shanghai"}, + "hik_cloud": { + "devices": [ + { + "device_serial": "EXAMPLE_DEVICE_SERIAL", + "channel_no": 1, + "name": "front", + } + ], + "time_ranges": [ + { + "begin": "2026-02-03 09:00:00", + "end": "2026-02-03 10:30:00", + } + ], + }, + } + + chunks = build_download_chunks(config) + + requested_begin = int( + datetime(2026, 2, 3, 9, 0, 0, tzinfo=ZoneInfo("Asia/Shanghai")).timestamp() + ) + requested_end = int( + datetime(2026, 2, 3, 10, 30, 0, tzinfo=ZoneInfo("Asia/Shanghai")).timestamp() + ) + self.assertEqual(len(chunks), 9) + self.assertEqual(chunks[0]["time_begin"], requested_begin) + self.assertEqual(chunks[0]["time_end"], requested_begin + 600) + self.assertEqual(chunks[-1]["time_begin"], requested_begin + 4800) + self.assertEqual(chunks[-1]["time_end"], requested_end) + for chunk in chunks: + self.assertLessEqual(chunk["time_end"] - chunk["time_begin"], 600) + + def test_build_download_chunks_allows_explicit_3600_second_chunks(self): + config = { + "runtime": {"timezone": "Asia/Shanghai"}, + "hik_cloud": { + "chunk_seconds": 3600, + "devices": [{"device_serial": "EXAMPLE_DEVICE_SERIAL", "channel_no": 1}], + "time_ranges": [ + { + "begin": "2026-02-03 09:00:00", + "end": "2026-02-03 10:30:00", + } + ], + }, + } + + chunks = build_download_chunks(config) + + requested_begin = int( + datetime(2026, 2, 3, 9, 0, 0, tzinfo=ZoneInfo("Asia/Shanghai")).timestamp() + ) + requested_end = int( + datetime(2026, 2, 3, 10, 30, 0, tzinfo=ZoneInfo("Asia/Shanghai")).timestamp() + ) + self.assertEqual(len(chunks), 2) + self.assertEqual(chunks[0]["time_begin"], requested_begin) + self.assertEqual(chunks[0]["time_end"], requested_begin + 3600) + self.assertEqual(chunks[1]["time_begin"], requested_begin + 3600) + self.assertEqual(chunks[1]["time_end"], requested_end) + for chunk in chunks: + self.assertLessEqual(chunk["time_end"] - chunk["time_begin"], 3600) + + def test_build_download_chunks_accepts_epoch_time_ranges(self): + config = { + "hik_cloud": { + "devices": [{"device_serial": "EXAMPLE_DEVICE_SERIAL", "channel_no": 1}], + "time_ranges": [{"begin": 1770080400, "end": 1770084000.0}], + } + } + + chunks = build_download_chunks(config) + + self.assertEqual(len(chunks), 6) + self.assertEqual(chunks[0]["time_begin"], 1770080400) + self.assertEqual(chunks[0]["time_end"], 1770081000) + self.assertEqual(chunks[-1]["time_begin"], 1770083400) + self.assertEqual(chunks[-1]["time_end"], 1770084000) + + def test_build_download_chunks_rejects_end_before_begin(self): + config = { + "hik_cloud": { + "devices": [{"device_serial": "EXAMPLE_DEVICE_SERIAL", "channel_no": 1}], + "time_ranges": [ + { + "begin": "2026-02-03 10:30:00", + "end": "2026-02-03 09:00:00", + } + ], + }, + } + + with self.assertRaisesRegex(ValueError, "end must be after begin"): + build_download_chunks(config) + + def test_build_download_chunks_rejects_chunk_seconds_over_3600(self): + config = { + "hik_cloud": { + "chunk_seconds": 7200, + "devices": [{"device_serial": "EXAMPLE_DEVICE_SERIAL", "channel_no": 1}], + "time_ranges": [ + { + "begin": "2026-02-03 09:00:00", + "end": "2026-02-03 11:30:00", + } + ], + }, + } + + with self.assertRaisesRegex( + ValueError, "chunk_seconds must be less than or equal to 3600" + ): + build_download_chunks(config) + + def test_resolve_access_token_prefers_literal_token_over_environment(self): + config = { + "hik_cloud": { + "access_token": "DIRECT_TOKEN", + "access_token_env": "HIK_CLOUD_ACCESS_TOKEN", + } + } + + with patch.dict(os.environ, {"HIK_CLOUD_ACCESS_TOKEN": "ENV_TOKEN"}): + token = resolve_access_token(config) + + self.assertEqual(token, "DIRECT_TOKEN") + + def test_resolve_access_token_reads_configured_environment_variable(self): + hik_config = {"access_token_env": "HIK_CLOUD_ACCESS_TOKEN"} + + with patch.dict(os.environ, {"HIK_CLOUD_ACCESS_TOKEN": "ENV_TOKEN"}): + token = resolve_access_token(hik_config) + + self.assertEqual(token, "ENV_TOKEN") + + def test_resolve_access_token_raises_without_leaking_secret_values(self): + hik_config = {"access_token_env": "HIK_CLOUD_ACCESS_TOKEN"} + + with patch.dict(os.environ, {}, clear=True): + with self.assertRaises(ValueError) as raised: + resolve_access_token(hik_config) + + message = str(raised.exception) + self.assertIn("access_token", message) + self.assertNotIn("TOKEN", message) + + def test_request_download_address_posts_expected_request_and_returns_success(self): + chunk = { + "device_serial": "EXAMPLE_DEVICE_SERIAL", + "channel_no": 1, + "requested_begin": 1764856787, + "requested_end": 1764856978, + "time_begin": 1764856787, + "time_end": 1764856978, + } + hik_config = { + "api_base_url": "https://api2.hik-cloud.com/", + "download_path": "/v1/carrier/cstorage/open/play/download", + "access_token": "TOKEN", + "timeout_seconds": 12, + } + calls = [] + + def fake_http_post(url, json_body, headers, timeout_seconds): + calls.append( + { + "url": url, + "json_body": json_body, + "headers": headers, + "timeout_seconds": timeout_seconds, + } + ) + return { + "code": 0, + "success": True, + "data": { + "url": "https://download.example/video.mp4?sig=abc", + "actualBeginTime": "1764856787", + "actualEndTime": "1764856978", + }, + } + + result = request_download_address(chunk, hik_config, http_post=fake_http_post) + + self.assertEqual(len(calls), 1) + self.assertEqual( + calls[0]["url"], + "https://api2.hik-cloud.com/v1/carrier/cstorage/open/play/download", + ) + self.assertEqual(calls[0]["headers"]["Authorization"], "bearer TOKEN") + self.assertEqual(calls[0]["headers"]["Content-Type"], "application/json") + self.assertEqual( + calls[0]["json_body"], + { + "deviceSerial": "EXAMPLE_DEVICE_SERIAL", + "channelNo": 1, + "timeBegin": 1764856787, + "timeEnd": 1764856978, + }, + ) + self.assertEqual(calls[0]["timeout_seconds"], 12) + self.assertEqual(result["status"], "address_ok") + self.assertEqual(result["url"], "https://download.example/video.mp4?sig=abc") + self.assertEqual(result["actual_begin"], 1764856787) + self.assertEqual(result["actual_end"], 1764856978) + self.assertEqual(result["device_serial"], "EXAMPLE_DEVICE_SERIAL") + self.assertEqual(result["channel_no"], 1) + self.assertEqual(result["requested_begin"], 1764856787) + self.assertEqual(result["requested_end"], 1764856978) + + def test_request_download_address_returns_no_recording_for_known_empty_code(self): + chunk = { + "device_serial": "EXAMPLE_DEVICE_SERIAL", + "channel_no": 1, + "requested_begin": 1764856787, + "requested_end": 1764856978, + "time_begin": 1764856787, + "time_end": 1764856978, + } + hik_config = { + "api_base_url": "https://api2.hik-cloud.com", + "download_path": "/v1/carrier/cstorage/open/play/download", + "access_token": "TOKEN", + } + + def fake_http_post(url, json_body, headers, timeout_seconds): + return {"code": 80438027, "msg": "no recording"} + + result = request_download_address(chunk, hik_config, http_post=fake_http_post) + + self.assertEqual(result["status"], "no_recording") + self.assertEqual(result["code"], 80438027) + self.assertEqual(result["device_serial"], "EXAMPLE_DEVICE_SERIAL") + self.assertNotIn("url", result) + + def test_request_download_address_returns_sanitized_failure_for_other_codes(self): + chunk = { + "device_serial": "EXAMPLE_DEVICE_SERIAL", + "channel_no": 1, + "requested_begin": 1764856787, + "requested_end": 1764856978, + "time_begin": 1764856787, + "time_end": 1764856978, + } + hik_config = { + "api_base_url": "https://api2.hik-cloud.com", + "download_path": "/v1/carrier/cstorage/open/play/download", + "access_token": "TOKEN", + } + + def fake_http_post(url, json_body, headers, timeout_seconds): + return {"code": 80430002, "msg": "bad TOKEN Authorization request"} + + result = request_download_address(chunk, hik_config, http_post=fake_http_post) + + self.assertEqual(result["status"], "address_failed") + self.assertEqual(result["code"], 80430002) + self.assertIn("last_error", result) + self.assertNotIn("TOKEN", str(result)) + self.assertNotIn("Authorization", str(result)) + + def test_download_hik_cloud_recordings_writes_file_records_and_manifest(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + config = _download_config() + address_calls = [] + download_calls = [] + + def fake_address_client(chunk, hik_config): + address_calls.append((chunk, hik_config)) + return { + **chunk, + "status": "address_ok", + "url": ( + "https://download.example/video.mp4?" + "sign=SECRET&sig=SECRET&TOKEN=SECRET" + ), + "actual_begin": chunk["time_begin"] + 1, + "actual_end": chunk["time_end"] - 1, + } + + def fake_download_url(url, timeout_seconds=None): + download_calls.append((url, timeout_seconds)) + return b"fake mp4 bytes" + + records = hik_cloud.download_hik_cloud_recordings( + config, + output_dir, + address_client=fake_address_client, + download_url=fake_download_url, + ) + + self.assertEqual(len(address_calls), 1) + self.assertEqual(len(download_calls), 1) + self.assertEqual(download_calls[0][1], 600) + expected_path = ( + output_dir + / "downloads" + / "hik_cloud" + / "EXAMPLE_DEVICE_SERIAL" + / "ch1" + / "EXAMPLE_DEVICE_SERIAL_ch1_1764856787_1764856978.mp4" + ).resolve(strict=False) + self.assertEqual(expected_path.read_bytes(), b"fake mp4 bytes") + self.assertEqual(len(records), 1) + self.assertEqual(records[0]["path"], str(expected_path)) + self.assertEqual(records[0]["source"], "hik_cloud") + self.assertEqual(records[0]["source_path"], "hik_cloud://EXAMPLE_DEVICE_SERIAL/ch1/1764856787-1764856978") + self.assertEqual(records[0]["device_serial"], "EXAMPLE_DEVICE_SERIAL") + self.assertEqual(records[0]["channel_no"], 1) + self.assertEqual(records[0]["requested_begin"], 1764856787) + self.assertEqual(records[0]["requested_end"], 1764856978) + self.assertEqual(records[0]["actual_begin"], 1764856788) + self.assertEqual(records[0]["actual_end"], 1764856977) + self.assertEqual(records[0]["status"], "downloaded") + + manifest = read_jsonl(output_dir / "hik_cloud_download_manifest.jsonl") + self.assertEqual(len(manifest), 1) + self.assertEqual(manifest[0]["status"], "downloaded") + self.assertIsNone(manifest[0]["last_error"]) + self.assertEqual(manifest[0]["download_url_host"], "download.example") + self.assertEqual(manifest[0]["path"], str(expected_path)) + serialized_path = expected_path.name + serialized_manifest = str(manifest) + self.assertNotIn("sign=", serialized_path) + self.assertNotIn("sig=", serialized_path) + self.assertNotIn("TOKEN", serialized_path) + self.assertNotIn("sign=", serialized_manifest) + self.assertNotIn("sig=", serialized_manifest) + self.assertNotIn("TOKEN", serialized_manifest) + + def test_download_hik_cloud_recordings_can_plan_without_downloading(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + config = _download_config() + download_calls = [] + + def fake_address_client(chunk, hik_config): + return { + **chunk, + "status": "address_ok", + "url": ( + "https://download.example/video.mp4?" + "sign=SECRET&sig=SECRET&TOKEN=SECRET" + ), + "actual_begin": chunk["time_begin"], + "actual_end": chunk["time_end"], + } + + def fake_download_url(url, timeout_seconds=None): + download_calls.append(url) + return b"unexpected" + + records = hik_cloud.download_hik_cloud_recordings( + config, + output_dir, + address_client=fake_address_client, + download_url=fake_download_url, + download=False, + ) + + self.assertEqual(records, []) + self.assertEqual(download_calls, []) + manifest = read_jsonl(output_dir / "hik_cloud_download_manifest.jsonl") + self.assertEqual(len(manifest), 1) + self.assertEqual(manifest[0]["status"], "address_ok") + self.assertIsNone(manifest[0]["path"]) + self.assertEqual(manifest[0]["download_url_host"], "download.example") + self.assertNotIn("sign=", str(manifest)) + self.assertNotIn("sig=", str(manifest)) + self.assertNotIn("TOKEN", str(manifest)) + + def test_download_hik_cloud_recordings_records_empty_and_address_failures(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + config = _download_config( + time_ranges=[ + {"begin": 1764856787, "end": 1764856978}, + {"begin": 1764857000, "end": 1764857100}, + ] + ) + statuses = ["no_recording", "address_failed"] + download_calls = [] + + def fake_address_client(chunk, hik_config): + status = statuses.pop(0) + return { + **chunk, + "status": status, + "actual_begin": None, + "actual_end": None, + "last_error": None if status == "no_recording" else "api failed", + } + + def fake_download_url(url, timeout_seconds=None): + download_calls.append(url) + return b"unexpected" + + records = hik_cloud.download_hik_cloud_recordings( + config, + output_dir, + address_client=fake_address_client, + download_url=fake_download_url, + ) + + self.assertEqual(records, []) + self.assertEqual(download_calls, []) + manifest = read_jsonl(output_dir / "hik_cloud_download_manifest.jsonl") + self.assertEqual([record["status"] for record in manifest], ["no_recording", "address_failed"]) + + def test_download_hik_cloud_recordings_records_download_failure_and_continues(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + config = _download_config( + time_ranges=[ + {"begin": 1764856787, "end": 1764856978}, + {"begin": 1764857000, "end": 1764857100}, + ] + ) + download_calls = [] + + def fake_address_client(chunk, hik_config): + return { + **chunk, + "status": "address_ok", + "url": ( + "https://download.example/video.mp4?" + "sign=SECRET&sig=SECRET&TOKEN=SECRET" + ), + "actual_begin": chunk["time_begin"], + "actual_end": chunk["time_end"], + } + + def fake_download_url(url, timeout_seconds=None): + download_calls.append(url) + if len(download_calls) == 1: + raise RuntimeError( + "download failed for query sign=SECRET&sig=SECRET&TOKEN=SECRET" + ) + return b"second chunk" + + records = hik_cloud.download_hik_cloud_recordings( + config, + output_dir, + address_client=fake_address_client, + download_url=fake_download_url, + ) + + self.assertEqual(len(download_calls), 2) + self.assertEqual(len(records), 1) + self.assertEqual(records[0]["status"], "downloaded") + manifest = read_jsonl(output_dir / "hik_cloud_download_manifest.jsonl") + self.assertEqual([record["status"] for record in manifest], ["download_failed", "downloaded"]) + self.assertIn("last_error", manifest[0]) + self.assertNotIn("sign=", str(manifest)) + self.assertNotIn("sig=", str(manifest)) + self.assertNotIn("TOKEN", str(manifest)) + self.assertNotIn("SECRET", str(manifest)) + + def test_download_hik_cloud_recordings_resume_skips_existing_downloaded_file(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + config = _download_config(resume=True) + downloaded_path = ( + output_dir + / "downloads" + / "hik_cloud" + / "EXAMPLE_DEVICE_SERIAL" + / "ch1" + / "EXAMPLE_DEVICE_SERIAL_ch1_1764856787_1764856978.mp4" + ) + downloaded_path.parent.mkdir(parents=True, exist_ok=True) + downloaded_path.write_bytes(b"existing") + existing_record = { + "source": "hik_cloud", + "path": str(downloaded_path), + "device_serial": "EXAMPLE_DEVICE_SERIAL", + "channel_no": 1, + "requested_begin": 1764856787, + "requested_end": 1764856978, + "actual_begin": 1764856787, + "actual_end": 1764856978, + "status": "downloaded", + "retry_count": 0, + "last_error": None, + } + write_manifest( + output_dir / "hik_cloud_download_manifest.jsonl", + [existing_record], + ) + + def failing_address_client(chunk, hik_config): + raise AssertionError("resume should skip address lookup") + + def failing_download_url(url, timeout_seconds=None): + raise AssertionError("resume should skip download") + + records = hik_cloud.download_hik_cloud_recordings( + config, + output_dir, + address_client=failing_address_client, + download_url=failing_download_url, + ) + + expected_video_record = { + **existing_record, + "source_path": "hik_cloud://EXAMPLE_DEVICE_SERIAL/ch1/1764856787-1764856978", + } + self.assertEqual(records, [expected_video_record]) + manifest = read_jsonl(output_dir / "hik_cloud_download_manifest.jsonl") + self.assertEqual(manifest, [existing_record]) + + +def _download_config( + *, + time_ranges=None, + resume: bool = False, +): + return { + "output": {"resume": resume}, + "hik_cloud": { + "access_token": "TOKEN", + "download_timeout_seconds": 600, + "devices": [{"device_serial": "EXAMPLE_DEVICE_SERIAL", "channel_no": 1}], + "time_ranges": time_ranges + or [{"begin": 1764856787, "end": 1764856978}], + }, + } + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_manifest.py b/tests/test_manifest.py new file mode 100644 index 0000000..6e98944 --- /dev/null +++ b/tests/test_manifest.py @@ -0,0 +1,30 @@ +import json +import tempfile +import unittest +from pathlib import Path + +from video_ai_analysis_poc.manifest import read_jsonl, write_manifest + + +class ManifestTests(unittest.TestCase): + def test_write_manifest_writes_status_retry_and_error_fields(self): + with tempfile.TemporaryDirectory() as tmp: + path = Path(tmp) / "video_manifest.jsonl" + records = [ + {"path": "/tmp/a.mp4", "status": "probed"}, + {"path": "/tmp/b.mp4", "status": "probe_failed", "last_error": "bad data"}, + ] + + write_manifest(path, records) + + lines = path.read_text(encoding="utf-8").splitlines() + decoded = [json.loads(line) for line in lines] + self.assertEqual(decoded[0]["retry_count"], 0) + self.assertIsNone(decoded[0]["last_error"]) + self.assertEqual(decoded[1]["status"], "probe_failed") + self.assertEqual(decoded[1]["last_error"], "bad data") + self.assertEqual(read_jsonl(path), decoded) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_probe.py b/tests/test_probe.py new file mode 100644 index 0000000..e701386 --- /dev/null +++ b/tests/test_probe.py @@ -0,0 +1,51 @@ +import subprocess +import unittest +from pathlib import Path +from unittest.mock import patch + +from video_ai_analysis_poc.probe import probe_video + + +class ProbeTests(unittest.TestCase): + def test_probe_video_returns_structured_metadata(self): + payload = ( + '{"streams":[{"codec_type":"video","codec_name":"h264",' + '"width":1920,"height":1080,"avg_frame_rate":"30000/1001"}],' + '"format":{"duration":"12.5","format_name":"mov,mp4,m4a,3gp,3g2,mj2",' + '"start_time":"0.000000"}}' + ) + completed = subprocess.CompletedProcess( + args=["ffprobe"], + returncode=0, + stdout=payload, + stderr="", + ) + + with patch("subprocess.run", return_value=completed): + result = probe_video(Path("/tmp/video.mp4"), timeout_seconds=3) + + self.assertEqual(result["status"], "probed") + self.assertEqual(result["codec_name"], "h264") + self.assertEqual(result["width"], 1920) + self.assertEqual(result["height"], 1080) + self.assertAlmostEqual(result["fps"], 29.97002997) + self.assertEqual(result["duration_seconds"], 12.5) + self.assertIsNone(result["last_error"]) + + def test_probe_video_returns_structured_failure(self): + failure = subprocess.CalledProcessError( + returncode=1, + cmd=["ffprobe"], + stderr="Invalid data found when processing input", + ) + + with patch("subprocess.run", side_effect=failure): + result = probe_video(Path("/tmp/bad.mp4"), timeout_seconds=3) + + self.assertEqual(result["status"], "probe_failed") + self.assertEqual(result["retry_count"], 0) + self.assertIn("Invalid data", result["last_error"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_result_parser.py b/tests/test_result_parser.py new file mode 100644 index 0000000..25506e9 --- /dev/null +++ b/tests/test_result_parser.py @@ -0,0 +1,135 @@ +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_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["monitoring_timeline"]["screen_time"], "") + self.assertEqual(result["raw_response"], "not json") + self.assertIn("JSON", result["error"]) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_vlm_client.py b/tests/test_vlm_client.py new file mode 100644 index 0000000..155ca4c --- /dev/null +++ b/tests/test_vlm_client.py @@ -0,0 +1,85 @@ +import base64 +import json +import tempfile +import unittest +from pathlib import Path + +from video_ai_analysis_poc.vlm_client import infer_clip + + +class VlmClientTests(unittest.TestCase): + def test_infer_clip_uses_config_prompt_url_and_data_uri_images(self): + with tempfile.TemporaryDirectory() as tmp: + output_dir = Path(tmp) + frame_path = output_dir / "frames" / "video-abc" / "000001.jpg" + frame_path.parent.mkdir(parents=True) + frame_path.write_bytes(b"jpg-bytes") + calls = [] + + def http_post(url, payload, timeout_seconds): + calls.append((url, payload, timeout_seconds)) + return { + "status": 200, + "body": { + "choices": [ + { + "message": { + "content": json.dumps( + {"screen_time": "10:00:01", "events": []} + ) + } + } + ] + }, + } + + result = infer_clip( + { + "clip_id": "video-abc_c000001", + "frame_times": [ + { + "frame_path": "frames/video-abc/000001.jpg", + "offset_seconds": 0.0, + "timecode": "00:00:00", + } + ], + }, + output_dir, + { + "api_base_url": "http://localhost:8679/", + "chat_completions_path": "/v1/chat/completions", + "model": "memai-zhengxin-v3-20260413", + "timeout_seconds": 17, + "max_tokens": 256, + "temperature": 0, + "image_transport": "data_uri", + }, + { + "system": "system prompt from config", + "user": "user prompt from config", + }, + http_post=http_post, + ) + + self.assertEqual(result["raw_response"], '{"screen_time": "10:00:01", "events": []}') + self.assertEqual(len(calls), 1) + url, payload, timeout_seconds = calls[0] + self.assertEqual(url, "http://localhost:8679/v1/chat/completions") + self.assertEqual(timeout_seconds, 17) + self.assertEqual(payload["model"], "memai-zhengxin-v3-20260413") + self.assertEqual(payload["messages"][0]["role"], "system") + self.assertEqual(payload["messages"][0]["content"], "system prompt from config") + user_content = payload["messages"][1]["content"] + self.assertEqual(user_content[0], {"type": "text", "text": "user prompt from config"}) + self.assertEqual(user_content[1]["type"], "image_url") + expected_data = base64.b64encode(b"jpg-bytes").decode("ascii") + self.assertEqual( + user_content[1]["image_url"]["url"], + f"data:image/jpeg;base64,{expected_data}", + ) + self.assertEqual(result["http_status"], 200) + self.assertIsInstance(result["latency_ms"], int) + + +if __name__ == "__main__": + unittest.main() diff --git a/video_ai_analysis_poc/__init__.py b/video_ai_analysis_poc/__init__.py new file mode 100644 index 0000000..f1fb8e0 --- /dev/null +++ b/video_ai_analysis_poc/__init__.py @@ -0,0 +1,9 @@ +"""Local video batch analysis PoC.""" + +__all__ = [ + "config", + "discovery", + "manifest", + "paths", + "probe", +] diff --git a/video_ai_analysis_poc/aggregator.py b/video_ai_analysis_poc/aggregator.py new file mode 100644 index 0000000..0238135 --- /dev/null +++ b/video_ai_analysis_poc/aggregator.py @@ -0,0 +1,403 @@ +from __future__ import annotations + +import json +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +from .manifest import read_jsonl + + +def aggregate_outputs( + output_dir: str | Path, + config: dict[str, Any], +) -> dict[str, Any]: + root = Path(output_dir).expanduser().resolve(strict=False) + started_at = _now_iso() + video_records = read_jsonl(root / "video_manifest.jsonl") + clip_records = read_jsonl(root / "clip_manifest.jsonl") + clip_results = read_jsonl(root / "clip_results.jsonl") + + schema_version = str(config.get("schema", {}).get("version", "local-batch-v1")) + merge_gap_seconds = float(config.get("schema", {}).get("merge_gap_seconds", 30)) + clips_by_video = _group_by_video(clip_records) + results_by_video = _group_by_video(clip_results) + + videos_summary = [] + folder_event_counts: dict[str, int] = {} + processed_video_count = 0 + failed_video_count = 0 + + for video_record in video_records: + video_id = str(video_record.get("video_id") or "") + if not video_id: + continue + video_clips = clips_by_video.get(video_id, []) + video_results = results_by_video.get(video_id, []) + video_result = _build_video_result( + video_record, + video_clips, + video_results, + schema_version=schema_version, + merge_gap_seconds=merge_gap_seconds, + started_at=started_at, + ) + result_path = root / "videos" / video_id / "video_result.json" + _write_json(result_path, video_result) + + failed_clip_count = int(video_result["failed_clip_count"]) + video_failed = video_record.get("status") != "probed" or failed_clip_count > 0 + if video_failed: + failed_video_count += 1 + else: + processed_video_count += 1 + for event_type, count in video_result["event_counts"].items(): + folder_event_counts[event_type] = folder_event_counts.get(event_type, 0) + int(count) + videos_summary.append( + { + "video_id": video_id, + "video_path": video_result["video_path"], + "status": "failed" if video_failed else "processed", + "clip_count": video_result["clip_count"], + "failed_clip_count": failed_clip_count, + "failed_clip_counts": video_result["failed_clip_counts"], + "event_counts": video_result["event_counts"], + "outputs": {"video_result_json": f"videos/{video_id}/video_result.json"}, + "error": video_record.get("last_error"), + } + ) + + folder_summary = { + "schema_version": schema_version, + "input_dir": str(config.get("input", {}).get("dir")), + "video_count": len(video_records), + "processed_video_count": processed_video_count, + "failed_video_count": failed_video_count, + "event_counts": dict(sorted(folder_event_counts.items())), + "videos": videos_summary, + "processing": { + "started_at": started_at, + "finished_at": _now_iso(), + }, + } + _write_json(root / "folder_summary.json", folder_summary) + return folder_summary + + +def _build_video_result( + video_record: dict[str, Any], + clip_records: list[dict[str, Any]], + clip_results: list[dict[str, Any]], + *, + schema_version: str, + merge_gap_seconds: float, + started_at: str, +) -> dict[str, Any]: + video_id = str(video_record.get("video_id")) + failed_clip_counts = _failed_clip_counts(clip_results) + merged_events = _merge_events(_event_records(clip_results), merge_gap_seconds) + event_counts = _event_counts(merged_events) + video_duration = _first_present( + video_record, + ("duration_seconds", "video_duration_seconds", "duration"), + ) + video_start_time = _video_start_time(video_record, clip_results) + return { + "schema_version": schema_version, + "video_id": video_id, + "video_path": _video_path(video_record, clip_results), + "probe": _probe(video_record), + "monitoring_timeline": { + "video_start_time": video_start_time, + "video_duration_seconds": video_duration, + }, + "clip_count": len(clip_records), + "failed_clip_count": sum(failed_clip_counts.values()), + "failed_clip_counts": failed_clip_counts, + "event_counts": event_counts, + "events": merged_events, + "outputs": {"clip_results_jsonl": "clip_results.jsonl"}, + "processing": { + "started_at": started_at, + "finished_at": _now_iso(), + }, + } + + +def _event_records(clip_results: list[dict[str, Any]]) -> list[dict[str, Any]]: + records = [] + for result in clip_results: + if result.get("status") != "ok": + continue + timeline = result.get("monitoring_timeline") or {} + if not isinstance(timeline, dict): + timeline = {} + for event in result.get("events") or []: + if not isinstance(event, dict): + continue + event_record = _normalize_event(event, result, timeline) + records.append(event_record) + return sorted( + records, + key=lambda event: ( + str(event.get("video_id")), + str(event.get("event_type")), + float(event.get("start_offset_seconds") or 0), + float(event.get("end_offset_seconds") or 0), + ), + ) + + +def _normalize_event( + event: dict[str, Any], + result: dict[str, Any], + timeline: dict[str, Any], +) -> dict[str, Any]: + clip_id = str(result.get("clip_id")) + frame_times = [ + dict(frame) + for frame in timeline.get("frame_times", []) + if isinstance(frame, dict) + ] + frame_paths = [ + str(frame.get("frame_path")) + for frame in frame_times + if frame.get("frame_path") is not None + ] + start = event.get("start_offset_seconds", timeline.get("clip_start_seconds")) + end = event.get("end_offset_seconds", timeline.get("clip_end_seconds")) + screen_time = str(timeline.get("screen_time") or "") + normalized = { + "video_id": str(result.get("video_id")), + "event_type": str(event.get("event_type") or "unknown"), + "start_time": event.get("start_time"), + "end_time": event.get("end_time"), + "start_offset_seconds": _float_or_none(start), + "end_offset_seconds": _float_or_none(end), + "confidence": event.get("confidence"), + "severity": event.get("severity"), + "attributes": event.get("attributes") if isinstance(event.get("attributes"), dict) else {}, + "screen_times": [screen_time] if screen_time else [], + "evidence": { + "clip_ids": [clip_id], + "frame_paths": frame_paths, + "frame_times": frame_times, + "clips": [ + { + "clip_id": clip_id, + "clip_start_seconds": timeline.get("clip_start_seconds"), + "clip_end_seconds": timeline.get("clip_end_seconds"), + "clip_start_timecode": timeline.get("clip_start_timecode"), + "clip_end_timecode": timeline.get("clip_end_timecode"), + "clip_start_beijing_time": timeline.get("clip_start_beijing_time"), + "clip_end_beijing_time": timeline.get("clip_end_beijing_time"), + "screen_time": screen_time, + } + ], + }, + "source_event_count": 1, + } + original_evidence = event.get("evidence") + if isinstance(original_evidence, dict): + original_clip_id = original_evidence.get("clip_id") + if original_clip_id: + normalized["evidence"]["clip_ids"] = _unique( + [*normalized["evidence"]["clip_ids"], str(original_clip_id)] + ) + original_frame_paths = original_evidence.get("frame_paths") + if isinstance(original_frame_paths, list): + normalized["evidence"]["frame_paths"] = _unique( + [*normalized["evidence"]["frame_paths"], *map(str, original_frame_paths)] + ) + return normalized + + +def _merge_events( + events: list[dict[str, Any]], + merge_gap_seconds: float, +) -> list[dict[str, Any]]: + merged: list[dict[str, Any]] = [] + for event in events: + if not merged or not _can_merge(merged[-1], event, merge_gap_seconds): + merged.append(_copy_event(event)) + continue + _merge_into(merged[-1], event) + for event in merged: + event.pop("video_id", None) + return merged + + +def _can_merge( + previous: dict[str, Any], + current: dict[str, Any], + merge_gap_seconds: float, +) -> bool: + if previous.get("video_id") != current.get("video_id"): + return False + if previous.get("event_type") != current.get("event_type"): + return False + previous_end = _float_or_none(previous.get("end_offset_seconds")) + current_start = _float_or_none(current.get("start_offset_seconds")) + if previous_end is None or current_start is None: + return False + return current_start - previous_end <= merge_gap_seconds + + +def _merge_into(target: dict[str, Any], event: dict[str, Any]) -> None: + target["start_offset_seconds"] = _min_number( + target.get("start_offset_seconds"), + event.get("start_offset_seconds"), + ) + target["end_offset_seconds"] = _max_number( + target.get("end_offset_seconds"), + event.get("end_offset_seconds"), + ) + target["screen_times"] = _unique( + [*target.get("screen_times", []), *event.get("screen_times", [])] + ) + target["source_event_count"] = int(target.get("source_event_count", 1)) + int( + event.get("source_event_count", 1) + ) + target["evidence"]["clip_ids"] = _unique( + [*target["evidence"].get("clip_ids", []), *event["evidence"].get("clip_ids", [])] + ) + target["evidence"]["frame_paths"] = _unique( + [ + *target["evidence"].get("frame_paths", []), + *event["evidence"].get("frame_paths", []), + ] + ) + target["evidence"]["frame_times"].extend(event["evidence"].get("frame_times", [])) + target["evidence"]["clips"].extend(event["evidence"].get("clips", [])) + if target.get("confidence") is None: + target["confidence"] = event.get("confidence") + elif event.get("confidence") is not None: + target["confidence"] = max(float(target["confidence"]), float(event["confidence"])) + + +def _copy_event(event: dict[str, Any]) -> dict[str, Any]: + copied = dict(event) + copied["screen_times"] = list(event.get("screen_times", [])) + copied["attributes"] = dict(event.get("attributes", {})) + copied["evidence"] = { + "clip_ids": list(event["evidence"].get("clip_ids", [])), + "frame_paths": list(event["evidence"].get("frame_paths", [])), + "frame_times": [dict(frame) for frame in event["evidence"].get("frame_times", [])], + "clips": [dict(clip) for clip in event["evidence"].get("clips", [])], + } + return copied + + +def _group_by_video(records: list[dict[str, Any]]) -> dict[str, list[dict[str, Any]]]: + grouped: dict[str, list[dict[str, Any]]] = {} + for record in records: + video_id = record.get("video_id") + if video_id: + grouped.setdefault(str(video_id), []).append(record) + return grouped + + +def _failed_clip_counts(clip_results: list[dict[str, Any]]) -> dict[str, int]: + counts = {"parse_failed": 0, "inference_failed": 0} + for result in clip_results: + status = result.get("status") + if status in counts: + counts[str(status)] += 1 + return counts + + +def _event_counts(events: list[dict[str, Any]]) -> dict[str, int]: + counts: dict[str, int] = {} + for event in events: + event_type = str(event.get("event_type") or "unknown") + counts[event_type] = counts.get(event_type, 0) + 1 + return dict(sorted(counts.items())) + + +def _probe(video_record: dict[str, Any]) -> dict[str, Any]: + excluded = {"video_id", "path", "source_path", "status", "retry_count", "last_error"} + probe = { + key: value + for key, value in video_record.items() + if key not in excluded + } + probe["status"] = video_record.get("status") + if video_record.get("last_error") is not None: + probe["last_error"] = video_record.get("last_error") + return probe + + +def _video_path( + video_record: dict[str, Any], + clip_results: list[dict[str, Any]], +) -> str | None: + path = video_record.get("path") or video_record.get("source_path") + if path is not None: + return str(path) + for result in clip_results: + if result.get("video_path") is not None: + return str(result["video_path"]) + return None + + +def _video_start_time( + video_record: dict[str, Any], + clip_results: list[dict[str, Any]], +) -> Any: + if video_record.get("video_start_time") is not None: + return video_record.get("video_start_time") + for result in clip_results: + timeline = result.get("monitoring_timeline") + if isinstance(timeline, dict) and timeline.get("video_start_time") is not None: + return timeline.get("video_start_time") + return None + + +def _first_present(record: dict[str, Any], keys: tuple[str, ...]) -> Any: + for key in keys: + if record.get(key) is not None: + return record.get(key) + return None + + +def _float_or_none(value: Any) -> float | None: + if value is None: + return None + try: + return float(value) + except (TypeError, ValueError): + return None + + +def _min_number(left: Any, right: Any) -> float | None: + values = [value for value in (_float_or_none(left), _float_or_none(right)) if value is not None] + return min(values) if values else None + + +def _max_number(left: Any, right: Any) -> float | None: + values = [value for value in (_float_or_none(left), _float_or_none(right)) if value is not None] + return max(values) if values else None + + +def _unique(values: list[Any]) -> list[Any]: + seen = set() + unique_values = [] + for value in values: + marker = json.dumps(value, sort_keys=True) if isinstance(value, dict) else value + if marker in seen: + continue + seen.add(marker) + unique_values.append(value) + return unique_values + + +def _write_json(path: Path, payload: dict[str, Any]) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text( + json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True) + "\n", + encoding="utf-8", + ) + + +def _now_iso() -> str: + return datetime.now(timezone.utc).isoformat() diff --git a/video_ai_analysis_poc/cli.py b/video_ai_analysis_poc/cli.py new file mode 100644 index 0000000..e2ceea0 --- /dev/null +++ b/video_ai_analysis_poc/cli.py @@ -0,0 +1,424 @@ +from __future__ import annotations + +import argparse +import json +from pathlib import Path +from typing import Sequence + +from .aggregator import aggregate_outputs +from .clips import build_clip_records +from .config import DEFAULT_CONFIG_PATH, load_config +from .discovery import discover_videos +from .ffmpeg_sampler import sample_video_frames +from .hik_cloud import download_hik_cloud_recordings +from .manifest import read_jsonl, write_manifest +from .paths import stable_video_id +from .probe import probe_video +from .result_parser import build_clip_result +from .timeline import DEFAULT_TIMEZONE, format_beijing_time, timeline_start_epoch +from .vlm_client import infer_clip + + +def main(argv: Sequence[str] | None = None) -> int: + parser = argparse.ArgumentParser( + description="Local video batch analysis PoC entrypoint." + ) + parser.add_argument("--config", default=str(DEFAULT_CONFIG_PATH)) + parser.add_argument("--input-dir") + parser.add_argument("--output-dir") + parser.add_argument("--dry-run", action="store_true") + parser.add_argument("--until", choices=["clips", "inference"]) + parser.add_argument("--limit-clips", type=int) + args = parser.parse_args(argv) + + config = load_config( + args.config, + input_dir=args.input_dir, + output_dir=args.output_dir, + ) + if args.dry_run and args.until: + parser.error("--dry-run cannot be combined with --until") + if args.limit_clips is not None and args.limit_clips < 0: + parser.error("--limit-clips must be non-negative") + + output_dir = Path(config["output"]["dir"]) + output_dir.mkdir(parents=True, exist_ok=True) + + video_manifest_path = output_dir / "video_manifest.jsonl" + resume_enabled = bool(config.get("output", {}).get("resume", False)) + records = _load_resume_records( + video_manifest_path, + resume=resume_enabled, + ) + record_indexes = { + _record_key(record): index + for index, record in enumerate(records) + if _record_key(record) is not None + } + + try: + _acquire_source_records( + config, + output_dir, + records, + record_indexes, + download_source=not args.dry_run, + ) + except ValueError as exc: + parser.error(str(exc)) + + write_manifest(video_manifest_path, records) + if args.dry_run: + return 0 + + clip_manifest_path = output_dir / "clip_manifest.jsonl" + existing_clip_records = read_jsonl(clip_manifest_path) if resume_enabled else [] + existing_clip_video_ids = { + str(record.get("video_id")) + for record in existing_clip_records + if record.get("video_id") + } + + frame_manifest_path = output_dir / "frame_manifest.jsonl" + frame_records = read_jsonl(frame_manifest_path) if resume_enabled else [] + timezone_name = str(config.get("runtime", {}).get("timezone", DEFAULT_TIMEZONE)) + backfilled_frame_video_ids = _backfill_frame_beijing_times( + frame_records, + records, + timezone_name=timezone_name, + ) + existing_sampled_video_ids = { + str(record.get("video_id")) + for record in frame_records + if record.get("status") == "sampled" and record.get("video_id") + } + changed_frame_video_ids: set[str] = set(backfilled_frame_video_ids) + for record in records: + if record.get("status") != "probed": + continue + video_id = str(record.get("video_id")) + if args.until == "inference" and video_id in existing_clip_video_ids: + continue + if video_id in existing_sampled_video_ids: + continue + frame_records = _without_video_records(frame_records, video_id) + ffmpeg_config = dict(config["ffmpeg"]) + ffmpeg_config["timezone"] = timezone_name + frame_records.extend( + sample_video_frames( + record, + output_dir, + ffmpeg_config, + manifest_path=None, + ) + ) + changed_frame_video_ids.add(video_id) + write_manifest(frame_manifest_path, frame_records) + + sampled_video_ids = { + str(record.get("video_id")) + for record in frame_records + if record.get("status") == "sampled" and record.get("video_id") + } + clip_rebuild_video_ids = changed_frame_video_ids | ( + sampled_video_ids - existing_clip_video_ids + ) + clip_records = [ + record + for record in existing_clip_records + if str(record.get("video_id")) not in clip_rebuild_video_ids + ] + frames_to_build = [ + record + for record in frame_records + if str(record.get("video_id")) in clip_rebuild_video_ids + ] + clip_records.extend(build_clip_records(frames_to_build, config["clip"])) + write_manifest(output_dir / "clip_manifest.jsonl", clip_records) + if args.until == "clips": + return 0 + + _run_inference( + clip_records, + records, + output_dir, + config, + limit_clips=args.limit_clips, + resume=resume_enabled, + ) + if args.until == "inference": + return 0 + aggregate_outputs(output_dir, config) + return 0 + + +def _load_resume_records(path: Path, *, resume: bool) -> list[dict[str, object]]: + if not resume: + return [] + return read_jsonl(path) + + +def _record_key(record: dict[str, object]) -> str | None: + video_id = record.get("video_id") + if video_id: + return str(video_id) + path = record.get("path") + if path: + return stable_video_id(str(path)) + return None + + +def _acquire_source_records( + config: dict[str, object], + output_dir: Path, + records: list[dict[str, object]], + record_indexes: dict[str, int], + *, + download_source: bool = True, +) -> None: + for source_record in _source_video_records( + config, + output_dir, + download_source=download_source, + ): + path = source_record.get("path") + if not path: + continue + video_id = stable_video_id(str(path)) + existing_index = record_indexes.get(video_id) + if ( + existing_index is not None + and records[existing_index].get("status") == "probed" + ): + continue + + probe_record = probe_video( + str(path), + timeout_seconds=config["ffprobe"]["timeout_seconds"], + ) + record = {**source_record, **probe_record, "video_id": video_id} + if existing_index is None: + record_indexes[video_id] = len(records) + records.append(record) + else: + records[existing_index] = record + + +def _source_video_records( + config: dict[str, object], + output_dir: Path, + *, + download_source: bool = True, +) -> list[dict[str, object]]: + source_config = config.get("source", {}) + source_mode = "local" + if isinstance(source_config, dict): + source_mode = str(source_config.get("mode", "local")) + + if source_mode == "local": + videos = discover_videos( + config["input"]["dir"], + config["input"]["extensions"], + recursive=config["input"]["recursive"], + ) + return [{"path": path} for path in videos] + + if source_mode == "hik_cloud": + return [ + record + for record in download_hik_cloud_recordings( + config, + output_dir, + download=download_source, + ) + if record.get("status") == "downloaded" + ] + + raise ValueError(f"unsupported source.mode: {source_mode}") + + +def _without_video_records( + records: list[dict[str, object]], + video_id: str, +) -> list[dict[str, object]]: + return [record for record in records if str(record.get("video_id")) != video_id] + + +def _backfill_frame_beijing_times( + frame_records: list[dict[str, object]], + video_records: list[dict[str, object]], + *, + timezone_name: str, +) -> set[str]: + video_by_id = { + str(record.get("video_id")): record + for record in video_records + if record.get("video_id") + } + changed_video_ids: set[str] = set() + for frame_record in frame_records: + if frame_record.get("status") != "sampled" or frame_record.get("beijing_time"): + continue + video_id = str(frame_record.get("video_id") or "") + start_epoch = timeline_start_epoch(video_by_id.get(video_id, {})) + beijing_time = format_beijing_time( + start_epoch, + offset_seconds=float(frame_record.get("offset_seconds") or 0), + timezone_name=timezone_name, + ) + if beijing_time is None: + continue + frame_record["beijing_time"] = beijing_time + changed_video_ids.add(video_id) + return changed_video_ids + + +def _run_inference( + clip_records: list[dict[str, object]], + video_records: list[dict[str, object]], + output_dir: Path, + config: dict[str, object], + *, + limit_clips: int | None, + resume: bool, +) -> None: + results_path = output_dir / "clip_results.jsonl" + result_records = read_jsonl(results_path) if resume else [] + clip_by_id = { + str(record.get("clip_id")): record + for record in clip_records + if record.get("clip_id") + } + result_records = [ + _refresh_result_timeline(record, clip_by_id, config) + for record in result_records + ] + ok_clip_ids = { + str(record.get("clip_id")) + for record in result_records + if record.get("status") == "ok" and record.get("clip_id") + } + video_by_id = { + str(record.get("video_id")): record + for record in video_records + if record.get("video_id") + } + processed = 0 + for clip_record in clip_records: + clip_id = str(clip_record.get("clip_id")) + if clip_id in ok_clip_ids: + continue + if limit_clips is not None and processed >= limit_clips: + break + + result_records = [ + record for record in result_records if str(record.get("clip_id")) != clip_id + ] + video_record = video_by_id.get(str(clip_record.get("video_id")), {}) + result = _infer_and_parse_clip(clip_record, video_record, output_dir, config) + result_records.append(result) + _write_jsonl_exact(results_path, result_records) + processed += 1 + + _write_jsonl_exact(results_path, result_records) + + +def _refresh_result_timeline( + result_record: dict[str, object], + clip_by_id: dict[str, dict[str, object]], + config: dict[str, object], +) -> dict[str, object]: + clip_record = clip_by_id.get(str(result_record.get("clip_id"))) + if not clip_record: + return result_record + if not _clip_has_beijing_timing(clip_record): + return result_record + timeline = dict(result_record.get("monitoring_timeline") or {}) + timeline.update( + { + "timezone": config.get("runtime", {}).get("timezone", DEFAULT_TIMEZONE), + "clip_start_seconds": clip_record.get("clip_start_seconds"), + "clip_end_seconds": clip_record.get("clip_end_seconds"), + "clip_start_timecode": clip_record.get("clip_start_timecode"), + "clip_end_timecode": clip_record.get("clip_end_timecode"), + "clip_start_beijing_time": clip_record.get("clip_start_beijing_time"), + "clip_end_beijing_time": clip_record.get("clip_end_beijing_time"), + "frame_times": clip_record.get("frame_times", []), + } + ) + refreshed = dict(result_record) + refreshed["monitoring_timeline"] = timeline + return refreshed + + +def _clip_has_beijing_timing(clip_record: dict[str, object]) -> bool: + if clip_record.get("clip_start_beijing_time") or clip_record.get("clip_end_beijing_time"): + return True + for frame in clip_record.get("frame_times", []) or []: + if isinstance(frame, dict) and frame.get("beijing_time"): + return True + return False + + +def _infer_and_parse_clip( + clip_record: dict[str, object], + video_record: dict[str, object], + output_dir: Path, + config: dict[str, object], +) -> dict[str, object]: + schema_config = config.get("schema", {}) + parse_retry = 0 + if isinstance(schema_config, dict): + parse_retry = int(schema_config.get("parse_retry", 0)) + + attempts = parse_retry + 1 + result: dict[str, object] | None = None + for attempt in range(attempts): + try: + inference = infer_clip( + clip_record, + output_dir, + config["vlm"], + config["prompt"], + ) + except Exception as exc: + return build_clip_result( + "", + clip_record, + video_record, + config, + processing={}, + status="inference_failed", + error=str(exc), + ) + + result = build_clip_result( + str(inference.get("raw_response", "")), + clip_record, + video_record, + config, + processing={ + "latency_ms": inference.get("latency_ms"), + "http_status": inference.get("http_status"), + "attempt": attempt + 1, + }, + ) + if result.get("status") != "parse_failed": + return result + if result is None: + raise RuntimeError("unreachable inference state") + return result + + +def _write_jsonl_exact( + path: Path, + records: list[dict[str, object]], +) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + with path.open("w", encoding="utf-8") as handle: + for record in records: + handle.write(json.dumps(record, ensure_ascii=False, sort_keys=True) + "\n") + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/video_ai_analysis_poc/clips.py b/video_ai_analysis_poc/clips.py new file mode 100644 index 0000000..8c2fc30 --- /dev/null +++ b/video_ai_analysis_poc/clips.py @@ -0,0 +1,158 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any + +from .frames import seconds_to_timecode +from .manifest import read_jsonl, write_manifest +from .timeline import derive_time_from_reference + + +def build_clip_records( + frame_records: list[dict[str, Any]], + clip_config: dict[str, Any], +) -> list[dict[str, Any]]: + sampled_frames = [ + record for record in frame_records if record.get("status") == "sampled" + ] + by_video: dict[str, list[dict[str, Any]]] = {} + for frame in sampled_frames: + by_video.setdefault(str(frame["video_id"]), []).append(frame) + + clips = [] + for video_id, frames in sorted(by_video.items()): + clips.extend(_build_video_clips(video_id, frames, clip_config)) + return clips + + +def build_clip_records_from_manifest( + frame_manifest_path: str | Path, + clip_manifest_path: str | Path, + clip_config: dict[str, Any], +) -> list[dict[str, Any]]: + clips = build_clip_records(read_jsonl(frame_manifest_path), clip_config) + write_manifest(clip_manifest_path, clips) + return clips + + +def _build_video_clips( + video_id: str, + frames: list[dict[str, Any]], + clip_config: dict[str, Any], +) -> list[dict[str, Any]]: + sorted_frames = sorted(frames, key=lambda frame: float(frame["offset_seconds"])) + if not sorted_frames: + return [] + + length_seconds = float(clip_config.get("length_seconds", 10)) + stride_seconds = float(clip_config.get("stride_seconds", length_seconds)) + frames_per_clip = int(clip_config.get("frames_per_clip", 8)) + min_frames_per_clip = int(clip_config.get("min_frames_per_clip", 4)) + max_offset = max(float(frame["offset_seconds"]) for frame in sorted_frames) + timeline_end = _estimated_timeline_end(sorted_frames) + + clips = [] + clip_index = 1 + start = 0.0 + while start <= max_offset: + end = min(start + length_seconds, timeline_end) + in_window = [ + frame + for frame in sorted_frames + if start <= float(frame["offset_seconds"]) < end + ] + if len(in_window) >= min_frames_per_clip: + selected_frames = _uniform_sample(in_window, frames_per_clip) + start_beijing_time, end_beijing_time = _clip_beijing_time_range( + in_window, + start, + end, + ) + clip = { + "video_id": video_id, + "clip_id": f"{video_id}_c{clip_index:06d}", + "clip_start_seconds": round(start, 6), + "clip_end_seconds": round(end, 6), + "clip_start_timecode": seconds_to_timecode(start), + "clip_end_timecode": seconds_to_timecode(end), + "frame_times": [_frame_time(frame) for frame in selected_frames], + "status": "pending", + "retry_count": 0, + "last_error": None, + } + if start_beijing_time is not None: + clip["clip_start_beijing_time"] = start_beijing_time + if end_beijing_time is not None: + clip["clip_end_beijing_time"] = end_beijing_time + clips.append(clip) + clip_index += 1 + start += stride_seconds + return clips + + +def _estimated_timeline_end(frames: list[dict[str, Any]]) -> float: + offsets = [float(frame["offset_seconds"]) for frame in frames] + if len(offsets) < 2: + return offsets[-1] + intervals = [ + current - previous + for previous, current in zip(offsets, offsets[1:]) + if current > previous + ] + if not intervals: + return offsets[-1] + return offsets[-1] + min(intervals) + + +def _uniform_sample( + frames: list[dict[str, Any]], + frames_per_clip: int, +) -> list[dict[str, Any]]: + if len(frames) <= frames_per_clip: + return frames + if frames_per_clip <= 1: + return [frames[0]] + last_index = len(frames) - 1 + indexes = [ + round(position * last_index / (frames_per_clip - 1)) + for position in range(frames_per_clip) + ] + return [frames[index] for index in indexes] + + +def _frame_time(frame: dict[str, Any]) -> dict[str, Any]: + record = { + "frame_id": frame.get("frame_id"), + "frame_path": frame.get("frame_path"), + "offset_seconds": frame.get("offset_seconds"), + "timecode": frame.get("timecode"), + "pts_time": frame.get("pts_time"), + } + if frame.get("beijing_time") is not None: + record["beijing_time"] = frame.get("beijing_time") + return record + + +def _clip_beijing_time_range( + frames: list[dict[str, Any]], + start: float, + end: float, +) -> tuple[str | None, str | None]: + for frame in frames: + reference_time = frame.get("beijing_time") + if not reference_time: + continue + reference_offset = frame.get("offset_seconds") + return ( + derive_time_from_reference( + str(reference_time), + reference_offset_seconds=reference_offset, + target_offset_seconds=start, + ), + derive_time_from_reference( + str(reference_time), + reference_offset_seconds=reference_offset, + target_offset_seconds=end, + ), + ) + return None, None diff --git a/video_ai_analysis_poc/config.py b/video_ai_analysis_poc/config.py new file mode 100644 index 0000000..9250f49 --- /dev/null +++ b/video_ai_analysis_poc/config.py @@ -0,0 +1,278 @@ +from __future__ import annotations + +import ast +from pathlib import Path +from typing import Any + +from .paths import resolve_path, validate_output_dir + + +DEFAULT_CONFIG_PATH = Path(__file__).resolve().parent.parent / "config" / "local_batch.yaml" + + +def load_config( + config_path: str | Path = DEFAULT_CONFIG_PATH, + *, + input_dir: str | Path | None = None, + output_dir: str | Path | None = None, +) -> dict[str, Any]: + path = Path(config_path).expanduser().resolve(strict=False) + raw_config = _parse_simple_yaml(path) + config = _with_defaults(raw_config) + + base_dir = path.parent.parent if path.parent.name == "config" else path.parent + + if input_dir is not None: + config["input"]["dir"] = str(input_dir) + if output_dir is not None: + config["output"]["dir"] = str(output_dir) + + config["input"]["dir"] = str(resolve_path(config["input"]["dir"], base_dir=base_dir)) + config["output"]["dir"] = str( + resolve_path(config["output"]["dir"], base_dir=base_dir) + ) + validate_output_dir(config["input"]["dir"], config["output"]["dir"]) + + extensions = config["input"].get("extensions", []) + config["input"]["extensions"] = _normalize_extensions(extensions) + config["input"]["recursive"] = bool(config["input"].get("recursive", True)) + config.setdefault("ffprobe", {}) + config["ffprobe"]["timeout_seconds"] = int( + config["ffprobe"].get("timeout_seconds", 30) + ) + return config + + +def _with_defaults(config: dict[str, Any]) -> dict[str, Any]: + merged: dict[str, Any] = { + "input": { + "dir": "./videos", + "recursive": True, + "extensions": [".mp4", ".mov", ".mkv", ".avi", ".flv", ".ts", ".m4v"], + }, + "output": { + "dir": "./outputs/local-batch", + "overwrite": False, + "resume": True, + "keep_frames": True, + }, + "source": {"mode": "local"}, + "hik_cloud": { + "api_base_url": "https://api2.hik-cloud.com", + "download_path": "/v1/carrier/cstorage/open/play/download", + "access_token": None, + "access_token_env": "HIK_CLOUD_ACCESS_TOKEN", + "devices": [], + "time_ranges": [], + "chunk_seconds": 600, + "timeout_seconds": 60, + "download_timeout_seconds": 600, + }, + "ffprobe": {"timeout_seconds": 30}, + "ffmpeg": { + "prefer_nvdec": True, + "allow_cpu_fallback": False, + "hwaccel": "cuda", + "codec_decoders": {"h264": "h264_cuvid", "hevc": "hevc_cuvid"}, + "frame_fps": 1, + "frame_width": 640, + "jpeg_quality": 4, + "timeout_seconds_per_video": 3600, + }, + "clip": { + "length_seconds": 10, + "stride_seconds": 10, + "frames_per_clip": 8, + "min_frames_per_clip": 4, + }, + "vlm": { + "api_base_url": "http://localhost:8679", + "chat_completions_path": "/v1/chat/completions", + "model": "memai-zhengxin-v3-20260413", + "timeout_seconds": 120, + "max_tokens": 512, + "temperature": 0, + "batch_size": 1, + "image_transport": "data_uri", + "retries": 1, + }, + "prompt": { + "system": "You are a store video analysis assistant. Return strict JSON only.", + "user": "Analyze this clip. Return events and screen_time. If no event, return events: [].", + }, + "schema": { + "version": "local-batch-v1", + "event_types": [ + "customer_enter", + "customer_leave", + "queue_detected", + "staff_absent", + "staff_present", + "area_crowded", + "abnormal_behavior", + "unknown", + ], + "require_strict_json": True, + "parse_retry": 1, + "merge_gap_seconds": 30, + }, + "runtime": {"timezone": "Asia/Shanghai", "log_level": "INFO"}, + } + for section, values in config.items(): + if isinstance(values, dict) and isinstance(merged.get(section), dict): + merged[section].update(values) + else: + merged[section] = values + return merged + + +def _normalize_extensions(extensions: list[str]) -> list[str]: + normalized = [] + for extension in extensions: + value = str(extension).lower() + if not value.startswith("."): + value = f".{value}" + normalized.append(value) + return normalized + + +def _parse_simple_yaml(path: Path) -> dict[str, Any]: + if not path.exists(): + raise FileNotFoundError(f"config file not found: {path}") + + root: dict[str, Any] = {} + stack: list[tuple[int, dict[str, Any] | list[Any]]] = [(-1, root)] + lines = path.read_text(encoding="utf-8").splitlines() + + index = 0 + while index < len(lines): + raw_line = lines[index].rstrip() + stripped = raw_line.strip() + if not stripped or raw_line.lstrip().startswith("#"): + index += 1 + continue + + indent = len(raw_line) - len(raw_line.lstrip(" ")) + while indent <= stack[-1][0]: + stack.pop() + parent = stack[-1][1] + + if stripped.startswith("- "): + if not isinstance(parent, list): + raise ValueError(f"list item without list parent: {raw_line}") + item = stripped[2:].strip() + if ":" in item: + key, value = item.split(":", 1) + mapping: dict[str, Any] = {} + parent.append(mapping) + key = key.strip() + value = value.strip() + if not value: + next_stripped = _next_stripped(lines, index) + child: dict[str, Any] | list[Any] + child = [] if next_stripped and next_stripped.startswith("- ") else {} + mapping[key] = child + stack.append((indent, mapping)) + stack.append((indent + 2, child)) + else: + mapping[key] = _parse_scalar(value) + stack.append((indent, mapping)) + else: + parent.append(_parse_scalar(item)) + index += 1 + continue + + if not isinstance(parent, dict): + raise ValueError(f"mapping entry inside list is not supported: {raw_line}") + + if ":" not in stripped: + raise ValueError(f"unsupported config line: {raw_line}") + + key, value = stripped.split(":", 1) + key = key.strip() + value = value.strip() + if _is_block_scalar(value): + parent[key], index = _parse_block_scalar(lines, index, indent, value) + continue + if not value: + next_stripped = _next_stripped(lines, index) + child: dict[str, Any] | list[Any] + child = [] if next_stripped and next_stripped.startswith("- ") else {} + parent[key] = child + stack.append((indent, child)) + else: + parent[key] = _parse_scalar(value) + index += 1 + + return root + + +def _next_stripped(lines: list[str], current_index: int) -> str | None: + for raw_line in lines[current_index + 1 :]: + stripped = raw_line.strip() + if stripped and not raw_line.lstrip().startswith("#"): + return stripped + return None + + +def _is_block_scalar(value: str) -> bool: + return value in {">", ">-", "|", "|-"} + + +def _parse_block_scalar( + lines: list[str], + start_index: int, + parent_indent: int, + marker: str, +) -> tuple[str, int]: + content_lines: list[str] = [] + content_indent: int | None = None + index = start_index + 1 + + while index < len(lines): + raw_line = lines[index].rstrip() + stripped = raw_line.strip() + if not stripped: + content_lines.append("") + index += 1 + continue + + indent = len(raw_line) - len(raw_line.lstrip(" ")) + if indent <= parent_indent: + break + if content_indent is None: + content_indent = indent + content_lines.append(raw_line[content_indent:]) + index += 1 + + if marker.endswith("-"): + while content_lines and content_lines[-1] == "": + content_lines.pop() + return "\n".join(content_lines), index + + +def _parse_scalar(value: str) -> Any: + lower = value.lower() + if lower == "true": + return True + if lower == "false": + return False + if lower in {"null", "none"}: + return None + if value.startswith("[") and value.endswith("]"): + parsed = ast.literal_eval(value) + if not isinstance(parsed, list): + raise ValueError(f"expected list value: {value}") + return parsed + if (value.startswith('"') and value.endswith('"')) or ( + value.startswith("'") and value.endswith("'") + ): + return ast.literal_eval(value) + try: + return int(value) + except ValueError: + pass + try: + return float(value) + except ValueError: + return value diff --git a/video_ai_analysis_poc/discovery.py b/video_ai_analysis_poc/discovery.py new file mode 100644 index 0000000..6ce8c2f --- /dev/null +++ b/video_ai_analysis_poc/discovery.py @@ -0,0 +1,27 @@ +from __future__ import annotations + +from pathlib import Path + + +def discover_videos( + input_dir: str | Path, + extensions: list[str], + *, + recursive: bool, +) -> list[Path]: + root = Path(input_dir).expanduser() + if not root.exists(): + raise FileNotFoundError(f"input dir not found: {root}") + if not root.is_dir(): + raise NotADirectoryError(f"input path is not a directory: {root}") + + allowed = { + extension.lower() if extension.startswith(".") else f".{extension.lower()}" + for extension in extensions + } + iterator = root.rglob("*") if recursive else root.iterdir() + return sorted( + path + for path in iterator + if path.is_file() and path.suffix.lower() in allowed + ) diff --git a/video_ai_analysis_poc/ffmpeg_sampler.py b/video_ai_analysis_poc/ffmpeg_sampler.py new file mode 100644 index 0000000..b724e7d --- /dev/null +++ b/video_ai_analysis_poc/ffmpeg_sampler.py @@ -0,0 +1,243 @@ +from __future__ import annotations + +import math +import subprocess +from pathlib import Path +from typing import Any + +from .frames import build_frame_records +from .manifest import read_jsonl, write_manifest +from .timeline import DEFAULT_TIMEZONE, timeline_start_epoch + + +NVDEC_CODECS = {"h264", "hevc"} + + +def build_sample_command( + video_path: str | Path, + output_dir: str | Path, + video_id: str, + ffmpeg_config: dict[str, Any], + *, + codec_name: str | None, + max_frames: int | None = None, + max_duration_seconds: float | None = None, +) -> list[str]: + frame_dir = Path(output_dir).expanduser() / "frames" / video_id + frame_pattern = frame_dir / "%06d.jpg" + command = ["ffmpeg", "-hide_banner", "-y"] + + codec = (codec_name or "").lower() + prefer_nvdec = bool(ffmpeg_config.get("prefer_nvdec", True)) + allow_cpu_fallback = bool(ffmpeg_config.get("allow_cpu_fallback", False)) + decoders = ffmpeg_config.get("codec_decoders", {}) + decoder = decoders.get(codec) if isinstance(decoders, dict) else None + + if prefer_nvdec and codec in NVDEC_CODECS and decoder: + command.extend( + [ + "-hwaccel", + str(ffmpeg_config.get("hwaccel", "cuda")), + "-c:v", + str(decoder), + ] + ) + elif not allow_cpu_fallback: + raise ValueError( + f"NVDEC decoder is required for codec {codec_name!r}; CPU fallback is disabled" + ) + + frame_fps = ffmpeg_config.get("frame_fps", 1) + frame_width = ffmpeg_config.get("frame_width", 640) + jpeg_quality = ffmpeg_config.get("jpeg_quality", 4) + command.extend( + [ + "-i", + str(Path(video_path).expanduser()), + ] + ) + if max_duration_seconds is not None and max_duration_seconds > 0: + command.extend(["-t", f"{max_duration_seconds:g}"]) + command.extend( + [ + "-vf", + f"fps={frame_fps},scale={frame_width}:-2", + "-q:v", + str(jpeg_quality), + ] + ) + if max_frames is not None and max_frames > 0: + command.extend(["-frames:v", str(max_frames)]) + command.append(str(frame_pattern)) + return command + + +def sample_video_frames( + video_record: dict[str, Any], + output_dir: str | Path, + ffmpeg_config: dict[str, Any], + *, + manifest_path: str | Path | None = None, +) -> list[dict[str, Any]]: + video_id = str(video_record["video_id"]) + output_root = Path(output_dir).expanduser().resolve(strict=False) + frame_dir = output_root / "frames" / video_id + frame_dir.mkdir(parents=True, exist_ok=True) + + try: + max_frames = _max_output_frames(video_record, ffmpeg_config) + timezone_name = str(ffmpeg_config.get("timezone", DEFAULT_TIMEZONE)) + start_epoch = timeline_start_epoch(video_record) + command = build_sample_command( + video_record.get("path") or video_record.get("source_path"), + output_root, + video_id, + ffmpeg_config, + codec_name=video_record.get("codec_name"), + max_frames=max_frames, + max_duration_seconds=_record_duration_seconds(video_record), + ) + completed = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + timeout=int(ffmpeg_config.get("timeout_seconds_per_video", 3600)), + ) + records = build_frame_records( + video_id, + output_root, + frame_dir.glob("*.jpg"), + frame_fps=float(ffmpeg_config.get("frame_fps", 1)), + timeline_start_epoch=start_epoch, + timezone_name=timezone_name, + ) + _attach_success_evidence( + records, + command, + stderr=completed.stderr, + ) + except subprocess.CalledProcessError as exc: + records = build_frame_records( + video_id, + output_root, + frame_dir.glob("*.jpg"), + frame_fps=float(ffmpeg_config.get("frame_fps", 1)), + timeline_start_epoch=start_epoch, + timezone_name=timezone_name, + ) + if records and (max_frames is None or len(records) >= max_frames): + _attach_success_evidence( + records, + command, + stderr=exc.stderr, + ) + else: + records = [_failure_record(video_id, exc)] + except (subprocess.TimeoutExpired, ValueError) as exc: + records = [_failure_record(video_id, exc)] + + if manifest_path is not None: + _replace_video_records(Path(manifest_path), video_id, records) + return records + + +def _replace_video_records( + manifest_path: Path, + video_id: str, + new_records: list[dict[str, Any]], +) -> None: + existing = [ + record + for record in read_jsonl(manifest_path) + if str(record.get("video_id")) != video_id + ] + write_manifest(manifest_path, [*existing, *new_records]) + + +def _failure_record(video_id: str, exc: BaseException) -> dict[str, Any]: + return { + "video_id": video_id, + "frame_id": None, + "frame_path": None, + "offset_seconds": None, + "timecode": None, + "pts_time": None, + "status": "sample_failed", + "retry_count": 0, + "last_error": _error_text(exc), + } + + +def _attach_success_evidence( + records: list[dict[str, Any]], + command: list[str], + *, + stderr: str | None, +) -> None: + evidence = { + "ffmpeg_command": command, + "decoder": _command_value_after(command, "-c:v"), + "hwaccel": _command_value_after(command, "-hwaccel"), + "stderr_summary": _stderr_summary(stderr), + } + for record in records: + record.update(evidence) + + +def _command_value_after(command: list[str], flag: str) -> str | None: + try: + index = command.index(flag) + except ValueError: + return None + if index + 1 >= len(command): + return None + return command[index + 1] + + +def _stderr_summary(stderr: str | None, *, limit: int = 2000) -> str: + if not stderr: + return "" + text = stderr.strip() + if len(text) <= limit: + return text + return text[:limit] + + +def _error_text(exc: BaseException) -> str: + if isinstance(exc, subprocess.CalledProcessError): + return str(exc.stderr or exc.stdout or exc) + if isinstance(exc, subprocess.TimeoutExpired): + return f"ffmpeg timed out after {exc.timeout}s" + return str(exc) + + +def _max_output_frames( + video_record: dict[str, Any], + ffmpeg_config: dict[str, Any], +) -> int | None: + frame_fps = _optional_float(ffmpeg_config.get("frame_fps", 1)) + if frame_fps is None or frame_fps <= 0: + return None + duration_seconds = _record_duration_seconds(video_record) + if duration_seconds is None or duration_seconds <= 0: + return None + return max(1, math.ceil(duration_seconds * frame_fps) + 1) + + +def _record_duration_seconds(video_record: dict[str, Any]) -> float | None: + for begin_key, end_key in ( + ("actual_begin", "actual_end"), + ("requested_begin", "requested_end"), + ): + begin = _optional_float(video_record.get(begin_key)) + end = _optional_float(video_record.get(end_key)) + if begin is not None and end is not None and end > begin: + return end - begin + return _optional_float(video_record.get("duration_seconds")) + + +def _optional_float(value: Any) -> float | None: + if value is None or value == "": + return None + return float(value) diff --git a/video_ai_analysis_poc/frames.py b/video_ai_analysis_poc/frames.py new file mode 100644 index 0000000..33dfd36 --- /dev/null +++ b/video_ai_analysis_poc/frames.py @@ -0,0 +1,59 @@ +from __future__ import annotations + +from pathlib import Path +from typing import Any, Iterable + +from .timeline import DEFAULT_TIMEZONE, format_beijing_time + + +def seconds_to_timecode(seconds: float | int | None) -> str | None: + if seconds is None: + return None + total_seconds = int(float(seconds)) + hours = total_seconds // 3600 + minutes = (total_seconds % 3600) // 60 + remaining_seconds = total_seconds % 60 + return f"{hours:02d}:{minutes:02d}:{remaining_seconds:02d}" + + +def build_frame_records( + video_id: str, + output_dir: str | Path, + frame_paths: Iterable[str | Path], + *, + frame_fps: float, + timeline_start_epoch: float | int | str | None = None, + timezone_name: str = DEFAULT_TIMEZONE, +) -> list[dict[str, Any]]: + base_dir = Path(output_dir).expanduser().resolve(strict=False) + records = [] + for index, frame_path in enumerate(sorted(Path(path) for path in frame_paths), start=1): + offset_seconds = round((index - 1) / frame_fps, 6) + record = { + "video_id": video_id, + "frame_id": f"{video_id}_f{index:06d}", + "frame_path": _relative_frame_path(frame_path, base_dir), + "offset_seconds": offset_seconds, + "timecode": seconds_to_timecode(offset_seconds), + "pts_time": offset_seconds, + "status": "sampled", + "retry_count": 0, + "last_error": None, + } + beijing_time = format_beijing_time( + timeline_start_epoch, + offset_seconds=offset_seconds, + timezone_name=timezone_name, + ) + if beijing_time is not None: + record["beijing_time"] = beijing_time + records.append(record) + return records + + +def _relative_frame_path(frame_path: Path, base_dir: Path) -> str: + resolved = frame_path.expanduser().resolve(strict=False) + try: + return resolved.relative_to(base_dir).as_posix() + except ValueError: + return resolved.as_posix() diff --git a/video_ai_analysis_poc/hik_cloud.py b/video_ai_analysis_poc/hik_cloud.py new file mode 100644 index 0000000..fd0df5d --- /dev/null +++ b/video_ai_analysis_poc/hik_cloud.py @@ -0,0 +1,450 @@ +from __future__ import annotations + +import json +import os +import re +from datetime import datetime +from pathlib import Path +from typing import Any +from urllib.parse import urlparse, urlunparse +import urllib.request +from zoneinfo import ZoneInfo + +from .manifest import read_jsonl, write_manifest +from .paths import hik_cloud_download_path + + +DEFAULT_TIMEZONE = "Asia/Shanghai" +DEFAULT_CHUNK_SECONDS = 600 +MAX_CHUNK_SECONDS = 3600 +DEFAULT_API_BASE_URL = "https://api2.hik-cloud.com" +DEFAULT_DOWNLOAD_PATH = "/v1/carrier/cstorage/open/play/download" +DEFAULT_TIMEOUT_SECONDS = 60 +DEFAULT_DOWNLOAD_TIMEOUT_SECONDS = 600 +DOWNLOAD_MANIFEST_NAME = "hik_cloud_download_manifest.jsonl" +NO_RECORDING_CODE = 80438027 +TIME_FORMAT = "%Y-%m-%d %H:%M:%S" + + +def parse_hik_time(value: str | int | float, timezone: str = DEFAULT_TIMEZONE) -> int: + if isinstance(value, bool): + raise ValueError(f"unsupported time value: {value!r}") + if isinstance(value, int | float): + return int(value) + if isinstance(value, str): + parsed = datetime.strptime(value, TIME_FORMAT) + return int(parsed.replace(tzinfo=ZoneInfo(timezone)).timestamp()) + raise ValueError(f"unsupported time value: {value!r}") + + +def build_download_chunks(config: dict[str, Any]) -> list[dict[str, Any]]: + hik_config = config.get("hik_cloud", {}) + runtime_config = config.get("runtime", {}) + timezone = runtime_config.get("timezone", DEFAULT_TIMEZONE) + chunk_seconds = int(hik_config.get("chunk_seconds", DEFAULT_CHUNK_SECONDS)) + if chunk_seconds <= 0: + raise ValueError("chunk_seconds must be greater than 0") + if chunk_seconds > MAX_CHUNK_SECONDS: + raise ValueError("chunk_seconds must be less than or equal to 3600") + + chunks: list[dict[str, Any]] = [] + devices = hik_config.get("devices", []) + time_ranges = hik_config.get("time_ranges", []) + for device in devices: + for time_range in time_ranges: + requested_begin = parse_hik_time(time_range["begin"], timezone) + requested_end = parse_hik_time(time_range["end"], timezone) + if requested_end <= requested_begin: + raise ValueError("time range end must be after begin") + + time_begin = requested_begin + while time_begin < requested_end: + time_end = min(time_begin + chunk_seconds, requested_end) + chunks.append( + { + "device_serial": device["device_serial"], + "channel_no": device["channel_no"], + "requested_begin": requested_begin, + "requested_end": requested_end, + "time_begin": time_begin, + "time_end": time_end, + } + ) + time_begin = time_end + return chunks + + +def resolve_access_token(config_or_hik_config: dict[str, Any]) -> str: + hik_config = _hik_config(config_or_hik_config) + access_token = hik_config.get("access_token") + if access_token: + return str(access_token) + + access_token_env = hik_config.get("access_token_env") + if access_token_env: + env_token = os.environ.get(str(access_token_env)) + if env_token: + return env_token + + raise ValueError( + "missing hik_cloud access_token; configure access_token or access_token_env" + ) + + +def request_download_address( + chunk: dict[str, Any], + hik_config: dict[str, Any], + *, + http_post: Any | None = None, +) -> dict[str, Any]: + token = resolve_access_token(hik_config) + api_base_url = str(hik_config.get("api_base_url") or DEFAULT_API_BASE_URL) + download_path = str(hik_config.get("download_path") or DEFAULT_DOWNLOAD_PATH) + url = api_base_url.rstrip("/") + download_path + headers = { + "Authorization": f"bearer {token}", + "Content-Type": "application/json", + } + json_body = { + "deviceSerial": chunk["device_serial"], + "channelNo": chunk["channel_no"], + "timeBegin": chunk["time_begin"], + "timeEnd": chunk["time_end"], + } + timeout_seconds = int(hik_config.get("timeout_seconds", DEFAULT_TIMEOUT_SECONDS)) + post = http_post or _post_json + + try: + response = post(url, json_body, headers, timeout_seconds) + except Exception as exc: # pragma: no cover - exact urllib failures vary. + return { + **_chunk_metadata(chunk), + "status": "address_failed", + "code": None, + "last_error": _sanitize_error(exc, token), + } + + code = _optional_int(response.get("code")) + if code == 0: + data = response.get("data") or {} + return { + **_chunk_metadata(chunk), + "status": "address_ok", + "code": code, + "url": data.get("url"), + "actual_begin": _optional_int(data.get("actualBeginTime")), + "actual_end": _optional_int(data.get("actualEndTime")), + } + + status = "no_recording" if code == NO_RECORDING_CODE else "address_failed" + result = { + **_chunk_metadata(chunk), + "status": status, + "code": code, + "last_error": _api_error_message(response, token), + } + return result + + +def download_hik_cloud_recordings( + config: dict[str, Any], + output_dir: str | Path, + *, + address_client: Any | None = None, + download_url: Any | None = None, + download: bool = True, +) -> list[dict[str, Any]]: + output_path = Path(output_dir).expanduser().resolve(strict=False) + manifest_path = output_path / DOWNLOAD_MANIFEST_NAME + hik_config = _hik_config(config) + chunks = build_download_chunks(config) + resume = bool(config.get("output", {}).get("resume", False)) + manifest_records = read_jsonl(manifest_path) if resume else [] + existing_downloads = { + _manifest_key(record): record + for record in manifest_records + if _is_resumable_download(record) + } + get_address = address_client or request_download_address + fetch = download_url or _download_url + download_timeout_seconds = int( + hik_config.get("download_timeout_seconds", DEFAULT_DOWNLOAD_TIMEOUT_SECONDS) + ) + token = _redaction_token(hik_config) + + video_records: list[dict[str, Any]] = [] + for chunk in chunks: + key = _chunk_key(chunk) + existing_record = existing_downloads.get(key) + if download and existing_record is not None: + video_records.append(_video_record_from_manifest(existing_record)) + continue + + address_result = get_address(chunk, hik_config) + status = address_result.get("status") + if status != "address_ok": + _upsert_manifest_record( + manifest_records, + _manifest_record( + chunk, + address_result, + status=str(status or "address_failed"), + token=token, + ), + ) + continue + + if not download: + _upsert_manifest_record( + manifest_records, + _manifest_record( + chunk, + address_result, + status="address_ok", + token=token, + ), + ) + continue + + url = str(address_result.get("url") or "") + target_path = hik_cloud_download_path( + output_path, + str(chunk["device_serial"]), + chunk["channel_no"], + int(chunk["time_begin"]), + int(chunk["time_end"]), + ) + try: + payload = fetch(url, timeout_seconds=download_timeout_seconds) + target_path.parent.mkdir(parents=True, exist_ok=True) + target_path.write_bytes(payload) + except Exception as exc: # pragma: no cover - concrete network failures vary. + _upsert_manifest_record( + manifest_records, + _manifest_record( + chunk, + address_result, + status="download_failed", + path=target_path, + last_error=_sanitize_error(exc, token), + token=token, + ), + ) + continue + + record = _downloaded_video_record(chunk, address_result, target_path) + video_records.append(record) + _upsert_manifest_record( + manifest_records, + _manifest_record( + chunk, + address_result, + status="downloaded", + path=target_path, + token=token, + ), + ) + + write_manifest(manifest_path, manifest_records) + return video_records + + +def _post_json( + url: str, + json_body: dict[str, Any], + headers: dict[str, str], + timeout_seconds: int, +) -> dict[str, Any]: + request = urllib.request.Request( + url, + data=json.dumps(json_body).encode("utf-8"), + headers=headers, + method="POST", + ) + with urllib.request.urlopen(request, timeout=timeout_seconds) as response: + return json.loads(response.read().decode("utf-8")) + + +def _download_url(url: str, *, timeout_seconds: int | None = None) -> bytes: + with urllib.request.urlopen(url, timeout=timeout_seconds) as response: + return response.read() + + +def _hik_config(config_or_hik_config: dict[str, Any]) -> dict[str, Any]: + hik_config = config_or_hik_config.get("hik_cloud") + if isinstance(hik_config, dict): + return hik_config + return config_or_hik_config + + +def _chunk_metadata(chunk: dict[str, Any]) -> dict[str, Any]: + return { + "device_serial": chunk["device_serial"], + "channel_no": chunk["channel_no"], + "requested_begin": chunk.get("requested_begin"), + "requested_end": chunk.get("requested_end"), + "time_begin": chunk["time_begin"], + "time_end": chunk["time_end"], + } + + +def _optional_int(value: Any) -> int | None: + if value is None or value == "": + return None + return int(value) + + +def _api_error_message(response: dict[str, Any], token: str) -> str: + code = response.get("code") + message = response.get("msg") or response.get("message") or "hik api error" + return _sanitize_error(f"hik api code {code}: {message}", token) + + +def _sanitize_error(value: Any, token: str = "") -> str | None: + if value is None: + return None + message = str(value) + for raw_url in re.findall(r"https?://[^\s'\"<>]+", message): + parsed = urlparse(raw_url) + sanitized_url = urlunparse( + (parsed.scheme, parsed.netloc, parsed.path, "", "", "") + ) + message = message.replace(raw_url, sanitized_url) + message = re.sub( + r"\b(?:sign|sig|token|access_token)=[^&\s'\"<>]+", + "[redacted-query]", + message, + flags=re.IGNORECASE, + ) + if token: + message = message.replace(token, "[redacted]") + message = message.replace("Authorization", "[redacted-header]") + return message + + +def _downloaded_video_record( + chunk: dict[str, Any], + address_result: dict[str, Any], + path: Path, +) -> dict[str, Any]: + return { + "source": "hik_cloud", + "path": str(path), + "source_path": _source_path(chunk), + "device_serial": chunk["device_serial"], + "channel_no": chunk["channel_no"], + "requested_begin": chunk["time_begin"], + "requested_end": chunk["time_end"], + "actual_begin": address_result.get("actual_begin"), + "actual_end": address_result.get("actual_end"), + "status": "downloaded", + "retry_count": 0, + "last_error": None, + } + + +def _manifest_record( + chunk: dict[str, Any], + address_result: dict[str, Any], + *, + status: str, + token: str, + path: Path | None = None, + last_error: str | None = None, +) -> dict[str, Any]: + url = address_result.get("url") + record = { + "source": "hik_cloud", + "device_serial": chunk["device_serial"], + "channel_no": chunk["channel_no"], + "requested_begin": chunk["time_begin"], + "requested_end": chunk["time_end"], + "actual_begin": address_result.get("actual_begin"), + "actual_end": address_result.get("actual_end"), + "path": str(path) if path is not None else None, + "status": status, + "retry_count": 0, + "last_error": _sanitize_error(last_error or address_result.get("last_error"), token), + } + if url: + record["download_url_host"] = urlparse(str(url)).netloc + if "code" in address_result: + record["code"] = address_result.get("code") + if status == "downloaded": + record["source_path"] = _source_path(chunk) + return record + + +def _source_path(chunk: dict[str, Any]) -> str: + time_begin = chunk.get("time_begin", chunk.get("requested_begin")) + time_end = chunk.get("time_end", chunk.get("requested_end")) + return ( + f"hik_cloud://{chunk['device_serial']}/ch{chunk['channel_no']}/" + f"{int(time_begin)}-{int(time_end)}" + ) + + +def _is_resumable_download(record: dict[str, Any]) -> bool: + path = record.get("path") + return ( + record.get("status") == "downloaded" + and isinstance(path, str) + and Path(path).exists() + ) + + +def _video_record_from_manifest(record: dict[str, Any]) -> dict[str, Any]: + return { + "source": "hik_cloud", + "path": record["path"], + "source_path": record.get("source_path") or _source_path(record), + "device_serial": record["device_serial"], + "channel_no": record["channel_no"], + "requested_begin": record["requested_begin"], + "requested_end": record["requested_end"], + "actual_begin": record.get("actual_begin"), + "actual_end": record.get("actual_end"), + "status": "downloaded", + "retry_count": record.get("retry_count", 0), + "last_error": record.get("last_error"), + } + + +def _upsert_manifest_record( + records: list[dict[str, Any]], + new_record: dict[str, Any], +) -> None: + new_key = _manifest_key(new_record) + for index, record in enumerate(records): + if _manifest_key(record) == new_key: + records[index] = new_record + return + records.append(new_record) + + +def _chunk_key(chunk: dict[str, Any]) -> tuple[Any, Any, Any, Any]: + return ( + chunk.get("device_serial"), + chunk.get("channel_no"), + chunk.get("time_begin"), + chunk.get("time_end"), + ) + + +def _manifest_key(record: dict[str, Any]) -> tuple[Any, Any, Any, Any]: + return ( + record.get("device_serial"), + record.get("channel_no"), + record.get("requested_begin"), + record.get("requested_end"), + ) + + +def _redaction_token(hik_config: dict[str, Any]) -> str: + token = hik_config.get("access_token") + if token: + return str(token) + token_env = hik_config.get("access_token_env") + if token_env: + return os.environ.get(str(token_env), "") + return "" diff --git a/video_ai_analysis_poc/manifest.py b/video_ai_analysis_poc/manifest.py new file mode 100644 index 0000000..49c85e0 --- /dev/null +++ b/video_ai_analysis_poc/manifest.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import json +from pathlib import Path +from typing import Any, Iterable + + +def write_manifest(path: str | Path, records: Iterable[dict[str, Any]]) -> None: + manifest_path = Path(path).expanduser().resolve(strict=False) + manifest_path.parent.mkdir(parents=True, exist_ok=True) + with manifest_path.open("w", encoding="utf-8") as handle: + for record in records: + normalized = _normalize_record(record) + handle.write( + json.dumps(normalized, ensure_ascii=False, sort_keys=True) + "\n" + ) + + +def read_jsonl(path: str | Path) -> list[dict[str, Any]]: + jsonl_path = Path(path).expanduser().resolve(strict=False) + if not jsonl_path.exists(): + return [] + records = [] + for line in jsonl_path.read_text(encoding="utf-8").splitlines(): + if line.strip(): + records.append(json.loads(line)) + return records + + +def _normalize_record(record: dict[str, Any]) -> dict[str, Any]: + normalized = dict(record) + normalized.setdefault("status", "pending") + normalized.setdefault("retry_count", 0) + normalized.setdefault("last_error", None) + return normalized diff --git a/video_ai_analysis_poc/paths.py b/video_ai_analysis_poc/paths.py new file mode 100644 index 0000000..6574ef3 --- /dev/null +++ b/video_ai_analysis_poc/paths.py @@ -0,0 +1,71 @@ +from __future__ import annotations + +import hashlib +from pathlib import Path + + +FORBIDDEN_REFERENCE_ROOT = Path("/Users/yoilun/AI-train/zhengxin-vlm-0413") + + +def resolve_path(path: str | Path, *, base_dir: Path | None = None) -> Path: + candidate = Path(path).expanduser() + if not candidate.is_absolute() and base_dir is not None: + candidate = base_dir / candidate + return candidate.resolve(strict=False) + + +def _is_relative_to(path: Path, parent: Path) -> bool: + try: + path.relative_to(parent) + return True + except ValueError: + return False + + +def validate_output_dir( + input_dir: str | Path, + output_dir: str | Path, + *, + forbidden_root: Path = FORBIDDEN_REFERENCE_ROOT, +) -> Path: + resolved_input = resolve_path(input_dir) + resolved_output = resolve_path(output_dir) + resolved_forbidden = resolve_path(forbidden_root) + + if resolved_output == resolved_input: + raise ValueError("output dir must not equal input dir") + if _is_relative_to(resolved_output, resolved_forbidden): + raise ValueError( + f"output dir must not be inside forbidden reference dir: {resolved_forbidden}" + ) + return resolved_output + + +def stable_video_id(path: str | Path) -> str: + resolved = str(resolve_path(path)) + digest = hashlib.sha1(resolved.encode("utf-8")).hexdigest()[:16] + return f"video-{digest}" + + +def hik_cloud_download_path( + output_dir: str | Path, + device_serial: str, + channel_no: int | str, + time_begin: int, + time_end: int, +) -> Path: + safe_device = _safe_path_component(device_serial) + safe_channel = _safe_path_component(str(channel_no)) + filename = f"{safe_device}_ch{safe_channel}_{int(time_begin)}_{int(time_end)}.mp4" + return ( + resolve_path(output_dir) + / "downloads" + / "hik_cloud" + / safe_device + / f"ch{safe_channel}" + / filename + ) + + +def _safe_path_component(value: str) -> str: + return "".join(char if char.isalnum() or char in "._-" else "_" for char in value) diff --git a/video_ai_analysis_poc/probe.py b/video_ai_analysis_poc/probe.py new file mode 100644 index 0000000..04dea00 --- /dev/null +++ b/video_ai_analysis_poc/probe.py @@ -0,0 +1,99 @@ +from __future__ import annotations + +import json +import subprocess +from pathlib import Path +from typing import Any + + +def probe_video(path: str | Path, *, timeout_seconds: int = 30) -> dict[str, Any]: + video_path = Path(path).expanduser().resolve(strict=False) + base_record: dict[str, Any] = { + "path": str(video_path), + "status": "probe_failed", + "retry_count": 0, + "last_error": None, + } + command = [ + "ffprobe", + "-v", + "error", + "-print_format", + "json", + "-show_format", + "-show_streams", + str(video_path), + ] + + try: + completed = subprocess.run( + command, + capture_output=True, + text=True, + check=True, + timeout=timeout_seconds, + ) + payload = json.loads(completed.stdout or "{}") + video_stream = _first_video_stream(payload) + format_info = payload.get("format", {}) + return { + **base_record, + "status": "probed", + "duration_seconds": _optional_float(format_info.get("duration")), + "codec_name": video_stream.get("codec_name"), + "width": _optional_int(video_stream.get("width")), + "height": _optional_int(video_stream.get("height")), + "fps": _parse_frame_rate( + video_stream.get("avg_frame_rate") or video_stream.get("r_frame_rate") + ), + "format_name": format_info.get("format_name"), + "start_time": _optional_float(format_info.get("start_time")), + } + except subprocess.TimeoutExpired as exc: + base_record["last_error"] = f"ffprobe timed out after {timeout_seconds}s" + if exc.stderr: + base_record["last_error"] += f": {exc.stderr}" + return base_record + except subprocess.CalledProcessError as exc: + base_record["last_error"] = _error_text(exc.stderr or exc.stdout or str(exc)) + return base_record + except (json.JSONDecodeError, ValueError) as exc: + base_record["last_error"] = f"ffprobe parse failed: {exc}" + return base_record + + +def _first_video_stream(payload: dict[str, Any]) -> dict[str, Any]: + for stream in payload.get("streams", []): + if stream.get("codec_type") == "video": + return stream + raise ValueError("ffprobe output did not contain a video stream") + + +def _parse_frame_rate(value: str | None) -> float | None: + if not value or value == "0/0": + return None + if "/" in value: + numerator, denominator = value.split("/", 1) + denominator_value = float(denominator) + if denominator_value == 0: + return None + return float(numerator) / denominator_value + return float(value) + + +def _optional_float(value: Any) -> float | None: + if value is None or value == "": + return None + return float(value) + + +def _optional_int(value: Any) -> int | None: + if value is None or value == "": + return None + return int(value) + + +def _error_text(value: Any) -> str: + if isinstance(value, bytes): + return value.decode("utf-8", errors="replace").strip() + return str(value).strip() diff --git a/video_ai_analysis_poc/result_parser.py b/video_ai_analysis_poc/result_parser.py new file mode 100644 index 0000000..e16827b --- /dev/null +++ b/video_ai_analysis_poc/result_parser.py @@ -0,0 +1,138 @@ +from __future__ import annotations + +import json +from typing import Any + + +def extract_json_payload(raw_response: str) -> dict[str, Any]: + text = raw_response.strip() + if not text: + raise ValueError("JSON payload is empty") + + try: + payload = json.loads(text) + if isinstance(payload, dict): + return payload + except json.JSONDecodeError: + pass + + decoder = json.JSONDecoder() + for index, char in enumerate(text): + if char != "{": + continue + try: + payload, _ = decoder.raw_decode(text[index:]) + except json.JSONDecodeError: + continue + if isinstance(payload, dict): + return payload + raise ValueError("JSON object not found in model response") + + +def build_clip_result( + raw_response: str, + clip_record: dict[str, Any], + video_record: dict[str, Any] | None, + config: dict[str, Any], + *, + processing: dict[str, Any] | None = None, + status: str | None = None, + error: str | None = None, +) -> dict[str, Any]: + processing_record = dict(processing or {}) + if status is not None: + payload: dict[str, Any] = {} + result_status = status + result_error = error + else: + try: + payload = extract_json_payload(raw_response) + result_status = "ok" + result_error = None + except ValueError as exc: + payload = {} + result_status = "parse_failed" + result_error = str(exc) + + timeline = _timeline(clip_record, config, payload) + return { + "schema_version": config.get("schema", {}).get("version", "local-batch-v1"), + "video_id": str(clip_record.get("video_id")), + "video_path": _video_path(video_record), + "clip_id": str(clip_record.get("clip_id")), + "status": result_status, + "monitoring_timeline": timeline, + "events": _events(payload, clip_record) if result_status == "ok" else [], + "raw_response": raw_response, + "processing": processing_record, + "error": result_error, + } + + +def _timeline( + clip_record: dict[str, Any], + config: dict[str, Any], + payload: dict[str, Any], +) -> dict[str, Any]: + return { + "timezone": config.get("runtime", {}).get("timezone", "Asia/Shanghai"), + "video_start_time": clip_record.get("video_start_time"), + "clip_start_seconds": clip_record.get("clip_start_seconds"), + "clip_end_seconds": clip_record.get("clip_end_seconds"), + "clip_start_timecode": clip_record.get("clip_start_timecode"), + "clip_end_timecode": clip_record.get("clip_end_timecode"), + "clip_start_beijing_time": clip_record.get("clip_start_beijing_time"), + "clip_end_beijing_time": clip_record.get("clip_end_beijing_time"), + "frame_times": clip_record.get("frame_times", []), + "screen_time": str( + payload.get("screen_time") or payload.get("画面时间") or payload.get("时间") or "" + ), + } + + +def _events( + payload: dict[str, Any], + clip_record: dict[str, Any], +) -> list[dict[str, Any]]: + raw_events = payload.get("events") or [] + if not isinstance(raw_events, list): + return [] + return [ + _event(event, clip_record) + for event in raw_events + if isinstance(event, dict) + ] + + +def _event( + event: dict[str, Any], + clip_record: dict[str, Any], +) -> dict[str, Any]: + normalized = dict(event) + normalized.setdefault("event_type", "unknown") + normalized.setdefault("start_time", None) + normalized.setdefault("end_time", None) + normalized.setdefault("start_offset_seconds", clip_record.get("clip_start_seconds")) + normalized.setdefault("end_offset_seconds", clip_record.get("clip_end_seconds")) + normalized.setdefault("confidence", None) + normalized.setdefault("severity", None) + normalized.setdefault("attributes", {}) + normalized.setdefault( + "evidence", + { + "clip_id": clip_record.get("clip_id"), + "frame_paths": [ + frame.get("frame_path") + for frame in clip_record.get("frame_times", []) + if frame.get("frame_path") + ], + }, + ) + return normalized + + +def _video_path(video_record: dict[str, Any] | None) -> str | None: + if not video_record: + return None + value = video_record.get("path") or video_record.get("source_path") + return str(value) if value is not None else None diff --git a/video_ai_analysis_poc/timeline.py b/video_ai_analysis_poc/timeline.py new file mode 100644 index 0000000..50d03f8 --- /dev/null +++ b/video_ai_analysis_poc/timeline.py @@ -0,0 +1,67 @@ +from __future__ import annotations + +from datetime import datetime, timedelta, timezone +from typing import Any +from zoneinfo import ZoneInfo, ZoneInfoNotFoundError + + +TIME_FORMAT = "%Y-%m-%d %H:%M:%S" +DEFAULT_TIMEZONE = "Asia/Shanghai" + + +def format_beijing_time( + epoch_seconds: float | int | str | None, + *, + offset_seconds: float | int = 0, + timezone_name: str = DEFAULT_TIMEZONE, +) -> str | None: + epoch = _optional_float(epoch_seconds) + if epoch is None: + return None + zone = _zone(timezone_name) + timestamp = epoch + float(offset_seconds) + return datetime.fromtimestamp(timestamp, tz=timezone.utc).astimezone(zone).strftime( + TIME_FORMAT + ) + + +def derive_time_from_reference( + reference_time: str | None, + *, + reference_offset_seconds: float | int | None, + target_offset_seconds: float | int | None, +) -> str | None: + if not reference_time: + return None + reference_offset = _optional_float(reference_offset_seconds) + target_offset = _optional_float(target_offset_seconds) + if reference_offset is None or target_offset is None: + return None + try: + reference = datetime.strptime(reference_time, TIME_FORMAT) + except ValueError: + return None + return (reference + timedelta(seconds=target_offset - reference_offset)).strftime( + TIME_FORMAT + ) + + +def timeline_start_epoch(record: dict[str, Any]) -> float | None: + for key in ("actual_begin", "requested_begin"): + value = _optional_float(record.get(key)) + if value is not None: + return value + return None + + +def _zone(timezone_name: str) -> ZoneInfo: + try: + return ZoneInfo(timezone_name) + except ZoneInfoNotFoundError: + return ZoneInfo(DEFAULT_TIMEZONE) + + +def _optional_float(value: Any) -> float | None: + if value is None or value == "": + return None + return float(value) diff --git a/video_ai_analysis_poc/vlm_client.py b/video_ai_analysis_poc/vlm_client.py new file mode 100644 index 0000000..877781c --- /dev/null +++ b/video_ai_analysis_poc/vlm_client.py @@ -0,0 +1,134 @@ +from __future__ import annotations + +import base64 +import json +import time +import urllib.request +from pathlib import Path +from typing import Any, Callable + + +HttpPost = Callable[[str, dict[str, Any], int], dict[str, Any]] + + +def infer_clip( + clip_record: dict[str, Any], + output_dir: str | Path, + vlm_config: dict[str, Any], + prompt_config: dict[str, Any], + *, + http_post: HttpPost | None = None, +) -> dict[str, Any]: + start = time.monotonic() + client = http_post or _post_json + url = build_chat_url(vlm_config) + payload = build_payload(clip_record, output_dir, vlm_config, prompt_config) + response = client(url, payload, int(vlm_config.get("timeout_seconds", 120))) + latency_ms = int((time.monotonic() - start) * 1000) + return { + "raw_response": _extract_message_content(response.get("body")), + "http_status": response.get("status"), + "latency_ms": latency_ms, + } + + +def build_chat_url(vlm_config: dict[str, Any]) -> str: + return ( + str(vlm_config["api_base_url"]).rstrip("/") + + str(vlm_config["chat_completions_path"]) + ) + + +def build_payload( + clip_record: dict[str, Any], + output_dir: str | Path, + vlm_config: dict[str, Any], + prompt_config: dict[str, Any], +) -> dict[str, Any]: + content: list[dict[str, Any]] = [ + {"type": "text", "text": str(prompt_config.get("user", ""))} + ] + for frame in clip_record.get("frame_times", []): + frame_path = frame.get("frame_path") + if not frame_path: + continue + content.append( + { + "type": "image_url", + "image_url": { + "url": _image_url( + frame_path, + output_dir, + str(vlm_config.get("image_transport", "data_uri")), + ) + }, + } + ) + + return { + "model": vlm_config.get("model"), + "messages": [ + {"role": "system", "content": str(prompt_config.get("system", ""))}, + {"role": "user", "content": content}, + ], + "temperature": vlm_config.get("temperature", 0), + "max_tokens": vlm_config.get("max_tokens", 512), + } + + +def _image_url( + frame_path: str | Path, + output_dir: str | Path, + image_transport: str, +) -> str: + if image_transport != "data_uri": + return str(frame_path) + path = Path(frame_path).expanduser() + if not path.is_absolute(): + path = Path(output_dir).expanduser() / path + data = base64.b64encode(path.read_bytes()).decode("ascii") + return f"data:{_mime_type(path)};base64,{data}" + + +def _mime_type(path: Path) -> str: + suffix = path.suffix.lower() + if suffix in {".jpg", ".jpeg"}: + return "image/jpeg" + if suffix == ".png": + return "image/png" + if suffix == ".webp": + return "image/webp" + return "application/octet-stream" + + +def _post_json( + url: str, + payload: dict[str, Any], + timeout_seconds: int, +) -> dict[str, Any]: + body = json.dumps(payload).encode("utf-8") + request = urllib.request.Request( + url, + data=body, + headers={"Content-Type": "application/json"}, + method="POST", + ) + with urllib.request.urlopen(request, timeout=timeout_seconds) as response: + response_body = response.read().decode("utf-8") + return { + "status": response.status, + "body": json.loads(response_body) if response_body else {}, + } + + +def _extract_message_content(body: Any) -> str: + if not isinstance(body, dict): + return "" + choices = body.get("choices") + if not choices: + return "" + message = choices[0].get("message", {}) if isinstance(choices[0], dict) else {} + content = message.get("content", "") + if isinstance(content, str): + return content + return json.dumps(content, ensure_ascii=False) diff --git a/video_ai_analysis_system_plan.md b/video_ai_analysis_system_plan.md new file mode 100644 index 0000000..a92464a --- /dev/null +++ b/video_ai_analysis_system_plan.md @@ -0,0 +1,1193 @@ +# 门店视频 AI 分析系统 PoC 实施方案 + +生成日期:2026-06-15 + +## 1. 系统架构 + +### 1.1 整体 Pipeline + +```text +[门店/摄像头配置] + | + v +[海康云眸接入层] + - 获取 access_token + - 查询云录像回放 URL / RTSP / HLS / MP4 + - 按 15-60 分钟切片拉取 + | + v +[本地视频缓存层: SSD] + - raw_segments/ + - segment_manifest.sqlite + - 记录下载、抽帧、推理状态 + | + v +[FFmpeg + NVDEC 抽帧层] + - GPU 硬解码 H.264/H.265 + - 1 FPS 抽帧 + - 输出带时间戳的 JPEG 帧 + | + v +[Clip 构建层] + - 10-20 秒窗口 + - 每个 clip 8-16 帧 + - 生成 clip manifest + | + v +[4B LoRA 模型推理层] + - FP16 + - batch size 1-4 + - clip 级推理 + | + v +[结果标准化层] + - clip_result.jsonl + - schema 校验 + - JSON 解析失败重试 + | + v +[门店级聚合层] + - 事件合并 + - 时间聚合 + - 输出 store_result.json +``` + +### 1.2 数据流向 + +系统按门店、摄像头、日期组织任务。 + +一个最小任务单元建议定义为: + +```text +store_id + camera_id + business_date +``` + +单路 24 小时视频不要一次性处理,而是拆成多个 segment: + +```text +store_001 / cam_01 / 2026-06-14 + -> 24 个 1 小时 segment + -> 每个 segment 独立拉取、解码、抽帧 + -> 所有帧按时间顺序组成 clip + -> clip 级模型推理 + -> 汇总为门店级 JSON +``` + +核心原则: + +- 视频接入和模型推理解耦。 +- 原始视频、抽帧结果、推理结果都可断点续跑。 +- 模型只对 clip 推理,不逐帧调用 LLM。 +- PoC 阶段优先可观测、可复跑,不追求极致流水线性能。 + +## 2. 模块拆解 + +### 2.1 视频接入层 + +#### 目标 + +从海康云眸获取指定门店、指定摄像头、指定时间范围内的 24 小时录像。 + +#### 推荐接入方式 + +优先级如下: + +```text +1. 云录像文件下载 URL / MP4 URL +2. HLS 回放 URL +3. RTSP 回放 URL +4. 直播 RTSP 本地录制 +``` + +PoC 推荐优先使用云录像回放或可下载视频文件。直播 RTSP 只能从当前时间开始录制,不适合补历史 24 小时数据。 + +#### 鉴权假设 + +海康云眸常见接入流程可抽象为: + +```text +app_key / app_secret + | + v +access_token + | + v +camera_id + begin_time + end_time + | + v +playback_url +``` + +系统应把 token 和 URL 视为有有效期的临时凭证。 + +建议保存: + +```text +camera_id +segment_start +segment_end +playback_url_created_at +playback_url_expire_at +fetch_status +retry_count +last_error +``` + +#### 24 小时录像拉取策略 + +不要一次请求 24 小时录像。 + +推荐拆分: + +```text +默认:24 个 1 小时 segment +网络不稳定时:48 个 30 分钟 segment +URL 过期较快时:96 个 15 分钟 segment +``` + +每个 segment 独立处理: + +```text +pending -> fetching -> fetched -> sampling -> sampled -> inferencing -> inferred -> aggregated +``` + +### 2.2 视频处理层 + +#### FFmpeg + NVDEC 硬解码 + +Ubuntu 24 上需要确认: + +```bash +ffmpeg -hwaccels +ffmpeg -decoders | grep cuvid +``` + +H.264 视频示例: + +```bash +ffmpeg \ + -hide_banner -nostdin -y \ + -rtsp_transport tcp \ + -hwaccel cuda \ + -c:v h264_cuvid \ + -i "$INPUT" \ + -vf "fps=1,scale=640:-2" \ + -q:v 4 \ + "$FRAME_DIR/%06d.jpg" +``` + +H.265 视频示例: + +```bash +ffmpeg \ + -hide_banner -nostdin -y \ + -rtsp_transport tcp \ + -hwaccel cuda \ + -c:v hevc_cuvid \ + -i "$INPUT" \ + -vf "fps=1,scale=640:-2" \ + -q:v 4 \ + "$FRAME_DIR/%06d.jpg" +``` + +如果输入是本地 MP4 文件,可以去掉 `-rtsp_transport tcp`。 + +#### 1 FPS 抽帧策略 + +24 小时视频按 1 FPS 抽帧: + +```text +1 小时:3600 张帧 +24 小时:86400 张帧 +2 路摄像头:172800 张帧 +``` + +PoC 阶段建议输出 JPEG: + +```text +质量:-q:v 4 +分辨率:scale=640:-2 或按模型输入要求调整 +命名:按 segment 内序号或绝对时间戳 +``` + +更推荐保存时间戳映射: + +```json +{"frame_path":"frames_1fps/000001.jpg","timestamp":"2026-06-14T00:00:01+08:00","segment_id":"seg_0000"} +``` + +#### 视频缓存策略 + +本地 SSD 目录建议: + +```text +/data/video-ai/ + stores/{store_id}/ + cameras/{camera_id}/ + {business_date}/ + raw_segments/ + 00_00_00__01_00_00.mp4 + frames_1fps/ + 00_00_00.jpg + 00_00_01.jpg + manifests/ + segments.sqlite + frames.jsonl + clips.jsonl + results/ + clip_results.jsonl + store_result.json +``` + +缓存策略: + +```text +raw video segment: + SSD 临时缓存,抽帧成功后可删除 + +1 FPS frames: + SSD 中间产物,推理完成后保留 1-7 天 + +clip tensor: + 不落盘,运行时构建 + +result JSONL: + 长期保留 +``` + +PoC 不建议使用全内存缓存。24 小时视频帧数较多,磁盘缓存更适合断点续跑和调试。 + +### 2.3 Clip 构建层 + +#### Clip 长度建议 + +PoC 默认: + +```text +clip_length = 10 秒 +stride = 10 秒 +frames_per_clip = 8 或 10 +``` + +对应规模: + +```text +1 小时视频: + 10 秒 clip -> 360 个 clip + 20 秒 clip -> 180 个 clip + +24 小时视频: + 10 秒 clip -> 8640 个 clip + 20 秒 clip -> 4320 个 clip +``` + +如果模型推理较慢,可以切换为: + +```text +clip_length = 20 秒 +stride = 20 秒 +frames_per_clip = 12 或 16 +``` + +#### 帧采样策略 + +不要用编码关键帧作为模型输入采样依据。关键帧是视频压缩概念,不一定对应行为变化。 + +推荐均匀采样: + +```text +10 秒 clip: + 1 FPS 得到 10 张帧 + 模型支持 10 帧时全部输入 + 模型只支持 8 帧时均匀采样 8 张 + +20 秒 clip: + 1 FPS 得到 20 张帧 + 均匀采样 12 或 16 张 +``` + +#### Clip Manifest + +建议为每个 clip 生成清单: + +```json +{ + "clip_id": "store_001_cam_01_20260614_123120", + "store_id": "store_001", + "camera_id": "cam_01", + "start_time": "2026-06-14T12:31:20+08:00", + "end_time": "2026-06-14T12:31:30+08:00", + "frame_paths": [ + "frames_1fps/12_31_20.jpg", + "frames_1fps/12_31_21.jpg" + ], + "status": "pending" +} +``` + +### 2.4 模型推理层 + +#### 3080 20GB 上运行 4B LoRA + +显存粗略估算: + +```text +4B FP16 base model: 约 8GB +LoRA adapter: 通常 < 1GB +vision encoder / projector / activation / KV cache: 4-8GB +运行余量: 3-6GB +``` + +推荐启动参数: + +```text +dtype: FP16 +batch_size: 1 +frames_per_clip: 8 +image_size: 336 或 448 +max_new_tokens: 256-512 +``` + +稳定后逐步尝试: + +```text +batch_size: 1 -> 2 -> 4 +frames_per_clip: 8 -> 12 -> 16 +image_size: 336 -> 448 -> 640 +``` + +出现 OOM 时按顺序回退: + +```text +1. batch_size 降低 +2. frames_per_clip 降低 +3. image_size 降低 +4. max_new_tokens 降低 +5. 必要时使用 8bit / 4bit 量化 +``` + +#### 推荐推理框架 + +PoC 首选: + +```text +PyTorch + Transformers + PEFT +``` + +原因: + +- 4B LoRA 加载简单。 +- 多图 / 视频帧输入适配成本低。 +- 更容易控制显存、batch、prompt、输出解析。 + +暂不首选: + +```text +vLLM +``` + +原因: + +- vLLM 更适合文本 LLM 高吞吐服务。 +- 多模态模型和 LoRA 的支持取决于具体模型。 +- 离线 PoC 的主要目标是链路跑通,不是低延迟在线服务。 + +#### 推理输入 + +每个 batch 包含多个 clip: + +```json +[ + { + "clip_id": "store_001_cam_01_20260614_123120", + "frames": ["...jpg", "...jpg"], + "prompt": "请分析该门店监控片段..." + } +] +``` + +Prompt 应约束输出为固定 JSON: + +```text +只输出 JSON。 +event_type 必须来自枚举。 +没有事件时输出 events: []。 +不要输出解释性文字。 +``` + +#### 推理输出 + +clip 级输出建议保存为 JSONL: + +```json +{ + "clip_id": "store_001_cam_01_20260614_123120", + "camera_id": "cam_01", + "start_time": "2026-06-14T12:31:20+08:00", + "end_time": "2026-06-14T12:31:30+08:00", + "status": "ok", + "events": [ + { + "event_type": "queue_detected", + "confidence": 0.86, + "severity": "medium", + "attributes": { + "estimated_people": 5, + "location": "checkout_area" + } + } + ], + "raw_response": null +} +``` + +JSON 解析失败时: + +```text +1. 用更严格 prompt 重试一次 +2. 仍失败则 status = parse_failed +3. 保存 raw_response +4. 聚合层跳过该 clip,但记录 failed_clip_count +``` + +### 2.5 输出结构设计 + +#### 门店级 JSON Schema + +```json +{ + "store_id": "store_001", + "business_date": "2026-06-14", + "timezone": "Asia/Shanghai", + "pipeline_version": "poc-v1", + "cameras": [ + { + "camera_id": "cam_01", + "video_start": "2026-06-14T00:00:00+08:00", + "video_end": "2026-06-15T00:00:00+08:00", + "processed_clip_count": 8640, + "failed_clip_count": 12 + } + ], + "summary": { + "total_events": 128, + "event_counts": { + "customer_enter": 53, + "staff_absent": 8, + "queue_detected": 12 + } + }, + "events": [ + { + "event_id": "evt_000001", + "camera_id": "cam_01", + "event_type": "queue_detected", + "start_time": "2026-06-14T12:31:20+08:00", + "end_time": "2026-06-14T12:32:10+08:00", + "duration_seconds": 50, + "confidence": 0.86, + "severity": "medium", + "attributes": { + "estimated_people": 5, + "location": "checkout_area" + }, + "evidence": { + "clip_ids": ["store_001_cam_01_20260614_123120"], + "frame_refs": ["frames_1fps/12_31_20.jpg"] + } + } + ], + "processing": { + "started_at": "2026-06-15T01:00:00+08:00", + "finished_at": "2026-06-15T05:40:00+08:00", + "status": "completed_with_warnings" + } +} +``` + +#### 事件级结构 + +事件字段建议固定: + +```text +event_id +store_id +camera_id +event_type +start_time +end_time +duration_seconds +confidence +severity +attributes +evidence +``` + +event_type 必须枚举化,例如: + +```text +customer_enter +customer_leave +queue_detected +staff_absent +staff_present +area_crowded +abnormal_behavior +unknown +``` + +PoC 阶段不要让模型自由发明事件类型。 + +#### 时间聚合规则 + +合并条件: + +```text +same camera_id +same event_type +相邻事件间隔 <= 30 秒 +``` + +合并方式: + +```text +start_time = 最早 start_time +end_time = 最晚 end_time +duration_seconds = end_time - start_time +confidence = max(confidence) 或按 clip 时长加权平均 +evidence.clip_ids = 合并所有 clip_id +``` + +## 3. 性能估算 + +### 3.1 数据规模 + +单路摄像头: + +```text +1 小时视频: + 1 FPS -> 3600 张帧 + 10 秒 clip -> 360 个 clip + 20 秒 clip -> 180 个 clip + +24 小时视频: + 1 FPS -> 86400 张帧 + 10 秒 clip -> 8640 个 clip + 20 秒 clip -> 4320 个 clip +``` + +双路摄像头: + +```text +24 小时: + 1 FPS -> 172800 张帧 + 10 秒 clip -> 17280 个 clip +``` + +### 3.2 单路 1 小时处理时间 + +如果视频已缓存到本地 SSD: + +```text +NVDEC 抽帧: + 3-10 分钟 + +模型推理: + 每 clip 0.5 秒 -> 约 3 分钟 + 每 clip 1.0 秒 -> 约 6 分钟 + 每 clip 2.0 秒 -> 约 12 分钟 + +聚合: + <1 分钟 + +合计: + 约 8-25 分钟 / 小时视频 +``` + +如果海康云眸回放只能按 1x 实时速度拉流: + +```text +1 小时录像最少需要 1 小时获取 +24 小时录像最少需要 24 小时获取 +``` + +这需要在 PoC 第一天优先验证。 + +### 3.3 单门店 24 小时处理时间 + +单路摄像头: + +```text +视频可快速下载: + 约 3-10 小时 + +视频只能 1x 回放: + 至少 24 小时 +``` + +双路摄像头: + +```text +视频可快速下载: + 约 6-20 小时 + +视频只能 1x 回放: + 至少 48 路小时 +``` + +### 3.4 GPU 瓶颈分析 + +大概率瓶颈: + +```text +1. 4B LoRA 多帧推理 +2. 云录像下载速度 +3. JPEG 编码和磁盘写入 +``` + +一般不是瓶颈: + +```text +NVDEC 解码能力 +门店级 JSON 聚合 +clip manifest 构建 +``` + +## 4. PoC 实施步骤 + +### Day 1:打通视频接入和 GPU 解码 + +任务: + +```text +1. 准备 Ubuntu 24 + NVIDIA driver + CUDA runtime。 +2. 确认 FFmpeg 支持 NVDEC。 +3. 从海康云眸获取 10 分钟历史回放 URL。 +4. 使用 FFmpeg 拉取或直接抽帧。 +5. 验证输出帧数量。 +``` + +命令: + +```bash +ffmpeg -hwaccels +ffmpeg -decoders | grep cuvid +``` + +验收标准: + +```text +10 分钟视频生成约 600 张 1 FPS 帧 +确认使用 h264_cuvid 或 hevc_cuvid +确认不是 CPU 解码 +``` + +### Day 2:实现 segment 化和本地缓存 + +任务: + +```text +1. 把 24 小时拆成 24 个 1 小时 segment。 +2. 每个 segment 独立请求 playback_url。 +3. 每个 segment 独立抽帧。 +4. 保存 segment 状态。 +5. 抽帧成功后生成 frames.jsonl。 +``` + +segment 状态: + +```text +pending +fetching +fetched +sampling +sampled +failed +``` + +验收标准: + +```text +能处理 1 小时录像 +中断后重跑不会重复处理已完成 segment +失败 segment 有 retry_count 和 last_error +``` + +### Day 3:实现 Clip 构建和模型推理 + +任务: + +```text +1. 读取 frames.jsonl。 +2. 按 10 秒窗口构建 clip。 +3. 每个 clip 均匀采样 8-10 帧。 +4. 加载 4B base model + LoRA adapter。 +5. 使用 FP16 推理。 +6. batch_size 从 1 开始。 +7. 输出 clip_results.jsonl。 +``` + +验收标准: + +```text +1 小时视频生成 360 个 10 秒 clip +模型完成 clip 级推理 +JSON 可解析率 > 95% +RTX 3080 20GB 不 OOM +``` + +### Day 4:实现聚合、容错和性能统计 + +任务: + +```text +1. 实现 clip_results.jsonl 到 store_result.json 的聚合。 +2. 增加 JSON schema 校验。 +3. 解析失败的 clip 重试一次。 +4. 统计下载、抽帧、推理耗时。 +5. 记录 GPU 峰值显存。 +``` + +需要记录的指标: + +```text +download_time_seconds +decode_time_seconds +frames_per_second +clips_per_second +gpu_memory_peak_mb +failed_segments +failed_clips +parse_failed_clips +``` + +验收标准: + +```text +1 小时完整链路跑通 +生成 store_result.json +失败任务可断点续跑 +``` + +### Day 5:跑完整 24 小时 + +任务: + +```text +1. 跑单路摄像头 24 小时。 +2. 跑双路摄像头 24 小时。 +3. 记录全链路耗时。 +4. 固化 PoC 参数。 +5. 输出失败清单和优化建议。 +``` + +最终参数需要确认: + +```text +clip_length +stride +frames_per_clip +batch_size +image_size +raw segment 是否保留 +frames 保留天数 +``` + +验收标准: + +```text +单门店 1-2 路摄像头 24 小时离线分析完成 +输出门店级 JSON +有可复跑的 segment 和 clip 状态 +``` + +## 5. 关键设计决策说明 + +### 5.1 先单机跑通 + +PoC 只做 1 家门店,单机单 GPU 足够验证链路。 + +不建议一开始引入: + +```text +Kafka +Spark +Kubernetes +复杂分布式任务系统 +``` + +PoC 阶段使用: + +```text +本地文件系统 +SQLite 或 JSONL manifest +单进程或少量 worker +``` + +### 5.2 使用磁盘帧缓存 + +原因: + +```text +1. 方便调试模型输入。 +2. 模型调参时不用重复拉视频。 +3. 海康 playback_url 过期后不影响后续实验。 +4. 支持断点续跑。 +``` + +后续链路稳定后,可以优化为: + +```text +FFmpeg pipe -> frame queue -> model worker +``` + +但 PoC 不优先做。 + +### 5.3 默认 10 秒 clip + +10 秒 clip 的优势: + +```text +语义粒度足够细 +事件定位较准确 +推理量可控 +方便聚合 +``` + +如果吞吐不够,切到 20 秒 clip: + +```text +clip 数量减少 50% +事件时间定位精度下降 +``` + +### 5.4 小 batch 推理 + +RTX 3080 20GB 显存有限。 + +建议从保守参数开始: + +```text +batch_size = 1 +frames_per_clip = 8 +image_size = 336 或 448 +``` + +稳定后再提高 batch。 + +### 5.5 结构化输出优先 + +模型输出必须被工程系统消费。 + +因此: + +```text +输出 JSON +event_type 枚举 +schema 校验 +失败重试 +保留 raw_response +``` + +不要依赖自然语言总结作为主输出。 + +## 6. 故障与容错设计 + +### 6.1 RTSP / 回放 URL 失败 + +处理方式: + +```text +1. 重新获取 playback_url。 +2. 使用 -rtsp_transport tcp。 +3. 将 1 小时 segment 拆成 30 或 15 分钟。 +4. 最多重试 3 次。 +5. 仍失败则标记 failed,不阻塞其他 segment。 +``` + +### 6.2 解码失败 + +处理方式: + +```text +1. 使用 ffprobe 获取 codec。 +2. H.264 使用 h264_cuvid。 +3. H.265 使用 hevc_cuvid。 +4. 失败后缩短 segment 重试。 +5. 仍失败则记录 ffmpeg stderr。 +``` + +由于项目约束要求必须 GPU 解码,不建议默认 fallback 到 CPU 解码。 + +### 6.3 模型 OOM + +处理顺序: + +```text +1. batch_size: 4 -> 2 -> 1 +2. frames_per_clip: 16 -> 12 -> 8 +3. image_size: 640 -> 448 -> 336 +4. max_new_tokens: 512 -> 256 +5. 必要时使用 8bit / 4bit 量化 +``` + +每次 OOM 后应: + +```text +torch.cuda.empty_cache() +记录失败 clip +用更小配置重试 +``` + +### 6.4 JSON 解析失败 + +处理方式: + +```text +1. 严格 prompt 重试一次。 +2. 仍失败则 status = parse_failed。 +3. 保存 raw_response。 +4. 聚合层跳过该 clip。 +5. 门店级结果记录 failed_clip_count。 +``` + +### 6.5 断点续跑 + +每层都要有 manifest: + +```text +segments.sqlite: + 记录每个视频段状态 + +frames.jsonl: + 记录每张帧和时间戳 + +clips.jsonl: + 记录每个 clip 和输入帧 + +clip_results.jsonl: + 记录每个 clip 的推理结果 +``` + +重跑逻辑: + +```text +已有 sampled segment 不重复抽帧 +已有 inferred clip 不重复推理 +只补 failed / missing / parse_failed +``` + +## 7. 可扩展性设计 + +### 7.1 从 1 家门店到 26 家门店 + +任务分片方式: + +```text +store_id + camera_id + business_date +``` + +26 家门店规模: + +```text +26 家 * 1-2 路摄像头 = 26-52 路摄像头 +``` + +如果每路 24 小时需要 3-10 GPU 小时: + +```text +每日全量处理需要 78-520 GPU 小时 +``` + +单张 RTX 3080 不适合长期处理 26 家全量 24 小时视频。 + +### 7.2 单机阶段 + +结构: + +```text +1 个 downloader +1 个 ffmpeg sampler +1 个 model worker +1 个 aggregator +``` + +建议: + +```text +下载和抽帧可以提前跑 +模型 worker 独占 GPU +不要多个模型进程抢同一张 3080 +``` + +### 7.3 单机多 GPU 阶段 + +结构: + +```text +1 个调度进程 +N 个 GPU worker +每张 GPU 一个模型实例 +``` + +任务分配: + +```text +按 camera-day 分配给不同 GPU +每个 GPU worker 独立读取 clip manifest +``` + +### 7.4 多机多 GPU 阶段 + +最小生产化结构: + +```text +Postgres: + 任务状态表 + +对象存储 / NAS: + 原始视频、帧、结果 + +多台 GPU 服务器: + 拉取任务 + 独立处理 + 写回状态 +``` + +暂不需要: + +```text +Kafka +Spark +复杂实时流处理 +``` + +## 8. 风险与解决方案 + +### 风险 1:海康云眸回放速度受限 + +影响: + +```text +如果只能 1x 回放,24 小时视频至少需要 24 小时获取。 +``` + +解决: + +```text +PoC 第一天验证是否支持快速下载历史录像。 +优先使用云录像文件下载 URL。 +如果只能 RTSP 回放,需要重新评估每日处理窗口。 +``` + +### 风险 2:RTX 3080 显存不足 + +影响: + +```text +4B LoRA + 多帧输入可能 OOM。 +``` + +解决: + +```text +batch_size 从 1 开始。 +frames_per_clip 从 8 开始。 +image_size 从 336 或 448 开始。 +必要时使用 8bit / 4bit 量化。 +``` + +### 风险 3:模型对门店事件识别不稳定 + +影响: + +```text +输出事件类型不一致,难以聚合。 +``` + +解决: + +```text +固定 event_type 枚举。 +固定 JSON schema。 +在 prompt 中要求没有事件时返回 events: []。 +保存证据帧用于人工复核。 +``` + +### 风险 4:抽帧结果和真实时间不对齐 + +影响: + +```text +事件时间戳错误。 +``` + +解决: + +```text +每个 segment 必须记录 segment_start。 +帧时间戳由 segment_start + frame_index 秒计算。 +如 FFmpeg 能输出 pts_time,则优先使用 pts_time。 +``` + +### 风险 5:磁盘占用增长过快 + +影响: + +```text +24 小时、多摄像头 JPEG 帧会占用大量 SSD。 +``` + +解决: + +```text +raw segment 抽帧成功后删除。 +frames 推理完成后保留 1-7 天。 +只长期保留结果 JSON 和事件证据帧。 +``` + +## 9. 推荐 PoC 默认参数 + +```text +segment_length: 1 hour +fallback_segment_length: 15 minutes +decode: NVDEC h264_cuvid / hevc_cuvid +frame_rate: 1 FPS +frame_format: JPEG +frame_width: 640 +clip_length: 10 seconds +clip_stride: 10 seconds +frames_per_clip: 8 +model_dtype: FP16 +batch_size: 1 +max_new_tokens: 256 +retry_count: 3 for segment +parse_retry_count: 1 for model output +``` + +## 10. 最小可行交付物 + +3-5 天 PoC 结束时应交付: + +```text +1. 能处理单路 24 小时视频的离线脚本或命令入口。 +2. 能处理 1 家门店 1-2 路摄像头。 +3. 使用 FFmpeg + NVDEC 完成 1 FPS 抽帧。 +4. 使用 4B LoRA 模型完成 clip 级推理。 +5. 输出 clip_results.jsonl。 +6. 输出 store_result.json。 +7. 支持 segment 和 clip 断点续跑。 +8. 有性能统计报告。 +9. 有失败 segment / failed clip 清单。 +``` + +不在 PoC 范围: + +```text +实时告警 +Web 管理后台 +复杂多租户权限 +分布式调度平台 +自动模型训练闭环 +``` + diff --git a/录像下载流程_1.pdf b/录像下载流程_1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f6f73afd7ba140d4a5f6b4e7378e83fd5c803071 GIT binary patch literal 477499 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

>0AOc_O+f=>NzW-PNC{x)n65@zW5; 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
SS`LdprcO{pe-XSr8uXP6 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 Tjvx5J^iu!|jY66{1>pK${^2P- literal 0 HcmV?d00001

38eVx!hN!-=9oRpM!om!OJrI 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 z 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%0DtRgW?cdl~XL_=XA;y#h&H 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