能否在Tkinter窗口添加60FPS MP4视频并实现缩放、循环播放?
在Tkinter窗口中嵌入60FPS MP4视频(适配窗口+循环播放)
完全可行,核心是通过OpenCV读取视频帧,结合PIL转换格式后在Tkinter的Label组件中逐帧刷新,同时监听窗口尺寸变化实现自适应缩放,视频播放到末尾时重置读取位置即可实现循环。
步骤1:安装依赖
需要两个第三方库,执行以下命令安装:
pip install opencv-python pillow
步骤2:完整实现代码
import tkinter as tk import cv2 from PIL import Image, ImageTk class VideoPlayer: def __init__(self, root, video_path): self.root = root self.video_path = video_path # 加载视频文件 self.cap = cv2.VideoCapture(video_path) # 获取视频原始尺寸 self.orig_width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH)) self.orig_height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 设置播放帧率为60(若要使用视频原帧率,替换为self.cap.get(cv2.CAP_PROP_FPS)) self.fps = 60 self.delay = int(1000 / self.fps) # 创建用于显示视频的Label self.video_label = tk.Label(root) self.video_label.pack(fill=tk.BOTH, expand=True) # 监听窗口大小变化事件 self.root.bind('<Configure>', self.on_window_resize) self.current_window_size = (root.winfo_width(), root.winfo_height()) # 启动播放 self.play_video() def on_window_resize(self, event): # 仅当窗口尺寸真正改变时更新记录 new_size = (event.width, event.height) if new_size != self.current_window_size: self.current_window_size = new_size def resize_frame(self, frame): # 按原比例缩放视频帧以适配窗口,避免拉伸变形 win_w, win_h = self.current_window_size scale = min(win_w / self.orig_width, win_h / self.orig_height) new_w = int(self.orig_width * scale) new_h = int(self.orig_height * scale) return cv2.resize(frame, (new_w, new_h)) def play_video(self): ret, frame = self.cap.read() if ret: # OpenCV读取的帧是BGR格式,转换为PIL需要的RGB格式 frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 调整帧尺寸适配当前窗口 frame = self.resize_frame(frame) # 转换为Tkinter可识别的图像格式 img = Image.fromarray(frame) imgtk = ImageTk.PhotoImage(image=img) # 保留图像引用,防止被Python垃圾回收机制销毁 self.video_label.imgtk = imgtk self.video_label.configure(image=imgtk) else: # 视频播放完毕,重置到开头继续播放 self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0) ret, frame = self.cap.read() frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) frame = self.resize_frame(frame) img = Image.fromarray(frame) imgtk = ImageTk.PhotoImage(image=img) self.video_label.imgtk = imgtk self.video_label.configure(image=imgtk) # 递归调用,按设定帧率刷新下一帧 self.root.after(self.delay, self.play_video) if __name__ == "__main__": root = tk.Tk() root.title("Tkinter视频播放器") root.geometry("800x600") # 替换为你的MP4文件路径 player = VideoPlayer(root, "your_video.mp4") root.mainloop()
关键说明
- 帧率控制:代码中手动设置为60FPS,若要使用视频自身帧率,将
self.fps = 60替换为self.fps = self.cap.get(cv2.CAP_PROP_FPS)即可。 - 自适应缩放:按视频原比例缩放,避免画面拉伸;若需要填充整个窗口(允许变形),可直接将
resize_frame方法中的缩放逻辑改为return cv2.resize(frame, self.current_window_size)。 - 循环播放:当
cap.read()返回False(视频播放完毕)时,通过cap.set(cv2.CAP_PROP_POS_FRAMES, 0)将视频读取位置重置到开头,继续播放。 - 图像引用:必须保留
imgtk的引用(self.video_label.imgtk = imgtk),否则Tkinter无法显示图像。
内容的提问来源于stack exchange,提问作者ersteroderletzter
相关产品推荐
相关产品推荐

