【问题标题】:How to use GStreamer1.0 with PyQt4 Phonon application?如何将 GStreamer1.0 与 PyQt4 Phonon 应用程序一起使用?
【发布时间】:2023-03-24 05:34:01
【问题描述】:

我有一个使用 PyQt4 和 Phonon(带有 gstreamer0.1 后端)的音乐应用程序。我想使用一些 GStreamer 代码添加一些音频分析。两组代码独立工作正常,但是当我尝试将它们组合在同一个应用程序中时,我收到以下错误并且应用程序挂起。测试代码如下。有什么想法吗?

> (python3:11922): GStreamer-WARNING **: Element factory metadata for 'bin' has no valid long-name field 

> phonon_gstreamer.py:110: Warning: cannot register existing type `GstObject'                            
  self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)

> phonon_gstreamer.py:110: Warning: g_once_init_leave: assertion `result != 0' failed
  self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)

> phonon_gstreamer.py:110: Warning: g_type_register_static: assertion `parent_type > 0' failed
  self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)

> phonon_gstreamer.py:110: Warning: g_object_newv: assertion `G_TYPE_IS_OBJECT (object_type)' failed
  self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)


from PyQt4 import QtGui
from PyQt4.phonon import Phonon

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

class AudioAnalysis(Gst.Bin):
    def __init__(self):
        super().__init__()

        # Create elements
        q1 = Gst.ElementFactory.make('queue', None)        

        convert = Gst.ElementFactory.make("audioconvert", None)
        resample = Gst.ElementFactory.make("audioresample", None)        
        self.analysis = Gst.ElementFactory.make("rganalysis", None)
        self.analysis.set_property("num-tracks", 1)

        q2 = Gst.ElementFactory.make('queue', None)

        # Add elements to Bin
        self.add(q1)
        self.add(convert)
        self.add(resample)
        self.add(self.analysis)
        self.add(q2)

        # Link elements
        q1.link(convert)
        convert.link(resample)
        resample.link(self.analysis)
        self.analysis.link(q2)

        # Add Ghost Pads
        self.add_pad(
            Gst.GhostPad.new('sink', q1.get_static_pad('sink'))
        )
        self.add_pad(
            Gst.GhostPad.new('src', q2.get_static_pad('src'))
        )

    def bus_message_tag(self, bus, message):
        pass

class Example:
    def __init__(self):        
        self.mainloop = GObject.MainLoop()
        self.pipeline = Gst.Pipeline()

        # Create elements
        self.src = Gst.ElementFactory.make('filesrc', None)
        self.dec = Gst.ElementFactory.make('decodebin', None)
        self.audio = AudioAnalysis()        
        self.sink =  Gst.ElementFactory.make('fakesink', None)

        # Add elements to pipeline      
        self.pipeline.add(self.src)
        self.pipeline.add(self.dec)
        self.pipeline.add(self.audio)
        self.pipeline.add(self.sink)

        # Set properties
        self.src.set_property('location', 'foo.mp3')

        # Connect signal handlers
        self.dec.connect('pad-added', self.on_pad_added)
        self.dec.connect('pad-removed', self.removed_decoded_pad)

        # Link elements
        self.src.link(self.dec)
        self.audio.link(self.sink)

        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect('message::eos', self.on_eos)
        self.bus.connect('message::error', self.on_error)
        self.bus.connect("message::tag", self.audio.bus_message_tag)       

    def run(self):
        self.pipeline.set_state(Gst.State.PLAYING)
        self.mainloop.run()

    def kill(self):
        self.pipeline.set_state(Gst.State.NULL)
        self.mainloop.quit()

    def removed_decoded_pad(self, dbin, pad):
        pad.unlink(self.audio.get_static_pad("sink"))

    def on_pad_added(self, element, pad):
        string = pad.query_caps(None).to_string()
        if string.startswith('audio/'):
            pad.link(self.audio.get_static_pad('sink'))

    def on_eos(self, bus, msg):
        self.kill()

    def on_error(self, bus, msg):
        print('on_error():', msg.parse_error())
        self.kill()

#example = Example()
#example.run()

class Window(QtGui.QPushButton):
    def __init__(self):
        QtGui.QPushButton.__init__(self, '')
        self.mediaObject = Phonon.MediaObject(self)
        self.audioOutput = Phonon.AudioOutput(Phonon.MusicCategory, self)
        Phonon.createPath(self.mediaObject, self.audioOutput)
        self.mediaObject.stateChanged.connect(self.handleStateChanged)
        self.mediaObject.setCurrentSource(Phonon.MediaSource(sys.argv[1]))
        self.mediaObject.play()

    def handleStateChanged(self, newstate, oldstate):
        if newstate == Phonon.PlayingState:
            self.setText('Playing')
        elif newstate == Phonon.StoppedState:
            self.setText('Stopped')
        elif newstate == Phonon.ErrorState:
            source = self.mediaObject.currentSource().fileName()
            print('ERROR: could not play:', source.toLocal8Bit().data())

if __name__ == '__main__':

    GObject.threads_init()
    Gst.init(None)

    import sys
    app = QtGui.QApplication(sys.argv)
    app.setApplicationName('Phonon')
    win = Window()
    win.resize(200, 100)
    win.show()
    sys.exit(app.exec_())

【问题讨论】:

    标签: python gstreamer phonon


    【解决方案1】:

    这是不可能的。 Gstreamer 0.10 和 1.x 不可并行链接。

    要么尝试使用这个分支:https://projects.kde.org/projects/kdesupport/phonon/phonon-gstreamer/repository/show?rev=1.0-porting(不稳定的 AFAIK)

    或者使用非 gstreamer 声子后端。或者你可以在单独的过程中实现分析代码,不要直接调用它。

    【讨论】:

      猜你喜欢
      • 2013-10-23
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-19
      • 1970-01-01
      相关资源
      最近更新 更多