Воспроизведение аудио и видео с помощью Pipeline в Gstreamer (Python) - PullRequest
7 голосов
/ 18 ноября 2011

Есть ли способ создать конвейер, который будет воспроизводить любой видеофайл (который также будет содержать аудио)?Я пытался связать элементы, такие как:

filesrc -> decodebin

вместе с

queue -> audioconvert -> autoaudiosink

и

queue -> autovideoconvert -> autovideosink

Это вызывает две проблемы:

  1. A queue нельзя связать с autovideoconvert.
  2. Я понятия не имею, как реализовать пэд с событием "pad-added", особенно когда конвейер поддерживает как аудио, так и видео.

Я хотел бы знать, как это сделать без необходимости gst.parse_launch.Кроме того, я хочу, чтобы pieline работал с любым форматом, который я выбрасываю (например, playbin), но не могу использовать playbin, так как мне нужно будет связывать другие элементы (level и volume).

В качестве альтернативы, есть ли способ соединить элементы (например, level) с playbin?

Ответы [ 4 ]

3 голосов
/ 21 ноября 2011

Я создал пример видеоплеера , который использует элементы, которые вы описали.

Он должен показать вам, как динамически подключать пэды друг к другу.

'''
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 /7836263/vosproizvedenie-audio-i-video-s-pomoschy-pipeline-v-gstreamer-python
- 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 голос
/ 14 июня 2015

В качестве альтернативы вы уже можете использовать GStreamer 1.0.

Там вы найдете новые свойства audio-filter и video-filter, которые можно использовать для подключения элементов (таких как level) к плейбину.

С помощью Python GObject Introspection это можно сделать так же просто, как:

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

playbin = Gst.ElementFactory.make("playbin")
playbin.props.audio_filter = level
1 голос
/ 16 августа 2012

Я уверен, что вы бы уже реализовали это.Но для тех, кто смотрит на ваш вопрос, мой ответ может помочь.Код выглядит следующим образом:

 #!/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()  
1 голос
/ 20 ноября 2011

queue не является исходным элементом, вам нужно иметь либо uridecodebin или decodebin, либо что-то похожее в качестве исходного элемента.

Это пример конвейера в формате 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

При необходимости вы можете добавить элемент queue между uridecodebin и 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
...