gpt4 book ai didi

python - 使 Python 中的 GStreamer 视频/音频流畅和循环

转载 作者:行者123 更新时间:2023-12-02 22:14:22 24 4
gpt4 key购买 nike

我正在尝试使用 GStreamer 流畅地循环播放 MPEG-4 文件。我想播放视频和音频(如果有的话)并循环播放。我的应用使用 GTK 作为 UI。

目前我遇到三个问题:

  1. 在 Raspberry Pi 4 上播放视频时断断续续,我正在运行它。断断续续/生涩,我的意思是每隔约 1-2 秒,播放会卡住几分之一秒。在 VLC 应用程序中播放同一视频时,很流畅。
  2. 没有播放音频。同样,在 VLC 中播放时,音频如预期的那样存在。据我了解,playbin 元素会自动播放音频和视频。
  3. 到达视频结尾时,最后一帧会卡住 1-2 秒,然后视频会再次从第一帧开始播放。

我目前有以下代码。


video_player.py:

#!/usr/bin/python3
import os
import gi

gi.require_version("Gst", "1.0")
gi.require_version("Gtk", "3.0")
gi.require_version("GstVideo", "1.0")
from gi.repository import Gst, Gtk, GstVideo


class VideoPlayer(Gtk.DrawingArea):
def __init__(self, video_uri: str, loop: bool):
super().__init__()
self.__loop = loop
self.__video_uri = "file:///" + os.path.abspath(video_uri)
self.__xid = None

Gst.init(None)
self.connect("realize", self.__on_realize)
self.set_size_request(1920, 1080) # Hardcoded for this example

self.__playbin = Gst.ElementFactory.make("playbin", "player")
self.__bus = self.__playbin.get_bus()
self.__bus.add_signal_watch()
self.__bus.connect("message::eos", self.__on_video_end)
self.__bus.enable_sync_message_emission()
self.__bus.connect("sync-message::element", self.__on_sync_message)
self.__playbin.set_property("uri", self.__video_uri)

def __on_realize(self, widget: Gtk.Window, data=None) -> None:
window = widget.get_window()
self.__xid = window.get_xid()

def __on_sync_message(self, bus: Gst.Bus, message: Gst.Message) -> None:
if message.get_structure().get_name() == "prepare-window-handle":
image_sink = message.src
image_sink.set_property("force-aspect-ratio", True)
image_sink.set_window_handle(self.__xid)

def __on_video_end(self, bus: Gst.Bus, message: Gst.Message) -> None:
if self.__loop:
self.__playbin.set_state(Gst.State.NULL)
self.__playbin.set_state(Gst.State.PLAYING)

def play(self) -> None:
if self.__playbin.get_state(0).state != Gst.State.PLAYING:
self.__playbin.set_state(Gst.State.PLAYING)

主要.py:

#!/usr/bin/python3
from video_player import VideoPlayer
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

window = Gtk.Window()
video_player = VideoPlayer("test_video.mp4", loop=True)

window.add(video_player)
window.fullscreen()
window.show_all()

video_player.play()

Gtk.main()

最佳答案

这个答案提供了一个使用 VLC 的例子;问题的作者接受了这一点(请参阅评论)——Raspberry Pi 4 和其他类似 SOC 上的 GStreamer 通常会出现滞后和软解决方案,如果不开始修改 Gstreamer 库,可能不会帮助 OP。

请注意代码的灵感来自 https://www.codementor.io/@princerapa/python-media-player-vlc-gtk-favehuy2b但已根据您的需要进行了修改。

进行视频循环所需的更改(上述链接中未提供)是将参数“--input-repeat=-1”传递给 vlcinstance。

安装依赖项(假设您已经安装了 gtk)

pip install python-vlc

您的代码:

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

关于python - 使 Python 中的 GStreamer 视频/音频流畅和循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63129603/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com