Way to play video files in Tkinter?
You could use python-gstreamer
for playing videos (this works for me on Linux, but it should also work on Windows). This requires python-gstreamer
and python-gobject
, I would recommend you to use this all-in-one installer.
Here is the code:
import osimport sysimport Tkinter as tkinterimport gobjectimport gstdef on_sync_message(bus, message, window_id): if not message.structure is None: if message.structure.get_name() == 'prepare-xwindow-id': image_sink = message.src image_sink.set_property('force-aspect-ratio', True) image_sink.set_xwindow_id(window_id)gobject.threads_init()window = tkinter.Tk()window.geometry('500x400')video = tkinter.Frame(window, bg='#000000')video.pack(side=tkinter.BOTTOM,anchor=tkinter.S,expand=tkinter.YES,fill=tkinter.BOTH)window_id = video.winfo_id()player = gst.element_factory_make('playbin2', 'player')player.set_property('video-sink', None)player.set_property('uri', 'file://%s' % (os.path.abspath(sys.argv[1])))player.set_state(gst.STATE_PLAYING)bus = player.get_bus()bus.add_signal_watch()bus.enable_sync_message_emission()bus.connect('sync-message::element', on_sync_message, window_id)window.mainloop()
The following code works for me with GStreamer 1.0 and Python 3 under Ubuntu 16.04. It also enables eight video players stacked in a column in a single window. (The sound channels are simply mixed together.)
The libav/ffmpeg fork created problems under Ubuntu 14.04, which seem to be solved under 16.04. Note that you need the package gstreamer1.0-libav in addition to gstreamer1.0-plugins-*.
The code builds on the 2011 answer by @koehlma, which assumed GStreamer 0.10 and Python 2.
import sysimport osif sys.version_info[0] < 3: import Tkinter as tkinterelse: import tkinterimport gigi.require_version('Gst', '1.0')from gi.repository import Gst, GObject# Needed for set_window_handle():gi.require_version('GstVideo', '1.0')from gi.repository import GstVideodef set_frame_handle(bus, message, frame_id): if not message.get_structure() is None: if message.get_structure().get_name() == 'prepare-window-handle': display_frame = message.src display_frame.set_property('force-aspect-ratio', True) display_frame.set_window_handle(frame_id)NUMBER_OF_FRAMES = 8 # with more frames than arguments, videos are repeatedrelative_height = 1 / float(NUMBER_OF_FRAMES)# Only argument number checked, not validity.number_of_file_names_given = len(sys.argv) - 1if number_of_file_names_given < 1: print('Give at least one video file name.') sys.exit()if number_of_file_names_given < NUMBER_OF_FRAMES: print('Up to', NUMBER_OF_FRAMES, 'video file names can be given.')file_names = list()for index in range(number_of_file_names_given): file_names.append(sys.argv[index + 1])window = tkinter.Tk()window.title("Multiple videos in a column using Tk and GST 1.0")window.geometry('480x960')Gst.init(None)GObject.threads_init()for number in range(NUMBER_OF_FRAMES): display_frame = tkinter.Frame(window, bg='') relative_y = number * relative_height display_frame.place(relx = 0, rely = relative_y, anchor = tkinter.NW, relwidth = 1, relheight = relative_height) frame_id = display_frame.winfo_id() player = Gst.ElementFactory.make('playbin', None) fullname = os.path.abspath(file_names[number % len(file_names)]) player.set_property('uri', 'file://%s' % fullname) player.set_state(Gst.State.PLAYING) bus = player.get_bus() bus.enable_sync_message_emission() bus.connect('sync-message::element', set_frame_handle, frame_id)window.mainloop()
Tha easy way is by using tkVideo
to install it
pip install tkVideo
this is script that show you how does it work easily!
from tkinter import *from tkvideo import tkvideoroot = Tk()my_label = Label(root)my_label.pack()player = tkvideo("C:\\path\\to\\video.mp4", my_label, loop = 1, size = (1280,720))player.play()root.mainloop()
this is PyPI link to it for more informations.