1 year ago

#363661

test-img

Chorum

How to record original Webcam Stream while displaying it

I would like to record a Webcamstream while displaying it in a Frame. (Later record up to 3 Streams and/or capturing a Frame with MQTT Data.)

I found a really nice Class for it and changed it for my needs. Thats the actual Class:

class multi_thread_stream:
        def __init__(self, ready=None):
            self.ready = ready
            self.cap = cv2.VideoCapture(cam1fullurl)
            self.capr = cv2.VideoCapture(cam1fullurl)
            self.frame = {}
            
            self.t1 = threading.Thread(target=self.capture_stream)
            self.t2 = threading.Thread(target=self.display_image)
            
            
            self.t1.name = 'capture_thread'
            self.t2.name = 'display_thread'
            self.t1.start()
            self.t2.start()
            threadpoolc1.append(self.t1)
            threadpoolc1.append(self.t2)
            global rec_mp4_key
        
        def setpicnostream_for_class(self):
            print('setpicnostream_for_class activated')
            global picnostream
            global videoframe
            global videolabel1
            global left_frame
            img = Image.open(r'C:\Users\User\Python\Medien\Bilder\streamoff.png')
            x = left_frame.winfo_width()
            y = left_frame.winfo_height()
            img = img.resize((x,y), Image.ANTIALIAS)
            picnostream = ImageTk.PhotoImage(img)
            label2.config(font=("Courier bold", 20),image = picnostream)
    
        def end(self):
            self.t1.exit()
            self.t2.exit()
    
        def capture_stream(self):
            global streamactivekey
            global screenshot
            global rec_mp4_key

            
            global cam1fullurl
            if streamactivekey == 'True':
                while True:
                    #if rec_mp4_key == 'False':
                    self.ret, self.frame = self.cap.read()
                   # self.capr = self.frame
                    #    break
                      
                    global readed_frame
                    readed_frame = self.frame
                    self.ready.set()
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                        break
                    if streamactivekey == 'False':
                        print('streamactivekey in capture_stream =',streamactivekey)
                        self.setpicnostream_for_class()
                        self.cap.release()
                        sys.exit()
                        break
                        

        def display_image(self):
            global rec_mp4_key
            global rec_stop
            print('display_image activated')
            self.counter = 0
            self.counterold = 0
            self.old = 0
            
            if streamactivekey == 'True':
                time.sleep(0.1)
                while True:  
                
                    """
                    if rec_mp4_key == 'True':
                        out = cv2.VideoWriter(filenamev, get_video_type(filenamev), frames_per_seconds, get_dims(capr, res=start_res))
                        rec_start = 'True'
                    """
                    
                    self.ready.wait()
                    fwidth = left_frame.winfo_width()
                    fheight = left_frame.winfo_height() 
                    frootx = left_frame.winfo_rootx()
                    frooty = left_frame.winfo_rooty()
                    global picnostreamsize
                    picnostreamsize = (frootx, frooty)
                    size = (fwidth, fheight)
                    framex=cv2.cvtColor(self.frame,cv2.COLOR_BGR2RGB)
                    cv2imageresized = cv2.resize(framex,size, interpolation = cv2.INTER_AREA)
                    now = datetime.now()
                    offset = 30
                    font                   = cv2.FONT_HERSHEY_TRIPLEX
                    bottomLeftCornerOfText = (50,offset)
                    upperRightCornerOfText = (710,offset)
                    fontScale              = 1
                    fontColor              = (255,0,0)
                    thickness              = 2
                    lineType               = 2
                    rawtime = now.strftime("%H : %M : %S : %f")
                    mytime = rawtime[:-4]
                    rawtime2 = now.strftime("%S")
                    rawtimex = int(now.strftime("%S"))
                    seconds = "0"+str(rawtimex)
                    if seconds == "31" or seconds == "01":
                        seconds = "0"
                    else:
                        seconds = "0"+str(rawtimex)
                    if rawtimex > 9:
                        seconds = rawtime2[:]
                    if seconds == self.old:
                        self.counter += 1
                    else:
                        print(f'Frame/Second = {self.counter}/{seconds}')
                        fpsstring = f'FPS : {self.counter}'
                        self.counter = 0
                        self.old = seconds
                        
                    frame = cv2.putText(cv2imageresized,fpsstring, upperRightCornerOfText, font, fontScale,fontColor,thickness,cv2.LINE_AA)
                    #frame = cv2.putText(cv2imageresized,fpsstring, bottomLeftCornerOfText, font, fontScale,fontColor,thickness,lineType)
                    #frame = cv2.putText(cv2imageresized,fpsstring, upperRightCornerOfText, font, fontScale,fontColor,thickness,cv2.LINE_AA)
                    #print(f'display_imagetime = {counter}---{seconds}-{rawtime}')
                    #print(f'Frame/Second = {counter}/{seconds}')
                    framex=Image.fromarray(cv2imageresized)
                    framex=ImageTk.PhotoImage(framex)
                    
                    """
                    if rec_mp4_key == 'True' and rec_start == 'True':
                        print('rec_mp4_key in display :',rec_mp4_key)
                        #out.write(self.frame)
                        cv2.imshow("In write Frame", self.frame)
                        if rec_stop == 'True':
                            print('rec_stop =',rec_stop)
                            rec_mp4_key = 'False'
                            capr.release()
                    """

                    label2.configure(image=framex)
                    label2.image=framex
                    self.ready.clear()
                    if cv2.waitKey(1) & 0xFF == ord('q'):
                        break;
                    if streamactivekey == 'False':
                        print('streamactivekey in display_image =',streamactivekey)
                        sys.exit()
                        break
        
        def record_stream(self):
            capr = self.capr
            global cam1fullurl
            global rec_mp4_key
            global rec_stop
            basepathinc = r'C:/Videotool/Videos'
            frames_per_seconds = 24.0
            start_res = '720p'
            
            def change_rec_resolution(capr,width,height):
                capr.set(3, width)
                capr.set(4, height)
                
            resolutions = {
            "480p": (640,480),
            "720p": (1280,720),
            "1080p": (1920,1080),
            "4k": (3840,2160),
            }
            
            def get_dims(capr, res='1080p'):
                width, height = resolutions['480p']
                if res in resolutions:
                    width, height = resolutions[res]
                change_rec_resolution(capr, width, height)
                return width, height
            
            VIDEO_TYPE = {
            'avi': cv2.VideoWriter_fourcc(*'mp4v'),
            'mp4': cv2.VideoWriter_fourcc(*'mp4v'),
            #'mp4': cv2.VideoWriter_fourcc(*'H264'),
            }
            
            print('Aufnahme')
            isExist = os.path.exists(basepathinc)
            print('path exists :',isExist)
            print('Video fullpath :',basepathinc)
            if not isExist:
                os.makedirs(basepathinc)
                print(f'path {basepathinc} created')
            os.chdir(basepathinc)
            now = datetime.now()
            rawtime = now.strftime("%H_%M_%S_%f")
            mytime = rawtime[:-4]
            filenamev='record'+mytime+'.mp4'
            print(filenamev)
            
            
            def get_video_type(filenamev):
                filenamev, ext = os.path.splitext(filenamev)
                if ext in VIDEO_TYPE:
                    return VIDEO_TYPE[ext]
                return VIDEO_TYPE['avi']
                
            rec_start = 'False'
            
            if streamactivekey == 'True':
                time.sleep(0.1)
                self.ready.wait()
                if rec_mp4_key == 'True':
                        out = cv2.VideoWriter(filenamev, get_video_type(filenamev), frames_per_seconds, get_dims(capr, res=start_res))
                        rec_start = 'True'
                while True:  
                
                    
                        
                    if rec_mp4_key == 'True' and rec_start == 'True':
                        print('rec_mp4_key in display :',rec_mp4_key)
                        #out.write(self.frame)
                        cv2.imshow("In write Frame", self.frame)
                        self.ready.clear()
                        if rec_stop == 'True':
                            print('rec_stop =',rec_stop)
                            rec_mp4_key = 'False'
                            capr.release()
        def __del__(self):
            self.cap.release()
            cv2.destroyAllWindows()

