forked from dsutanto/zenai-kpc-python
cap written stream error
This commit is contained in:
1 parent
b52e876eed
commit
706f9261fb
3 files changed
+57
-3
No files matched your search
@@ -207,6 +207,10 @@ WARMUP_FRAMES=30
|
|||||||
RECONNECT_DELAY_SEC=3
|
RECONNECT_DELAY_SEC=3
|
||||||
# Maximum reconnection attempts (0 = infinite)
|
# Maximum reconnection attempts (0 = infinite)
|
||||||
MAX_RECONNECT_ATTEMPTS=0
|
MAX_RECONNECT_ATTEMPTS=0
|
||||||
|
# Max stream-error log lines per outage (Cannot open / Stream dropped).
|
||||||
|
# After this, further errors are silent until the stream recovers; then the
|
||||||
|
# budget resets for the next outage. 0 = unlimited.
|
||||||
|
STREAM_ERROR_LOG_MAX=3
|
||||||
# Seconds after which a tracked but unseen object is pruned from the active set
|
# Seconds after which a tracked but unseen object is pruned from the active set
|
||||||
TRACKED_PRUNE_SEC=300
|
TRACKED_PRUNE_SEC=300
|
||||||
|
|
||||||
|
|||||||
+51
-3
@@ -96,6 +96,10 @@ RATE_WINDOW_SEC = int(os.getenv("RATE_WINDOW_SEC", "60"))
|
|||||||
WARMUP_FRAMES = int(os.getenv("WARMUP_FRAMES", "30"))
|
WARMUP_FRAMES = int(os.getenv("WARMUP_FRAMES", "30"))
|
||||||
RECONNECT_DELAY_SEC = int(os.getenv("RECONNECT_DELAY_SEC", "3"))
|
RECONNECT_DELAY_SEC = int(os.getenv("RECONNECT_DELAY_SEC", "3"))
|
||||||
MAX_RECONNECT_ATTEMPTS = int(os.getenv("MAX_RECONNECT_ATTEMPTS", "0"))
|
MAX_RECONNECT_ATTEMPTS = int(os.getenv("MAX_RECONNECT_ATTEMPTS", "0"))
|
||||||
|
# Max stream-error prints per outage (Cannot open / Stream dropped). After this,
|
||||||
|
# further errors are silent until the stream recovers, then the budget resets.
|
||||||
|
# 0 = unlimited (old behavior).
|
||||||
|
STREAM_ERROR_LOG_MAX = int(os.getenv("STREAM_ERROR_LOG_MAX", "3"))
|
||||||
TRACKED_PRUNE_SEC = int(os.getenv("TRACKED_PRUNE_SEC", "300"))
|
TRACKED_PRUNE_SEC = int(os.getenv("TRACKED_PRUNE_SEC", "300"))
|
||||||
RECORD_VIDEO = os.getenv("RECORD_VIDEO", "false").lower() == "true"
|
RECORD_VIDEO = os.getenv("RECORD_VIDEO", "false").lower() == "true"
|
||||||
VIDEO_SEGMENT_SEC = int(os.getenv("VIDEO_SEGMENT_SEC", "3600")) # legacy segment mode only
|
VIDEO_SEGMENT_SEC = int(os.getenv("VIDEO_SEGMENT_SEC", "3600")) # legacy segment mode only
|
||||||
@@ -1168,6 +1172,46 @@ def draw_popups(img, popups, frame_idx):
|
|||||||
return alive
|
return alive
|
||||||
|
|
||||||
|
|
||||||
|
class StreamErrorLog:
|
||||||
|
"""Rate-limit stream error prints to STREAM_ERROR_LOG_MAX per outage.
|
||||||
|
|
||||||
|
After the cap, messages are suppressed until note_up() when the stream
|
||||||
|
is healthy again; the next drop starts a fresh budget.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, max_logs=STREAM_ERROR_LOG_MAX):
|
||||||
|
self.max_logs = int(max_logs)
|
||||||
|
self._emitted = 0
|
||||||
|
self._suppressed = 0
|
||||||
|
|
||||||
|
def emit(self, msg: str) -> None:
|
||||||
|
if self.max_logs <= 0:
|
||||||
|
print(msg)
|
||||||
|
return
|
||||||
|
if self._emitted < self.max_logs:
|
||||||
|
self._emitted += 1
|
||||||
|
print(msg)
|
||||||
|
if self._emitted >= self.max_logs:
|
||||||
|
print(
|
||||||
|
f"[{now_str()}] Stream errors capped at {self.max_logs} "
|
||||||
|
f"this outage — further messages suppressed until stream recovers"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._suppressed += 1
|
||||||
|
|
||||||
|
def note_up(self) -> None:
|
||||||
|
if self._suppressed > 0:
|
||||||
|
print(
|
||||||
|
f"[{now_str()}] Stream recovered "
|
||||||
|
f"(suppressed {self._suppressed} error log(s) during outage)"
|
||||||
|
)
|
||||||
|
self._emitted = 0
|
||||||
|
self._suppressed = 0
|
||||||
|
|
||||||
|
|
||||||
|
stream_error_log = StreamErrorLog()
|
||||||
|
|
||||||
|
|
||||||
def connect_stream(source, warmup=WARMUP_FRAMES):
|
def connect_stream(source, warmup=WARMUP_FRAMES):
|
||||||
attempts = 0
|
attempts = 0
|
||||||
while not shutdown_requested:
|
while not shutdown_requested:
|
||||||
@@ -1178,7 +1222,9 @@ def connect_stream(source, warmup=WARMUP_FRAMES):
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
f"Cannot open source after {attempts} attempts: {source}"
|
f"Cannot open source after {attempts} attempts: {source}"
|
||||||
)
|
)
|
||||||
print(f"Cannot open source, retry in {RECONNECT_DELAY_SEC}s...")
|
stream_error_log.emit(
|
||||||
|
f"Cannot open source, retry in {RECONNECT_DELAY_SEC}s..."
|
||||||
|
)
|
||||||
time.sleep(RECONNECT_DELAY_SEC)
|
time.sleep(RECONNECT_DELAY_SEC)
|
||||||
continue
|
continue
|
||||||
if warmup > 0 and source.lower().startswith(("rtsp://", "http://")):
|
if warmup > 0 and source.lower().startswith(("rtsp://", "http://")):
|
||||||
@@ -1188,6 +1234,7 @@ def connect_stream(source, warmup=WARMUP_FRAMES):
|
|||||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||||
if not fps or fps <= 1:
|
if not fps or fps <= 1:
|
||||||
fps = OUTPUT_FPS
|
fps = OUTPUT_FPS
|
||||||
|
stream_error_log.note_up()
|
||||||
return cap, w, h, fps
|
return cap, w, h, fps
|
||||||
return None, 0, 0, OUTPUT_FPS
|
return None, 0, 0, OUTPUT_FPS
|
||||||
|
|
||||||
@@ -1349,8 +1396,9 @@ def run():
|
|||||||
if not IS_LIVE:
|
if not IS_LIVE:
|
||||||
break
|
break
|
||||||
reconnect_count += 1
|
reconnect_count += 1
|
||||||
print(
|
stream_error_log.emit(
|
||||||
f"Stream dropped (attempt {reconnect_count}), reconnecting in {RECONNECT_DELAY_SEC}s..."
|
f"Stream dropped (attempt {reconnect_count}), "
|
||||||
|
f"reconnecting in {RECONNECT_DELAY_SEC}s..."
|
||||||
)
|
)
|
||||||
cap.release()
|
cap.release()
|
||||||
time.sleep(RECONNECT_DELAY_SEC)
|
time.sleep(RECONNECT_DELAY_SEC)
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ RATE_WINDOW_SEC=60
|
|||||||
WARMUP_FRAMES=30
|
WARMUP_FRAMES=30
|
||||||
RECONNECT_DELAY_SEC=3
|
RECONNECT_DELAY_SEC=3
|
||||||
MAX_RECONNECT_ATTEMPTS=0
|
MAX_RECONNECT_ATTEMPTS=0
|
||||||
|
# Max stream-error logs per outage; resets when stream recovers. 0 = unlimited.
|
||||||
|
STREAM_ERROR_LOG_MAX=3
|
||||||
TRACKED_PRUNE_SEC=300
|
TRACKED_PRUNE_SEC=300
|
||||||
|
|
||||||
# --- Live stream snapshot ---
|
# --- Live stream snapshot ---
|
||||||
|
|||||||
Reference in new issue
Block a user