Metadata-Version: 2.4
Name: flicker-detector-gpu
Version: 0.1.2
Summary: GPU flicker detection via PredNet SavedModel (dvdface/next-frame-predict): CLI, web server, HTTP client.
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: tensorflow<3,>=2.14
Requires-Dist: pillow>=9.0
Requires-Dist: huggingface_hub>=0.20
Requires-Dist: opencv-python-headless>=4.8
Requires-Dist: fastapi>=0.110
Requires-Dist: uvicorn[standard]>=0.27
Requires-Dist: python-multipart>=0.0.9
Requires-Dist: pydantic>=2.6
Requires-Dist: httpx>=0.27
Provides-Extra: dev
Requires-Dist: ruff>=0.4; extra == "dev"

# flicker-detector-gpu

安装后提供三个命令行入口（Windows 下为 `Scripts` 目录中的 **`gpu-flicker-detector.exe`**、**`gpu-flicker-detector-server.exe`**、**`gpu-flicker-detector-client.exe`**）：本地检测、启动带 Web 界面的服务、以及作为客户端调用已运行的服务。

```bash
pip install flicker-detector-gpu
```

---

## `gpu-flicker-detector`（本地检测）

在本地直接跑 PredNet 推理，将结果写入 **JSON 文件**。

### 常用参数

| 参数 | 说明 |
|------|------|
| `--type` | **必填**。`dir`：单层目录内图片（自然排序）；`video`：单个视频；`sequence`：多张图片，每个文件一次 `--input` |
| `--input` | **必填**，可重复。`dir`/`video` 各 1 个路径；`sequence` 至少 **4** 个图片路径（GPU 版 PredNet 滑动窗为 4 帧） |
| `--output` | **必填**。输出 JSON 路径（父目录不存在时会创建） |
| `--fps` | 仅视频：覆盖 FPS，`0` 表示从容器读取 |
| `--frame-interval-ms` | `dir` / `sequence`：大于 0 时，用 `帧索引 × 毫秒` 作为时间戳 |
| `--model-dir` | SavedModel 目录；省略时使用环境变量或自动下载（需网络时可配置 Hub 令牌等） |
| `--threshold` | 异常阈值，默认 `0.025`（与训练时多层预测误差加权损失同量纲，需按模型自行标定） |
| `--layer-loss-weights` | 逗号分隔浮点，须与模型层数一致；默认 `1,0.1,0.1,0.1` |
| `--write-pred-frames DIR` | 若指定，将每帧 PredNet 预测 RGB 存为 `DIR` 下 `pred_00000.png` 等 |

**支持的视频扩展名示例**：`.mp4`、`.webm`、`.mov`、`.mkv`、`.avi`、`.m4v`。

**最少帧数**：任意模式均需至少 **4** 帧，否则进程以非零退出并在 stderr 说明原因。

### 退出码

- **`0`**：成功写出 `--output`
- **`2`**：输入/模型/参数等错误（详情在 stderr）

### 输出 JSON（`--output`）

顶层字段：

| 字段 | 含义 |
|------|------|
| `version` | 结果格式版本号（整数） |
| `input_type` | `dir` \| `video` \| `sequence` |
| `findings` | 异常区段列表（见下） |
| `frame_scores` | 逐帧分数与阈值信息（见下） |
| `pred_frames` | 仅当使用 `--write-pred-frames` 时出现：预测图相对路径与帧索引、时间 |

**`findings[]` 每项**（合并后的连续异常段）：

- `flash_type`：固定为 PredNet 异常类型标识  
- `scene`：场景标签（当前为 `STABLE`）  
- `start_time_ms` / `end_time_ms`：区段起止时间（毫秒）  
- `during_time_ms`：持续时间  
- `video_start_time_ms` / `video_end_time_ms`：相对序列起点的时间  
- `start_frame` / `end_frame`：帧索引  
- `path_start` / `path_end`：起止帧对应的路径或标签  
- `score_peak`：该段内峰值分数  
- `metric`：分数名称（`prednet_total`，与训练 `val_loss` 量纲一致）

**`frame_scores`**：

- `values`：每帧一个浮点分数（与 `metric` 一致）  
- `metric`：`prednet_total`  
- `threshold`：使用的阈值  
- `max_value`：全序列最大分数（若无有效值则为 `null`）

---

## `gpu-flicker-detector-server`（HTTP 服务 + 界面）

