Search code examples
pythonpython-3.xtkinterpygamemoviepy

How to display video preview in tkinter window


I am having problem that how to display a video preview window inside the tkinter window. Below code will play video but i want to show that video in the tkinter window..

Python Code:

from moviepy.editor import *
from moviepy.video.fx.resize import resize  
import pygame   

pygame.display.set_caption('Kumawat!')   
clip=VideoFileClip('mk.mp4')    
w=1300    
h=700    
display=(w,h)       
clip.resize(display).preview()    
pygame.quit()    

Solution

  • After some researching it does not seem you can embed the clip easily into a tkinter frame. The solution I came up with is:

    • use imageio to download the video
    • extract each video frame using an iterator into an image
    • convert the image to a ImageTk
    • add this image to a tkinter label

    In below example I have added two control buttons to start and stop the video as well as an waiting loop to run the video at real time assuming 24 frames per second. I have not investigated how to include sound.

    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()