import cv2
|
import tkinter as tk
|
from tkinter import filedialog, ttk
|
from PIL import Image, ImageTk
|
|
|
class VideoPlayer:
|
def __init__(self, root):
|
self.root = root
|
self.root.title("Tkinter MP4 播放器")
|
|
# 视频控件
|
self.video_label = tk.Label(root)
|
self.video_label.pack()
|
|
# 按钮和进度条区域
|
controls_frame = tk.Frame(root)
|
controls_frame.pack()
|
|
self.play_button = tk.Button(controls_frame, text="播放", command=self.toggle_play_pause)
|
self.play_button.grid(row=0, column=0, padx=5)
|
|
self.replay_button = tk.Button(controls_frame, text="重新播放", command=self.replay_video)
|
self.replay_button.grid(row=0, column=1, padx=5)
|
|
self.progress = ttk.Scale(controls_frame, from_=0, to=1, orient="horizontal", command=self.seek_video)
|
self.progress.grid(row=0, column=2, padx=5, sticky="ew")
|
|
controls_frame.columnconfigure(2, weight=1)
|
|
# 状态变量
|
self.cap = None
|
self.is_playing = False
|
self.current_frame = 0
|
self.total_frames = 0
|
self.fps = 30
|
self.video_path = None
|
|
# 文件打开按钮
|
self.open_button = tk.Button(root, text="打开视频", command=self.open_file)
|
self.open_button.pack()
|
|
def open_file(self):
|
self.video_path = filedialog.askopenfilename(filetypes=[("MP4文件", "*.mp4"), ("所有文件", "*.*")])
|
if not self.video_path:
|
return
|
self.load_video()
|
|
def load_video(self):
|
if self.cap:
|
self.cap.release()
|
self.cap = cv2.VideoCapture(self.video_path)
|
if not self.cap.isOpened():
|
tk.messagebox.showerror("错误", "无法打开视频")
|
return
|
self.fps = int(self.cap.get(cv2.CAP_PROP_FPS))
|
self.total_frames = int(self.cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
self.current_frame = 0
|
self.progress.config(to=self.total_frames)
|
self.is_playing = True
|
self.play_button.config(text="暂停")
|
self.play_video()
|
|
def play_video(self):
|
if not self.is_playing or not self.cap:
|
return
|
|
ret, frame = self.cap.read()
|
if ret:
|
self.current_frame += 1
|
self.progress.set(self.current_frame)
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
img = ImageTk.PhotoImage(Image.fromarray(frame))
|
self.video_label.config(image=img)
|
self.video_label.image = img
|
self.root.after(int(1000 / self.fps), self.play_video)
|
else:
|
self.is_playing = False
|
self.play_button.config(text="播放")
|
|
def toggle_play_pause(self):
|
if not self.cap:
|
return
|
if self.is_playing:
|
self.is_playing = False
|
self.play_button.config(text="播放")
|
else:
|
self.is_playing = True
|
self.play_button.config(text="暂停")
|
self.play_video()
|
|
def replay_video(self):
|
if not self.cap:
|
return
|
self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
|
self.current_frame = 0
|
self.progress.set(0)
|
self.is_playing = True
|
self.play_button.config(text="暂停")
|
self.play_video()
|
|
def seek_video(self, value):
|
if not self.cap:
|
return
|
self.current_frame = int(float(value))
|
self.cap.set(cv2.CAP_PROP_POS_FRAMES, self.current_frame)
|
if not self.is_playing:
|
self.play_video()
|
|
|
# 创建主窗口
|
root = tk.Tk()
|
app = VideoPlayer(root)
|
root.mainloop()
|