启动 **FastAPI** 服务；若本机已安装 **Docker Compose v2** 且能找到项目内 compose 文件，**默认优先**用 Docker 拉起 GPU 镜像，否则在本机用 **Uvicorn** 直接跑 API。

### 参数

| 参数 | 说明 |
|------|------|
| `--host` | 监听地址；默认来自 `FLICKER_DETECTOR_BIND` / `FLASH_DETECTOR_BIND`，再否则 `127.0.0.1` |
| `--port` | 端口；默认来自 `FLICKER_DETECTOR_PORT` / `FLASH_DETECTOR_PORT`，再否则 **8765** |
| `--docker-build` | 仅在 Docker 模式下：启动前执行 `docker compose up --build` |

### 常用环境变量

| 变量 | 作用 |
|------|------|
| `FLICKER_DETECTOR_USE_DOCKER` | 设为 `0` / `false` / `no` / `off` 时强制本机 Uvicorn，不尝试 Docker |
| `FLICKER_DETECTOR_COMPOSE_DIR` | 含 `docker-compose.yml` 的目录（否则自动在包内 `deploy`、仓库根、`cwd` 等查找） |
| `FLICKER_DETECTOR_WEB_DATA` / `FLASH_DETECTOR_WEB_DATA` | 数据根目录（上传、SQLite 等）；默认当前工作目录下 `flicker_detector_web_data` |
| `FLICKER_DETECTOR_ARGV_JSON` | JSON 字符串数组，自定义检测子进程 argv（最高优先级） |
| `FLICKER_DETECTOR_EXE` | 指定检测可执行文件路径（不设则默认 `python -m flicker_detector_gpu.cli`） |
| `FLICKER_DETECTOR_RELOAD` | 设为 `1` 时仅在本机 Uvicorn 下开启代码热重载 |

启动成功后，在浏览器打开 **`http://<host>:<port>/`**（本机默认 `http://127.0.0.1:8765/`）。若已构建并打包前端静态资源，根路径会提供 SPA。

### Web 界面说明

顶部导航为 **「闪屏检测」** 品牌与两个入口：

| 路由 | 说明 |
|------|------|
| **`/` 工作台** | 创建检测任务：上传视频或图片（文件夹/多图），查看任务列表与状态 |
| **`/reports` 检测记录** | 历史任务与统计趋势等报表视图 |
| **`/job/:jobId`** | 单个任务的详情页（从列表或链接进入） |

界面通过同源的 **`/api/*`** 与后端通信；CLI 客户端则使用下文 **`gpu-flicker-detector-client`** 访问同一套 API。

---

## `gpu-flicker-detector-client`（调用远程服务）

向已运行的 `gpu-flicker-detector-server` **创建任务、轮询状态**，结束时将 **完整任务 JSON** 打印到标准输出或写入文件。

### 参数

| 参数 | 说明 |
|------|------|
| `--url` | 服务根地址，默认 `http://127.0.0.1:8765` |
| `--mode` | **必填**。`video`：1 个视频路径；`sequence`：至少 **4** 个图片路径；`folder`：1 个目录（递归收集图片，至少 4 张） |
| `--poll` | 轮询间隔（秒），默认 `0.5` |
| `--timeout` | 等待任务结束的最长时间（秒），默认 `7200` |
| `--http-timeout` | 单次 HTTP 超时（秒），默认 `60` |
| `--upload-timeout` | `POST /api/jobs` 超时（秒），默认 `3600` |
| `-o` / `--output` | 将最终 JSON 写入文件 |
| `-q` / `--quiet` | 减少控制台输出 |
| `--skip-health` | 跳过启动时的 `GET /api/health` |
| **位置参数 `paths`** | 由 `--mode` 决定数量与含义（见上） |

### 输出

- 默认（非 `-q`）：先打印 **`/api/health`** 的 JSON（除非 `--skip-health`），再打印 `job_id` 与轮询过程中的 `[status] stage` 行。  
- 任务结束后：打印 **完整任务对象 JSON**（与 `-o` 写入文件内容相同），字段含 `status`（如 `done` / `failed`）、`stage`、结果与错误信息等（与 Web 详情一致）。

### 退出码

| 码 | 含义 |
|----|------|
| `0` | 任务成功完成（`status == done`） |
| `1` | 任务结束但失败 |
| `2` | HTTP 错误或响应异常 |
| `3` | 命令行路径 / 模式校验失败 |
| `4` | 等待结果超时 |

---

更完整的部署、Docker、开发与模型说明见仓库根目录 **`README.md`**。
