Files
yovision/docs/raw/02-需求分析.md
T

801 lines
46 KiB
Markdown
Raw Normal View History

# 🔍 YoVision 智能视频事件平台 — 需求分析文档
> 版本 v0.3 · 2026-08-03
> 上游:《01-需求收集》 · 下游:《03-通用场景应用方案》
> 本文档负责把原始需求**分层、规格化、发现矛盾、推导出架构性约束**,不负责技术选型细节
---
# 1. 分析结论摘要
先给结论,后面是推导过程。
| # | 结论 | 依据 |
| --- | --- | --- |
| C1 | 系统必须切成「**通用底座 + 场景包**」两层,场景包是配置与插件,不是分支代码 | 三个场景 60% 需求重合,但检测能力与升级策略完全不同(§3) |
| C2 | 事件(Event)与预警(Alert)是**两个独立实体**,不可合并 | 一次事件可产生多次预警、多条投递;一次预警可聚合多个事件(§5.2) |
| C3 | 「指定人群」的判定分四类并在**能力层解耦**;**ReID 为默认手段,人脸识别为按租户授权开启的可插拔能力** | 合规风险与技术依赖不同;多数"同一性"需求不需要知道"是谁"(§4.3、§4.4) |
| C4 | 规则引擎必须放在**推理之后、告警之前**的独立环节,不能编进模型插件 | 规则变更频率远高于模型,且需支持热更新与多级覆盖(§6) |
| C5 | 接入层必须**控制面/数据面分离**,且数据面为边缘主动推流 | 家庭场景摄像头在 NAT 后,中心不可达(§7.1) |
| C6 | 系统状态一致性靠**水平触发的对账器**,不靠事件驱动 | 三个下游系统(媒体路由、推理、存储)无分布式事务(§7.3) |
| C7 | 默认 16 路可用单媒体/推理分片起步;扩展到 128 路必须**横向分片**,触发式推理用于降低平均算力 | GPU 数量不能由路数直接推导,须按真实模型、分辨率、FPS、batch 与硬件压测(§8.1–8.2) |
| C8 | 业务预警系统的核心是 **ack 与升级**,不是"发消息" | 没有 ack 环节的告警系统等于没有(§9.2) |
| C9 | **误报反馈闭环是产品飞轮,必须在 M3 第一天就有**,不是后期优化项 | 真实误报案例是最稀缺的训练数据(§10) |
---
# 2. 需求分层
原始需求(《01》共 8 个场景需求组 + 36 条通用需求)按变化频率重新分层。**同一层内的东西一起变,不同层之间靠契约解耦。**
```mermaid
flowchart TD
L5["L5 场景包<br/>规则模板 · 升级策略 · 话术 · 报表口径"]
L4["L4 业务编排<br/>事件生成 · 去重防抖 · 预警状态机 · 处置流"]
L3["L3 能力层<br/>检测 · 姿态 · 跟踪 · ReID · 属性 · (人脸)"]
L2["L2 流水线层<br/>解码 · 抽帧 · 调度 · 故障隔离 · 触发式唤醒"]
L1["L1 接入层<br/>设备台账 · ONVIF · 媒体路由 · 隧道 · 对账"]
L0["L0 基础设施<br/>多租户 · RBAC · 存储 · 可观测 · 审计"]
L5 --> L4 --> L3 --> L2 --> L1 --> L0
```
| 层 | 变化频率 | 谁在改 | 改动方式 |
| --- | --- | --- | --- |
| L5 场景包 | 每周 | 实施/产品 | 配置,不发版 |
| L4 业务编排 | 每月 | 后端 | 发版 |
| L3 能力层 | 每季度 | 算法 | 模型热替换 |
| L2 流水线 | 半年 | 平台 | 发版 |
| L1 接入 | 半年 | 平台 | 发版 |
| L0 基础设施 | 年 | 平台 | 发版 |
> **这张表是本文档最重要的产出。** 如果一个需求变更需要同时改 L5 和 L1,说明分层错了。典型反例:把"上课时段"这个校历概念写进 mediamtx 的 path 配置。
---
# 3. 场景共性与差异分析
## 3.1 共性度量
把《01》§4.2 的场景需求逐条拆成原子能力,统计复用度:
| 原子能力 | S1 家庭 | S2 校园 | S3 社区 | 复用 |
| --- | :---: | :---: | :---: | :---: |
| 人体检测 + 跟踪 | ✅ | ✅ | ✅ | 3/3 |
| 姿态关键点 | ✅ | ✅ | ✅ | 3/3 |
| 跌倒判定 | ✅ | ✅ | ✅ | 3/3 |
| 区域入侵 / 越线 | ○ | ✅ | ✅ | 2/3 |
| 停留 / 徘徊时长 | ✅ | ✅ | ✅ | 3/3 |
| 静止 / 无活动 | ✅ | ○ | ✅ | 2/3 |
| 人群聚集 / 密度 | — | ✅ | ○ | 1.5/3 |
| 打架 / 剧烈动作 | — | ✅ | ○ | 1.5/3 |
| 攀爬 / 翻越 | — | ✅ | ✅ | 2/3 |
| 非人目标(电动车、堆物) | — | ○ | ✅ | 1.5/3 |
| ReID 跨镜跟踪(匿名) | ○ | ✅ | ✅ | 2.5/3 |
| 身份比对(人脸) | ○ | 🔐 | 🔐 | 授权后启用 |
| 高空抛物 | — | — | ✅ | 1/3 |
✅ 核心 ○ 可选 — 不需要 🔐 需租户授权 + 前置条件齐备(§4.4)
**结论**:前 6 项覆盖了三个场景的 P0 需求主体,构成**通用能力包**;后续按场景增量。高空抛物(RQ-S3-04)需要专用仰拍机位与独立轨迹算法,与其余能力无复用,**建议独立立项或后期外采,不进本期通用底座**。
## 3.2 差异分析(差异才是场景包要装的东西)
| 维度 | S1 家庭 | S2 校园 | S3 社区 |
| --- | --- | --- | --- |
| 单点位路数 | 1–3 | 100–500 | 50–300 |
| 部署形态 | 边缘盒子(必须) | 校内边缘或中心 | 混合 |
| 摄像头可达性 | NAT 后 | 专网可达 | 专网可达 |
| 预警接收人 | 家属(非专业、随时可能没看手机) | 安保值班室(7×24 有人) | 物业值班(夜间可能无人) |
| 升级链 | 4 级,含语音电话与呼叫中心 | 2 级,值班室 → 校领导 | 3 级,值班 → 主管 → 业主群 |
| 超时容忍 | 30s / 60s / 90s | 2min / 10min | 1min / 5min |
| 误报容忍 | **极低**(家属会卸载 App) | 中(有人筛) | 中 |
| 隐私敏感度 | **极高** | 高(未成年人) | 中 |
| 常态录像 | ❌ 禁止上云 | ✅ 允许 | ✅ 允许 |
> **关键洞察**:S1 的接收人是非专业个人,没有值班室兜底,所以升级链必须做到"穿透勿扰模式"级别;S2/S3 有值班室,升级链可以简化,但需要**批量事件的看板与工单**能力(S1 完全不需要)。**这两种形态的 UI 和交互是两个东西,不要试图用一套界面覆盖。**
---
# 4. 领域模型
## 4.1 核心实体关系
```mermaid
erDiagram
TENANT ||--o{ SITE : "拥有"
SITE ||--o{ AREA : "划分"
SITE ||--o{ DEVICE : "部署"
DEVICE ||--o{ STREAM_BINDING : "产生"
AREA ||--o{ ZONE : "标注(多边形/警戒线)"
DEVICE ||--o{ ZONE : "画在画面上"
TENANT ||--o{ RULE : "定义"
RULE }o--|| SCENE_PACK : "继承自"
RULE ||--o{ EVENT : "命中生成"
EVENT ||--o{ EVIDENCE : "附带"
EVENT }o--o{ ALERT : "触发/聚合"
ALERT ||--o{ DELIVERY : "投递"
ALERT ||--o{ ALERT_LOG : "审计"
SITE ||--o{ CONTACT_CHAIN : "配置"
ALERT }o--|| CONTACT_CHAIN : "按级投递"
```
## 4.2 实体职责界定
| 实体 | 定义 | 关键约束 |
| --- | --- | --- |
| **Tenant 租户** | 计费与数据隔离的最小单位 | 所有查询必须带 tenant_id,无例外 |
| **Site 站点** | 一个物理场所(一户 / 一所学校 / 一个小区) | 升级链、时段策略挂在这一层 |
| **Area 区域** | 站点内的逻辑分区(教学楼 / 单元 / 客厅),由 Bell 统一管理 | 用于权限范围、报表口径与设备准入;`capture_policy` 表达是否仅允许非成像设备,Sense 只消费带版本的策略投影 |
2026-08-04 10:05:56 +08:00
| **Device 设备** | **不叫 Camera**;`modality` 表达 video/radar/contact/button/wearable/other,`capabilities` 表达成像、媒体、遥测等具体能力 | 模态负责稳定分类,能力负责决定字段与操作,避免接入新设备时重做台账和页面 |
| **Zone 画面区域** | 画在某路画面上的多边形或警戒线 | 与 Area 是两回事:Area 是物理概念,Zone 是像素坐标 |
| **Rule 规则** | 「主体 × 条件 × 时空 × 动作」的可配置组合 | 三级覆盖:租户默认 → 站点 → 设备 |
| **Event 事件** | 一次被判定成立的客观发生 | **不可变**。误判只能被标记,不能被删改 |
| **Alert 预警** | 一次需要人响应的通知过程 | 有生命周期状态机,可被 ack |
| **Delivery 投递** | 一次向某人某通道的发送尝试 | **独立实体**,一次 Alert 有多条 |
## 4.3 「指定人群」的建模
《01》§5 提出四类判定。分析后确定为**主体过滤器(Subject Filter)**,作用于跟踪目标而非规则整体:
```
Track(跟踪目标)
├─ class: person | vehicle | e_bike | object
├─ attributes: {age_group, posture, ppe, ...} ← A 类,模型直接产出
├─ states: {falling, running, loitering_sec, ...} ← B 类,时序分析产出
├─ anon_id: "pid_88213" | null ← B+ 类,ReID 匿名同一性,默认开
└─ identity: {ref_id, group, confidence} | null ← C 类,人脸,按租户授权开
```
| 判定类 | 实现位置 | 默认 | 开启条件 | 回答什么问题 |
| --- | --- | --- | --- | --- |
| A 属性 | 检测模型多头输出 / 独立分类器 | 开 | — | 他是什么样的人 |
| B 状态 | 时序窗口分析插件 | 开 | — | 他在做什么 |
| **B+ ReID** | ReID 模型,跨镜特征匹配 | **开(默认手段)** | — | **是不是同一个人** |
| C 身份 | 独立身份服务,异步比对后回填 | **关** | 租户授权 + §4.4 全部前置条件 | 他是谁 |
**设计原则(已定)**:
1. **能用 ReID 解决的不上人脸。** 徘徊、尾随、跟随、跨镜追踪这类"同一性"需求一律走 B+ 类。人脸只用于必须知道"是谁"的需求(白名单放行、关注名单告警、访客核验),且需逐条论证"为什么 ReID 不够"。
2. **`identity` 为 null 时规则必须仍能工作**,降级为"未知人员"。身份服务不可用、比对超时、人脸角度不佳都会产生 null——**不得因此漏报**。这条决定了规则 DSL 必须显式声明 `on_unavailable` 语义(见《03》§2.5)。
3. **`anon_id` 与 `identity` 是两个独立字段**,不可互相顶替。ReID 的 anon_id 只在会话/时间窗内有效,不是身份标识,也不应被持久化成长期人员画像。
## 4.4 身份识别(人脸)子系统的需求分析
客户已确认将授权使用人脸识别,因此该能力**进入方案范围**。但授权解决的是"能不能用",不解决"怎么用才安全"。分析出以下约束:
### 4.4.1 授权是租户级开关,不是全局开关
| 层级 | 语义 |
| --- | --- |
| 平台级 | 能力是否编译/部署(私有化交付时可整体不部署) |
| **租户级** | **主开关**。未授权租户在 API 与 UI 层均不可见该能力,不是"能看到但点不动" |
| 站点级 | 在已授权租户内进一步限定生效范围(如只在校门口,不在教室) |
| 规则级 | 单条规则是否使用 identity 过滤 |
> 未授权租户"看得到但用不了"是错误设计——它会诱导客户询问和绕过,也会让审计难以证明"该租户从未启用"。
### 4.4.2 底库是独立的高敏资产
| 需求 | 理由 |
| --- | --- |
| 底库与业务库**逻辑分离**,独立加密 | 泄露后果与一般业务数据不在一个量级 |
| **默认只存特征向量,不存原始人脸图** | 原图泄露可直接冒用;特征向量至少不可直接还原为可用照片。若业务必须留原图(如核验展示),原图单独分库 + 单独授权 |
| 人员档案必须有**有效期** | 学生毕业、住户搬离、访客当日有效——没有有效期的底库必然越积越脏 |
| 到期自动失效,不依赖人工清理 | 依赖运维记得清理是不可靠的 |
| 支持整体导出与彻底删除 | 客户终止服务时的义务 |
| 每次比对命中与每次底库查询均独立审计 | "谁查了谁"必须可追溯 |
### 4.4.3 比对是异步旁路,不在主判定链路上
```
主链路(必须实时):检测 → 跟踪 → 姿态/行为 → 规则 → 事件
↑
旁路(可延迟、可失败):人脸检测 → 质量筛选 → 特征提取 → 底库比对 → 回填 identity
```
**推导**:若把比对放进主链路,一次底库慢查询会拖垮整条 pipeline 的实时性;而人身安全类事件(跌倒、打架)根本不需要知道是谁。
派生需求:
| 编号 | 需求 |
| --- | --- |
| FR-ID-01 | 比对为异步旁路,超时/失败不阻塞事件生成 |
| FR-ID-02 | identity 回填有时间窗;超窗未回填则事件以 `identity: null` 定稿 |
| FR-ID-03 | 依赖 identity 的规则须声明 `on_unavailable`:`treat_as_unknown`(默认,倾向报警)或 `skip`(倾向不报) |
| FR-ID-04 | 人脸质量筛选(角度、清晰度、遮挡、尺寸)前置,低质量帧不送比对,避免误配 |
| FR-ID-05 | 置信度阈值可配;高风险动作(如触发告警、拒绝放行)前可要求人工复核 |
> FR-ID-03 的两个取值对应两种业务倾向。**默认必须是 `treat_as_unknown`**:在监护与安防场景,"不确定是谁"应当倾向于报警而非放过。若某条规则选 `skip`,需在规则上显式写明并有审批记录。
### 4.4.4 误识别的后果分级
人脸比对有两种错误,后果完全不同,阈值不能用同一个:
| 错误类型 | 场景 | 后果 | 阈值倾向 |
| --- | --- | --- | --- |
| 假阳性(认错人) | 白名单放行 | 陌生人被当成住户放行 → 安防失效 | **阈值调高**,宁可认不出 |
| 假阳性(认错人) | 关注名单告警 | 无辜者被当成关注对象告警 → **对个人的实质伤害** | **阈值调最高 + 强制人工复核** |
| 假阴性(认不出) | 白名单放行 | 住户被当成陌生人 → 体验差,但安全 | 可容忍 |
| 假阴性(认不出) | 关注名单告警 | 漏报 | 靠 ReID 与其他规则兜底 |
> **关注名单类规则不得自动触发对人的处置动作**(如自动锁门、自动通报),只能生成待人工确认的事件。这是产品红线,写进 L4 编排层的硬约束。
---
# 5. 核心流程分析
## 5.1 主流程
```mermaid
flowchart TD
A["摄像头 / 传感器"] --> B["接入层<br/>台账 · 隧道 · 媒体路由"]
B --> C{"触发判定<br/>常态 / 运动 / 传感器"}
C -->|无触发| C
C -->|唤醒| D["推理流水线<br/>检测 · 跟踪 · 姿态 · 属性"]
D --> E["规则引擎<br/>主体过滤 × 时空 × 条件"]
E -->|未命中| F["丢弃<br/>仅记指标"]
E -->|命中| G["事件生成器<br/>回捞 pre-roll · 抓拍 · 元数据"]
G --> H{"去重 / 防抖 / 聚合"}
H -->|抑制| I["静默记录"]
H -->|通过| J["事件实例落库"]
J --> K["管理系统<br/>看板 · 详情 · 处置"]
J --> L{"是否需要预警"}
L -->|是| M["预警状态机<br/>投递 → ack → 升级"]
M --> N["App / 短信 / 语音 / Webhook / 大屏"]
N --> O["处置结果回填"]
K --> O
O --> P["误报标记 → 标注队列 → 模型迭代"]
```
## 5.2 为什么 Event 和 Alert 必须分开(C2 的推导)
反例:把预警状态直接放在事件表上。会立刻遇到三个无法表达的情况:
| 情况 | 合并模型下的困境 |
| --- | --- |
| 客厅两个机位拍到**同一次**跌倒 | 两条事件、两次预警,家属收到两遍 |
| 消防通道堆物**持续存在** | 每帧都命中规则,要么事件爆炸,要么无法表达"仍未整改" |
| 一次事件在**不同时间**升级到不同人 | 事件表上放不下多级投递记录 |
| 值班员**批量确认** 20 条事件 | ack 语义作用在哪个粒度说不清 |
正确关系:
```
Event N ──┐
├──> Alert 1 ──> Delivery N
Event N ──┘
```
- **Event**:一次客观发生,不可变,是证据与统计的单位
- **Alert**:一次需要人响应的过程,可聚合多个事件,是 SLA 与考核的单位
## 5.3 预警生命周期状态机
```
[触发] ─→ [投递中] ─→ [已送达] ─→ [已确认 ack] ─→ [处置中] ─→ [关闭]
│ │ │ │
│ │ └─超时未 ack─→ [升级] ─→ 下一级投递 │
│ └─投递失败─→ [升级] │
└─防抖命中─→ [抑制] [标记误报] ←───┘
```
**硬约束(继承参考项目 §10.10)**:告警**先落库再投递**。进程崩溃重启后,扫描所有非终态告警并接续升级链——与 §7.3 对账器的"水平触发"是同一个思路。
## 5.4 三个不同的事实,不可混淆
| 事实 | 含义 | 字段 | 拿不到时的处理 |
| --- | --- | --- | --- |
| 发出去了 | 调用了上游 API | `sent_at` | — |
| 送达了 | 上游回执确认到达终端 | `receipt_at` | **当失败处理并升级**,不做乐观假设 |
| 被看到了 | 用户主动 ack | `acked_at` | 超时升级 |
---
# 6. 规则引擎需求分析
## 6.1 为什么必须独立(C4 的推导)
| 如果把规则写进模型插件 | 后果 |
| --- | --- |
| 客户要改一个停留时长阈值 | 要改 Python 代码、重启 pipeline、影响同机所有路 |
| 不同租户要不同阈值 | 插件里写 if tenant == ... |
| 要审计"这条事件是哪条规则判的" | 无从追溯 |
| 要做规则的灰度/回滚 | 做不了 |
**结论**:模型插件只输出**客观观测**(这里有个人、他的姿态是躺倒、他在多边形 A 内停留了 12 秒),规则引擎负责**主观判定**(这属于需要报警的情况)。这条边界要写进代码规范。
## 6.2 规则表达能力需求
一条规则必须能表达的五个维度:
| 维度 | 内容 | 例 |
| --- | --- | --- |
| **主体** | class + 属性过滤 + 身份过滤 | 人 且 未识别为本校学生 |
| **时空** | 哪些设备/Zone + 哪些时段/日历 | 实验室 B 区 且 非上课时段 |
| **条件** | 观测量的逻辑组合 + 持续时长 | 进入区域 且 停留 > 3s 且 无教师同行 |
| **抑制** | 冷却期、聚合键、静默窗口 | 同区域 5 分钟内不重复 |
| **动作** | 事件等级 + 证据规格 + 通知策略 | 高危 + 前 10s 后 15s + 升级链 A |
## 6.3 三级覆盖模型
```
场景包默认规则 ──继承──> 租户规则 ──覆盖──> 站点规则 ──覆盖──> 设备规则
```
覆盖语义必须明确定义(否则运维会被"为什么这条没生效"折磨死):
| 字段类型 | 覆盖语义 |
| --- | --- |
| 标量(阈值、时长) | 就近覆盖 |
| 列表(联系人、通道) | **替换**,不合并(合并会导致意外扩大通知面) |
| 开关(enabled) | 就近覆盖,且允许下级关闭上级下发的规则 |
| Zone 坐标 | 只能在设备级定义,上级不可下发 |
## 6.4 规则变更的非功能要求
| 要求 | 理由 |
| --- | --- |
| 热生效,不重启 pipeline | 一次重启影响同机全部路数 |
| 变更有版本与操作人记录 | 事故复盘时"谁把阈值改了" |
| 支持"试运行"模式:命中但不通知 | 新规则上线前评估误报量 |
| 支持按规则统计命中量与误报率 | 规则质量可度量,否则只能靠感觉调 |
> **试运行模式是被低估的需求。** 没有它,每条新规则上线都是拿真实用户做实验。
---
# 7. 接入层需求分析
## 7.1 NAT 约束推导(C5)
家庭场景摄像头在运营商 NAT + 家庭路由 NAT 之后,中心机房**无法主动发起连接**。校园/社区虽有专网,但不能假设每个项目都有公网 IP。
分析出的唯一可行结构:**控制面与数据面分离**(直接继承参考项目 §2.1)
| 平面 | 方向 | 通道 | 流量 |
| --- | --- | --- | --- |
| 控制面 | 中心 → 设备 | 边缘侧 WireGuard 隧道 | 极小,仅配置与探活 |
| 数据面 | 边缘 → 中心 | 边缘主动推流(RTSP announce / SRT / RTMP) | 大 |
派生需求:
| 编号 | 需求 |
| --- | --- |
| FR-ACC-01 | 每个站点分配不冲突的内网段,设备地址确定化(如 `10.<站点高位>.<站点低位>.0/24`,摄像头从 `.10` 起) |
| FR-ACC-02 | 控制面失联**不得**中断视频推流(两者已解耦),仅告警 |
| FR-ACC-03 | 边缘侧断网时本地缓存事件与证据,恢复后补传 |
| FR-ACC-04 | 推流鉴权走 HTTP 回调到自有服务,注销/欠费/隐私模式在业务库判断,媒体层零配置变更 |
## 7.2 设备身份与状态机
| 需求 | 理由 |
| --- | --- |
| 设备身份用**序列号**,不用 IP | DHCP 续租、Wi-Fi 漫游换 AP 都会换 IP |
| IP 变化时按序列号自动重定位并重连 | 家庭场景常态 |
| 设备状态含 `pending_activation` | 批量开通必然有凭据待补的中间态 |
| 探活用独立的 ONVIF 轻量调用,**不用流状态代替设备状态** | 「设备离线」与「无人订阅」在媒体层表现相同 |
设备状态机:
```
[录入] → [pending_activation] ──补齐凭据──> [active] ⇄ [offline]
│ │
└──────────────> [disabled] <──┘
```
## 7.3 对账器:一致性方案(C6 的推导)
一次设备开通需要在**多个独立系统**各做一次操作,且它们之间**没有分布式事务**:
```
数据库(唯一真相源)
├──> 媒体路由:建 path
├──> 推理流水线:挂 source
└──> 存储:建 bucket/前缀
```
### 为什么必须是水平触发而非事件驱动
| 方案 | 部分失败时 |
| --- | --- |
| 事件驱动(边沿触发) | 事件丢了就永久不一致,需要补偿事务,补偿也会失败 |
| **水平触发(对账)** | 不处理"事件",只不断比对期望与实际并向期望收敛。失败自动在下一轮重试 |
### 派生的硬性需求
| 编号 | 需求 | 理由 |
| --- | --- | --- |
| FR-REC-01 | 数据库是唯一真相源,下游均为被驱动的从属状态 | — |
| FR-REC-02 | 建 path 前先查是否存在,绝不盲目 add | 盲目 add 会踢掉正在推流的 publisher |
| FR-REC-03 | 改配置前比对 `desired_hash` / `applied_hash`,没变**绝不**调 API | 同上 |
| FR-REC-04 | 每个下游系统一行 sync_state,全部收敛才算开通成功 | 中间态必须可见 |
| FR-REC-05 | 开通顺序:媒体路由先 → 推理后;停用顺序:推理先 → 媒体路由后 | 建立与拆除逆序,写进代码注释 |
| FR-REC-06 | 部分失败**不回滚,只收敛**(退避重试) | 回滚本身会失败,导致回滚的回滚,无限递归 |
| FR-REC-07 | 每个下游系统独立限流预算(各 8 并发),不共享信号量 | 一个系统变慢会饿死另一个 |
| FR-REC-08 | 孤儿资源清理需有**安全闸**:单轮删除量 > 总量 10% 时停止并告警 | 防止"期望集合意外为空"把全部路数拆掉 |
| FR-REC-09 | 不设放弃阈值,持续重试 + 告警引入人工 | 对账器放弃 = 设备静默不工作,监护场景不可接受 |
| FR-REC-10 | 循环周期:正常 30s,有未收敛项降到 5s,另有 10min 全量对账(含孤儿扫描) | — |
### 必须暴露的指标
| 指标 | 用途 |
| --- | --- |
| `reconciler_unconverged_bindings{system}` | 核心健康指标,持续 > 0 即异常 |
| `reconciler_orphans_detected{type}` | 有人手改了生产系统 |
| `reconciler_safety_brake_triggered` | 安全闸触发,**应当直接呼人** |
| `reconciler_loop_duration_seconds` | 循环超时 = 规模到顶,该分片了 |
---
# 8. 非功能需求分析
## 8.1 容量模型
本项目以**单站点 16 路为默认交付规格**,支持 32 / 64 / 128 路扩展,单站点本阶段上限 128 路。16 是默认配额而非代码上限;128 路通过增加媒体分片与推理 Worker 实现,不把全部流压在一个进程或一块 GPU 上。
以下仅用于初步预算,最终以 M1–M5 的真实流水线压测为准:
| 项 | 默认 16 路 | 上限 128 路 | 说明 |
| --- | ---: | ---: | --- |
| 子码流 640×360 @ 512 kbps | ≈ 8 Mbps | ≈ 64 Mbps | 推理优先使用子码流 |
| 主码流按 4–6 Mbps | ≈ 64–96 Mbps | ≈ 512–768 Mbps | 常态录像与证据回捞的预算口径 |
| 抽帧 5 fps | 80 帧/秒 | 640 帧/秒 | GPU、解码器和 batch 均需实测 |
| 媒体分片 | 1 个 | 建议 4 个起步 | `media_shard.max_streams` 初始建议 32;可按故障域降为 16 |
| 推理分片 | 1 个逻辑分片 | 最多 8 个 16 路逻辑分片 | 一个 Worker 可承载几个分片由压测决定 |
容量必须按四个维度分别验收:接入/录像带宽、同时解码、AI 推理、证据存储。不能用“NVR 能录 128 路”推导“GPU 能分析 128 路”。连续录像时每 1 Mbps 约产生 10.8 GB/天;因此默认由客户已有 NVR 承担常态录像,YoVision 优先保存事件证据,避免重复存储全量视频。
> **实现约束**:`site.max_video_channels` 默认 16、最大 128;`media_shard.max_streams` 与 `inference_profile.max_sources` 为配置项。数据库、规则、数组、前端分页与批量操作中不得写死 16。
## 8.2 算力与触发式推理(C7 的推导)
| 模式 | 默认 16 路 | 扩展到 128 路 | 适用 |
| --- | --- | --- | --- |
| 常态全量推理 | 单逻辑推理分片起步 | 按 16 路切成最多 8 个逻辑分片,分配到多个 Worker | 高价值点位 |
| **触发式推理** | 保持同一分片结构,空闲时不解码/不推理 | 通过降低各分片占空比减少平均 GPU 需求 | 家庭、社区大部分点位 |
GPU 型号和数量不在需求阶段写死。M1 用 5 路打通,M3 以 16 路建立性能基线,再依次验证 64 路和 128 路;每档都以端到端 P95/P99 延迟、丢帧率和故障隔离为出口标准。
触发信号的三个来源(按成本与可靠性排序):
| 触发源 | 成本 | 可靠性 | 适用 |
| --- | --- | --- | --- |
| 运动侦测(软件,参考 Frigate 思路) | 零 | 中(光照变化、树叶晃动会误触) | 通用兜底 |
| 摄像头 ONVIF 事件订阅 | 零 | 中 | 支持的型号 |
| **毫米波雷达等传感器** | 硬件成本 | 高 | 家庭卧室/卫生间(且解决隐私) |
> **重要澄清**:流水线框架(Savant 等)主要解决多路调度、复用与故障隔离,不会自动降低单帧推理成本。触发式推理是降低平均算力的主要手段之一,但最终容量仍取决于模型、分辨率、FPS、batch、解码方式与硬件实测。
## 8.3 两级判定与误报(准确性需求的可实现形式)
单一信号源的误报都会让使用者很快失去信任:
| 信号源 | 典型误判 |
| --- | --- |
| 纯视觉 | 遮挡、逆光、坐下、弯腰、宠物、访客 |
| 纯雷达 | 快速坐下、弯腰 |
**两级串联是行业标准做法**:
- 一级(低成本、常开):宁可多报,不能漏报
- 二级(高成本、按需唤醒):审核一级的候选,剥离干扰
派生需求:架构必须支持"一级触发源"可插拔(运动侦测 / ONVIF 事件 / 雷达 / 门磁),且触发入口独立成 handler,接新传感器时不改动流控制逻辑。
## 8.4 分类粒度对误报的影响
参考实现的经验:`GajuuzZ/Human-Falling-Detect-Tracks` 对每个人轨迹每 30 帧预测动作,输出**站立/行走/坐下/躺下/起身/坐下动作/跌倒共 7 类**。
> **七分类而非二分类是降误报的关键。** 二分类模型面对"坐下"只能在"跌倒/非跌倒"之间硬选;七分类可以明确输出"这是坐下"。本项目所有行为判定模型均按此原则设计。
**负面经验**:`Y-B-Class-Projects/Human-Fall-Detection` 用约 500 张网络图片训 LSTM 完全学不会,最终退回 if-else 规则。→ **小数据量下时序模型学不动,先解决数据再上模型。**
## 8.5 可用性与降级
| 故障 | 要求 | 降级行为 |
| --- | --- | --- |
| 单路摄像头掉线 | 不影响其他路 | 告警 + 自动重连 |
| 推理节点崩溃 | 不影响接入与其他节点 | 该分片流量转移或降级为仅录制 |
| 算力不足 | 不得积压至崩溃 | **实时模式:主动丢帧优于积压** |
| 突发流量(早晨集中活动) | 不丢事件 | 持久化磁盘缓冲,抗突发 |
| 中心平台不可达 | 不丢事件 | 边缘缓存,恢复后补传 |
| 通知供应商故障 | 不丢预警 | 多供应商冗余,`provider` 字段为切换预留 |
## 8.6 安全需求
| 编号 | 需求 |
| --- | --- |
| NFR-SEC-01 | 设备凭据(ONVIF 用户名密码)加密存储,不落明文日志 |
| NFR-SEC-02 | 推流鉴权,未授权设备推不上来 |
| NFR-SEC-03 | 所有查询强制带 tenant_id,在数据访问层统一拦截,不依赖业务代码自觉 |
| NFR-SEC-04 | 证据文件访问用带时效的签名 URL,不可枚举 |
| NFR-SEC-05 | 管理界面不得对局域网默认无密码暴露(第三方面板的常见坑) |
| NFR-SEC-06 | 人脸底库(若启用)独立加密存储,独立审计,独立授权 |
## 8.7 合规需求
| 编号 | 需求 |
| --- | --- |
| NFR-CMP-01 | `alerts` 与 `alert_deliveries` **只追加不修改**,状态变更写事件表,独立备份 |
| NFR-CMP-02 | 每条预警须能回答:何时触发、基于什么证据、向谁发过、走什么通道、是否送达、谁在何时确认、处置结果、升到第几级、每级耗时 |
| NFR-CMP-03 | 证据留存期限可配置,到期自动清理并留清理记录 |
| NFR-CMP-04 | 数据主体的知情同意记录可查 |
| NFR-CMP-05 | 隐私区域(卧室、卫生间)在设备录入时即标记,系统层面拒绝配置摄像头类设备 |
> NFR-CMP-05 是**代码层面的硬约束**,不是流程约束。依赖实施人员"记得别装"是不可靠的。
---
# 9. 预警系统需求分析
## 9.1 两类告警必须彻底分开
| | 运维告警 | 业务预警 |
| --- | --- | --- |
| 触发源 | 设备离线、对账未收敛、GPU 过载、缓冲积压 | 规则命中 |
| 收件人 | 运维团队 | 家属 / 值班员 / 呼叫中心 |
| 延迟容忍 | 分钟级 | **秒级** |
| 漏报后果 | 服务降级 | 人身伤害 + 法律责任 |
| 方案 | Prometheus + Alertmanager(现成) | **自研状态机 + 复用投递通道** |
> **两套系统不得共用投递通道和值班配置**,否则运维噪声会淡化业务预警。这是本节最重要的一条。
## 9.2 ack 是核心,不是附加功能(C8)
「发出去」和「被人看到」是两回事。整个预警系统的设计围绕 **确认或升级** 这一对概念展开:
- 无 ack → 无法知道是否有人在处理 → 无法决定是否升级 → 升级链形同虚设
- 无 ack → 无法度量响应时长 → 无法做 SLA 与考核
- 无 ack → 出事后无法举证"我们报了且某人确认了"
## 9.3 升级链需求
| 需求 | 说明 |
| --- | --- |
| 层级数与超时值按站点可配 | 独居老人与有同住家属的策略应当不同 |
| 时段策略 | 白天找子女、夜间找同住者;校园白天找安保、夜间找宿管 |
| 通道冗余 | 至少两条独立路径,**且需有绕过互联网的通道** |
| 联系人可用性 | 支持轮值排班,而非固定人 |
**通道独立性分析**:推送依赖 APNs/FCM,短信依赖运营商,任何单一通道都可能整体故障。语音电话是唯一能穿透勿扰模式且不依赖互联网的通道,**在 S1 场景是必需项**。
## 9.4 去重与防抖
| 规则 | 参数 | 理由 |
| --- | --- | --- |
| 同设备冷却期 | 默认 5min | 避免同一事件多次触发 |
| 同站点聚合 | 多设备同时触发合并为一条 | 两个机位拍到同一次跌倒 |
| 已处置抑制 | 已 ack 期间不再新建同类 | 人已到现场 |
| 维护窗口 | 用户主动静默 | **必须强制限时(建议最长 4h)并到期前提醒** |
> **永久静默是这类系统最常见的事故成因。** 静默功能的限时是硬约束,不提供"永久"选项。
---
# 10. 数据闭环需求(C9)
## 10.1 为什么这是 P0 而非优化项
| 事实 | 后果 |
| --- | --- |
| 公开数据集(Le2i / UR Fall 等)是演员摆拍的表演性动作 | 与真实场景分布不符,训出来的模型现场表现差 |
| 真实误报案例是最稀缺的训练数据 | 只能靠运营积累,无法采购 |
| 没有闭环,模型不会随运营时间变好 | 产品没有护城河 |
## 10.2 闭环设计
```
用户点「误报」→ 自动把 evidence(视频片段 + 结构化观测序列)推进标注队列
用户确认「有效」→ 样本进正例库
↓
定期评估 → 规则阈值调整 / 模型重训 → 灰度上线(试运行模式)
```
**要求:从 M3 第一天就开始存,不要等到想训模型时才发现没数据。** `outcome = true_positive` 的样本同样是金矿。
## 10.3 派生的数据需求
| 编号 | 需求 |
| --- | --- |
| FR-DAT-01 | 事件证据须包含**结构化观测序列**(关键点、包围框、track_id 时序),不只是视频 |
| FR-DAT-02 | 误报标记须记录归因(遮挡/光照/宠物/坐下/其他),供分类统计 |
| FR-DAT-03 | 标注队列与训练数据的导出需符合 NFR-CMP-03 的留存与脱敏要求 |
| FR-DAT-04 | 每条规则的命中量、误报率可查询,作为规则质量指标 |
---
# 11. 数据模型(分析层)
在参考项目基础上扩展多租户与规则/事件。**字段级设计见《03》,此处只给结构与关键约束。**
```sql
-- ── 组织(Bell 为真相源;Sense 不直接写这些表)────────
tenants(id, code, name, status, plan, created_at)
sites(id, tenant_id, code, name, scene_pack, subnet CIDR, timezone, status,
max_video_channels INT NOT NULL DEFAULT 16 CHECK (max_video_channels BETWEEN 1 AND 128))
2026-08-04 10:05:56 +08:00
areas(id, site_id, name, parent_id,
capture_policy) -- video_allowed | non_imaging_only
-- ── Sense 只读投影(来源版本与同步时间必须可追溯)────
site_quota_projections(site_id, max_video_channels, source_version, synced_at)
area_policy_projections(area_id, site_id, capture_policy, source_version, synced_at)
-- ── Sense 设备(不叫 cameras,为异构传感器预留)────
devices(
id, tenant_id, site_id, area_id,
2026-08-04 10:05:56 +08:00
modality, -- video | radar | contact | button | wearable | other
device_kind, -- camera | mmwave_radar | door_contact | panic_button | ...
capabilities JSONB, -- captures_image / media_stream / telemetry / battery / spatial_config / ...
serial UNIQUE, -- ⚠️ 身份用序列号,不用 IP
vendor, model,
onvif_addr, onvif_user, onvif_secret, -- secret 加密存储
state, -- pending_activation | active | offline | disabled
last_seen_at
)
stream_bindings(id, device_id, mtx_instance, inference_shard, path_name, rtsp_url, profile_token, enabled,
UNIQUE(mtx_instance, path_name))
-- ── 对账(每下游系统一行)──────────────
sync_state(binding_id, system, desired_hash, applied_hash,
last_error, attempt, retry_after, updated_at,
PRIMARY KEY(binding_id, system))
-- system ∈ {'mediamtx','inference','storage'}
-- 全部行 desired_hash = applied_hash 才算真正开通
-- ── 规则 ──────────────────────────────
scene_packs(id, code, name, version, spec JSONB) -- 场景包模板
zones(id, device_id, name, geom_type, coords JSONB) -- 画面区域,仅设备级
rules(id, tenant_id, site_id, device_id, -- 三级覆盖,逐级可为 NULL
scene_pack_id, code, name, enabled, dry_run, -- dry_run = 试运行
spec JSONB, version, updated_by, updated_at)
rule_versions(rule_id, version, spec, updated_by, updated_at) -- 变更审计
-- ── 事件(不可变)──────────────────────
events(
id, tenant_id, site_id, device_id, rule_id, rule_version,
kind, severity, confidence,
occurred_at, detected_at, -- 发生时刻 vs 判定时刻,两者都要
subject JSONB, -- track_id / 属性 / anon_id(ReID) / identity + identity_status
observation JSONB, -- 触发时的客观观测量
evidence_uri, snapshot_uris,
dedup_key, aggregated_into, -- 聚合关系
outcome, -- true_positive | false_positive | unknown
outcome_reason, outcome_by, outcome_at
)
-- ── 身份识别(独立库/独立 schema,独立加密与审计)────
-- 仅在租户授权后创建;未授权租户无此 schema 的任何数据
tenant_features(tenant_id, feature, enabled, authorized_by,
authorized_at, expires_at, doc_uri) -- feature='face_recognition'
face_libraries(id, tenant_id, site_id, name, purpose, retention_days)
-- purpose ∈ {'whitelist','watchlist','visitor'};不同 purpose 的阈值与处置策略不同
persons(id, library_id, external_ref, display_name,
group_tags, valid_from, valid_until, -- ⚠️ 有效期必填,到期自动失效
consent_ref, -- 知情同意留档指针
created_by, created_at, revoked_at)
face_vectors(id, person_id, embedding VECTOR, model_ver,
quality_score, source, created_at) -- 默认只存向量
face_images(id, person_id, image_uri, created_at) -- 可选,单独授权才写入
face_match_logs(id, tenant_id, site_id, device_id, at,
person_id, score, threshold, decision, -- matched / below_threshold / no_candidate
event_id, reviewed_by, reviewed_at) -- 只追加,独立审计
-- ── 预警 ──────────────────────────────
alerts(id, tenant_id, site_id, kind, severity, state,
triggered_at, acked_by, acked_at, closed_at,
escalation_level, contact_chain_id)
alert_events(alert_id, event_id) -- 多对多
contact_chains(id, site_id, level, contact_name, channels JSONB,
active_hours, timeout_sec, UNIQUE(site_id, level))
alert_deliveries(id, alert_id, level, channel, provider,
sent_at, receipt_at, failed_reason)
alert_logs(id, alert_id, at, actor, from_state, to_state, detail JSONB) -- 只追加
CREATE INDEX ON alerts(state) WHERE state NOT IN ('closed','suppressed');
```
**关键约束复述**:
1. `devices` 而非 `cameras`——为雷达/门磁/按钮预留
2. 设备身份用 `serial`——IP 会变
3. `sync_state` 每系统一行——无分布式事务,中间态必须可见
4. `alert_deliveries` 是独立实体——一次预警多条投递,各自有回执
5. `events` 与 `alert_logs` 只追加——合规要求
6. `events.subject` 中 `anon_id`(ReID)与 `identity`(人脸)是两个独立字段,不可互相顶替
7. 人脸相关表独立 schema、独立加密、独立审计;`persons.valid_until` 必填,无"永久有效"选项
8. `sites.max_video_channels` 默认 16、最大 128;配额在写入设备时校验,分片容量由运行时配置与压测决定
9. `sites.max_video_channels` 由 Bell 持有,Sense 通过版本化内部 API 或只读投影校验设备新增/启用;不得跨 schema 直接写入
10. Tenant/Site/Area/RBAC、配额与全局审计属于 Bell;Sense 仅使用稳定逻辑 ID 关联并保存带 `source_version` / `synced_at` 的执行投影
11. 高风险设备写操作与本地审计 outbox 在 Sense 同一事务提交,再由幂等 relay 异步汇入 Bell;审计接口字段、签名和重放规则另立契约任务冻结
---
# 12. 优先级与里程碑映射
## 12.1 MoSCoW
| 级别 | 内容 |
| --- | --- |
| **Must** | 摄像头接入与台账、NAT 穿透、对账器、人体检测+跟踪+姿态、跌倒/区域入侵/停留三类规则、事件实例与证据、预警状态机与升级链、多租户与 RBAC、审计、误报反馈闭环 |
| **Should** | 触发式推理、**ReID(匿名同一性,默认手段)**、时段/日历策略、试运行模式、统计报表、边缘缓存补传、Grafana 看板 |
| **Could** | **人脸识别子系统**(租户授权开启:底库管理、异步比对旁路、审计)、人群聚集/打架检测、非人目标(电动车/堆物)、雷达接入、国标 GB/T 28181 对接、大屏与声光联动 |
| **Won't(本期)** | 高空抛物、S4 园区场景、车牌识别、**人脸在未成年人场景(S2)的启用**(待专项合规意见) |
> **人脸识别的排期说明**:客户已确认授权,能力进入方案范围,但它**不在主线关键路径上**(§4.4.3 已论证比对是异步旁路)。因此定为 Could 并安排在 M5——这样 M3 的端到端主线不被合规流程与底库模块阻塞。ReID 提到 Should 并在 M4 交付,先把"同一性"类需求兜住。
## 12.2 里程碑与出口标准
| 阶段 | 内容 | 出口标准 |
| --- | --- | --- |
| **M0** | 摄像头兼容性验证 + 需求定稿 | 可直接运行 MiBeeNvr 作为隔离实验室测试台;3–5 款型号跑通 GetProfiles/GetStreamUri/SetSystemDateAndTime,采购白名单归档;M0 代码不得作为生产基线;《01》§8 的 Q1–Q12 有答案 |
| **M1** | 接入骨架 + 媒体路由 | **MediaMTX 正式进入且不得由完整 MiBeeNvr 替代**;5 路自动建 path、探活、断线重建;设备台账可用 |
| **M2** | 对账器 + 多租户 + 隧道 | 10 个站点试点,至少一个站点完成 16 路开通/停用全流程;`unconverged = 0` 稳定 |
| **M3** | 推理接入 + 规则引擎 + 事件与预警 | **默认 16 路**端到端稳定运行;跑通一个场景的三类规则;拿到现场误报基线,反馈闭环已收数据 |
| **M4** | 64 路分片 + 灰度扩容 + 管理系统 | 64 路稳定运行;单分片故障不影响其他分片;看板、批量操作与处置流可用 |
| **M5** | 128 路容量验收 + 第二/第三场景包 + 触发式推理 + **人脸识别子系统** | **128 路通过横向分片稳定运行,扩容不改业务代码**;场景包为纯配置交付;人脸能力在一个已授权租户上跑通 |
| **M6(阶段二)** | 异构传感器接入 + 两级判定 | 误报率显著下降,视频常态采集下降 |
> **M5 的出口标准是本项目的架构验收点。** 如果新增场景需要改 L1–L4 的代码,说明 §2 的分层没做成,需要返工而不是继续叠加。
---
# 13. 风险清单
| 风险 | 影响 | 缓解 |
| --- | --- | --- |
| **Ultralytics YOLO 商业授权未按时到位** | 已决策沿用 YOLO;未购授权则落在 AGPL-3.0 第 13 条,需开源整个服务端 | **M3 前完成采购**;逃生通道:检测换 YOLOX(Apache-2.0,同属 YOLO 家族)、姿态换 RTMPose(COCO 17 点,判定算法不用改) |
| 授权范围未覆盖全部形态 | 私有化实例、边缘盒子内模型、二次训练权重可能不在授权内 | 采购时逐项书面确认 |
| **人脸误识别造成对个人的实质伤害** | 无辜者被当成关注对象告警 | §4.4.4 分级阈值;关注名单类规则**不得自动触发对人的处置动作**,只生成待人工确认事件 |
| **人脸底库泄露** | 生物识别信息泄露,后果与一般数据不在一个量级 | 独立 schema + 独立加密 + 默认只存特征向量不存原图 + 独立访问审计 |
| 底库越积越脏(毕业/搬离人员未清) | 误配率上升,合规风险累积 | `valid_until` 必填,到期自动失效,无"永久有效"选项 |
| 人脸能力拖累主线工期 | M3 被合规流程阻塞 | §4.4.3 比对为异步旁路;排期在 M5,不进 M3 关键路径 |
| 人脸模型权重许可与代码许可不一致 | 侵权 | 启用前逐个核对权重许可 |
| **公开数据集与真实场景脱节** | 模型上线后表现远低于论文指标 | M3 首要产出是**真实误报案例库**,不是模型指标;不承诺绝对准确率 |
| 摄像头 ONVIF 实现差异 | 部分型号无法接入 | 采购前真机验证(M0),白名单管控 |
| 摄像头时钟漂移 | 事件时间戳全乱,审计失效 | 开通时校时,定期校准 |
| NAT 隧道不稳 | 控制面失联 | 已与数据面解耦,告警但不阻断推流 |
| path reload 踢流 | 用户看到卡顿 | 变更前比对哈希,变更集中在维护窗口 |
| H.265 兼容性 | 浏览器无法原生预览 | 统一设为 H.264 |
| **隐私合规不过** | 项目无法落地 | 尽早引入触发式采集减少常态视频;隐私区域代码级硬约束;法务前置 |
| 推理框架绑定 NVIDIA | 硬件选型受限,信创环境不可用 | 推理代码与框架解耦,预留 ONNX Runtime / Pipeless 备选 |
| 场景包泛化失败,变成三套代码 | 维护成本三倍 | M5 出口标准强制验收 |
| 值班员被误报淹没后忽略全部告警 | 真实事件被漏 | 试运行模式 + 规则质量指标 + 误报率看板 |
| 客户要求"什么都能查"的全量录像 | 与隐私需求冲突且成本高 | 需求收集期即明确事件驱动采集的边界 |
---
# 14. 需求追溯矩阵(节选)
| 原始需求 | 分析结论 | 实现层 | 里程碑 |
| --- | --- | --- | --- |
| RQ-C-02 NAT 后接入 | C5 控制面/数据面分离 | L1 | M1/M2 |
| RQ-C-03 序列号身份 | §7.2 设备状态机 | L1 | M1 |
| RQ-C-11 规则组合表达 | C4 独立规则引擎,§6.2 五维度 | L4 | M3 |
| RQ-C-12 三级覆盖 | §6.3 覆盖语义表 | L4/L5 | M3 |
| RQ-C-16 人脸按租户授权 | C3 四类判定;§4.4 租户级主开关 | L3 | M5 |
| RQ-FR-01 未授权租户不可见 | §4.4.1 不是"看得到点不动" | L0/L3 | M5 |
| RQ-FR-03 底库有效期自动失效 | §4.4.2 无"永久有效" | L3 | M5 |
| RQ-FR-04 只存特征不存原图 | §4.4.2 | L3 | M5 |
| RQ-FR-06 不可用时不得漏报 | §4.3 原则 2 + FR-ID-03 `on_unavailable` | L3/L4 | M5 |
| RQ-S3-05 陌生人徘徊 | §4.3 原则 1:走 ReID,不上人脸 | L3 | M4 |
| RQ-S2-04 尾随进校 | 同上,ReID + 门禁事件融合 | L3/L4 | M4 |
| RQ-C-17 事件实例 | C2 Event/Alert 分离 | L4 | M3 |
| RQ-C-19 去重防抖 | §9.4 四条规则 | L4 | M3 |
| RQ-C-21 误报标记 | C9 数据闭环 | L4 | **M3(不可延后)** |
| RQ-C-23 ack 与升级 | C8 预警状态机 | L4 | M3 |
| RQ-C-25 通道独立 | §9.3 语音电话必需 | L4 | M3 |
| RQ-C-28 限时静默 | §9.4 硬约束,无永久选项 | L4 | M3 |
| RQ-C-29 两类告警分离 | §9.1 | L0/L4 | M2 |
| RQ-C-30 先落库再投递 | §5.3 硬约束 | L4 | M3 |
| RQ-C-31 多租户 | §11 强制 tenant_id 拦截 | L0 | M2 |
| RQ-S1-05 隐私区域禁摄像头 | NFR-CMP-05 代码级约束 | L0/L1 | M2 |
| RQ-S1-08 3 分钟人工介入 | §9.3 升级链,站点级配置 | L5 | M3 |
| RQ-S2-08 未成年人合规 | §7.3 法务阻塞项 | — | M0 |
| RQ-S3-04 高空抛物 | §3.1 无复用,建议独立立项 | — | 移出本期 |
---
> 本文档的分析结论(§1 的 C1–C9)是《03-通用场景应用方案》的输入约束。任何技术选型若与这些结论冲突,应先回来修改本文档,而不是在方案里悄悄绕过。