使Python中的GStreamer视频/音频平滑循环
我正在尝试使用GStreamer平滑地循环MPEG-4文件。我想播放视频和音频,如果有,并循环播放。我的应用程序使用GTK作为UI 现在我有三个问题:使Python中的GStreamer视频/音频平滑循环,python,python-3.x,audio,video,gstreamer,Python,Python 3.x,Audio,Video,Gstreamer,我正在尝试使用GStreamer平滑地循环MPEG-4文件。我想播放视频和音频,如果有,并循环播放。我的应用程序使用GTK作为UI 现在我有三个问题: Raspberry Pi 4的视频播放不稳定/不稳定,我正在运行它。我所说的“起伏/急促”是指每1-2秒,播放就会冻结几秒钟。当在VLC应用程序中播放相同的视频时,它是平滑的 不播放音频。同样,在VLC中播放时,音频如预期的那样存在。据我所知,playbin元素自动播放音频和视频 当到达视频结束时,最后一帧将冻结1-2秒,然后再从第一帧开始播放视
playbin
元素自动播放音频和视频视频_player.py:
#/usr/bin/python3
导入操作系统
导入gi
gi.要求_版本(“Gst”、“1.0”)
gi.要求_版本(“Gtk”、“3.0”)
gi.需要_版本(“GstVideo”、“1.0”)
从gi.repository导入Gst、Gtk、GstVideo
类视频播放器(Gtk.DrawingArea):
定义初始化(self,video\u uri:str,loop:bool):
super()。\uuuu init\uuuuu()
自我循环=循环
self.\uu video\u uri=“file://”+os.path.abspath(video\u uri)
self.\uuxid=无
Gst.init(无)
self.connect(“实现”,self.\u on\u实现)
self.set_size_request(19201080)#本例中的硬编码
self.\uu playbin=Gst.ElementFactory.make(“playbin”,“player”)
self.\u总线=self.\u playbin.get\u总线()
self.\uuuu总线。添加信号\u手表()
self.\uuu总线.connect(“消息::eos”,self.\uu在视频端)
self.\u总线.启用\u同步\u消息\u发射()
self.\u总线.connect(“同步消息::元素”,self.\u在同步消息上)
self.\u playbin.set\u属性(“uri”,self.\u video\u uri)
def_uuon_urealize(self,widget:Gtk.Window,data=None)->None:
window=widget.get_window()
self.\uxid=window.get\uxid()
同步消息上的定义(self,总线:Gst.bus,消息:Gst.message)->无:
如果message.get_structure().get_name()=“准备窗口句柄”:
image\u sink=message.src
image_sink.set_属性(“强制纵横比”,True)
图像\u接收器。设置\u窗口\u句柄(self.\u xid)
视频端上的定义(self,总线:Gst.bus,消息:Gst.message)->无:
如果是自循环:
self.\u playbin.set\u state(Gst.state.NULL)
self.\u playbin.set\u state(Gst.state.PLAYING)
def播放(自)->无:
如果self.\u playbin.get\u state(0).state!=Gst.State.PLAYING:
self.\u playbin.set\u state(Gst.state.PLAYING)
main.py:
#/usr/bin/python3
从视频播放器导入视频播放器
导入gi
gi.要求_版本(“Gtk”、“3.0”)
从gi.repository导入Gtk
window=Gtk.window()
视频播放器=视频播放器(“test\u video.mp4”,loop=True)
添加(视频播放器)
window.fullscreen()
window.show_all()
视频播放器。播放()
Gtk.main()
这个答案提供了一个使用VLC的示例;这一点被问题的作者所接受(见评论)——Raspberry Pi 4和其他类似SOC上的GStreamer通常是滞后的,如果不开始修改GStreamer库,软解决方案可能对OP没有帮助
请注意,该代码受到了您的启发,但已根据您的需要进行了修改
进行视频循环所需的更改(上述链接中未提供)是将参数'--input REPLATE=-1'传递给vlcinstance
安装依赖项(假设您已经安装了gtk)
您的代码:
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
MRL = "" # File to play
WIDTH = 300
HEIGHT = 300
class ApplicationWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Python-Vlc Media Player")
self.player_paused=False
self.is_player_active = False
self.connect("destroy",Gtk.main_quit)
def show(self):
self.show_all()
def setup_objects_and_events(self):
self.playback_button = Gtk.Button()
self.stop_button = Gtk.Button()
self.play_image = Gtk.Image.new_from_icon_name(
"gtk-media-play",
Gtk.IconSize.MENU
)
self.pause_image = Gtk.Image.new_from_icon_name(
"gtk-media-pause",
Gtk.IconSize.MENU
)
self.stop_image = Gtk.Image.new_from_icon_name(
"gtk-media-stop",
Gtk.IconSize.MENU
)
self.playback_button.set_image(self.play_image)
self.stop_button.set_image(self.stop_image)
self.playback_button.connect("clicked", self.toggle_player_playback)
self.stop_button.connect("clicked", self.stop_player)
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(WIDTH,HEIGHT)
self.draw_area.connect("realize",self._realized)
self.hbox = Gtk.Box(spacing=6)
self.hbox.pack_start(self.playback_button, True, True, 0)
self.hbox.pack_start(self.stop_button, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.draw_area, True, True, 0)
self.vbox.pack_start(self.hbox, False, False, 0)
def stop_player(self, widget, data=None):
self.player.stop()
self.is_player_active = False
self.playback_button.set_image(self.play_image)
def toggle_player_playback(self, widget, data=None):
"""
Handler for Player's Playback Button (Play/Pause).
"""
if self.is_player_active == False and self.player_paused == False:
self.player.play()
self.playback_button.set_image(self.pause_image)
self.is_player_active = True
elif self.is_player_active == True and self.player_paused == True:
self.player.play()
self.playback_button.set_image(self.pause_image)
self.player_paused = False
elif self.is_player_active == True and self.player_paused == False:
self.player.pause()
self.playback_button.set_image(self.play_image)
self.player_paused = True
else:
pass
def _realized(self, widget, data=None):
self.vlcInstance = vlc.Instance("--no-xlib", "--input-repeat=-1")
self.player = self.vlcInstance.media_player_new()
win_id = widget.get_window().get_xid()
self.player.set_xwindow(win_id)
self.player.set_mrl(MRL)
self.player.play()
self.playback_button.set_image(self.pause_image)
self.is_player_active = True
if __name__ == '__main__':
if not sys.argv[1:]:
print("Exiting \nMust provide the MRL.")
sys.exit(1)
if len(sys.argv[1:]) == 1:
MRL = sys.argv[1]
window = ApplicationWindow()
window.setup_objects_and_events()
window.show()
Gtk.main()
window.player.stop()
window.vlcInstance.release()
我对覆盆子皮4的Gstreamer有严重的问题。一个阻碍问题是。但可能还有更多。目前,对于Gstreamer应用程序,我仍然被迫使用Pi 3。许多人报告说,在诸如rpi等平台上,Gstreamer存在问题,关于如何使用vlc绑定或调用Popen()实现这一点的代码示例也可以接受吗?@Alexisdevarenes是的,使用vlc绑定也很好well@alexisdevarennes如果可能的话,请包含显示如何在GTK小部件中显示视频的代码
import sys
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
gi.require_version('GdkX11', '3.0')
from gi.repository import GdkX11
import vlc
MRL = "" # File to play
WIDTH = 300
HEIGHT = 300
class ApplicationWindow(Gtk.Window):
def __init__(self):
Gtk.Window.__init__(self, title="Python-Vlc Media Player")
self.player_paused=False
self.is_player_active = False
self.connect("destroy",Gtk.main_quit)
def show(self):
self.show_all()
def setup_objects_and_events(self):
self.playback_button = Gtk.Button()
self.stop_button = Gtk.Button()
self.play_image = Gtk.Image.new_from_icon_name(
"gtk-media-play",
Gtk.IconSize.MENU
)
self.pause_image = Gtk.Image.new_from_icon_name(
"gtk-media-pause",
Gtk.IconSize.MENU
)
self.stop_image = Gtk.Image.new_from_icon_name(
"gtk-media-stop",
Gtk.IconSize.MENU
)
self.playback_button.set_image(self.play_image)
self.stop_button.set_image(self.stop_image)
self.playback_button.connect("clicked", self.toggle_player_playback)
self.stop_button.connect("clicked", self.stop_player)
self.draw_area = Gtk.DrawingArea()
self.draw_area.set_size_request(WIDTH,HEIGHT)
self.draw_area.connect("realize",self._realized)
self.hbox = Gtk.Box(spacing=6)
self.hbox.pack_start(self.playback_button, True, True, 0)
self.hbox.pack_start(self.stop_button, True, True, 0)
self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
self.add(self.vbox)
self.vbox.pack_start(self.draw_area, True, True, 0)
self.vbox.pack_start(self.hbox, False, False, 0)
def stop_player(self, widget, data=None):
self.player.stop()
self.is_player_active = False
self.playback_button.set_image(self.play_image)
def toggle_player_playback(self, widget, data=None):
"""
Handler for Player's Playback Button (Play/Pause).
"""
if self.is_player_active == False and self.player_paused == False:
self.player.play()
self.playback_button.set_image(self.pause_image)
self.is_player_active = True
elif self.is_player_active == True and self.player_paused == True:
self.player.play()
self.playback_button.set_image(self.pause_image)
self.player_paused = False
elif self.is_player_active == True and self.player_paused == False:
self.player.pause()
self.playback_button.set_image(self.play_image)
self.player_paused = True
else:
pass
def _realized(self, widget, data=None):
self.vlcInstance = vlc.Instance("--no-xlib", "--input-repeat=-1")
self.player = self.vlcInstance.media_player_new()
win_id = widget.get_window().get_xid()
self.player.set_xwindow(win_id)
self.player.set_mrl(MRL)
self.player.play()
self.playback_button.set_image(self.pause_image)
self.is_player_active = True
if __name__ == '__main__':
if not sys.argv[1:]:
print("Exiting \nMust provide the MRL.")
sys.exit(1)
if len(sys.argv[1:]) == 1:
MRL = sys.argv[1]
window = ApplicationWindow()
window.setup_objects_and_events()
window.show()
Gtk.main()
window.player.stop()
window.vlcInstance.release()