I have a multi frame/pages Tkinter application and in one page/frame I have a camera frame which starts the camera and stars capturing when I navigate to that page now I want to record that video but when I tried to record it I am getting a 6kb ```avi`` file which is not working at all and seems corrupted.
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))
#creating buttons and frames --
self.end= tk.Button(self.buttonFrame, text="STOP", font=small_Font, bg=dark_blue, fg="White")
self.end.grid(row=2, column=0, ipadx=10, pady=(0, 5))
self.end['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(someOtherPage)
#----------------------------------------------------------------------------------------------
# setup callbacks for switching in and out events starts and stops when I change frames
self.bind('<<SwitchIn>>', self.start_capture)
self.bind('<<SwitchOut>>', self.stop_capture)
self.capture = None # task id for the capture loop
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)
self.fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
self.out = cv2.VideoWriter('output.avi', self.fourcc, 20.0, (width, height))
self.lmain = tk.Label(self.cameraFrame)
self.lmain.pack()
def start_capture(self, event=None):
if self.capture is None:
self.show_frame()
print('capture started')
def stop_capture(self, event=None):
if self.capture:
self.after_cancel(self.capture)
self.out.release()
self.capture = None
print('capture stopped')
def show_frame(self):
ret, frame = self.cap.read()
if ret:
frame = cv2.flip(frame, 1)
cv2image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGBA)
img = Image.fromarray(cv2image)
#----------------------------------------------------------------
self.out.write(cv2image)
#----------------------------------------------------------------
self.imgtk = ImageTk.PhotoImage(image=img)
self.lmain.configure(image=self.imgtk)
self.capture = self.after(10, self.show_frame)
CodePudding user response:
It is because the actual frame size returned by self.cap.read()
does not match the size when creating the video writer.
You need to get the actual frame size using self.cap.get(...)
after calling self.cap.set(...)
:
class FrontCameraPage(tk.Frame):
def __init__(self, parent, controller):
tk.Frame.__init__(self, parent)
self.controller = controller
...
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)
# get the final frame size
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('M', 'J', 'P', 'G')
self.out = cv2.VideoWriter('output.avi', self.fourcc, 20.0, (width, height))
...