Python 如何在tkinter窗口中显示视频预览

Python 如何在tkinter窗口中显示视频预览,python,python-3.x,tkinter,pygame,moviepy,Python,Python 3.x,Tkinter,Pygame,Moviepy,我遇到了如何在tkinter窗口内显示视频预览窗口的问题。下面的代码将播放视频,但我想在tkinter窗口中显示该视频 Python代码: 从moviepy.editor导入* 从moviepy.video.fx.resize导入调整大小 导入pygame pygame.display.set_标题('Kumawat!') clip=VideoFileClip('mk.mp4') w=1300 h=700 显示=(宽,高) clip.resize(display.preview)() pygam

我遇到了如何在tkinter窗口内显示视频预览窗口的问题。下面的代码将播放视频,但我想在tkinter窗口中显示该视频

Python代码:

从moviepy.editor导入*
从moviepy.video.fx.resize导入调整大小
导入pygame
pygame.display.set_标题('Kumawat!')
clip=VideoFileClip('mk.mp4')
w=1300
h=700
显示=(宽,高)
clip.resize(display.preview)()
pygame.quit()

经过一些研究,您似乎无法轻松地将剪辑嵌入到tkinter帧中。我提出的解决方案是:

  • 使用
    imageio
    下载视频
  • 使用迭代器将每个视频帧提取到图像中
  • 将图像转换为ImageTk
  • 将此图像添加到tkinter标签
在下面的示例中,我添加了两个控制按钮来启动和停止视频,以及一个等待循环来实时运行视频(假设每秒24帧)。我还没有研究如何包括声音

import time
import tkinter as tk
import imageio
from PIL import Image, ImageTk

global pause_video

# download video at: http://www.html5videoplayer.net/videos/toystory.mp4
video_name = "toystory.mp4"
video = imageio.get_reader(video_name)


def video_frame_generator():
    def current_time():
        return time.time()

    start_time = current_time()
    _time = 0
    for frame, image in enumerate(video.iter_data()):

        # turn video array into an image and reduce the size
        image = Image.fromarray(image)
        image.thumbnail((750, 750), Image.ANTIALIAS)

        # make image in a tk Image and put in the label
        image = ImageTk.PhotoImage(image)

        # introduce a wait loop so movie is real time -- asuming frame rate is 24 fps
        # if there is no wait check if time needs to be reset in the event the video was paused
        _time += 1 / 24
        run_time = current_time() - start_time
        while run_time < _time:
            run_time = current_time() - start_time
        else:
            if run_time - _time > 0.1:
                start_time = current_time()
                _time = 0

        yield frame, image


def _stop():
    global pause_video
    pause_video = True


def _start():
    global pause_video
    pause_video = False


if __name__ == "__main__":

    root = tk.Tk()
    root.title('Video in tkinter')

    my_label = tk.Label(root)
    my_label.pack()
    tk.Button(root, text='start', command=_start).pack(side=tk.LEFT)
    tk.Button(root, text='stop', command=_stop).pack(side=tk.LEFT)

    pause_video = False
    movie_frame = video_frame_generator()

    while True:
        if not pause_video:
            frame_number, frame = next(movie_frame)
            my_label.config(image=frame)

        root.update()

    root.mainloop()
导入时间
将tkinter作为tk导入
导入图像
从PIL导入图像,ImageTk
全球暂停视频
#下载视频地址:http://www.html5videoplayer.net/videos/toystory.mp4
video_name=“toystory.mp4”
视频=图像IO.get\u读取器(视频\u名称)
def视频帧生成器():
定义当前_时间():
返回时间
开始时间=当前时间()
_时间=0
对于帧,枚举中的图像(video.iter_data()):
#将视频阵列转换为图像并缩小大小
image=image.fromarray(image)
image.缩略图((750750),image.ANTIALIAS)
#在tk图像中制作图像并放入标签
image=ImageTk.PhotoImage(图像)
#引入一个等待循环,使电影是实时的——帧速率为24 fps
#如果没有等待,请检查视频暂停时是否需要重置时间
_时间+=1/24
运行时间=当前时间()-开始时间
运行时间<运行时间:
运行时间=当前时间()-开始时间
其他:
如果运行时间-\u时间>0.1:
开始时间=当前时间()
_时间=0
屈服框架、图像
def_stop():
全球暂停视频
暂停视频=真
def_start():
全球暂停视频
暂停视频=错误
如果名称=“\uuuuu main\uuuuuuuu”:
root=tk.tk()
root.title('tkinter'中的视频)
my_label=tk.label(根)
my_label.pack()
按钮(root,text='start',command=\u start).pack(side=tk.LEFT)
按钮(root,text='stop',command=\u stop).pack(side=tk.LEFT)
暂停视频=错误
电影\帧=视频\帧\生成器()
尽管如此:
如果不暂停视频:
帧号,帧=下一帧(电影帧)
my_label.config(image=frame)
root.update()
root.mainloop()

通常的方法是生成视频文件的胶片。除非预览意味着以较小的大小播放整个文件。如果必须使用
moviepy
,则可以对剪辑中的图像使用
。iter_frames()
逐帧显示,如@BrunoVermeulen answer中所示。据我所知,
Moviepy
也使用
imageio