使用Gstreamer中的管道播放音频和视频

2024-10-02 00:29:15 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有办法制作一个管道来播放任何视频文件(也包含音频)?我尝试过将以下元素链接起来:

filesrc -> decodebin

连同

queue -> audioconvert -> autoaudiosink

queue -> autovideoconvert -> autovideosink

这导致两个问题:

  1. 无法将queue链接到autovideoconvert
  2. 我不知道如何使用"pad-added"事件实现pad,特别是当管道同时支持音频和视频时

我想知道如何做到这一点而不需要gst.parse_launch。此外,我希望pieline可以使用我抛出的任何格式(如playbin),但不能使用playbin,因为我需要链接其他元素(levelvolume

或者,是否有方法将元素(如level)连接到playbin


Tags: 元素管道queue链接音频level视频文件pad
3条回答

我已经构建了一个example video player,它利用了您描述的元素

它应该向您展示如何动态连接焊盘

'''
Copyright (c) 2011 Joar Wandborg <http://wandborg.se>

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

或者您现在可以使用GStreamer 1.0

您将在那里找到新的属性^{}^{},它们可用于将元素(如level))连接到playbin

通过Python GObject内省,可以很容易地做到这一点:

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

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

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

如果需要,可以在uridecodebinaudioconvert之间添加queue元素


更新

我可以使用下面的gst启动命令执行您描述的操作

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

相关问题 更多 >

    热门问题