修改rtsp获取帧相关代码,使得减少数据丢失,测试有效

This commit is contained in:
zqc
2026-01-09 14:46:58 +08:00
parent 9b81c10248
commit 9f1ef55a6a

View File

@@ -42,7 +42,7 @@ police_prisoner_input_size = 1280
# RTSP 服务配置
RTSP_TARGET_FPS = 30.0
FRAMES_PER_SEGMENT = 1800
FRAMES_PER_SEGMENT = 300
VIDEO_OUTPUT_DIR = "./videos"
WS_HOST = "0.0.0.0"
WS_PORT = 8765
@@ -412,29 +412,90 @@ class RTSPCaptureWorker(threading.Thread):
self.camera_cfg = camera_cfg
self.raw_queue = raw_queue
self.stop_event = stop_event
# 添加重连计数器
self.reconnect_count = 0
self.max_reconnects = 10
def run(self):
cap = cv2.VideoCapture(self.camera_cfg.rtsp_url, cv2.CAP_FFMPEG)
if not cap.isOpened():
print(f"[ERROR] Cannot open RTSP: {self.camera_cfg.rtsp_url}")
return
print(f"[INFO] Capturing {self.camera_cfg.name} (ID:{self.camera_cfg.id})")
while not self.stop_event.is_set():
ret, frame = cap.read()
if not ret:
time.sleep(0.2)
continue
item = {
"camera_id": self.camera_cfg.id,
"camera_name": self.camera_cfg.name,
"timestamp": time.time(),
"frame": frame,
}
while not self.stop_event.is_set() and self.reconnect_count < self.max_reconnects:
try:
self.raw_queue.put(item, timeout=1.0)
except queue.Full:
pass
cap.release()
# 方法1使用TCP传输更稳定
rtsp_url = self.camera_cfg.rtsp_url
if "?" not in rtsp_url:
rtsp_url += "?transport=tcp" # 强制TCP传输
else:
rtsp_url += "&transport=tcp"
# 方法2添加更多FFmpeg参数
cap = cv2.VideoCapture(rtsp_url, cv2.CAP_FFMPEG)
# 方法3设置缓冲区大小
cap.set(cv2.CAP_PROP_BUFFERSIZE, 10) # 增加缓冲区
# 方法4设置超时和重连参数
os.environ["OPENCV_FFMPEG_CAPTURE_OPTIONS"] = \
"rtsp_transport;tcp|buffer_size;1024000|max_delay;500000|stimeout;2000000"
# 方法5设置解码器flags忽略解码错误
# cap.set(cv2.CAP_PROP_HW_ACCELERATION, cv2.VIDEO_ACCELERATION_ANY)
if not cap.isOpened():
print(f"[ERROR] Cannot open RTSP: {self.camera_cfg.rtsp_url}")
time.sleep(2)
self.reconnect_count += 1
continue
print(f"[INFO] Successfully opened RTSP: {self.camera_cfg.name}")
self.reconnect_count = 0 # 重置重连计数
# # 设置帧率(可选)
# cap.set(cv2.CAP_PROP_FPS, 25)
while not self.stop_event.is_set():
ret, frame = cap.read()
if not ret:
# 检查流是否结束
print(f"[WARN] Failed to read frame from {self.camera_cfg.name}")
# 检查是否还有数据
time.sleep(0.1)
# 尝试几次后重连
break
item = {
"camera_id": self.camera_cfg.id,
"camera_name": self.camera_cfg.name,
"timestamp": time.time(),
"frame": frame,
}
try:
# 添加队列满时的处理
if self.raw_queue.full():
# 丢弃最旧的一帧
try:
self.raw_queue.get_nowait()
self.raw_queue.task_done()
except queue.Empty:
pass
self.raw_queue.put(item, timeout=0.5)
except queue.Full:
print(f"[WARN] Queue full, dropping frame from {self.camera_cfg.name}")
continue
# 控制读取速度,避免过快
time.sleep(0.02) # 约50ms间隔
cap.release()
except Exception as e:
print(f"[ERROR] Error in RTSP capture for {self.camera_cfg.name}: {e}")
time.sleep(2)
self.reconnect_count += 1
if self.reconnect_count >= self.max_reconnects:
print(f"[ERROR] Max reconnects reached for {self.camera_cfg.name}, stopping.")
# ========================= 帧处理线程 =========================
@@ -495,6 +556,7 @@ class FrameProcessorWorker(threading.Thread):
def run(self):
target_interval = 1.0 / RTSP_TARGET_FPS
# last_processed_time = {} # 记录每个摄像头上次处理时间
while not self.stop_event.is_set():
try:
item = self.raw_queue.get(timeout=0.5)
@@ -516,6 +578,16 @@ class FrameProcessorWorker(threading.Thread):
self.kadian_detectors[cam_id] = KadianDetector()
detector = self.kadian_detectors[cam_id]
# # 计算距离上次处理的时间间隔
# current_time = time.time()
# time_since_last = 0
# if cam_id in last_processed_time:
# time_since_last = (current_time - last_processed_time[cam_id]) * 1000 # 转换为毫秒
# last_processed_time[cam_id] = current_time
#
# if time_since_last > 0:
# print(f"[DEBUG] 摄像头{cam_id} - 距离上次处理间隔: {time_since_last:.1f}ms")
# 2) 进行人脸识别(如果启用)
current_face_alert = None
face_results = []