Home > Net >  how to stop OpenCV video capturing/recording after sometime and start again in tkinter
how to stop OpenCV video capturing/recording after sometime and start again in tkinter

Time:12-11

I have a python application which have many frames/pages when I go to some some camera page I start the camera and after 20 second I want to close the video recording and start recording in a new file. basically splitting a the recording into 20 second videos. now I have a function stop_20_seconds() function which stops the recording after 20 second and starts again. but right now I am getting multiple file without the 20 second break one after another.

my code

class FrontCameraPage(tk.Frame):
    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent)
        self.controller = controller

        self.label = tk.Label(self, text="FRONT CAMERA", font=MediumFont, bg="white").grid(row=0, column=0, columnspan=2, sticky="nsew")
        self.cameraFrame = tk.Frame(self, bg=gray)
        self.cameraFrame.grid(row=1, column=0, sticky="nsew")
        self.buttonFrame = tk.Frame(self, bg="white")
        self.buttonFrame.grid(row=1, column=1, sticky="nsew", padx=(10, 0))


        self.endTrip = tk.Button(self.buttonFrame, text="END TRIP", font=small_Font, bg=dark_blue, fg="White")
        self.endTrip.grid(row=2, column=0, ipadx=10, pady=(0, 5))
        self.endTrip['command'] = self.stop_capture

        self.cancelButton = tk.Button(self.buttonFrame, text="Cancel", font=small_Font, bg=dark_blue, fg="white")
        self.cancelButton.grid(row=3, column=0, ipadx=10)
        self.cancelButton['command'] = lambda: controller.show_frame(changepage)

        # setup callbacks for switching in and out events
        self.bind('<<SwitchIn>>', self.start_capture)
        self.bind('<<SwitchOut>>', self.stop_capture)

        self.capture = None 
        self.lmain = tk.Label(self.cameraFrame)
        self.lmain.pack()

    def start_capture(self, event=None):
        if self.capture is None:
            #-----------------------------------
            width, height = 200, 200
            self.cap = cv2.VideoCapture(0)
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
            width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
            self.out = cv2.VideoWriter('output.avi', self.fourcc, 25, (width, height))       
            #-----------------------------------
            self.timer =0
            self.show_frame()
            print('capture started')


    def stop_capture(self, event=None):
        if self.capture:
            self.after_cancel(self.capture)
            #-----------------------------------
            self.cap.release()
            self.out.release()
            #------------------------------
            self.capture = None
            print('capture stopped')


    def show_frame(self):
        ret, frame = self.cap.read()
        if ret:
            self.out.write(frame)
            frame = cv2.flip(frame, 1)
            cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
            img = Image.fromarray(cv2image)
            self.imgtk = ImageTk.PhotoImage(image=img)
            self.lmain.configure(image=self.imgtk)

        self.stop20Sec =  self.after(5000, self.stop_20_seconds)
        self.capture = self.after(10, self.show_frame)
    
    def stop_20_seconds(self):
        self.timer  = 1
        self.out.release()
        width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        self.out = cv2.VideoWriter(f'{str(self.timer)}.avi', self.fourcc, 25, (width, height))
        self.after_cancel(self.capture)
        self.after_cancel(self.stop20Sec)
        self.stop20Sec = None
        self.capture = None
        self.show_frame()

CodePudding user response:

Actually you don't need stop_20_seconds(). Just do the output file rotation inside show_frame():

    def start_capture(self, event=None):
        if self.capture is None:
            #-----------------------------------
            width, height = 200, 200
            self.cap = cv2.VideoCapture(0)
            self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
            self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
            # used instance variables for width and height
            self.width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            self.height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            # initialize file rotation and frame counters
            self.timer = 1    # file rotation counter
            self.frames = 0   # frame counter
            self.fourcc = cv2.VideoWriter_fourcc(*'XVID')
            self.out = cv2.VideoWriter(f'{self.timer}.avi', self.fourcc, 25, (self.width, self.height))       
            #-----------------------------------
            self.show_frame()
            print('capture started')

    ...

    def show_frame(self):
        ret, frame = self.cap.read()
        if ret:
            self.out.write(frame)
            self.frames  = 1   # update frame counter
            if self.frames >= 500:    # reach 20 seconds (20x25 frames)
                self.out.release()    # close current output file
                self.timer  = 1       # update file rotation counter
                self.out.open(f'{self.timer}.avi', self.fourcc, 25, (self.width, self.height))
                self.frames = 0       # reset frame counter
            frame = cv2.flip(frame, 1)
            cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
            img = Image.fromarray(cv2image)
            self.imgtk = ImageTk.PhotoImage(image=img)
            self.lmain.configure(image=self.imgtk)

        self.capture = self.after(10, self.show_frame)

Note: since the actual capture frame rate is not the same as the output frame rate, the actual time period in each video file may not be 20 seconds in real time.

  • Related