- 一开始,直接使用opencv的
cv2.VideoCapture
直接读取rtsp视频流,但是这样做的缺点是延迟严重、出现掉帧、花屏现象等,原因在于opencv自己有一个缓存,每次会顺序从自己的缓存中读取,而不是直接读取最新帧,代码如下:
import cv2
cap = cv2.VideoCapture("rtsp://admin:admin@IP地址:端口号/live0")
ret,frame = cap.read()
while ret:
ret,frame = cap.read()
cv2.imshow("frame",frame)
if cv2.waitKey(25) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
cap.release()
- 采用多线程的方式,新开一个线程,利用变量、队列等方式保存最新帧,使得每次都读取最新帧,而不是opencv自己缓存中的顺序帧,不会延迟,不会花屏了,代码如下:
import cv2
import threading
import sys
class RTSCapture(cv2.VideoCapture):
_cur_frame = None
_reading = False
schemes = ["rtsp://","rtmp://"]
@staticmethod
def create(url, *schemes):
rtscap = RTSCapture(url)
rtscap.frame_receiver = threading.Thread(target=rtscap.recv_frame, daemon=True)
rtscap.schemes.extend(schemes)
if isinstance(url, str) and url.startswith(tuple(rtscap.schemes)):
rtscap._reading = True
elif isinstance(url, int):
pass
return rtscap
def isStarted(self):
ok = self.isOpened()
if ok and self._reading:
ok = self.frame_receiver.is_alive()
return ok
def recv_frame(self):
while self._reading and self.isOpened():
ok, frame = self.read()
if not ok: break
self._cur_frame = frame
self._reading = False
def read2(self):
frame = self._cur_frame
self._cur_frame = None
return frame is not None, frame
def start_read(self):
self.frame_receiver.start()
self.read_latest_frame = self.read2 if self._reading else self.read
def stop_read(self):
self._reading = False
if self.frame_receiver.is_alive(): self.frame_receiver.join()
if __name__ == '__main__':
if len(sys.argv) < 2:
print("usage:")
print("need rtsp://xxx")
sys.exit()
rtscap = RTSCapture.create(sys.argv[1])
rtscap.start_read()
while rtscap.isStarted():
ok, frame = rtscap.read_latest_frame()
if cv2.waitKey(100) & 0xFF == ord('q'):
break
if not ok:
continue
# inhere
cv2.imshow("cam", frame)
rtscap.stop_read()
rtscap.release()
cv2.destroyAllWindows()
使用时python python文件名 "rtsp://admin:admin@IP地址:端口号/live0"
参考链接: