使用Gstreamer中的Pipeline播放音频和视频(Python)

时间:2011-11-18 18:30:12

标签: python c gstreamer pipeline

有没有办法让管道能够播放任何视频文件(也会包含音频)?我尝试过链接元素,如:

filesrc -> decodebin

一起
queue -> audioconvert -> autoaudiosink

queue -> autovideoconvert -> autovideosink

这会导致两个问题:

  1. queue无法与autovideoconvert相关联。
  2. 我不知道如何使用"pad-added"事件实现pad,尤其是当管道支持音频和视频时。
  3. 我想知道如何在不需要gst.parse_launch的情况下执行此操作。另外,我希望pieline可以使用我抛出的任何格式(如playbin),但不能使用playbin,因为我需要链接其他元素(levelvolume)。

    或者,有没有办法将元素(例如level)连接到播放箱?

5 个答案:

答案 0 :(得分:3)

我已经构建了example video player,它使用了您描述的元素。

它应该向您展示如何动态地将打击垫连接到彼此。

'''
Copyright (c) 2011 Joar Wandborg 

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

---

- A response to http://stackoverflow.com/questions/8187257/play-audio-and-video-with-a-pipeline-in-gstreamer-python/8197837
- Like it? Buy me a beer! https://flattr.com/thing/422997/Joar-Wandborg
'''

import gst
import gobject
gobject.threads_init()
import logging


logging.basicConfig()

_log = logging.getLogger(__name__)
_log.setLevel(logging.DEBUG)


class VideoPlayer(object):
    '''
    Simple video player
    '''

    source_file = None

    def __init__(self, **kwargs):
        self.loop = gobject.MainLoop()

        if kwargs.get('src'):
            self.source_file = kwargs.get('src')

        self.__setup()

    def run(self):
        self.loop.run()

    def stop(self):
        self.loop.quit()

    def __setup(self):
        _log.info('Setting up VideoPlayer...')
        self.__setup_pipeline()
        _log.info('Set up')

    def __setup_pipeline(self):
        self.pipeline = gst.Pipeline('video-player-pipeline')

        # Source element
        self.filesrc = gst.element_factory_make('filesrc')
        self.filesrc.set_property('location', self.source_file)
        self.pipeline.add(self.filesrc)

        # Demuxer
        self.decoder = gst.element_factory_make('decodebin2')
        self.decoder.connect('pad-added', self.__on_decoded_pad)
        self.pipeline.add(self.decoder)

        # Video elements
        self.videoqueue = gst.element_factory_make('queue', 'videoqueue')
        self.pipeline.add(self.videoqueue)

        self.autovideoconvert = gst.element_factory_make('autovideoconvert')
        self.pipeline.add(self.autovideoconvert)

        self.autovideosink = gst.element_factory_make('autovideosink')
        self.pipeline.add(self.autovideosink)

        # Audio elements
        self.audioqueue = gst.element_factory_make('queue', 'audioqueue')
        self.pipeline.add(self.audioqueue)

        self.audioconvert = gst.element_factory_make('audioconvert')
        self.pipeline.add(self.audioconvert)

        self.autoaudiosink = gst.element_factory_make('autoaudiosink')
        self.pipeline.add(self.autoaudiosink)

        self.progressreport = gst.element_factory_make('progressreport')
        self.progressreport.set_property('update-freq', 1)
        self.pipeline.add(self.progressreport)

        # Link source and demuxer
        linkres = gst.element_link_many(
            self.filesrc,
            self.decoder)

        if not linkres:
            _log.error('Could not link source & demuxer elements!\n{0}'.format(
                    linkres))

        linkres = gst.element_link_many(
            self.audioqueue,
            self.audioconvert,
            self.autoaudiosink)

        if not linkres:
            _log.error('Could not link audio elements!\n{0}'.format(
                    linkres))

        linkres = gst.element_link_many(
            self.videoqueue,
            self.progressreport,
            self.autovideoconvert,
            self.autovideosink)

        if not linkres:
            _log.error('Could not link video elements!\n{0}'.format(
                    linkres))

        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect('message', self.__on_message)

        self.pipeline.set_state(gst.STATE_PLAYING)

    def __on_decoded_pad(self, pad, data):
        _log.debug('on_decoded_pad: {0}'.format(pad))

        if pad.get_caps()[0].to_string().startswith('audio'):
            pad.link(self.audioqueue.get_pad('sink'))
        else:
            pad.link(self.videoqueue.get_pad('sink'))

    def __on_message(self, bus, message):
        _log.debug(' - MESSAGE: {0}'.format(message))


