# 三系统职责划分:Sense / Brain / Bell > 本文档回答一个问题:**一段代码该写进哪个目录。** > 划分依据来自《03-通用场景应用方案》的 L0–L5 分层与组件选型,本文档只是把它按三个可独立开发的系统重新切分。 > 定稿:2026-08-03 --- ## 1. 三系统总表 | | **Sense** | **Brain** | **Bell** | | --- | --- | --- | --- | | 中文 | 感知系统 | 推理系统 | 管理系统 | | 小学生版 | 感觉到 | 想一想 | 打铃叫人 | | 对应层 | L1 接入 | L2 流水线 + L3 算法 | L4 业务 + L0 基座 | | 语言 | Go | Python / CUDA | Go + 前端 | | 有无状态 | 有(设备台账) | **无状态** | 有(事件、告警) | | DB schema | `sense` | 无 | `bell` | | 契约角色 | 供流与信号 → Brain | **产出**事件 | **消费**事件 | | 首次交付 | M1 | M3 | M3(最小)→ M4(完整) | ### 1.1 各自装什么 **Sense —— 把现场的流和信号稳定地拿进来并管住** - 设备台账(`devices`,含 `modality`:video / radar / contact / button / wearable / other,以及决定成像、媒体、遥测、空间配置等页面与操作的 `capabilities`) - ONVIF 客户端:连接、GetProfiles、GetStreamUri、SetSystemDateAndTime - mediamtx API 客户端(**自行用 oapi-codegen 从其 OpenAPI 生成**,不依赖第三方 SDK) - **对账器**:水平触发、`sync_state`、独立信号量、10% 孤儿删除安全闸、只收敛不回滚 - 探活与断线重建 - WireGuard 控制面隧道 - mediamtx 鉴权回调(401 + 踢流是四种停用粒度之一) - 容量配额执行:设备新增/启用时读取 Bell 的站点配额,只拒绝超额变更;配额服务暂时不可用时不影响已有流 - Area 准入执行:消费 Bell 的版本化 `capture_policy` 投影;策略不可用时只拒绝相关新写入,不静默中断已有设备 - 流绑定与媒体分片调度:维护 `mtx_instance`,默认 16 路交付;扩到 128 路时按 `media_shard.max_streams` 横向分片 - 边缘节点 agent:推流、本地环形缓冲、断网续传 - **设备型触发源**:雷达、门磁、按钮、ONVIF 事件订阅 - 非视频传感器的信号接收(signal plane,不走 mediamtx) **Brain —— 看画面、出判定** - Savant 流水线与适配器(ZeroMQ 边界,适配器故障隔离,实时模式丢帧) - 模型:检测 / 姿态 / 跟踪 / ReID(`anon_id`)/(M5)人脸 - **`Detector` 与 `PoseEstimator` 接口解耦**——这是 AGPL 逃生通道的前提,换 YOLOX + RTMPose 时判定算法不动 - 判定内核:几何证据 + 时间窗状态机(从 silver_pose 抽取,两边共用) - 事件 mapper:判定结果 → 事件契约 v0.1 - **像素级**运动侦测触发(要解码,所以在这里) - 推理 worker 注册与分片:单逻辑推理分片默认最多 16 路;64/128 路由多个 worker 承担,路由变更不改判定代码 **Bell —— 记录、派发、追到人确认** - 事件接收与校验(schema 校验 + 契约 README §5 那六条代码级断言 + 生成 ULID) - 事件存储:**不可变**,误判只改 `outcome` - 规则引擎 + 场景包加载 - 告警状态机:升级链、ack、抑制、静默(**≤4h,无永久选项**) - 投递:push / 短信 / 语音,**双供应商** - 误报反馈闭环:`outcome` 回写 Brain - Tenant/Site/Area、`capture_policy`、多租户 RBAC、`tenant_features`(人脸授权开关:未授权时能力在 API 与 UI 中**不可见**,不是禁用) - 全局审计日志;接收 Sense 设备操作审计并保留来源上下文 - 站点容量配额的唯一真相源:`site.max_video_channels` 默认 16、上限 128;提供版本化内部读取接口/投影给 Sense 执行 - 管理后台前端 + 大屏:按 128 路设计分页/虚拟列表、筛选与批量操作,不一次性加载全部视频 ### 1.2 不属于任何一个目录的东西 | 组件 | 说明 | | --- | --- | | **mediamtx** | 独立二进制,外部依赖。Sense 管它的配置与生命周期,`Sense/deploy/` 放基线配置 | | **PostgreSQL / MinIO / Prometheus** | 基础设施,独立部署清单 | | **silver_pose** | 独立仓库,是 Brain 判定内核的来源与单机演示形态。**不改名、不合并**——它现在能卖,Brain 还不能 | | **`_reference/`** | 只读参考源码(如 MiBeeNvr)。按《03》§1.4 白名单借鉴 ONVIF、IP 自愈、健康检测、测试组织与 UI 交互;禁止复制媒体内核、SQLite 真相源、AI/用户体系,禁止整仓进生产或加入 go.mod | --- ## 2. 目录结构 ### 2.1 Sense(Go) ``` Sense/ ├── cmd/ │ ├── sense-api/ 控制面服务:设备台账、鉴权回调、对账器 │ └── sense-agent/ 边缘节点:推流、环形缓冲、隧道 ├── internal/ │ ├── device/ 设备台账(devices,含 modality + capabilities) │ ├── onvif/ 连接、GetProfiles、GetStreamUri、SetSystemDateAndTime │ ├── mtx/ oapi-codegen 生成的 mediamtx 客户端 + 薄封装 │ ├── reconcile/ 对账循环(幂等 + 退避 + 安全闸) │ ├── probe/ 探活 │ ├── trigger/ 设备型触发源(雷达/门磁/按钮/ONVIF 事件) │ ├── tunnel/ WireGuard 控制面 │ ├── authcb/ mediamtx 鉴权回调 │ └── store/ M1 先 SQLite,schema 与生产 Postgres 保持一致 ├── deploy/ │ └── mediamtx.yml 基线配置 └── api/openapi.yaml ``` ### 2.2 Brain(Python / CUDA) ``` Brain/ ├── pipeline/ Savant 流水线定义与适配器 ├── models/ │ ├── detector/ Detector 接口 + YOLO / YOLOX 实现 │ ├── pose/ PoseEstimator 接口 + YOLO-pose / RTMPose 实现 │ ├── tracker/ ByteTrack / BoT-SORT │ └── reid/ 匿名同一性,产出 anon_id ├── judge/ │ ├── evidence.py 几何证据(躯干角、髋部下坠比) │ └── state.py 时间窗状态机 NORMAL/SUSPECT/CONFIRMED/RECOVERING ├── emit/ │ ├── mapper.py 判定结果 → 契约 v0.1 │ └── publisher.py 投递(HTTP 起步 → ZeroMQ);**失败落本地队列重试,不阻塞主链路** ├── trigger/ 像素级运动侦测 └── contracts/ ← 与 Bell/contracts/ 逐字节相同 ``` ### 2.3 Bell(Go + 前端) ``` Bell/ ├── cmd/bell-api/ ├── internal/ │ ├── ingest/ 接收事件、schema 校验、六条断言、生成 ULID │ ├── event/ 事件存储(不可变,只允许追加 outcome) │ ├── rule/ 规则引擎 + 场景包加载 │ ├── alert/ 告警状态机、升级链、ack、静默 │ ├── deliver/ push / 短信 / 语音,双供应商 │ ├── feedback/ 误报回流,outcome 回写 Brain │ ├── tenant/ 多租户 RBAC、tenant_features │ ├── audit/ 审计日志 │ └── store/ Postgres(schema: bell) ├── web/ 管理后台前端 ├── packs/ 场景包(**纯配置** —— M5 架构验收点) └── contracts/ ← 与 Brain/contracts/ 逐字节相同 ``` > `contracts/` 只在 Brain 与 Bell 各存一份(生产者与消费者),**Sense 不需要**——它不碰事件契约。 --- ## 3. 八条边界(不写死就会漂) | # | 边界 | 定论 | | --- | --- | --- | | 1 | mediamtx 二进制归谁 | 独立进程。**Sense** 管配置与生命周期,部署清单放 `Sense/deploy/` | | 2 | 触发源归谁 | 按性质切:**设备型**(雷达/门磁/按钮/ONVIF 事件)→ Sense,它们本来就是设备;**像素级**运动侦测 → Brain,它要解码 | | 3 | pre-roll 证据切片谁裁 | 录制在 Sense(mediamtx),事件在 Brain 产出。**Bell 发起回捞**(它拥有事件),Sense 提供切片接口 | | 4 | ULID 谁生成 | **Bell**。Brain 只填 `source_event_id`。见契约 README §4 | | 5 | 一个 PostgreSQL 还是三个 | **一个实例,schema 分离**(`sense` / `bell`),Brain 无 schema。"DB 是唯一真相源"是对账器成立的前提,拆库即失效 | | 6 | 16 路与 128 路分别指什么 | **16 路是默认交付规格,128 路是本阶段单逻辑站点上限**,都不是“单进程/单服务器保证值”。媒体与推理必须横向分片;单机承载量由分辨率、码率、帧率、模型和硬件基准测试决定 | | 7 | 站点配额谁拥有、谁执行 | **Bell 拥有 `sites.max_video_channels`,Sense 在设备新增/启用写路径执行**。通过版本化内部 API 或只读投影同步,不允许 Sense 直接写 Bell schema;依赖暂时不可用时拒绝新变更,但已有视频链路继续运行 | | 8 | 设备模态与隐私准入怎么建模 | 台账使用 `modality + capabilities`,不以摄像头作为唯一根实体;**Bell 拥有 Area 与 `capture_policy`,Sense 消费带版本投影并按设备 `captures_image` 能力在新增/启用写路径执行**。策略不可用时拒绝相关新变更并告警,已有链路不静默停用;M1 固化模型,M6 再增加非视频适配器 | | 9 | 接入操作审计怎么进入 Bell | Sense 在同一事务写设备期望态和持久化 outbox,再由幂等 relay 异步汇入 Bell 全局审计;不得先执行高风险操作再尽力入队。字段、签名、重放和留存由独立 API/契约任务冻结 | 第 2、3、6、7、8、9 条是本文档新定的,若实施中发现更合适的切法,改这里并同步《02》《03》。 --- ## 4. 标识符约定 ``` 仓库/目录 Sense Brain Bell 镜像 yov/sense:x.y yov/brain:x.y yov/bell:x.y 日志/指标前缀 sense_ brain_ bell_ 三字母码 SEN BRN BEL DB schema sense — bell ``` **命名规则:系统名不得是该系统领域模型里的实体名。** `bell` 域内有 `alerts` 表 → 系统不能叫 Alert(`alert.alerts` 无法读,且撞 Prometheus 内置的 `ALERTS` 序列)。另两个同样干净:`sense` 域内是 `devices`/`streams`,`brain` 域内是 `models`/`detections`。 --- ## 5. 里程碑与目录的对应 | 阶段 | 动哪个目录 | | --- | --- | | **M0** 摄像头兼容性验证 | 无生产代码;可直接运行 MiBeeNvr 等 `_reference/` 项目作为隔离实验室测试台,产物允许丢弃 | | **M1** 5 路接入骨架 + mediamtx | **仅 Sense**;MediaMTX 正式进入,完整 MiBeeNvr 不得替代生产媒体数据面 | | **M2** 对账器 + 多租户 + 隧道 + 16 路开通 | **仅 Sense**;至少一个站点验证默认 16 路配额与全流程 | | **M3** 默认 16 路推理 + 规则引擎 + 事件预警 | **Brain + Bell 同时起步**,契约在此首次被真实使用 | | **M4** 64 路分片 + 灰度 + 管理系统 | Sense 与 Brain 完成横向分片,Bell 完成 128 路规模下的列表与批量交互;验证单分片故障隔离 | | **M5** 128 路容量验收 + 第二三场景包 + 触发式推理 + 人脸 | Sense/Brain 验证扩容不改业务代码;Bell 的 `packs/`(**纯配置**)+ Brain 的模型与触发 | | **M6** 异构传感器 + 两级判定 | Sense 的 `trigger/` 与 `device/` 增加非视频协议适配器与能力实现(`modality + capabilities` 模型已从 M1 保留)+ Brain 两级判定 | > M3 是契约第一次被真实使用的时刻。**在此之前契约允许原地修订,之后版本递增规则绝对生效**(契约 README §1)。