Re-play slow motion doesn't play anything

44 views Asked by At

The code below selects and plays in slow motion the last 8 seconds of a video.

Problem:
When the the button clean is pressed, it resets the video path, and allows for selecting a new video (path) by pressing select button again.

However, when the button play slow motion is pressed, it doesn't play anything after the new video is selected. What could be causing this?

 import tkinter as tk
 from tkinter import filedialog
 import cv2
 import threading
 from PIL import Image, ImageTk

 class VideoPlayerApp:
     def __init__(self, root):
         self.root = root
         self.root.title("Multimedia")
    
         self.root.geometry("900x542+200+1")

         self.right_frame = tk.Frame(self.root, bg="#2271b3")
         self.right_frame.place(relx=0.8333, rely=0, relwidth=0.1667, relheight=1)

         button_height = 0.15
         button_spacing = 0.08

         self.select_button = tk.Button(self.right_frame, text="Select video", command=self.select_video, height=2, width=15)
         self.select_button.place(relx=0.5, rely=button_height, anchor=tk.CENTER)

         self.play_button = tk.Button(self.right_frame, text="Play Slow Motion", command=self.play_slow, height=2, width=15)
         self.play_button.place(relx=0.5, rely=button_height + button_spacing, anchor=tk.CENTER)

         self.freeze_button = tk.Button(self.right_frame, text="Freeze", command=self.freeze_video, height=2, width=15)
         self.freeze_button.place(relx=0.5, rely=button_height + 2*button_spacing, anchor=tk.CENTER)

         self.clean_button = tk.Button(self.right_frame, text="Clean", command=self.clean_video, height=2, width=15)
         self.clean_button.place(relx=0.5, rely=button_height + 3*button_spacing, anchor=tk.CENTER)  # New clean button

         self.left_frame = tk.Frame(self.root)
         self.left_frame.place(relx=0, rely=0, relwidth=0.8333, relheight=1)

         self.video_label = None  # Placeholder for video label
         self.paused = False
         self.video_path = None  # Initialize video path

    # Add white frames to right frame
    self.white_frame_top_right = tk.Frame(self.right_frame, bg="white")
        self.white_frame_top_right.place(relx=0, rely=0, relwidth=1, relheight=0.05)

        self.white_frame_bottom_right = tk.Frame(self.right_frame, bg="white")
        self.white_frame_bottom_right.place(relx=0, rely=0.95, relwidth=1, relheight=0.05)

    def select_video(self):
        self.video_path = filedialog.askopenfilename(filetypes=[("Video files", "*.mp4 *.avi *.mov")])

    def play_slow(self):
        if self.video_path:
        threading.Thread(target=self.play_video_slow).start()

    def freeze_video(self):
        self.paused = not self.paused

    def clean_video(self):
        self.paused = True
        if self.video_label:
            self.video_label.destroy()  # Eliminate the current video label
            self.video_label = None  # Reset to None
            self.video_path = None  # Reset video path

    def play_video_slow(self):
        if self.video_path:
            cap = cv2.VideoCapture(self.video_path)
            fps = int(cap.get(cv2.CAP_PROP_FPS))
            total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

            duration = 8
            start_frame = total_frames - (duration * fps)
            if start_frame < 0:
                start_frame = 0

            cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)

            while True:
                if self.paused:
                    continue

                ret, frame = cap.read()
                if not ret:
                    break

                frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
                img_pil = Image.fromarray(frame)
                img_pil = img_pil.resize((self.left_frame.winfo_width(), self.left_frame.winfo_height()), Image.ANTIALIAS)

                img = ImageTk.PhotoImage(image=img_pil)

                if not self.video_label:  # If video label does not exist, create it
                self.video_label = tk.Label(self.left_frame, image=img)
                self.video_label.image = img  # Keep a reference to the image to prevent garbage collection
                self.video_label.place(relx=0, rely=0, relwidth=1, relheight=1)
                else:
                    self.video_label.configure(image=img)  # Update the existing video label
                    self.video_label.image = img  # Keep a reference to the image to prevent garbage collection

                if cv2.waitKey(3900 // fps) & 0xFF == ord('q'):
                    break

           cap.release()
if __name__ == "__main__":   
    root = tk.Tk()
    app = VideoPlayerApp(root)
    root.mainloop()
0

There are 0 answers