update at 2026-06-04 14:09:16
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user