沃兹沃斯不断的缩略图

我正在尝试使用gst-python构建视频缩略图,它看起来像这样。

from __future__ import division

import sys
import logging
import pdb

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

try:
    import gobject
    gobject.threads_init()
except:
    raise Exception('gobject could not be found')

try:
    import pygst
    pygst.require('0.10')
    import gst
    from gst import pbutils
    from gst.extend import discoverer
except:
    raise Exception('gst/pygst 0.10 could not be found')

class VideoThumbnailer:
    '''
        Creates a video thumbnail

     - Sets up discoverer & transcoding pipeline.
       Discoverer finds out information about the media file
     - Launches gobject.MainLoop, this triggers the discoverer to start running
     - Once the discoverer is done, it calls the __discovered callback function
     - The __discovered callback function launches the transcoding process
     - The _on_message callback is called from the transcoding process until it
       gets a message of type gst.MESSAGE_EOS, then it calls __stop which shuts
       down the gobject.MainLoop
    '''

    def __init__(self, src, dst, **kwargs):
        _log.info('Initializing VideoThumbnailer...')

        # Set instance variables
        self.loop = gobject.MainLoop()
        self.source_path = src
        self.destination_path = dst
        self.destination_dimensions = kwargs.get('dimensions') or (180, 180)

        if not type(self.destination_dimensions) == tuple:
            raise Exception('dimensions must be tuple: (width, height)')

        # Run setup
        self._setup()
        # Run.
        self._run()

    def _setup(self):
        self._setup_pipeline()
        self._setup_discover()

    def _run(self):
        _log.info('Discovering...')
        self.discoverer.discover()
        _log.info('Done')

        _log.debug('Initializing MainLoop()')
        self.loop.run()

    def _setup_discover(self):
        self.discoverer = discoverer.Discoverer(self.source_path)

        # Connect self.__discovered to the 'discovered' event
        self.discoverer.connect('discovered', self.__discovered)

    def __discovered(self, data, is_media):
        '''
        Callback for media discoverer.
        '''
        if not is_media:
            self.__stop()
            raise Exception('Could not discover {0}'.format(self.source_path))

        _log.debug('__discovered, data: {0}'.format(data))

        self.data = data

        # Run any tasks that depend on the info from the discovery
        self._on_discovered()

        # Tell the transcoding pipeline to start running
        #self.pipeline.set_state(gst.STATE_PLAYING)
        _log.info('Transcoding...')

    def _on_discovered(self):
        self.__setup_capsfilter()

    def _setup_pipeline(self):
        # Create a new pipeline
        self.pipeline = gst.Pipeline('VideoThumbnailerPipeline')

        # Create the elements in the pipeline
        self.filesrc = gst.element_factory_make('filesrc', 'filesrc')
        self.filesrc.set_property('location', self.source_path)
        self.pipeline.add(self.filesrc)

        self.decoder = gst.element_factory_make('decodebin2', 'decoder')
        self.decoder.connect('new-decoded-pad', self._on_dynamic_pad)
        self.pipeline.add(self.decoder)

        self.ffmpegcolorspace = gst.element_factory_make(
            'ffmpegcolorspace', 'ffmpegcolorspace')
        self.pipeline.add(self.ffmpegcolorspace)

        self.videoscale = gst.element_factory_make('videoscale', 'videoscale')
        self.videoscale.set_property('method', 'bilinear')
        self.pipeline.add(self.videoscale)

        self.capsfilter = gst.element_factory_make('capsfilter', 'capsfilter')
        self.pipeline.add(self.capsfilter)

        self.jpegenc = gst.element_factory_make('jpegenc', 'jpegenc')
        self.pipeline.add(self.jpegenc)

        self.filesink = gst.element_factory_make('filesink', 'filesink')
        self.filesink.set_property('location', self.destination_path)
        self.pipeline.add(self.filesink)

        # Link all the elements together
        self.filesrc.link(self.decoder)
        self.ffmpegcolorspace.link(self.videoscale)
        self.videoscale.link(self.capsfilter)
        self.capsfilter.link(self.jpegenc)
        self.jpegenc.link(self.filesink)

        self._setup_bus()

    def _on_dynamic_pad(self, dbin, pad, islast):
        '''
        Callback called when ``decodebin2`` has a pad that we can connect to
        '''
        # Intersect the capabilities of the video sink and the pad src
        # Then check if they have common capabilities.
        if not self.ffmpegcolorspace.get_pad_template('sink')
                .get_caps().intersect(pad.get_caps()).is_empty():
            # It IS a video src pad.
            pad.link(self.ffmpegcolorspace.get_pad('sink'))

    def _setup_bus(self):
        self.bus = self.pipeline.get_bus()
        self.bus.add_signal_watch()
        self.bus.connect('message', self._on_message)

    def __setup_capsfilter(self):
        caps = ['video/x-raw-rgb']

        if self.data.videoheight > self.data.videowidth:
            # Whoa! We have ourselves a portrait video!
            caps.append('height={0}'.format(
                    self.destination_dimensions[1]))
        else:
            # It's a landscape, phew, how normal.
            caps.append('width={0}'.format(
                    self.destination_dimensions[0]))

        self.capsfilter.set_property(
            'caps',
            gst.caps_from_string(
                ', '.join(caps)))

    def _on_message(self, bus, message):
        _log.debug((bus, message))

        t = message.type

        if t == gst.MESSAGE_EOS:
            self.__stop()
            _log.info('Done')
        elif t == gst.MESSAGE_ERROR:
            _log.error((bus, message))
            self.__stop()

    def __stop(self):
        _log.debug(self.loop)

        self.pipeline.set_state(gst.STATE_NULL)

        gobject.idle_add(self.loop.quit)

它能做什么

  • filesrc加载一个视频文件
  • decodebin2解复用视频文件,将视频src板连接到ffmpegcolorspace接收器
  • ffmpegcolorspace可以处理视频流的颜色空间
  • videoscale缩放视频
  • capsfilter告诉videoscale使视频适合180x180盒子
  • jpegenc捕获一个单一的框架
  • filesink保存jpeg文件
  • 我想要它做什么

  • filesrc加载一个视频文件
  • decodebin2解复用视频文件,将视频src板连接到ffmpegcolorspace接收器
  • ffmpegcolorspace可以处理视频流的颜色空间
  • videoscale缩放视频
  • capsfilter告诉videoscale使视频适合180x180盒子
  • jpegenc捕获30%视频中的单帧
  • filesink保存jpeg文件
  • 我尝试过

        self.decoder.seek_simple(
            gst.FORMAT_PERCENT,
            gst.SEEK_FLAG_FLUSH,
            self.WADSWORTH_CONSTANT) # int(30)
    

    放在_on_dynamic_pad ,焊盘连接后,唉,无济于事。


    这现在在https://github.com/jwandborg/mediagoblin/blob/video_gstreamer-only/mediagoblin/media_types/video/transcoders.py#L53的VideoThumbnailer类中实现。

    链接地址: http://www.djcxy.com/p/60171.html

    上一篇: Wadsworth's constant thumbnailer

    下一篇: Gstreamer: Pausing/resuming video in RTP streams