前段时间我们一直在做景区人流量统计及智能分析的功能,目前该功能已经进入了实际测试阶段。在景区现场人流量统计测试中,有景区会出现摄像头rtsp流断开的情况,远程使用VLC播放也播放不出来。
对该问题的出现,我们第一时间开始查找原因,我们了解到在该景区中,在晚上摄像头设备会断电,等早上工作人员来后再把设备的电供应上。所以第二天早上会出现错误:Failed to open rtsp://xxxxxx。
我们打开rtsp流错误,所以只能从代码中分析问题所在。首先要定位到是哪个地方输入的rtsp流:
随后找到在哪里打开的rtsp流:
LoadStreams进行了初始化,并输入其中一个参数rtsp流:
代码语言:javascript复制for i, s in enumerate(sources):
# Start the thread to read frames from the video stream
print(f'{i 1}/{n}: {s}... ', end='')
cap = cv2.VideoCapture(eval(s) if s.isnumeric() else s)
assert cap.isOpened(), f'Failed to open {s}'
w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS) % 100
_, self.imgs[i] = cap.read() # guarantee first frame
thread = Thread(target=self.update, args=([i, cap]), daemon=True)
print(f' success ({w}x{h} at {fps:.2f} FPS).')
thread.start()
print('') # newline
刚开始运行程序会进行初始化打开rtsp流,但是已经rtsp运行成功了,就不会进去初始化重新打开rtsp流,所以还有个线程函数如下:
代码语言:javascript复制Thread = Thread(target=self.update, args=([i, cap]), daemon=True)
线程有个self.update函数,进去此方法,是rtsp断开,隔一段时间重新连接:
代码语言:javascript复制def update(self, index, cap):
# Read next stream frame in a daemon thread
n = 0
while cap.isOpened():
n = 1
# _, self.imgs[index] = cap.read()
cap.grab()
if n == 4: # read every 4th frame
success, im = cap.retrieve()
self.imgs[index] = im if success else self.imgs[index] * 0
n = 0
time.sleep(0.01) # wait time
知道问题所在,只需要修改线程中update函数方法即可。
首先查看从rtsp能不能读到图像,如果读不到图像,说明rtsp流已经断开连接,需要再次打开rtsp流,延迟几秒,再次打开rtsp,一直重复此操作,一直到成功。
代码语言:javascript复制self.ret, self.imgs[self.index] = self.cap.read()
if not self.ret:
print("Camera is disconnected!")
time.sleep(5 * 60)
n = len(self.my_sources)
self.imgs = [None] * n
self.sources = [clean_str(x) for x in self.my_sources] # clean source names for later
for i, s in enumerate(self.my_sources):
# Start the thread to read frames from the video stream
print(f'{i 1}/{n}: {s}... ', end='')
cap = cv2.VideoCapture(eval(s) if s.isnumeric() else s)
if not cap.isOpened():
continue
assert cap.isOpened(), f'Failed to open {s}'
print("rtsp success")
self.index = i
self.cap = cap
continue