Я сделал это быстрее, читая фреймы, используя FFmpeg напрямую. Там могут быть лучшие способы сделать это, но это одобрение. Я полагаю, вы уже запускаете видеокадры в разных процессах, это правильно? Иначе это тоже был бы мудрый шаг.
import numpy
from subprocess import Popen, PIPE
import cv2
class ffmpeg_videocapture:
def __init__(self, stream, width=640, height=360, scale=1, fps=15):
self.command = 'ffmpeg -rtsp_transport udp -i {i} -pix_fmt bgr24 -s {w}x{h} -vcodec rawvideo ' \
'-an -sn -r {fps} -f image2pipe pipe:1'
self.stream = stream
self.width = width
self.height = height
self.scale = scale
self.fps = fps
self.errors = []
self.start()
def start(self):
width = int(self.width * self.scale)
height = int(self.height * self.scale)
command = self.command.format(i=self.stream, w=width, h=height, fps=self.fps)
self.capture = Popen(command.split(' '), stdout=PIPE, stderr=PIPE, bufsize=10 ** 8)
def read(self):
width = int(self.width * self.scale)
height = int(self.height * self.scale)
raw_image = self.capture.stdout.read(width * height * 3)
frame = numpy.fromstring(raw_image, dtype='uint8')
frame = frame.reshape((height, width, 3))
self.capture.stdout.flush()
return frame is not None, frame
def __exit__(self, exc_type, exc_val, exc_tb):
self.capture.terminate()
def single_camera(rtsp_stream):
cap = ffmpeg_videocapture(rtsp_stream)
while True:
ret, frame = cap.read()
cv2.imshow("frame", frame)
if __name__ == "__main__":
rtsp_stream_list = [
"rtsp_stream_1",
"rtsp_stream_2",
"etc...",
]
for rtsp_stream in rtsp_stream_list:
t = Process(target=single_camera, args=rtsp_stream)
t.start()