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.