Route live recording through ffmpeg MP4 segments and the 5.15 batch subprocess, remove simulated RTSP chain 2, purge expired slices on startup and hourly, and expose TTL settings to the demo client. Co-authored-by: Cursor <cursoragent@cursor.com>
7.1 KiB
Executable File
7.1 KiB
Executable File
视频双后端说明(RTSP / 海康 HCNetSDK)
目标容器
- 推荐:
Linux x86_64+ glibc(与当前python:3.13-slim-bookworm一致)。 - 不推荐:Alpine(musl)加载海康预编译
.so往往失败。 - 镜像已安装 ffmpeg 与 OpenCV 常用系统库,便于 RTSP 录像切片与预览。
RTSP 模式(默认)
- 配置
**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未给出某路时使用。
- 调用
POST /client/surgeries/start时,camera_ids用于语音终端绑定;默认仅RTSP_PRIMARY_CAMERA_ID(or-cam-03) 参与 RTSP 录像与 batch 算法。 - 开录确认:主摄 RTSP 录像进程在超时内成功连接并写入首段数据后,才认为开录成功。
RTSP 录像切片(链路 1)
- FastAPI 进程内 ffmpeg 从 RTSP 拉流,默认每 120 秒(
RTSP_SEGMENT_DURATION_SEC)落盘一个 MP4 切片到logs/rtsp_segments/{surgery_id}/{camera_id}/。 - 每个完整切片通过
BatchAlgorithmService子进程调用algorithm_subprocesses/5.15/main.py(与链路 3 相同),解析result.tsv后写入活跃会话。 - 停录时 flush 尾切片并等待 batch 队列 drain(
RTSP_SLICE_BATCH_DRAIN_TIMEOUT_SEC)。 - 落盘切片默认 24 小时后自动删除(
RTSP_SEGMENT_TTL_HOURS;进程启动与后台定时 sweep)。 - 设置
RTSP_RECORD_ALL_CAMERAS=true可对请求中所有可解析 RTSP 的机位分别录像+跑 batch(多机位代码已预留)。
Docker 与 RTSP 地址
- 站点 JSON 中的局域网 IP(如
[or_site_config.sample.json](../app/resources/or_site_config.sample.json)的192.168.3.x):API 在默认 bridge 网络下出站流量经 宿主机 转发,只要宿主机能访问该网段,容器内一般可直接使用相同 URL,无需改成172.x等。 127.0.0.1/localhost:在容器内指向容器自身。若 RTSP 服务跑在宿主机或本机 MediaMTX,URL 应使用rtsp://host.docker.internal:<端口>/<路径>。backend/docker-compose.yml已为api服务配置extra_hosts: host.docker.internal:host-gateway(Linux 兼容;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=trueHIKVISION_DEVICE_IP/HIKVISION_USER/HIKVISION_PASSWORD(以及可选端口)HIKVISION_PREVIEW_RTSP_TEMPLATE或HIKVISION_CAMERA_RTSP_URLS_JSON:登录成功后仍通过 RTSP 取帧送模型(与常见部署一致:SDK 负责设备会话,码流仍走 RTSP)。
行为概要:
- 进程内对
NET_DVR_Init使用引用计数;每路使用 SDK 的工作线程在登录后NET_DVR_Logout,线程结束时配对NET_DVR_Cleanup。 - 若
HIKVISION_SDK_FALLBACK_TO_RTSP=true(默认),在无法加载动态库、登录失败或未配置凭据时,自动回退到 OR 站点配置中的video_rtsp_urls或VIDEO_RTSP_URL_TEMPLATE拉流。
注意:NET_DVR_Login_V30 的设备信息结构体在不同 SDK 版本上可能存在差异;若登录异常,请优先使用 RTSP 回退或按厂商文档校对 ctypes 绑定。
推理与结果查询
链路 1:RTSP 切片 + batch(5.15/main.py)
- 开录后 FastAPI 用 ffmpeg 录像并按
RTSP_SEGMENT_DURATION_SEC切片;每段 MP4 经 batch 子进程推理,结果按 TSV 置信度写入会话。 - 候选耗材清单(
candidate_consumables):非空时仅清单内名称参与自动记账与待确认;缺省或[]时,用consumable_classifier_labels.yaml的 全部类名作为候选。 - 当 Top1 置信度 ≥
VIDEO_AUTO_CONFIRM_CONFIDENCE(默认 0.9)且标签在候选清单内时,自动写入source=video_batch明细;中间区间入待确认队列,由语音终端 TTS/确认。 - 客户端
GET /client/surgeries/{surgery_id}/pending-confirmation,确认后POST .../pending-confirmation/{id}/resolve等。
链路 3:离线 batch(POST /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;无明细(已开录但尚未记账、已结束但零消耗、或尚无归档等)返回 503RESULT_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:8888);hls-preview-init 种子共享卷后 MediaMTX 直接读 /config/mediamtx.yml(官方镜像是 scratch,勿用 /bin/sh entrypoint);ensure 写共享 mediamtx.yml 并 docker restart orm-mediamtx-hls;DEMO_HLS_PREVIEW_UPSTREAM=http://mediamtx-hls:8888 |
| 本机 uvicorn | 未设 upstream 时按需 docker run 临时 MediaMTX(端口默认 127.0.0.1:18888) |
| 链路 | 行为 |
|---|---|
| 链路 1(真 RTSP) | POST /internal/demo/hls-preview/ensure 按 or_site_config 的 video_rtsp_urls 配置 MediaMTX 路径 |
- 播放地址:
GET /internal/demo/hls-preview/{camera_id}/index.m3u8(playlist 内 URL 重写为 API 路径)。 - Compose 需将 docker.sock 挂入
api(用于 reload mediamtx-hls)。
单帧 JPEG 预览仍保留:GET /internal/demo/rtsp-preview/{camera_id}/frame.jpg。
相关环境变量
详见 backend/.env.example 中「视频:RTSP + 切片 batch」、HLS 预览与可选海康 HCNetSDK 相关注释。