connect live API to 6-4 stream algorithm
This commit is contained in:
@@ -25,14 +25,14 @@ operation-room-monitor/
|
||||
|
||||
- Docker Compose V2、NVIDIA 驱动、NVIDIA Container Toolkit
|
||||
- 复制 `backend/.env.example` 为 `backend/.env` 并填写
|
||||
- 算法子进程包:`backend/algorithm_subprocesses/5.15/`(含 `main.py` 与 `weights/`;镜像构建时会 `COPY` 进容器,勿在 `.dockerignore` 中整目录排除)
|
||||
- 实时算法子进程包:`backend/algorithm_subprocesses/6-4/`(含 `main_basket_stream.py`、`configs/` 与 `weights/`;镜像构建时会 `COPY` 进容器,勿在 `.dockerignore` 中整目录排除)
|
||||
- 标注视频中文字体:镜像内已安装 `fonts-noto-cjk`、`fonts-wqy-microhei`(供 `visualize_result_video.py` 绘制耗材标签)
|
||||
- 医生识别(MediaPipe Pose):镜像内已安装 `libgles2`、`libegl1`、`libegl-mesa0`、`libglx-mesa0`、`libgl1-mesa-dri` 等 Mesa/GLVND 库;构建阶段会 `import mediapipe` 校验 `libGLESv2.so.2` 可用。子进程强制 CPU delegate。若仍见该错误,请 **`docker compose build --no-cache api`** 后重启(勿沿用旧 tarball 镜像)
|
||||
- MediaPipe 手检/医生识别:镜像内已安装 `libgles2`、`libegl1`、`libegl-mesa0`、`libglx-mesa0`、`libgl1-mesa-dri` 等 Mesa/GLVND 库;构建阶段会 `import mediapipe` 校验 `libGLESv2.so.2` 可用。若仍见该错误,请 **`docker compose build --no-cache api`** 后重启(勿沿用旧 tarball 镜像)
|
||||
- **构建时预下载的预训练资源**(`scripts/bake_pretrained_weights.py`,本地有则跳过,见 `backend/weights/.gitkeep`):
|
||||
- `swin3d_t-7615ae03.pth`(VideoSwin / batch Phase1)
|
||||
- `resnet50-0676ba61.pth`(医生 ReID 骨干)
|
||||
- `pose_landmarker_lite.task`(MediaPipe Pose)
|
||||
- 业务权重随 `algorithm_subprocesses/5.15/weights/` 打进镜像(YOLO / ActionFormer 等,非 hub 下载)
|
||||
- `hand_landmarker.task`(MediaPipe Hand Landmarker,构建阶段写入 `algorithm_subprocesses/6-4/weights/`)
|
||||
- 业务权重随 `algorithm_subprocesses/6-4/weights/` 打进镜像(手检备用 YOLO / 好坏帧 / 耗材分类等,非 hub 下载)
|
||||
- 可选备用:`backend/app/resources/actionformer_epoch_045.pth.tar`
|
||||
|
||||
---
|
||||
|
||||
@@ -11,17 +11,17 @@
|
||||
1. 配置 `**camera_id` → RTSP URL** 映射:
|
||||
- `**OR_SITE_CONFIG_JSON_FILE**`(推荐):UTF-8 JSON 文件,**仅支持**站点对象:`{"video_rtsp_urls":{...},"voice_or_room_bindings":[...]}`。根级只允许这两个键;`voice_or_room_bindings` 可为 `[]`。见 `[app/resources/or_site_config.sample.json](../app/resources/or_site_config.sample.json)`。服务每次解析映射时会重新读文件,便于联调覆盖 `video_rtsp_urls`。
|
||||
- `**VIDEO_RTSP_URL_TEMPLATE**`(可选):单模板字符串,可用 `{camera_id}`;在 `video_rtsp_urls` 未给出某路时使用。
|
||||
2. 调用 `POST /client/surgeries/start` 时,`camera_ids` 用于语音终端绑定;**默认仅 `RTSP_PRIMARY_CAMERA_ID`(or-cam-03)** 参与 RTSP 录像与 batch 算法。
|
||||
2. 调用 `POST /client/surgeries/start` 时,`camera_ids` 用于语音终端绑定,`basket_roi_xyxy` 提供主摄篮子 ROI;**默认仅 `RTSP_PRIMARY_CAMERA_ID`(or-cam-03)** 参与 RTSP 录像与 6-4 篮子推流算法。
|
||||
3. **开录确认**:主摄 RTSP 录像进程在超时内成功连接并写入首段数据后,才认为开录成功。
|
||||
4. **RTSP 预热(可选)**:设置 `RTSP_PREWARM_ENABLED=true` 后,API 进程启动即对站点 JSON 中 **全部** `video_rtsp_urls` 机位后台 ffmpeg keep-alive 拉流;开录/停录时暂停/恢复对应机位,避免与录像双拉。日志含 `RTSP prewarm connected`(`connect_ms`)与 `RTSP start_surgery timing`(`resolve_ms` / `spawn_ms` / `ready_ms` / `prewarm_was_warm`)。
|
||||
|
||||
## RTSP 录像切片(链路 1)
|
||||
## RTSP 录像与 6-4 推流算法(链路 1)
|
||||
|
||||
- FastAPI 进程内 **ffmpeg** 从 RTSP 拉流,默认每 **120 秒**(`RTSP_SEGMENT_DURATION_SEC`)落盘一个 MP4 切片到 `logs/rtsp_segments/{surgery_id}/{camera_id}/`。
|
||||
- 每个完整切片通过 [`BatchAlgorithmService`](../backend/app/algo_host/batch_service.py) 子进程调用 `algorithm_subprocesses/5.15/main.py`(与链路 3 相同),解析 `result.tsv` 后写入活跃会话。
|
||||
- 停录时 flush 尾切片并等待 batch 队列 drain(`RTSP_SLICE_BATCH_DRAIN_TIMEOUT_SEC`)。
|
||||
- 开录后服务端同时为主摄启动 `algorithm_subprocesses/6-4/main_basket_stream.py` 长驻子进程,传入 `basket_roi_xyxy` 生成的 ROI JSON,避免无头容器弹窗框选。
|
||||
- 停录时向 6-4 子进程发送中断信号,等待其写出 `logs/sixfour_stream/{surgery_id}/{camera_id}/output/result.tsv`,解析 TSV 后写入活跃会话并持久化最终结果。
|
||||
- 落盘切片默认 **24 小时**后自动删除(`RTSP_SEGMENT_TTL_HOURS`;进程启动与后台定时 sweep)。
|
||||
- 设置 `RTSP_RECORD_ALL_CAMERAS=true` 可对请求中所有可解析 RTSP 的机位分别录像+跑 batch(多机位代码已预留)。
|
||||
- 设置 `RTSP_RECORD_ALL_CAMERAS=true` 可对请求中所有可解析 RTSP 的机位分别录像;当前 6-4 算法只跑服务端选出的主摄。
|
||||
- **同一机位同时只允许一场手术录制**(默认主摄 `RTSP_PRIMARY_CAMERA_ID`):另一场次开录同一 camera 时返回 `409` / `CAMERA_ALREADY_RECORDING`;注册表在拉起 ffmpeg 前即占用机位,避免双路 RTSP 抢流导致录像周期性丢帧。
|
||||
- **宿主机读切片**:Compose 中 `api` 使用 `HOST_UID`/`HOST_GID` 与宿主机对齐落盘权限;详见 [Docker部署.md](Docker部署.md)「RTSP 切片在宿主机无法用 VLC 打开」。
|
||||
|
||||
@@ -48,11 +48,11 @@ SDK **不作为构建期依赖**:将厂商提供的 Linux x86_64 动态库挂
|
||||
|
||||
## 推理与结果查询
|
||||
|
||||
### 链路 1:RTSP 切片 + batch(`5.15/main.py`)
|
||||
### 链路 1:RTSP + 6-4 推流算法(`main_basket_stream.py`)
|
||||
|
||||
- 开录后 FastAPI 用 ffmpeg 录像并按 `RTSP_SEGMENT_DURATION_SEC` 切片;每段 MP4 经 batch 子进程推理,结果按 TSV 置信度写入会话。
|
||||
- 开录后 FastAPI 用 ffmpeg 保留录像,同时启动 6-4 篮子推流子进程;客户端必须传主摄 `basket_roi_xyxy`。
|
||||
- **候选耗材清单**(`candidate_consumables`):非空时**仅**清单内名称参与自动记账与待确认;**缺省或 `[]`** 时,用 `consumable_classifier_labels.yaml` 的 **全部类名**作为候选。
|
||||
- 当 Top1 置信度 **≥** `VIDEO_AUTO_CONFIRM_CONFIDENCE`(**默认 0.9**)且标签在候选清单内时,自动写入 `source=video_batch` 明细;中间区间入待确认队列,由语音终端 TTS/确认。
|
||||
- 当 Top1 置信度 **≥** `VIDEO_AUTO_CONFIRM_CONFIDENCE`(**默认 0.9**)且标签在候选清单内时,自动写入 `source=sixfour_stream` 明细;中间区间入待确认队列,由语音终端 TTS/确认。
|
||||
- 客户端 `GET /client/surgeries/{surgery_id}/pending-confirmation`,确认后 `POST .../pending-confirmation/{id}/resolve` 等。
|
||||
|
||||
### 链路 3:离线 batch(`POST /internal/demo/offline-batch`)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
## 2. 摄像头 ID 与 RTSP
|
||||
|
||||
RTSP 地址、账号、口令等由客户端对接工程师提供给服务端运维,运维再写入服务端环境。客户端只在 **链路 1** 的 `POST /client/surgeries/start` 中传 `camera_ids`。**链路 3 上传视频不需要 `camera_ids`。**
|
||||
RTSP 地址、账号、口令等由客户端对接工程师提供给服务端运维,运维再写入服务端环境。客户端只在 **链路 1** 的 `POST /client/surgeries/start` 中传 `camera_ids` 与主摄 `basket_roi_xyxy`。**链路 3 上传视频不需要 `camera_ids`。**
|
||||
|
||||
| **camera_id** | **RTSP** | **备注** |
|
||||
| ------------- | -------- | -------- |
|
||||
@@ -114,7 +114,7 @@ sequenceDiagram
|
||||
participant Server as 服务端
|
||||
|
||||
Client->>Server: POST /client/surgeries/start
|
||||
Note over Client,Server: body: surgery_id, camera_ids, candidate_consumables
|
||||
Note over Client,Server: body: surgery_id, camera_ids, basket_roi_xyxy, candidate_consumables
|
||||
Server-->>Client: 200 accepted(开录已确认)
|
||||
|
||||
par 术中
|
||||
@@ -248,12 +248,13 @@ sequenceDiagram
|
||||
|
||||
**业务说明**
|
||||
|
||||
- 服务端会为 `camera_ids` 中的每个摄像头建立拉流与推理任务,只有在确认开录成功(如首帧就绪)后才返回 HTTP `200`。
|
||||
- 服务端会为主摄启动 6-4 篮子推流算法,并保留 RTSP 录像任务;只有在确认开录成功(如首帧就绪)后才返回 HTTP `200`。
|
||||
- 本接口**同步阻塞**直至开录确认;默认 RTSP 等待约 **95 秒/次**、最多 **3 次重试**。客户端 HTTP 超时建议 **≥ 300 秒**(Apipost 等工具默认 30–60 秒易触发 `ESOCKETTIMEDOUT`)。服务端可通过 `VIDEO_OPEN_TIMEOUT_SEC` 调大(默认 90)。
|
||||
|
||||
- `candidate_consumables` 缺省或 `[]` 时,服务端会展开为 `consumable_classifier_labels.yaml` 中的全部类名(无有效 yaml 时开录失败)。
|
||||
- 非空时,每项可为**耗材名称**或**产品编码**(`label_id`);编码通过 yaml 解析为类名后再参与推理与白名单。亦支持医院导出对象(见下表)。
|
||||
- **41 类完整类名与产品编码对照**:见 [`docs/耗材产品编码与类名对照表.md`](耗材产品编码与类名对照表.md)(须用完整类名或编码,口语简称如「纱布」不会自动映射)。
|
||||
- `basket_roi_xyxy` 为主摄篮子 ROI 的原始像素坐标,必须基于服务端实际算法主摄(默认 `RTSP_PRIMARY_CAMERA_ID`,常为 `or-cam-03`)的预览画面标注。
|
||||
|
||||
**请求体(JSON)**
|
||||
|
||||
@@ -261,6 +262,7 @@ sequenceDiagram
|
||||
| ----------------------- | ---------- | ------ | ----------------------------------- |
|
||||
| `surgery_id` | `string` | 是 | 6 位数字 |
|
||||
| `camera_ids` | `string[]` | 是 | 至少 1 个;必须与运维配置的摄像头 ID 完全一致,见第 2 节 |
|
||||
| `basket_roi_xyxy` | `number[4]` | 是 | 主摄篮子 ROI,格式 `[x1,y1,x2,y2]`,原始像素坐标,要求 `x2>x1` 且 `y2>y1` |
|
||||
| `candidate_consumables` | `string[]` 或对象数组 | 否 | 非空时仅这些名称/编码参与自动记账与待确认;缺省或 `[]` 时使用全部候选。字符串可为类名或 `label_id`;对象见下 |
|
||||
|
||||
**`candidate_consumables` 数组元素**
|
||||
@@ -285,7 +287,7 @@ sequenceDiagram
|
||||
| **HTTP** | **说明** |
|
||||
| -------- | -------------------------------------------------------- |
|
||||
| `200` | 开录已确认 |
|
||||
| `422` | 参数校验失败,例如 `surgery_id` 非 6 位或 `camera_ids` 为空数组 |
|
||||
| `422` | 参数校验失败,例如 `surgery_id` 非 6 位、`camera_ids` 为空数组或缺少/非法 `basket_roi_xyxy` |
|
||||
| `503` | 开录未确认或录制子系统故障;`detail.code` 常见为 `RECORDING_CANNOT_START` |
|
||||
|
||||
**请求示例**
|
||||
@@ -294,6 +296,7 @@ sequenceDiagram
|
||||
{
|
||||
"surgery_id": "123456",
|
||||
"camera_ids": ["or-cam-01", "or-cam-02", "or-cam-03", "or-cam-04"],
|
||||
"basket_roi_xyxy": [260, 180, 1120, 860],
|
||||
"candidate_consumables": ["纱布", "缝线", "止血钳"]
|
||||
}
|
||||
```
|
||||
@@ -304,6 +307,7 @@ sequenceDiagram
|
||||
{
|
||||
"surgery_id": "123456",
|
||||
"camera_ids": ["or-cam-01"],
|
||||
"basket_roi_xyxy": [260, 180, 1120, 860],
|
||||
"candidate_consumables": ["14764-2-4", "8036-5-22"]
|
||||
}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user