Files
operating-room-monitor-server/docs/video-backends.md

8.1 KiB
Executable File
Raw Blame History

视频双后端说明RTSP / 海康 HCNetSDK

目标容器

  • 推荐Linux x86_64 + glibc(与当前 python:3.13-slim-bookworm 一致)。
  • 不推荐Alpinemusl加载海康预编译 .so 往往失败。
  • 镜像已安装 ffmpeg 与 OpenCV 常用系统库,便于 RTSP 录像切片与预览。

RTSP 模式(默认)

  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 未给出某路时使用。
  1. 调用 POST /client/surgeries/start 时,camera_ids 用于语音终端绑定,basket_roi_xyxy 提供主摄篮子 ROI默认仅 RTSP_PRIMARY_CAMERA_IDor-cam-03 参与 RTSP 录像与 6-4 篮子推流算法。
  2. 开录确认:主摄 RTSP 录像进程在超时内成功连接并写入首段数据后,才认为开录成功。
  3. RTSP 预热(可选):设置 RTSP_PREWARM_ENABLED=trueAPI 进程启动即对站点 JSON 中 全部 video_rtsp_urls 机位后台 ffmpeg keep-alive 拉流;开录/停录时暂停/恢复对应机位,避免与录像双拉。日志含 RTSP prewarm connectedconnect_ms)与 RTSP start_surgery timingresolve_ms / spawn_ms / ready_ms / prewarm_was_warm)。

RTSP 录像与 6-4 推流算法(链路 1

  • FastAPI 进程内 ffmpeg 从 RTSP 拉流,默认每 120 秒RTSP_SEGMENT_DURATION_SEC)落盘一个 MP4 切片到 logs/rtsp_segments/{surgery_id}/{camera_id}/
  • 开录后服务端同时为主摄启动 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 的机位分别录像;当前 6-4 算法只跑服务端选出的主摄。
  • 同一机位同时只允许一场手术录制(默认主摄 RTSP_PRIMARY_CAMERA_ID):另一场次开录同一 camera 时返回 409 / CAMERA_ALREADY_RECORDING;注册表在拉起 ffmpeg 前即占用机位,避免双路 RTSP 抢流导致录像周期性丢帧。
  • 宿主机读切片Compose 中 api 使用 HOST_UID/HOST_GID 与宿主机对齐落盘权限;详见 Docker部署.md「RTSP 切片在宿主机无法用 VLC 打开」。

