feat(video): 可配置 RTSP 打开超时并提高默认时长
- Settings 增加 video_open_timeout_sec(VIDEO_OPEN_TIMEOUT_SEC),默认 45s - SessionManager 全部就绪等待为该值 + 5s;StreamWorker 传入单路超时 - baked pipeline 回退默认值与配置对齐;.env.example 补充说明 - or_site_config.sample.json 扩展穿透摄像头与术间绑定示例 - 同步 uv.lock
This commit is contained in:
@@ -19,6 +19,8 @@ POSTGRES_PORT=35432
|
||||
# UVICORN_RELOAD=true
|
||||
|
||||
# --- Video:RTSP 与按路后端(须与客户端 camera_ids 一致)---
|
||||
# 单路 RTSP 首次打开超时(秒);四路须在「该值 + 5」秒内全部就绪,穿透/公网链路可调大(默认 45)。
|
||||
# VIDEO_OPEN_TIMEOUT_SEC=45
|
||||
# VIDEO_DEFAULT_BACKEND=rtsp
|
||||
# VIDEO_CAMERA_BACKEND_OVERRIDES_JSON={"or-cam-01":"rtsp","or-cam-02":"hikvision_sdk"}
|
||||
# 站点 JSON:术间↔摄像头↔语音终端只在这里维护(voice_or_room_bindings);须同时含 video_rtsp_urls;可为 []。
|
||||
|
||||
@@ -5,7 +5,8 @@ SURGERY_RECORDING_MAX_ATTEMPTS: int = 3
|
||||
SURGERY_RECORDING_RETRY_DELAY_SECONDS: float = 1.0
|
||||
|
||||
# --- RTSP 连接与抽帧、推理门控(不含 URL,URL 在 Settings)---
|
||||
VIDEO_OPEN_TIMEOUT_SEC: float = 15.0
|
||||
# 运行时以 Settings.video_open_timeout_sec(环境变量 VIDEO_OPEN_TIMEOUT_SEC)为准;此处为未注入 Settings 时的回退默认。
|
||||
VIDEO_OPEN_TIMEOUT_SEC: float = 45.0
|
||||
VIDEO_READ_FAILURE_RECONNECT_THRESHOLD: int = 15
|
||||
VIDEO_RECONNECT_BACKOFF_SECONDS: float = 1.0
|
||||
VIDEO_INFERENCE_INTERVAL_SEC: float = 2.0
|
||||
|
||||
@@ -41,6 +41,7 @@ class _VideoGroup(_SettingsGroup):
|
||||
"video_default_backend",
|
||||
"video_camera_backend_overrides_json",
|
||||
"video_rtsp_url_template",
|
||||
"video_open_timeout_sec",
|
||||
"or_site_config_json_file",
|
||||
)
|
||||
|
||||
@@ -142,6 +143,13 @@ class Settings(BaseSettings):
|
||||
video_default_backend: Literal["rtsp", "hikvision_sdk", "auto"] = "rtsp"
|
||||
video_camera_backend_overrides_json: str = ""
|
||||
video_rtsp_url_template: str = ""
|
||||
#: 单路 RTSP 首次打开超时(秒);术间「全部摄像头就绪」等待为该值 + 5s。穿透/公网链路可调大。
|
||||
video_open_timeout_sec: float = Field(
|
||||
default=45.0,
|
||||
ge=5.0,
|
||||
le=900.0,
|
||||
validation_alias=AliasChoices("VIDEO_OPEN_TIMEOUT_SEC", "video_open_timeout_sec"),
|
||||
)
|
||||
#: 手术室站点配置(UTF-8 JSON):须含 video_rtsp_urls 与 voice_or_room_bindings,见 or_site_config.sample.json
|
||||
or_site_config_json_file: str = ""
|
||||
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"video_rtsp_urls": {
|
||||
"or-cam-01": "rtsp://admin:Aa183137@192.168.3.2:554/Streaming/Channels/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"
|
||||
"or-cam-01": "rtsp://127.0.0.1:18554/demo1"
|
||||
},
|
||||
"voice_or_room_bindings": [
|
||||
{
|
||||
@@ -13,6 +10,16 @@
|
||||
"or-cam-03",
|
||||
"or-cam-04"
|
||||
],
|
||||
"or_room_id": "OR-ROOM1",
|
||||
"voice_terminal_id": "desktop-2"
|
||||
},
|
||||
{
|
||||
"camera_ids": [
|
||||
"or-cam-101",
|
||||
"or-cam-102",
|
||||
"or-cam-103",
|
||||
"or-cam-104"
|
||||
],
|
||||
"or_room_id": "OR-TEST",
|
||||
"voice_terminal_id": "desktop-1"
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ class CameraSessionManager:
|
||||
stop_event = asyncio.Event()
|
||||
readies = [asyncio.Event() for _ in camera_ids]
|
||||
tasks: list[asyncio.Task[None]] = []
|
||||
open_timeout = bp.VIDEO_OPEN_TIMEOUT_SEC + 5.0
|
||||
open_timeout = float(self._s.video_open_timeout_sec) + 5.0
|
||||
|
||||
for cam_id, ready in zip(camera_ids, readies, strict=True):
|
||||
tasks.append(
|
||||
@@ -438,6 +438,7 @@ class CameraSessionManager:
|
||||
surgery_id=surgery_id,
|
||||
camera_id=camera_id,
|
||||
url=url,
|
||||
open_timeout_sec=self._s.video_open_timeout_sec,
|
||||
)
|
||||
try:
|
||||
await w_tear.run(
|
||||
@@ -518,6 +519,7 @@ class CameraSessionManager:
|
||||
surgery_id=surgery_id,
|
||||
camera_id=camera_id,
|
||||
url=url,
|
||||
open_timeout_sec=self._s.video_open_timeout_sec,
|
||||
)
|
||||
await worker.run(
|
||||
stream_ready=stream_ready,
|
||||
|
||||
@@ -41,10 +41,14 @@ class CameraStreamWorker:
|
||||
surgery_id: str,
|
||||
camera_id: str,
|
||||
url: str,
|
||||
open_timeout_sec: float | None = None,
|
||||
) -> None:
|
||||
self._surgery_id = surgery_id
|
||||
self._camera_id = camera_id
|
||||
self._url = url
|
||||
self._open_timeout_sec = (
|
||||
float(open_timeout_sec) if open_timeout_sec is not None else bp.VIDEO_OPEN_TIMEOUT_SEC
|
||||
)
|
||||
|
||||
async def run(
|
||||
self,
|
||||
@@ -63,7 +67,7 @@ class CameraStreamWorker:
|
||||
if cap is None:
|
||||
try:
|
||||
cap = RtspCapture(
|
||||
self._url, open_timeout_sec=bp.VIDEO_OPEN_TIMEOUT_SEC
|
||||
self._url, open_timeout_sec=self._open_timeout_sec
|
||||
)
|
||||
await asyncio.to_thread(cap.open)
|
||||
consecutive_failures = 0
|
||||
|
||||
Reference in New Issue
Block a user