在Tkinter中播放视频文件的方法?

27

有没有一种方法可以播放像 AVI, MP4 等的视频文件?

我尝试使用 PyMedia,但显然它只适用于 Pygame

我的问题有什么解决方案吗?

6个回答

21

你可以使用 python-gstreamer 来播放视频(在Linux上对我起作用,但在Windows上也应该能正常工作)。这需要安装 python-gstreamerpython-gobject,我建议你使用这个一体化安装程序。

这是代码:

import os
import sys
import Tkinter as tkinter

import gobject
import gst

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

1
@koehima 在同一个窗口上播放多个视频是否可行?我想显示视频缩略图。bus.connect需要window_id吗?它能够与frame或label一起使用吗? - ealfonso
1
我已经尝试过这个方法,但以上的指南对我没有用:我只是得到了一个空白的Tkinter窗口。有什么调试的想法吗? - ealfonso
1
我得到了与erjoalgo相同的结果。只有一个空白窗口。 - Tennessee Leeuwenburg
我无法安装gst。 - Adarsh Maurya

4
以下代码适用于我在Ubuntu 16.04下使用GStreamer 1.0和Python 3,并在单个窗口中启用了八个堆叠的视频播放器。(声音通道仅简单混合在一起。)请注意,libav / ffmpeg分支在Ubuntu 14.04下引起问题,这些问题似乎在16.04下得到解决。请注意,除了gstreamer1.0-plugins- *之外,您还需要安装gstreamer1.0-libav软件包。该代码建立在@koehlma的2011年答案之上,该答案假定GStreamer 0.10和Python 2。
import sys
import os

if sys.version_info[0] < 3:
    import Tkinter as tkinter
else:
    import tkinter

import gi
gi.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 GstVideo

def 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 repeated
relative_height = 1 / float(NUMBER_OF_FRAMES)

# Only argument number checked, not validity.
number_of_file_names_given = len(sys.argv) - 1
if 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()

3

使用版本号>=2.0.0的tkvideoplayer库,可以帮助您播放、暂停、快进或获取视频元数据等功能。

pip install tkvideoplayer

样例示例:

import tkinter as tk
from tkVideoPlayer import TkinterVideo

root = tk.Tk()

videoplayer = TkinterVideo(master=root, scaled=True)
videoplayer.load(r"samplevideo.mp4")
videoplayer.pack(expand=True, fill="both")

videoplayer.play() # play the video

root.mainloop()

在GitHub页面中有一个创建完整视频播放器的示例 page
请参考文档

2

最简单的方法是使用tkVideo

安装它

pip install tkVideo

这是一个脚本,可以轻松地展示它的工作原理!

from tkinter import *
from tkvideo import tkvideo

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

这是PyPI的链接,点击可获取更多信息。


当我尝试使用那个解决方案时,TK视频的帧率不稳定。 - Adam B

1

koehlma的回答已经过时。"Tkinter"应该是 "tkinter";"gst" 应该是 "Gst";"playbin2" 应该是 "playbin"。"STATE_PLAYING" 应该是 "State.PLAYING"。以下设置和代码适用于2022年4月5日Debian 11。

首先,需要安装以下软件包:

apt install python3-gi python3-gst-1.0 python3-tk

代码应该更新为:

import os
import sys
import tkinter as tkinter

import gi
gi.require_version('Gst', '1.0')
from gi.repository import Gst as gst
from gi.repository import GObject as gobject

def on_sync_message(bus, message, window_id):
        return
        # message does not have structure field any more.
        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()

gst.init(None)
player = gst.ElementFactory.make('playbin', '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()

0

我最近制作了一个包来实现这个功能,无边框视频播放器。它还可以同步播放音频。

pip install bvPlayer

代码:

from bvPlayer import bvPlayer

bvPlayer("file.mp4")

代码库


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接