client/server ipcameras over network usage at least cpu

26 views Asked by At

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 cv2
import zmq
import threading
import os
import subprocess
import base64
import datetime
import asyncio
import zmq.asyncio

class 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




0

There are 0 answers