I have 32 of ip cameras with 5 mp and high resolution and I send frames with this code over network but this code get many cpu usage and when frames receive to client loss some of frames , please give me solved this problems
when increase my cameras use full of cpu and do not work well
I wrote Client code and check this code work well with cameras
import cv2import zmqimport threadingimport osimport subprocessimport base64import datetimeimport asyncioimport zmq.asyncioclass VideoStreamer: def __init__(self, video_files, port=5555, server_ip="10.129.163.200", store=False): self.video_files = video_files self.context = zmq.asyncio.Context() self.sockets = [] self.server_ip = server_ip self.port = port self.sockets_open = False self.video_captures = [] self.store = store cv2.cuda.setDevice(0) def toggle_sockets(self): if self.sockets_open: self.close_sockets() else: self.open_sockets() def open_sockets(self): self.sockets = [self.context.socket(zmq.PUB) for _ in range(len(self.video_files))] for i, socket in enumerate(self.sockets): socket.bind(f"tcp://{self.server_ip}:{self.port + i}") self.sockets_open = True self.stopped = False def close_sockets(self): for socket in self.sockets: socket.close() self.sockets_open = False self.stopped = True self.video_threads.clear() self.sockets.clear() self.stopped = False def start(self): self.video_thread_captures = [threading.Thread(target=self.send_video, args=(video_stream, i)) for i, video_stream in enumerate(self.video_files)] for thread in self.video_thread_captures: thread.start() def send_video(self, video_file, client_index): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(self.send_video_async(video_file, client_index)) loop.close() async def send_video_async(self, video_file, client_index): cap = cv2.VideoCapture(video_file['url']) cap.set(cv2.CAP_PROP_BUFFERSIZE, 3) width = cap.get(cv2.CAP_PROP_FRAME_WIDTH) height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT) fps = cap.get(cv2.CAP_PROP_FPS) while not self.stopped: ret, frame = cap.read() if ret: # frame_cuda = cv2.cuda_GpuMat() # frame_cuda.upload(frame) # frame_cuda_resized = cv2.cuda.resize(frame_cuda, (100, 75)) # cv_rgb_image_cuda = cv2.cuda.cvtColor(frame_cuda_resized, cv2.COLOR_BGR2RGB) # # frame_resized = cv_rgb_image_cuda.download() _, video_frame = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 90]) # _, video_frame = cv2.imencode('.h264', frame) jpg_bytes = video_frame.tobytes() jpg_base64 = base64.b64encode(jpg_bytes).decode('utf-8') frame_with_ip = {"IP":video_file['ip'], "Frame":jpg_base64} if self.store: video_file['buffer'].append(frame) if len(video_file['buffer']) > 100: now = datetime.now() dt_string = now.strftime("%d-%m-%Y_%H-%M-%S") ffmpeg_d = self.export_video(video_file['root'] + dt_string, video_file['root'], width, height, fps) for cached_frame in video_file['buffer']: ffmpeg_d.stdin.write(cached_frame.tobytes()) # ffmpeg_d.stdin.close() # ffmpeg_d.wait() video_file['buffer'] = [] # # Send the frame to the specific client if self.sockets_open: await self.sockets[client_index].send_json(frame_with_ip) await asyncio.sleep(0.3) # Adjust the delay as needed # self.sockets[client_index].send(jpg_bytes) # cv2.waitKey(delay) # time.sleep(0.03) # Adjust the delay based on your frame rate def export_video(self, name, directory, width, height, fps): file_name = f"{name}.mp4" if not os.path.exists(directory): os.makedirs(directory) output_file = os.path.join(directory, file_name) ffmpeg_cmd = ['ffmpeg','-y', # Overwrite output file if it exists'-f', 'rawvideo','-vcodec', 'rawvideo','-s', f'{int(width)}x{int(height)}','-pix_fmt', 'bgr24','-r', str(fps),'-i', '-','-c:v', 'h264_nvenc', # '-c:v' , 'h264','-pix_fmt', 'yuv420p', output_file ] # Open subprocess for ffmpeg ffmpeg_process = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE) return ffmpeg_process