This commit is contained in:
Kevin
2026-04-28 10:41:48 +08:00
parent 482b016872
commit 15884bd68e
60 changed files with 2092 additions and 1994 deletions

View File

@@ -8,7 +8,7 @@
| **开始手术** | `POST /client/surgeries/start`,只有在开录确认成功后才返回 `200`。 |
| **结束手术** | `POST /client/surgeries/end`,只有在停录确认成功后才返回 `200`。 |
| **查询结果** | `GET /client/surgeries/{surgery_id}/result`,至少存在一条消耗明细时返回 `200`;否则返回 `503`,常见错误码为 `RESULT_NOT_READY`。 |
| **待确认播报** | `GET /client/surgeries/{surgery_id}/pending-confirmation`,拉取队首低置信度任务,返回话术文本和 MP3 Base64。 |
| **待确认播报** | **官方浏览器客户端**(仓库 `web/voice-confirmation/`,可独立部署):同一 WebSocket 上推送 `voice_pending`(载荷与 `GET .../pending-confirmation` 成功体一致,另含 `type`);无队首时 `voice_pending_empty`**不轮询 GET**。**第三方**仍可用 `GET .../pending-confirmation` 拉取队首。 |
| **待确认答复** | `POST /client/surgeries/{surgery_id}/pending-confirmation/{confirmation_id}/resolve`,上传医生答复的 WAV 录音,服务端完成 ASR 后入账或关闭。该录音与播报音频无关。 |
## 1. 服务与基础信息
@@ -21,15 +21,18 @@
| **`start` / `end` 请求体** | JSON |
| **`resolve` 请求体** | `multipart/form-data`,字段名为 `audio` |
| **在线文档** | `/docs``/redoc` |
| **语音确认官方页面** | 仓库 `web/voice-confirmation/`(静态资源,与 API 分宿;需为浏览器配置 CORS见该目录 `README.md` |
## 2. 摄像头 ID 与 RTSP
RTSP 地址、账号、口令等由客户端对接工程师提供给服务端运维,运维再写入服务端环境。客户端只在 `POST /client/surgeries/start` 中传 `camera_ids`
| **camera_id** | **RTSP** | **备注** |
| ------------- | -------------------------------- | ------ |
| `or-cam-01` | `rtsp://...`(由现场或 NVR 文档整理后交给运维) | 术间、机位 |
| `or-cam-02` | `...` | `...` |
| **camera_id** | **RTSP** | **备注** |
| ------------- | -------- | -------- |
| `or-cam-01` | `rtsp://admin:Aa183137@192.168.3.2:554/Streaming/Channels/101` | 测试手术室,主码流 ch.101 |
| `or-cam-02` | `rtsp://admin:Aa183137@192.168.3.3:554/Streaming/Channels/101` | 同上 |
| `or-cam-03` | `rtsp://admin:Aa183137@192.168.3.4:554/Streaming/Channels/101` | 同上 |
| `or-cam-04` | `rtsp://admin:Aa183137@192.168.3.5:554/Streaming/Channels/101` | 同上 |
## 3. HTTP 路由一览
@@ -41,8 +44,8 @@ RTSP 地址、账号、口令等由客户端对接工程师提供给服务端运
| 4 | `GET` | `/client/surgeries/{surgery_id}/result` | 查询手术结果 |
| 5 | `GET` | `/client/surgeries/{surgery_id}/pending-confirmation` | 拉取待确认耗材 |
| 6 | `POST` | `/client/surgeries/{surgery_id}/pending-confirmation/{confirmation_id}/resolve` | 提交医生答复 |
| 7 | `GET` | `/client/voice-terminals/{terminal_id}/assignment` | 可选:查询当前指派(调试或简易集成;**官方桌面客户端仅用 WebSocket** |
| 8 | `WS` | `/client/voice-terminals/ws?terminal_id=...` | 语音桌面终端长连接,接收开录/停录指派(**推荐** |
| 7 | `GET` | `/client/voice-terminals/{terminal_id}/assignment` | 可选:查询当前指派(调试或简易集成;**官方浏览器客户端仅用 WebSocket** |
| 8 | `WS` | `/client/voice-terminals/ws?terminal_id=...` | 语音终端长连接,接收开录/停录指派(**推荐**;与 `web/voice-confirmation` 共用 |
| | | | |
**术间与语音终端绑定(服务端配置)**
@@ -51,6 +54,7 @@ RTSP 地址、账号、口令等由客户端对接工程师提供给服务端运
- **`POST /client/surgeries/start`** 在 **HTTP 200 且开录已成功** 后:用请求体中的 `camera_ids``voice_or_room_bindings` 中解析终端(**精确匹配**术间 camera 集合,或 **开录路集为某术间 camera 集合的子集** 时匹配该术间);命中则向对应 `voice_terminal_id` 推送 **`action":"start"`**(并更新 assignment未配置站点文件、或数组为空、或未命中则仅打日志不影响 200。
- **`POST /client/surgeries/end`** 在停录 **HTTP 200** 后:向该手术会话记录的终端推送 **`action":"end"`**(并清除 assignment
- 推送 JSON 形如:`{"type":"voice_assignment","action":"start"|"end","surgery_id":"123456"}`
- **待确认队列(与 HTTP GET 成功体对齐)**:有新队首或队首变化时推送 `{"type":"voice_pending", "surgery_id":"...", "confirmation_id":"...", "pending_queue_length":1, "pending_queue_position":1, "pending_cumulative_ordinal":1, "prompt_text":"...", "prompt_audio_mp3_base64":"...", "options":[...], "model_top1_label":"...", "model_top1_confidence":0.0, "created_at":"..."}`(字段与 `GET /client/surgeries/{surgery_id}/pending-confirmation` 的 200 响应相同,并多一个 `type`。FIFO 无待确认项时推送 `{"type":"voice_pending_empty","surgery_id":"123456"}`。触发时机包括:开录指派后(后台任务)、视觉入队待确认后、医生 `resolve` 成功弹出队首后、终端 **WebSocket 刚连接且当前已有指派** 时(先补发 `voice_assignment` start再补发队首或 empty
- **多 worker**:当前实现为进程内内存;多 Uvicorn worker 时需 sticky session 或 Redis 等另行同步。
## 4. 流程
@@ -189,7 +193,7 @@ flowchart LR
```
{
"surgery_id": "123456",
"camera_ids": ["or-cam-01", "or-cam-02"],
"camera_ids": ["or-cam-01", "or-cam-02", "or-cam-03", "or-cam-04"],
"candidate_consumables": ["纱布", "缝线", "止血钳"]
}
```
@@ -352,6 +356,9 @@ flowchart LR
| ------------------------- | -------- | ------------------------- |
| `surgery_id` | `string` | 手术号 |
| `confirmation_id` | `string` | 待确认项 ID提交 5.6 节接口时原样放入路径 |
| `pending_queue_length` | `int` | 当前 FIFO 中仍为 pending 的条数(含本条) |
| `pending_queue_position` | `int` | 本条在 `pending_fifo` 中的排队序号1-based队首为 1 |
| `pending_cumulative_ordinal` | `int` | 本场手术中待确认任务累计入队序号(第几条入队) |
| `prompt_text` | `string` | 播报或展示用语,与 MP3 内容一致 |
| `prompt_audio_mp3_base64` | `string` | MP3 的 Base64 |
| `options` | `array` | 候选项列表,字段见下文 |
@@ -437,7 +444,7 @@ curl -sS -X POST \
**路径** `GET /client/voice-terminals/{terminal_id}/assignment`
仓库内 **手术室耗材语音确认桌面客户端** 仅通过 **§5.8 WebSocket** 接收指派,**不调用**本接口。此处供运维脚本、未实现 WS 的第三方临时拉取 `active_surgery_id`
仓库内 **手术室耗材语音确认浏览器客户端**`web/voice-confirmation/`仅通过 **§5.8 WebSocket** 接收指派,**不调用**本接口。此处供运维脚本、未实现 WS 的第三方临时拉取 `active_surgery_id`
**响应 200**