# ezviz-sync — 萤石摄像头录像同步与智能分析 从萤石(EZVIZ)摄像头同步 SD 卡报警录像到本地,对录像做 AI 分析(人物检测、摔倒检测、活动语义打标),并提供 Web 界面浏览和回放。 目标设备:萤石 CB60,序列号 `BH5455783`。 ## 目录结构 ``` ezviz-sync/ ├── automate.py # 主力下载脚本:ADB 自动化模拟器内萤石 App 批量下载 ├── sync.py # [已废弃] 开放平台 API 下载方案,保留作备选 ├── probe.py # API 探测调试脚本 ├── analyze.py # 视频分析主入口(7 阶段流水线) ├── config.py # 萤石开放平台配置(密钥,已 gitignore) ├── config.example.py # 配置模板 ├── requirements.txt # 直接依赖 ├── requirements.lock # 锁定版本的完整依赖(pip freeze) ├── recordings/ # 下载的录像,按 设备号/日期/ 归档 ├── analysis.db # SQLite 元数据库(运行时生成) ├── thumbnails/ # 事件缩略图(运行时生成) ├── transcoded/ # Web 播放转码缓存(运行时生成) ├── analysis/ # 分析模块 │ ├── db.py # SQLite 建表与 CRUD │ ├── config.py # 分析参数配置(阈值、模型名、路径) │ ├── video_scanner.py # 扫描录像文件入库 + MD5 查重 │ ├── motion_filter.py # MOG2 背景建模检测活动窗口 │ ├── person_tracker.py # YOLO11 + ByteTrack 人物跟踪 │ ├── fall_detector.py # MediaPipe Pose 摔倒检测 │ ├── activity_tagger.py # Ollama VLM 活动语义打标 │ ├── thumbnail.py # 事件缩略图抽取 │ ├── timestamp_reader.py # OSD 时间戳水印识别(模板匹配) │ ├── backfill_start_time.py # 精确时间戳回填 │ ├── dedup_finder.py # 重复视频检测(生成报告) │ ├── dedup_cleanup.py # 重复视频清理(默认 dry-run) │ ├── cleanup_orphans.py # 清理文件已删除的数据库孤儿记录 │ ├── hashing.py # MD5 计算 │ ├── ollama_client.py # Ollama VLM 调用封装 │ ├── frida_spawn.py # Frida SSL pinning 绕过(抓包用) │ ├── unpin.js # Frida 脱壳脚本 │ ├── models/ # MediaPipe pose 模型权重 │ └── templates/ # OSD 数字识别模板库 ├── webapp/ # Flask Web 界面 │ ├── app.py # 路由:事件列表、统计、视频流、缩略图 │ ├── transcode_cache.py # 按需转码缓存(HEVC→H264) │ ├── templates/index.html │ └── static/ # app.js, style.css └── yolo11n.pt # YOLO11 目标检测权重(首次运行自动下载) ``` ## 环境依赖 | 工具 | 用途 | 安装 | |---|---|---| | Python 3.12 | 运行环境 | `pyenv install 3.12` 或系统包管理器 | | ffmpeg / ffprobe | 视频处理、抽帧、转码 | `brew install ffmpeg` | | ImageMagick (`magick`) | 截图像素分析(automate.py 蓝勾/行检测) | `brew install imagemagick` | | Android SDK + ADB | 模拟器控制 | `brew install --cask android-platform-tools` | | Android 模拟器 | 运行萤石 App | Android Studio AVD 或第三方模拟器 | | Ollama | 本地 VLM 推理(活动打标) | `brew install ollama && ollama pull qwen2.5vl:7b` | ## 安装 ```bash # 1. 克隆项目 git clone && cd ezviz-sync # 2. 创建虚拟环境 python3.12 -m venv .venv source .venv/bin/activate # 3. 安装依赖(用 lock 文件保证版本一致) pip install -r requirements.lock # 4. 配置萤石开放平台 cp config.example.py config.py # 编辑 config.py 填入 AppKey / AppSecret / 设备序列号 / 验证码 # 5. 初始化数据库(首次运行 analyze.py 自动建表) python analyze.py --only-stage scan ``` ## 使用方法 ### 1. 下载录像 ```bash # 下载昨天的录像(默认) python automate.py # 下载最近 7 天的录像 python automate.py 7 ``` 下载流程:启动模拟器内萤石 App → 导航到指定日期 → 批量下载 → adb pull 到本地 `recordings/设备号/日期/`。 ### 2. 分析录像 ```bash # 跑完整流水线(scan → backfill → motion → person → fall → activity → thumbnail) python analyze.py # 只跑某个阶段 python analyze.py --only-stage motion # 小批量测试 python analyze.py --only-stage person --limit 10 # 强制重跑某个阶段(回退已完成的视频状态) python analyze.py --only-stage activity --force ``` 流水线状态机:`pending → motion_done → person_done → fall_done → activity_done`,每个阶段只处理上一阶段完成的视频,重复运行幂等。 ### 3. 启动 Web 界面 ```bash python -m webapp.app # 打开 http://127.0.0.1:5050 ``` 功能:按事件类型/日期筛选、点击事件跳转播放对应时间点、转码缓存管理。 ### 4. 维护工具 ```bash # 检测重复视频(只生成报告,不删除) python -m analysis.dedup_finder # 清理重复视频(先预览,确认后加 --execute) python -m analysis.dedup_cleanup python -m analysis.dedup_cleanup --execute # 清理数据库中文件已不存在的孤儿记录 python -m analysis.cleanup_orphans # dry-run python -m analysis.cleanup_orphans --execute ``` ## 分析流水线详解 | 阶段 | 输入状态 | 输出状态 | 方法 | 说明 | |---|---|---|---|---| | scan | — | pending/corrupt/duplicate | ffprobe + MD5 | 扫描 recordings/ 入库,按 MD5 标记重复 | | backfill | pending | pending(不变) | 模板匹配 OCR | 读取画面 OSD 时间戳,回填精确 start_time | | motion | pending | motion_done | MOG2 背景建模 | 检测有活动的时间窗口,空场景跳过后续重模型 | | person | motion_done | person_done | YOLO11n + ByteTrack | 只在活动窗口内跑人物检测跟踪 | | fall | person_done | fall_done | MediaPipe Pose | 只在有人的时间段跑姿态估计,规则引擎判摔倒 | | activity | fall_done | activity_done | Ollama Qwen2.5-VL | 活动窗口抽帧,VLM 分类为 走动/进食/坐下/站立/离开/其他 | | thumbnail | — | — | ffmpeg 抽帧 | 给每条事件生成缩略图 | ## 关键设计决策 - **下载用 ADB 自动化而非开放平台 API**:开放平台 API 的 FLV 回放流把 24 小时录像拼接成一个文件,丢失了分段信息和精确时间戳;ADB 方案直接下载 App 内的分段报警录像,文件名含时间戳。 - **分析流水线分层过滤**:先用轻量 MOG2 预筛活动窗口,再在窗口内跑 YOLO,有人的时间段才跑姿态估计和 VLM,避免对空场景浪费算力。 - **摔倒检测用规则引擎而非 VLM**:安全信号需要可解释、可调阈值、宁可多报不漏报,MediaPipe 关键点 + "直立骤变横躺并持续"规则比模型黑盒更可靠。 - **Web 播放按需转码**:源文件是 HEVC 编码且 mp4 容器 sample entry 标签缺失,浏览器无法直接播放;第一次播放时用 VideoToolbox 硬件转码为 H264 并缓存,之后复用。 ## 常见问题 **Q: automate.py 报错 `magick: command not found`** A: 没装 ImageMagick。`brew install imagemagick`。automate.py 的蓝勾检测和卡片行定位都依赖 `magick` 命令。 **Q: analyze.py 跑 activity 阶段很慢/卡住** A: 检查 Ollama 是否在运行:`ollama ps`。模型 `qwen2.5vl:7b` 需要约 6GB 显存/内存。 **Q: Web 端视频播放不了** A: 首次播放会触发转码(HEVC→H264),大文件可能需要几十秒。转码缓存在 `transcoded/`,可在 Web 界面清空。 **Q: 数据库里有很多 duplicate 记录** A: automate.py 早期版本有重复下载问题(已修复),同一段录像被下载成多份。scan 阶段按 MD5 自动标记 duplicate 并跳过分析。可用 `dedup_cleanup.py` 清理多余文件。