You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:36:18