Docker 与 RTSP 地址

  • 站点 JSON 中的局域网 IP(如 [or_site_config.sample.json](../app/resources/or_site_config.sample.json)192.168.3.xAPI 在默认 bridge 网络下出站流量经 宿主机 转发,只要宿主机能访问该网段,容器内一般可直接使用相同 URL无需改成 172.x 等。
  • 127.0.0.1 / localhost:在容器内指向容器自身。若 RTSP 服务跑在宿主机或本机 MediaMTXURL 应使用 rtsp://host.docker.internal:<端口>/<路径>backend/docker-compose.yml 已为 api 服务配置 extra_hosts: host.docker.internal:host-gatewayLinux 兼容macOS/Windows Desktop 通常已内置该主机名)。
  • 传输协议compose 默认设置环境变量 OPENCV_FFMPEG_CAPTURE_OPTIONS=rtsp_transport;tcp,使 ffmpeg/OpenCV 经 TCP 拉 RTSP降低容器/NAT 下 UDP 丢包导致的首帧超时;可通过环境变量覆盖。

海康官方 SDK 模式(可选)

SDK 不作为构建期依赖:将厂商提供的 Linux x86_64 动态库挂载到容器内(例如 /opt/hikvision/lib/libhcnetsdk.so),并设置:

  • HIKVISION_SDK_ENABLED=true
  • HIKVISION_DEVICE_IP / HIKVISION_USER / HIKVISION_PASSWORD(以及可选端口)
  • HIKVISION_PREVIEW_RTSP_TEMPLATEHIKVISION_CAMERA_RTSP_URLS_JSON:登录成功后仍通过 RTSP 取帧送模型与常见部署一致SDK 负责设备会话,码流仍走 RTSP

行为概要:

  1. 进程内对 NET_DVR_Init 使用引用计数;每路使用 SDK 的工作线程在登录后 NET_DVR_Logout,线程结束时配对 NET_DVR_Cleanup
  2. HIKVISION_SDK_FALLBACK_TO_RTSP=true(默认),在无法加载动态库登录失败未配置凭据时,自动回退到 OR 站点配置中的 video_rtsp_urlsVIDEO_RTSP_URL_TEMPLATE 拉流。

注意NET_DVR_Login_V30 的设备信息结构体在不同 SDK 版本上可能存在差异;若登录异常,请优先使用 RTSP 回退或按厂商文档校对 ctypes 绑定。

推理与结果查询

链路 1RTSP + 6-4 推流算法(main_basket_stream.py

  • 开录后 FastAPI 用 ffmpeg 保留录像,同时启动 6-4 篮子推流子进程;客户端必须传主摄 basket_roi_xyxy
  • 候选耗材清单candidate_consumables):非空时清单内名称参与自动记账与待确认;缺省或 [] 时,用 consumable_classifier_labels.yaml全部类名作为候选。
  • 当 Top1 置信度 VIDEO_AUTO_CONFIRM_CONFIDENCE默认 0.9)且标签在候选清单内时,自动写入 source=sixfour_stream 明细;中间区间入待确认队列,由语音终端 TTS/确认。
  • 客户端 GET /client/surgeries/{surgery_id}/pending-confirmation,确认后 POST .../pending-confirmation/{id}/resolve 等。

链路 3离线 batchPOST /internal/demo/offline-batch

  • FastAPI 编排层 app/algo_host 为 5.15 准备工作目录(config.yaml、白名单、商品表),子进程直调 algorithm_subprocesses/5.15/main.py --config;解析 result.tsv 后入库。在 API 进程内加载模型,修改 5.15 源码。
  • 可选标注视频由子进程 visualize_result_video.py 生成;结果缓存键为 sha256(video) + candidate_list(跨手术号复用)。
  • 启动实时会话、触发语音终端。

通用

  • GET /client/surgeries/{surgery_id}/result 仅在存在至少一条消耗明细时返回 200无明细已开录但尚未记账、已结束但零消耗、或尚无归档等返回 503 RESULT_NOT_READY
  • 同类物品写入受 VIDEO_DETAIL_COOLDOWN_SEC 节流。

Demo 联调台HLS 浏览器预览

浏览器无法直接播放 RTSP。联调台通过 MediaMTX 将 RTSP 转为 HLS,由 FastAPI 反代 m3u8/ts 后由 hls.js 播放。

部署方式 行为
Docker Compose推荐 固定服务 mediamtx-hls(宿主机 127.0.0.1:18888,容器内 mediamtx-hls:8888hls-preview-init 种子共享卷后 MediaMTX 直接读 /config/mediamtx.yml(官方镜像是 scratch勿用 /bin/sh entrypointensure 写共享 mediamtx.ymldocker restart orm-mediamtx-hlsDEMO_HLS_PREVIEW_UPSTREAM=http://mediamtx-hls:8888
本机 uvicorn 未设 upstream 时按需 docker run 临时 MediaMTX端口默认 127.0.0.1:18888
链路 行为
链路 1(真 RTSP POST /internal/demo/hls-preview/ensureor_site_configvideo_rtsp_urls 配置 MediaMTX 路径
  • 播放地址:GET /internal/demo/hls-preview/{camera_id}/index.m3u8playlist 内 URL 重写为 API 路径)。
  • Compose 需将 docker.sock 挂入 api(用于 reload mediamtx-hls

单帧 JPEG 预览仍保留:GET /internal/demo/rtsp-preview/{camera_id}/frame.jpg

相关环境变量

详见 backend/.env.example 中「视频RTSP + 切片 batch」、RTSP 预热、HLS 预览与可选海康 HCNetSDK 相关注释。