1

I wrote a code to make a KIOSK video booth, the video playback is faster than real time. For example, if I record a 10 second video, it will only have <1 second of video playback. What is wrong with my code?

Specification: Raspberry pi 4, camera module 3 (IMX708), HDMI output to LCD

import os
import cv2
import tkinter as tk
from tkinter import messagebox
from picamera2 import Picamera2
import time
from PIL import Image, ImageTk

class KioskApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Kiosk Camera Application")
        self.root.geometry("800x600")  # Set the window size
        self.root.configure(bg='black')

        self.picam2 = Picamera2()
        self.picam2.configure(self.picam2.create_preview_configuration(main={"size": (640, 480)}))
        self.picam2.start()

        self.canvas = tk.Canvas(root, width=640, height=480)
        self.canvas.pack(pady=20)

        self.take_photo_button = tk.Button(root, text="Take Photo", command=self.take_photo)
        self.take_photo_button.pack(pady=10)

        self.start_record_button = tk.Button(root, text="Start Recording", command=self.start_recording)
        self.start_record_button.pack(pady=10)

        self.stop_record_button = tk.Button(root, text="Stop Recording", command=self.stop_recording, state=tk.DISABLED)
        self.stop_record_button.pack(pady=10)

        self.quit_button = tk.Button(root, text="Quit", command=self.quit_app)
        self.quit_button.pack(pady=10)

        self.video_writer = None
        self.is_recording = False
        self.output_video_file = None
        self.frame_rate = 25  # Target frame rate (adjust as needed)
        self.last_frame_time = time.time()  # To keep track of frame timing

        self.update_frame()

    def get_next_filename(self, base_name, ext):
        index = 1
        while True:
            filename = f"{base_name}_{index}.{ext}"
            if not os.path.exists(filename):
                return filename
            index += 1

    def update_frame(self):
        frame = self.picam2.capture_array()

        # Convert frame from RGB to BGR
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

        # Convert frame to RGB for display
        img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        img = cv2.resize(img, (640, 480))
        self.photo = ImageTk.PhotoImage(image=self.array_to_image(img))
        self.canvas.create_image(0, 0, image=self.photo, anchor=tk.NW)

        # Record video if in recording mode
        if self.is_recording:
            current_time = time.time()
            elapsed_time = current_time - self.last_frame_time
            if elapsed_time >= 1 / self.frame_rate:  # Maintain target frame rate
                self.video_writer.write(cv2.resize(frame, (1920, 1080)))  # Save video at 1080p
                self.last_frame_time = current_time

        self.root.after(10, self.update_frame)  # 10ms delay for responsive UI

    def array_to_image(self, img_array):
        img = Image.fromarray(img_array)
        return img

    def start_recording(self):
        if not self.is_recording:
            video_filename = self.get_next_filename("video", "avi")

            fourcc = cv2.VideoWriter_fourcc(*'XVID')  # Codec for video writing
            self.video_writer = cv2.VideoWriter(video_filename, fourcc, self.frame_rate, (1920, 1080))  # Set frame rate to 25 fps
            self.is_recording = True
            self.start_record_button.config(state=tk.DISABLED)
            self.stop_record_button.config(state=tk.NORMAL)

            # Store output file names
            self.output_video_file = video_filename
            self.last_frame_time = time.time()  # Reset frame timer

    def stop_recording(self):
        if self.is_recording:
            self.video_writer.release()
            self.is_recording = False
            self.start_record_button.config(state=tk.NORMAL)
            self.stop_record_button.config(state=tk.DISABLED)

            messagebox.showinfo("Recording Stopped", "Video has been saved.")

    def take_photo(self):
        frame = self.picam2.capture_array()

        # Convert frame from RGB to BGR
        frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)

        filename = self.get_next_filename("photo", "jpg")
        cv2.imwrite(filename, frame)
        messagebox.showinfo("Photo Saved", f"Photo saved as {filename}")

    def quit_app(self):
        self.picam2.stop()
        if self.is_recording:
            self.video_writer.release()  # Release video writer if recording
        self.root.quit()

if __name__ == "__main__":
    root = tk.Tk()
    app = KioskApp(root)
    root.attributes('-fullscreen', True)  # Fullscreen mode
    root.mainloop()
1
  • maybe the problem is with the recording
    – jsotola
    Commented Oct 19 at 15:39

0

Browse other questions tagged or ask your own question.