Files
yingshiyun/README.md
T
yuming b3608f534e feat: 新增视频分析流水线、Web界面、孤儿清理工具;修复健壮性问题
- 新增 analysis/ 模块:MOG2活动检测、YOLO人物跟踪、MediaPipe摔倒检测、Ollama活动打标、缩略图抽取
- 新增 webapp/:Flask事件浏览界面,按需HEVC→H264转码缓存
- 新增 analyze.py:7阶段状态机流水线(scan→backfill→motion→person→fall→activity→thumbnail)
- 新增 cleanup_orphans.py:清理文件已删除的数据库孤儿记录
- 修复:motion/person/activity三阶段加单视频异常兜底,避免批次中断
- 修复:ollama_client加健康检查和3次重试,num_ctx从8192降到2048
- 修复:transcode_cache加fcntl文件锁,防止并发转码同一视频
- 修复:SQLite开WAL模式+busy_timeout,支持读写并发
- 修复:sync.py ffmpeg路径改为shutil.which查找,删除automate.py死代码PYTHON
- 修复:thumbnail失败加3次重试上限,避免无限重试损坏文件
- 新增:requirements.lock锁定版本、README文档
- 更新:.gitignore排除.playwright-mcp、截图、备份文件
2026-09-18 15:52:49 +08:00

171 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 <repo> && 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` 清理多余文件。