- Refine effective candidate consumables and classifier labels - Adjust vision algorithm, TSV logging, and video session wiring - Refresh client surgery HTTP contract doc and staging/video docs - Update settings, docker-compose prod, tests, and uv.lock Made-with: Cursor
18 KiB
手术室监控服务:客户端手术通信接口说明
能力概览
| 能力 | 说明 |
|---|---|
| 探活 | GET /health,用于检查进程和数据库状态,详见 5.1 节。 |
| 开始手术 | 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。 |
| 待确认答复 | POST /client/surgeries/{surgery_id}/pending-confirmation/{confirmation_id}/resolve,上传医生答复的 WAV 录音,服务端完成 ASR 后入账或关闭。该录音与播报音频无关。 |
1. 服务与基础信息
| 项目 | 说明 |
|---|---|
| 协议 | HTTP/HTTPS |
| 端口 | 38080,生产环境以实际入口为准 |
| 路由 | 无全局前缀;业务接口位于 /client/...,健康检查位于 /health |
start / end 请求体 |
JSON |
resolve 请求体 |
multipart/form-data,字段名为 audio |
| 在线文档 | /docs、/redoc |
2. 摄像头 ID 与 RTSP
RTSP 地址、账号、口令等由客户端对接工程师提供给服务端运维,运维再写入服务端环境。客户端只在 POST /client/surgeries/start 中传 camera_ids。
| camera_id | RTSP | 备注 |
|---|---|---|
or-cam-01 |
rtsp://...(由现场或 NVR 文档整理后交给运维) |
术间、机位 |
or-cam-02 |
... |
... |
3. HTTP 路由一览
| 序号 | 方法 | 路径 | 说明 |
|---|---|---|---|
| 1 | GET |
/health |
探活 |
| 2 | POST |
/client/surgeries/start |
开始手术 |
| 3 | POST |
/client/surgeries/end |
结束手术 |
| 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 |
提交医生答复 |
4. 流程
4.1 时序图
sequenceDiagram
participant Client as 客户端
participant Server as 服务端
Client->>Server: POST /client/surgeries/start
Note over Client,Server: body: surgery_id, camera_ids, candidate_consumables
Server-->>Client: 200 accepted(开录已确认)
par 术中
loop 轮询结果
Client->>Server: GET .../result
Server-->>Client: 200 或 503 RESULT_NOT_READY
end
loop 轮询待确认
Client->>Server: GET .../pending-confirmation
Server-->>Client: 200 或 404
opt 有待确认
Client->>Client: 播放 prompt_audio_mp3_base64
Client->>Server: POST .../resolve(multipart audio)
Server-->>Client: 200 accepted
end
end
end
Client->>Server: POST /client/surgeries/end
Server-->>Client: 200 accepted(停录已确认)
Client->>Server: GET .../result
Server-->>Client: 200(持久化后可查时返回)
4.2 状态图
flowchart LR
A[未开始] -->|start 200| B[录制 / 推理中]
B -->|result 200| C[有消耗数据可查]
B -->|pending 200| D[待确认]
D -->|resolve| B
B -->|end 200| E[已结束]
E -->|result 200| C
5. 接口详情
路径参数 surgery_id
| 约束项 | 说明 |
|---|---|
| 长度 | 固定 6 |
| 字符集 | 仅数字 |
| 正则 | ^\d{6}$ |
业务错误响应
多数业务失败在 4xx 或 5xx 下返回如下 JSON:
{
"detail": {
"code": "错误码字符串",
"message": "人类可读说明",
"surgery_id": "123456"
}
}
5.1 探活
基本信息
| 项目 | 内容 |
|---|---|
| 方法 | GET |
| 路径 | /health |
| 请求体 | 无 |
响应说明
| HTTP | 说明 | 响应体示例 |
|---|---|---|
200 |
进程正常且数据库可连通 | {"status":"ok","database":"connected"} |
503 |
数据库不可用(降级) | {"status":"degraded","database":"unavailable"} |
5.2 开始手术
基本信息
| 项目 | 内容 |
|---|---|
| 方法 | POST |
| 路径 | /client/surgeries/start |
| Content-Type | application/json; charset=utf-8 |
业务说明
-
服务端会为
camera_ids中的每个摄像头建立拉流与推理任务,只有在确认开录成功(如首帧就绪)后才返回 HTTP200。 -
candidate_consumables为空时,服务端会展开为目录中的全部耗材名。
请求体(JSON)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
surgery_id |
string |
是 | 6 位数字 |
camera_ids |
string[] |
是 | 至少 1 个;必须与运维配置的摄像头 ID 完全一致,见第 2 节 |
candidate_consumables |
string[] |
否 | 非空时仅这些名称参与自动记账与待确认;缺省或 [] 时使用全部候选 |
响应体(200)
| 字段 | 类型 | 说明 |
|---|---|---|
surgery_id |
string |
与请求一致 |
status |
string |
成功时通常为 accepted |
message |
string |
说明文案 |
状态码
| HTTP | 说明 |
|---|---|
200 |
开录已确认 |
422 |
参数校验失败,例如 surgery_id 非 6 位或 camera_ids 为空数组 |
503 |
开录未确认或录制子系统故障;detail.code 常见为 RECORDING_CANNOT_START |
请求示例
{
"surgery_id": "123456",
"camera_ids": ["or-cam-01", "or-cam-02"],
"candidate_consumables": ["纱布", "缝线", "止血钳"]
}
响应示例(200)
{
"surgery_id": "123456",
"status": "accepted",
"message": "摄像头录制已开始,手术已启动。"
}
5.3 结束手术
基本信息
| 项目 | 内容 |
|---|---|
| 方法 | POST |
| 路径 | /client/surgeries/end |
| Content-Type | application/json; charset=utf-8 |
业务说明
停止该 surgery_id 关联的全部摄像头任务,只有在确认停录完成后才返回 200。
请求体(JSON)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
surgery_id |
string |
是 | 6 位数字 |
响应体(200)
字段含义与 5.2 节一致,message 示例为 摄像头录制已停止,手术已结束。
状态码
| HTTP | 说明 |
|---|---|
200 |
停录已确认 |
422 |
参数校验失败 |
503 |
停录未确认或故障;detail.code 常见为 RECORDING_NOT_STOPPED |
请求示例
{
"surgery_id": "123456"
}
5.4 查询手术结果
基本信息
| 项目 | 内容 |
|---|---|
| 方法 | GET |
| 路径 | /client/surgeries/{surgery_id}/result |
| 路径参数 | surgery_id |
| 请求体 | 无 |
业务说明
-
仅当存在至少一条消耗明细时返回
200。 -
无明细(包括已归档但零消耗)、手术未开始、未成功开录或当前尚不可查时,返回
503。 -
上述
503场景的常见错误码为RESULT_NOT_READY。
响应体(200)
| 字段 | 类型 | 说明 |
|---|---|---|
surgery_id |
string |
手术号 |
status |
string |
成功时通常为 completed |
message |
string |
说明 |
details |
array |
消耗明细列表,字段见下文 |
summary |
array |
按 item_id 汇总的结果,字段见下文 |
details[] 元素
| 字段 | 类型 | 说明 |
|---|---|---|
item_id |
string |
物品 ID;有目录时多为产品编码,否则通常与名称或模型类名一致 |
item_name |
string |
物品名称 |
qty |
integer |
本条记录数量,当前恒为 1;一次识别或一次人工确认只追加一条明细 |
doctor_id |
string |
记账关联的医生或系统标识 |
timestamp |
string |
ISO 8601 时间(date-time) |
summary[] 元素
| 字段 | 类型 | 说明 |
|---|---|---|
item_id |
string |
与明细一致 |
item_name |
string |
名称,通常取该 item_id 首条明细中的名称 |
total_quantity |
integer |
该物品在本台手术中的合计数量,>= 0 |
状态码
| HTTP | 说明 |
|---|---|
200 |
至少有一条明细 |
422 |
surgery_id 路径不符合约束 |
503 |
RESULT_NOT_READY,当前无可用明细或不可查 |
响应示例(200)
{
"surgery_id": "123456",
"status": "completed",
"message": "查询成功。",
"details": [
{
"item_id": "19246-3-14",
"item_name": "医用纱布敷料",
"qty": 1,
"doctor_id": "6611",
"timestamp": "2026-04-21T10:30:00+08:00"
}
],
"summary": [
{
"item_id": "19246-3-14",
"item_name": "医用纱布敷料",
"total_quantity": 1
}
]
}
5.5 拉取待确认耗材
基本信息
| 项目 | 内容 |
|---|---|
| 方法 | GET |
| 路径 | /client/surgeries/{surgery_id}/pending-confirmation |
| 路径参数 | surgery_id |
| 请求体 | 无 |
业务说明
-
返回当前 FIFO 队首的一条低置信度识别任务。
-
prompt_audio_mp3_base64与prompt_text内容一致,为标准 Base64 的 MP3 字符串(无换行)。 -
客户端解码后应按
audio/mpeg播放。
响应体(200)
| 字段 | 类型 | 说明 |
|---|---|---|
surgery_id |
string |
手术号 |
confirmation_id |
string |
待确认项 ID;提交 5.6 节接口时原样放入路径 |
prompt_text |
string |
播报或展示用语,与 MP3 内容一致 |
prompt_audio_mp3_base64 |
string |
MP3 的 Base64 |
options |
array |
候选项列表,字段见下文 |
model_top1_label |
string |
模型原始 Top1 类名,可能不在本台候选内 |
model_top1_confidence |
number |
Top1 置信度 |
created_at |
string |
创建时间(ISO 8601) |
options[] 元素
| 字段 | 类型 | 说明 |
|---|---|---|
label |
string |
展示给医生的选项名称 |
confidence |
number |
该选项对应的置信度 |
状态码
| HTTP | 说明 |
|---|---|
200 |
当前有一条待确认 |
404 |
无待确认或手术未活跃;常见错误码为 NO_PENDING_CONFIRMATION |
422 |
例如话术为空导致无法 TTS;错误码见响应,如 TTS_TEXT_EMPTY |
503 |
语音服务未配置或 TTS 失败;例如 BAIDU_NOT_CONFIGURED、TTS_ERROR |
5.6 提交待确认结果(医生语音)
基本信息
| 项目 | 内容 |
|---|---|
| 方法 | POST |
| 路径 | /client/surgeries/{surgery_id}/pending-confirmation/{confirmation_id}/resolve |
| Content-Type | multipart/form-data |
路径参数
| 参数 | 约束 | 说明 |
|---|---|---|
surgery_id |
6 位数字 | 同 5.0 节 |
confirmation_id |
长度 1 到 128 | 与 5.5 节响应中的 confirmation_id 一致 |
请求体(multipart)
| 字段名 | 类型 | 必填 | 说明 |
|---|---|---|---|
audio |
file |
是 | 单个 .wav 文件;建议使用 16 kHz 单声道 PCM;非 .wav 扩展名会返回 422 |
业务说明
音频上传至对象存储后执行 ASR 和候选解析。若识别为确认某个候选项,则记一条消耗;若识别为否认全部候选,则不记消耗。
响应体(200)
| 字段 | 类型 | 说明 |
|---|---|---|
surgery_id |
string |
手术号 |
confirmation_id |
string |
待确认 ID |
status |
string |
成功时为 accepted |
message |
string |
说明 |
resolved_label |
string | null |
确认后的耗材名称;否认全部候选时为 null |
rejected |
boolean |
是否否认全部候选,不记消耗时为 true |
asr_text |
string | null |
语音识别文本 |
audio_object_key |
string | null |
对象存储中的原始 WAV 键,便于追溯 |
状态码
| HTTP | 说明 |
|---|---|
200 |
已受理并完成解析 |
404 |
确认项不存在或手术未活跃;例如 CONFIRMATION_NOT_FOUND |
409 |
当前确认项已处理过;例如 CONFIRMATION_ALREADY_RESOLVED |
422 |
空文件、非 .wav、VOICE_AUDIO_INVALID、ASR/解析失败等,具体错误码见响应 |
503 |
MinIO、百度等依赖不可用;例如 MINIO_NOT_CONFIGURED、MINIO_UPLOAD_FAILED、BAIDU_NOT_CONFIGURED |
cURL 示例
curl -sS -X POST \
"http://<主机>:38080/client/surgeries/123456/pending-confirmation/<confirmation_id>/resolve" \
-F "audio=@/path/to/voice.wav;type=audio/wav"