- machine_config:系统级 + 用户级 voice_client.json 合并,界面失焦保存至用户目录 - 移除「当前手术号」表单项与占位文案;指派后仅在窗口标题显示手术号 - WebSocket 连接日志附带绑定/开录路径排查说明 - 开录未推送时服务端 WARNING(无站点绑定或 camera_ids 不匹配) - 测试、README、.env.example 同步 Made-with: Cursor
5.8 KiB
手术室耗材语音确认客户端(桌面版)
独立桌面程序:按可配置间隔(默认 5 秒)轮询 GET /client/surgeries/{surgery_id}/pending-confirmation,播放服务端返回的 MP3 话术,录制医生麦克风为 16 kHz 单声道 WAV,并调用 POST .../pending-confirmation/{confirmation_id}/resolve(multipart 字段名 audio)。协议与 [docs/客户端手术通信接口说明.md](../docs/客户端手术通信接口说明.md) 一致。
环境
- Python 3.13+(与主项目一致)
- 安装可选依赖组 voice-client(PySide6、httpx、numpy、sounddevice、websocket-client)
cd /path/to/operation-room-monitor-server
uv sync --group voice-client
运行(开发态)
未配置项目 build-system 时,uv 可能不会注册 voice-confirmation-client 命令,推荐:
./start_voice_confirmation_client.sh
或在仓库根目录:
uv run --group voice-client python -m voice_confirmation_client
Windows(仓库根目录):
start_voice_confirmation_client.bat
若 entry point 已可用,也可:
uv run --group voice-client voice-confirmation-client
术间 / 摄像头 / 语音终端对应关系只在服务端 **OR_SITE_CONFIG_JSON_FILE** 里维护一份(voice_or_room_bindings);桌面程序不读该文件。
本机要做的只有两件事:服务端 Base URL,以及 本机语音终端 ID(须等于 JSON 里某条 voice_terminal_id)。手术号不在客户端输入:勾选 启用服务端自动指派 后,开录/停录仅通过 WebSocket voice_assignment 下发(断线后自动重连,不用 HTTP 轮询);当前手术号在窗口标题中显示;停录后自动停止。可用 停止监控(本机) 做本地紧急中断。
配置文件(系统级 + 用户级)
字段均为 UTF-8 JSON(voice_terminal_id、http_base_url,均可选)。启动时 合并 两层配置:用户级覆盖系统级 同名字段。
| 层级 | 用途 | 默认路径 |
|---|---|---|
| 系统级 | 运维装机下发(只读亦可) | Windows %ProgramData%\OperationRoomMonitor\voice_client.json;macOS /Library/Application Support/OperationRoomMonitor/voice_client.json;Linux /etc/operation-room-monitor/voice_client.json |
| 用户级 | 在界面修改「服务端 Base URL」或「本机语音终端 ID」并 离开输入框 后自动保存 | Windows %LOCALAPPDATA%\OperationRoomMonitor\voice_client.json;macOS ~/Library/Application Support/OperationRoomMonitor/voice_client.json;Linux ~/.config/operation-room-monitor/voice_client.json |
测试或定制安装可用环境变量 VOICE_CLIENT_MACHINE_CONFIG_FILE、VOICE_CLIENT_USER_CONFIG_FILE 分别覆盖上述两个路径。
示例见 voice_confirmation_client/resources/voice_client.sample.json(通常用作系统级模板)。
日志(loguru)
客户端使用 loguru:右侧日志区与启动终端 stderr 会同时输出。开录无反应时请看是否出现「本机语音终端 ID 为空」、WebSocket 已连接、收到 voice_assignment start、或反复「WebSocket 断开」等行。
音频说明
- 播放 MP3:优先使用本机
ffplay(ffmpeg),其次 macOS 使用afplay;可将ffplay放到voice_confirmation_client/bin/(与包同级目录下的bin/)以便离线环境使用。 - 录音:默认使用 sounddevice 录制并重采样为 16 kHz 单声道 WAV(与浏览器 Demo 一致)。可选勾选 优先使用 ffmpeg 录音(依赖本机 ffmpeg 及可用的设备参数;Windows 默认设备名可能需按现场调整,见
voice_confirmation_client/core/record.py中default_ffmpeg_input_args)。
打包(PyInstaller)
在 目标操作系统 上构建(不要交叉编译 Qt 桌面程序)。
uv sync --group voice-client-build
uv run --group voice-client-build pyinstaller voice_client.spec --noconfirm
# 或
uv run --group voice-client-build python scripts/build_voice_client.py
Windows 一键打包(仓库根目录):双击或在 cmd 中执行 build_voice_confirmation_client.bat;需要干净构建时加参数 --clean(会先删除 build/、dist/)。
产物目录:dist/voice-confirmation-client/(目录分发,内含可执行文件)。Windows 下可执行文件为 voice-confirmation-client.exe。
说明:
- 体积较大(含 PySide6);杀毒软件可能对 PyInstaller 打包的 exe 误报,可向医院 IT 申请加白。
- macOS:未签名/未公证的
.app可能需在「隐私与安全性」中手动允许;正式发布需 Apple 开发者签名与公证。 - 可选:将
ffmpeg/ffplay二进制放入打包目录下的voice_confirmation_bin/,程序会优先使用(需在 spec 中增加datas将该目录打入包内,或手动复制到分发目录)。
术间排查
- 网络:客户端机器能访问监控服务 HTTP/HTTPS 端口(默认文档为
38080)。 - 麦克风:在「输入设备」中选择正确设备;无列表时检查系统隐私权限(麦克风)。
- 无待确认:轮询返回 404 为常态;可关闭「隐藏 404 轮询日志」观察请求节奏。
- 解析失败:使用 重试本轮 重新播放 + 录音 + 上传;或使用 仅重播话术 听清提示。
与浏览器 Demo 的差异
- 浏览器 Demo(
scripts/demo_client/)默认 10 秒 轮询;本客户端默认 5 秒,可在界面修改。 - 本客户端无「开始/结束手术」按钮;手术需由既有流程或他端调用
POST /client/surgeries/start启动;若启用自动指派,开录成功后本机将自动开始待确认轮询。