修改rtsp获取帧相关代码,使得减少数据丢失,测试有效
This commit is contained in:
@@ -42,7 +42,7 @@ police_prisoner_input_size = 1280
|
|||||||
|
|
||||||
# RTSP 服务配置
|
# RTSP 服务配置
|
||||||
RTSP_TARGET_FPS = 30.0
|
RTSP_TARGET_FPS = 30.0
|
||||||
FRAMES_PER_SEGMENT = 1800
|
FRAMES_PER_SEGMENT = 300
|
||||||
VIDEO_OUTPUT_DIR = "./videos"
|
VIDEO_OUTPUT_DIR = "./videos"
|
||||||
WS_HOST = "0.0.0.0"
|
WS_HOST = "0.0.0.0"
|
||||||
WS_PORT = 8765
|
WS_PORT = 8765
|
||||||
@@ -412,30 +412,91 @@ class RTSPCaptureWorker(threading.Thread):
|
|||||||
self.camera_cfg = camera_cfg
|
self.camera_cfg = camera_cfg
|
||||||
self.raw_queue = raw_queue
|
self.raw_queue = raw_queue
|
||||||
self.stop_event = stop_event
|
self.stop_event = stop_event
|
||||||
|
# 添加重连计数器
|
||||||
|
self.reconnect_count = 0
|
||||||
|
self.max_reconnects = 10
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
cap = cv2.VideoCapture(self.camera_cfg.rtsp_url, cv2.CAP_FFMPEG)
|
while not self.stop_event.is_set() and self.reconnect_count < self.max_reconnects:
|
||||||
|
try:
|
||||||
|
# 方法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():
|
if not cap.isOpened():
|
||||||
print(f"[ERROR] Cannot open RTSP: {self.camera_cfg.rtsp_url}")
|
print(f"[ERROR] Cannot open RTSP: {self.camera_cfg.rtsp_url}")
|
||||||
return
|
time.sleep(2)
|
||||||
print(f"[INFO] Capturing {self.camera_cfg.name} (ID:{self.camera_cfg.id})")
|
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():
|
while not self.stop_event.is_set():
|
||||||
ret, frame = cap.read()
|
ret, frame = cap.read()
|
||||||
if not ret:
|
if not ret:
|
||||||
time.sleep(0.2)
|
# 检查流是否结束
|
||||||
continue
|
print(f"[WARN] Failed to read frame from {self.camera_cfg.name}")
|
||||||
|
|
||||||
|
# 检查是否还有数据
|
||||||
|
time.sleep(0.1)
|
||||||
|
# 尝试几次后重连
|
||||||
|
break
|
||||||
|
|
||||||
item = {
|
item = {
|
||||||
"camera_id": self.camera_cfg.id,
|
"camera_id": self.camera_cfg.id,
|
||||||
"camera_name": self.camera_cfg.name,
|
"camera_name": self.camera_cfg.name,
|
||||||
"timestamp": time.time(),
|
"timestamp": time.time(),
|
||||||
"frame": frame,
|
"frame": frame,
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.raw_queue.put(item, timeout=1.0)
|
# 添加队列满时的处理
|
||||||
except queue.Full:
|
if self.raw_queue.full():
|
||||||
|
# 丢弃最旧的一帧
|
||||||
|
try:
|
||||||
|
self.raw_queue.get_nowait()
|
||||||
|
self.raw_queue.task_done()
|
||||||
|
except queue.Empty:
|
||||||
pass
|
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()
|
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.")
|
||||||
|
|
||||||
|
|
||||||
# ========================= 帧处理线程 =========================
|
# ========================= 帧处理线程 =========================
|
||||||
class FrameProcessorWorker(threading.Thread):
|
class FrameProcessorWorker(threading.Thread):
|
||||||
@@ -495,6 +556,7 @@ class FrameProcessorWorker(threading.Thread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
target_interval = 1.0 / RTSP_TARGET_FPS
|
target_interval = 1.0 / RTSP_TARGET_FPS
|
||||||
|
# last_processed_time = {} # 记录每个摄像头上次处理时间
|
||||||
while not self.stop_event.is_set():
|
while not self.stop_event.is_set():
|
||||||
try:
|
try:
|
||||||
item = self.raw_queue.get(timeout=0.5)
|
item = self.raw_queue.get(timeout=0.5)
|
||||||
@@ -516,6 +578,16 @@ class FrameProcessorWorker(threading.Thread):
|
|||||||
self.kadian_detectors[cam_id] = KadianDetector()
|
self.kadian_detectors[cam_id] = KadianDetector()
|
||||||
detector = self.kadian_detectors[cam_id]
|
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) 进行人脸识别(如果启用)
|
# 2) 进行人脸识别(如果启用)
|
||||||
current_face_alert = None
|
current_face_alert = None
|
||||||
face_results = []
|
face_results = []
|
||||||
|
|||||||
Reference in New Issue
Block a user