if __name__ == '__main__':
    player = VideoPlayer(
        src='/home/joar/Videos/big_buck_bunny_1080p_stereo.avi')

    player.run()

答案 1 :(得分:1)

queue不是源元素,您需要uridecodebindecodebin或类似于源元素的东西。

这是gst-launch格式的示例管道。

uridecodebin \
    uri="file:///home/joar/Dropbox/Music/04 - Deadmau5 - Clockwork (Jonas Steur Remix).mp3" \
! audioconvert ! autoaudiosink

这意味着在管道中有

  • uridecodebin - 解码箱,能够解码与GStreamer兼容的任何源文件,uri属性设置为file:///home/joar/Dropbox/Music/04 - Deadmau5 - Clockwork (Jonas Steur Remix).mp3
  • audioconvert - 在不同格式之间转换音频
  • autoaudiosink

如果需要,您可以在queueuridecodebin之间添加audioconvert元素。


更新

我可以使用以下gst-launch命令

执行您所描述的操作
gst-launch-0.10 filesrc \
    location="/home/joar/Dropbox/Skrillex vs. Adele - Set Fire to Everybody.mov" \
! decodebin name=dmux \
dmux. ! queue ! audioconvert ! autoaudiosink \
dmux. ! queue ! autovideoconvert ! autovideosink

答案 2 :(得分:1)

我相信你现在已经实现了这一点。但对于那些关注你问题的人来说,我的回答可能有所帮助。代码如下

 #!/usr/bin/python
 import pygst
 pygst.require('0.10')
 import gst

 import pygtk
 pygtk.require('2.0')
 import gtk

 # this is very important, without this, callbacks from gstreamer thread
 # will messed our program up


 def on_new_decoded_pad(dbin, pad, islast):
     structure_name = pad.get_caps()[0].get_name()
     decode = pad.get_parent()
     pipeline = decode.get_parent()
     if structure_name.startswith("video"):
            queuev = pipeline.get_by_name('queuev')
        decode.link(queuev)
     if structure_name.startswith("audio"):
            queuea = pipeline.get_by_name('queuea')
    print queuea
        decode.link(queuea)


 def main():
     pipeline = gst.Pipeline('pipleline')

     filesrc = gst.element_factory_make("filesrc", "filesrc")
     filesrc.set_property('location', '/home/thothadri/Videos/nuclear.avi')

     decode = gst.element_factory_make("decodebin", "decode")

     queuev = gst.element_factory_make("queue", "queuev")

     sink = gst.element_factory_make("autovideosink", "sink")

     queuea = gst.element_factory_make("queue", "queuea")

     convert = gst.element_factory_make('audioconvert', 'convert')

     sink_audio = gst.element_factory_make("autoaudiosink", "sink_audio")

     pipeline.add(filesrc,decode,queuev,queuea,convert,sink,sink_audio)

     gst.element_link_many(filesrc, decode)
     gst.element_link_many(queuev,sink)
     gst.element_link_many(queuea,convert,sink_audio)

     decode.connect("new-decoded-pad", on_new_decoded_pad)

     pipeline.set_state(gst.STATE_PLAYING)



 main()
 gtk.gdk.threads_init()
 gtk.main()  

答案 3 :(得分:1)

或者您现在可以使用GStreamer 1.0。

您可以找到新属性audio-filtervideo-filter,可用于将元素(例如level))连接到播放列表。

使用Python GObject Introspection,这可以轻松完成:

level = Gst.ElementFactory.make('level')

playbin = Gst.ElementFactory.make("playbin")
playbin.props.audio_filter = level

答案 4 :(得分:0)

在本地播放音频和视频的管道:

gst-launch-1.0 -v filesrc location=random-file.mpeg ! decodebin 名称=demux demux。 !队列 !视频转换! xvimagesink 解复用器。 !队列 !音频转换!脉冲接收器

我们可以使用 autovideosink 代替 xvimagesink。