update at 2026-06-04 14:09:16

This commit is contained in:
陈赣
2026-06-04 14:09:16 +08:00
parent 41bd03123c
commit 4603914e85
11 changed files with 692 additions and 68 deletions

View File

@@ -26,6 +26,7 @@ class StreamWorker:
self.lock = threading.Lock()
self.latest_jpeg: bytes | None = None
self.latest_frame_rgb: Any | None = None
self.latest_detections: list[dict[str, Any]] = []
self.frame_id = 0
self.updated_at = 0.0
@@ -56,21 +57,30 @@ class StreamWorker:
def reconnect(self) -> None:
with self.lock:
self.latest_jpeg = None
self.latest_frame_rgb = None
self.latest_detections = []
self.frame_id = 0
self.fps = 0.0
self.reconnect_requested = True
self.reconnect_version += 1
version = self.reconnect_version
self.connected = False
self.error = "正在切换视频源"
self.resolve_ms = 0.0
self.open_ms = 0.0
self.first_frame_ms = 0.0
print(f"[device-switch] worker reconnect requested version={version}", flush=True)
def get_jpeg(self) -> bytes | None:
with self.lock:
return self.latest_jpeg
def get_frame_rgb(self) -> Any | None:
with self.lock:
if self.latest_frame_rgb is None:
return None
return self.latest_frame_rgb.copy()
def get_snapshot(self) -> dict[str, Any]:
with self.lock:
return {
@@ -100,16 +110,29 @@ class StreamWorker:
run_version = self.reconnect_version
self.reconnect_requested = False
if should_reconnect:
print(f"[device-switch] worker reconnect handling version={run_version}", flush=True)
# 切换摄像头时必须释放旧连接,否则 OpenCV 会继续阻塞读旧流。
if cap is not None:
cap.release()
cap = None
print(f"[device-switch] worker released old capture version={run_version}", flush=True)
if cap is None or not cap.isOpened():
started = time.monotonic()
stream_url = self.stream_url() if callable(self.stream_url) else self.stream_url
try:
stream_url = self.stream_url() if callable(self.stream_url) else self.stream_url
except Exception as exc:
resolve_ms = round((time.monotonic() - started) * 1000, 2)
with self.lock:
self.resolve_ms = resolve_ms
self.open_ms = 0.0
self.first_frame_ms = 0.0
self._set_connection_state(False, f"获取播放地址失败:{exc}2 秒后重试")
time.sleep(2)
continue
resolve_ms = round((time.monotonic() - started) * 1000, 2)
started = time.monotonic()
print(f"[device-switch] worker open start version={run_version}", flush=True)
cap = cv2.VideoCapture(stream_url)
open_ms = round((time.monotonic() - started) * 1000, 2)
with self.lock:
@@ -117,11 +140,13 @@ class StreamWorker:
self.resolve_ms = resolve_ms
self.first_frame_ms = 0.0
if not cap.isOpened():
print(f"[device-switch] worker open failed version={run_version} open_ms={open_ms}", flush=True)
self._set_connection_state(False, "无法打开视频流2 秒后重试")
cap.release()
cap = None
time.sleep(2)
continue
print(f"[device-switch] worker open success version={run_version} open_ms={open_ms}", flush=True)
self._set_connection_state(True, "已连接")
started = time.monotonic()
@@ -143,9 +168,9 @@ class StreamWorker:
frame = self._resize(frame)
self.frame_id += 1
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
if self.frame_id % self.frame_skip == 0:
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
last_detections = self.detector.detect(frame_rgb)
annotated = self._draw(frame, last_detections)
@@ -173,6 +198,7 @@ class StreamWorker:
with self.lock:
self.latest_jpeg = jpeg.tobytes()
self.latest_frame_rgb = frame_rgb.copy()
self.latest_detections = list(last_detections)
self.updated_at = time.time()
self.connected = True