Sorry for the Comments and may be bad Coding, I am new in Python. May be there are not needed Lines left in the Code...

The Capture and the Displaying are working in different Threads and Threadpools, because of the I/O Blocking. For Displaying, everything is fine. I would be happy for some more FPS but its ok.

But my attempts to write the Stream to a File while displaying the Stream, are not working. For Testing i use a simple imshow()

The posted Code let the displayed Stream run with normal FPS, but the imshow() Window pops up in Gray and dont respond anymore.

May be its a Problem to access the Stream 2 Times ?

The strange thing is, that the Line :

out = cv2.VideoWriter(filenamev, get_video_type(filenamev), frames_per_seconds, get_dims(capr, res=start_res))

is writing a full named mp4 File with 1kb size. (Nothing in it) That should not happen. out.write(self.frame)should do that later.

I would be happy, if Someone could help me with my Problem.

Here are the Start and Stop Functions:

        def stop_rec():
            print('stop_rec activated')
            global rec_mp4_key
            global rec_stop
            rec_stop = 'True'

        def start_rec():
            print('start_rec activated')
            global rec_mp4_key
            rec_mp4_key = 'True'
            global rec_stop
            rec_stop = 'False'
            global mts
            t3 = threading.Thread(target=mts.record_stream)
            t3.name = 'record thread'
            t3.start()
            threadpoolcamrecord.append(t3)

python

multithreading

opencv

webcam

0 Answers

Your Answer

Accepted video resources