Видеопроигрыватель от Python tkinter, Когда я приостанавливаю видео, я не могу повторно воспроизвести - PullRequest
0 голосов
/ 01 февраля 2019

Я создаю графический интерфейс для воспроизведения видеофайлов.Проблема в том, что когда я приостанавливаю видео, кнопка «Воспроизведение» не может повторно воспроизвести это видео, и мне приходится снова выбирать видеофайл.

Примечание. Поскольку я хочу показать видео в том же окне tkinter, я не использую команду OpenCV imshow.Вместо этого я использую метод "window.after".

Ниже приведен мой код:

Я пытаюсь использовать переменную «self.pause» для контроля состояния паузы.Когда я нажимаю кнопку Пауза, эта логическая переменная становится Истиной.Однако я не смог найти подходящего места, чтобы сделать его ложным, когда я снова нажму кнопку «Воспроизвести».

from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import PIL.Image, PIL.ImageTk
import cv2


class videoGUI:

    def __init__(self, window, window_title):

        self.window = window
        self.window.title(window_title)

        top_frame = Frame(self.window)
        top_frame.pack(side=TOP, pady=5)

        bottom_frame = Frame(self.window)
        bottom_frame.pack(side=BOTTOM, pady=5)

        self.pause = False   # Parameter that controls pause button

        self.canvas = Canvas(top_frame)
        self.canvas.pack()

        # Select Button
        self.btn_select=Button(bottom_frame, text="Select video file", width=15, command=self.open_file)
        self.btn_select.grid(row=0, column=0)

        # Play Button
        self.btn_play=Button(bottom_frame, text="Play", width=15, command=self.play_video)
        self.btn_play.grid(row=0, column=1)

        # Pause Button
        self.btn_pause=Button(bottom_frame, text="Pause", width=15, command=self.pause_video)
        self.btn_pause.grid(row=0, column=2)

        self.delay = 15   # ms

        self.window.mainloop()


    def open_file(self):

        self.pause = False

        self.filename = filedialog.askopenfilename(title="Select file", filetypes=(("MP4 files", "*.mp4"),
                                                                                         ("WMV files", "*.wmv"), ("AVI files", "*.avi")))
        print(self.filename)

        # Open the video file
        self.cap = cv2.VideoCapture(self.filename)

        self.width = self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.height = self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

        self.canvas.config(width = self.width, height = self.height)


    def get_frame(self):   # get only one frame

        try:

            if self.cap.isOpened():
                ret, frame = self.cap.read()
                return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

        except:
            messagebox.showerror(title='Video file not found', message='Please select a video file.')


    def play_video(self):

        # Get a frame from the video source, and go to the next frame automatically
        ret, frame = self.get_frame()

        if ret:
            self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
            self.canvas.create_image(0, 0, image = self.photo, anchor = NW)

        if not self.pause:
            self.window.after(self.delay, self.play_video)


    def pause_video(self):
        self.pause = True


    # Release the video source when the object is destroyed
    def __del__(self):
        if self.cap.isOpened():
            self.cap.release()

##### End Class #####


# Create a window and pass it to videoGUI Class
videoGUI(Tk(), "EnJapan")

Если я напишу следующий код в функции play_video:

self.pause = False

Кнопка паузы не будет работать.Потому что метод «window.after» автоматически вызывает функцию «play_video» и делает «self.pause» ложным.Поэтому кнопка Пауза не будет иметь никакого эффекта.

Ответы [ 4 ]

0 голосов
/ 18 марта 2019
from tkinter import *
from tkinter import messagebox
from tkinter import filedialog
import PIL.Image, PIL.ImageTk
import cv2


class videoGUI:

    def __init__(self, window, window_title):

        self.window = window
        self.window.title(window_title)

        top_frame = Frame(self.window)
        top_frame.pack(side=TOP, pady=5)

        bottom_frame = Frame(self.window)
        bottom_frame.pack(side=BOTTOM, pady=5)

        self.pause = False   # Parameter that controls pause button

        self.canvas = Canvas(top_frame)
        self.canvas.pack()

        # Select Button
        self.btn_select=Button(bottom_frame, text="Select video file", width=15, command=self.open_file)
        self.btn_select.grid(row=0, column=0)

        # Play Button
        self.btn_play=Button(bottom_frame, text="Play", width=15, command=self.play_video)
        self.btn_play.grid(row=0, column=1)

        # Pause Button
        self.btn_pause=Button(bottom_frame, text="Pause", width=15, command=self.pause_video)
        self.btn_pause.grid(row=0, column=2)

        # Resume Button
        self.btn_resume=Button(bottom_frame, text="resume", width=15, command=self.resume_video)
        self.btn_resume.grid(row=0, column=3)

        self.delay = 15   # ms

        self.window.mainloop()


    def open_file(self):

        self.pause = False

        self.filename = filedialog.askopenfilename(title="Select file", filetypes=(("MP4 files", "*.mp4"),
                                                                                         ("WMV files", "*.wmv"), ("AVI files", "*.avi")))
        print(self.filename)

        # Open the video file
        self.cap = cv2.VideoCapture(self.filename)

        self.width = self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.height = self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

        self.canvas.config(width = self.width, height = self.height)


    def get_frame(self):   # get only one frame

        try:

            if self.cap.isOpened():
                ret, frame = self.cap.read()
                return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))

        except:
            messagebox.showerror(title='Video file not found', message='Please select a video file.')


    def play_video(self):

        # Get a frame from the video source, and go to the next frame automatically
        ret, frame = self.get_frame()

        if ret:
            self.photo = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame))
            self.canvas.create_image(0, 0, image = self.photo, anchor = NW)

        if not self.pause:
            self.window.after(self.delay, self.play_video)


    def pause_video(self):
        self.pause = True

#Addition
    def resume_video(self):
        self.pause=False
        self.play_video()


    # Release the video source when the object is destroyed
    def __del__(self):
        if self.cap.isOpened():
            self.cap.release()

##### End Class #####


# Create a window and pass it to videoGUI Class
videoGUI(Tk(), "EnJapan")
0 голосов
/ 05 февраля 2019

Вопрос : кнопка паузы не будет работать.

К cancel уже поставленной в очередь events для self.play_video изменить следующее:

def play_video(self):
    ...

    if self.pause:
        self.after_cancel(self.after_id)
    else:
        self.after_id = self.window.after(self.delay, self.play_video)
0 голосов
/ 05 февраля 2019

простой метод play_video (self)

if self.pause == True: self.pause = ложное возвращение

0 голосов
/ 01 февраля 2019

Я бы создал другой метод для обратного вызова кнопки воспроизведения.Примерно так:

def play_start(self):
    self.pause = False
    self.play_video()

Однако я бы позаботился о том, чтобы вы отключили кнопку воспроизведения, если она уже воспроизводится.В противном случае вы можете получить несколько «экземпляров», равных play_video, если нажать кнопку воспроизведения несколько раз.


В качестве альтернативы можно объединить кнопку воспроизведения и паузы, чтобы она переключала значение self.pause.Тогда у вас может быть только одна кнопка с одной функцией обратного вызова.

...