2011-11-04 38 views
1

我正在編寫一個使用GStreamer將媒體文件轉換爲mp3文件的程序。它的工作原理,但我想知道音頻流的持續時間。以下是簡化代碼。如何使用GStreamer獲取蒸汽數據的持續時間

import logging 

import pygst 
pygst.require('0.10') 
import gst 

# this is very important, without this, callbacks from gstreamer thread 
# will messed our program up 
import gobject 
gobject.threads_init() 


def on_new_buffer(appsink): 
    buf = appsink.emit('pull-buffer') 
    print 'new buffer', len(buf) 

def on_new_preroll(appsink): 
    buf = appsink.emit('pull-preroll') 
    print 'new preroll', len(buf) 

def on_pad_added(decoder, pad): 
    print 'Pad added' 
    decoder.link(converter) 
    pipeline.set_state(gst.STATE_PLAYING) 

def on_msg(msg): 
    if msg.type == gst.MESSAGE_ERROR: 
     error, debug = msg.parse_error() 
     print error, debug 
    elif msg.type == gst.MESSAGE_EOS: 
     duration = pipeline.query_duration(gst.FORMAT_TIME) 
     print 'Duration', duration 

pipeline = gst.Pipeline('pipeline') 

appsrc = gst.element_factory_make('appsrc', 'src') 
decoder = gst.element_factory_make('decodebin2', 'decoder') 
converter = gst.element_factory_make('audioconvert', 'converter') 
lame = gst.element_factory_make('lamemp3enc', 'lame') 
appsink = gst.element_factory_make('appsink', 'sink') 

pipeline.add(appsrc, decoder, lame, converter, appsink) 
gst.element_link_many(appsrc, decoder) 
gst.element_link_many(converter, lame, appsink) 

# -- setup appskink -- 

# -- setup decoder -- 
decoder.connect('pad-added', on_pad_added) 

# -- setup mp3 encoder -- 
lame.set_property('bitrate', 128) 

# -- setup appsink -- 
# this makes appsink emit singals 
appsink.set_property('emit-signals', True) 
# turns off sync to make decoding as fast as possible 
appsink.set_property('sync', False) 
appsink.connect('new-buffer', on_new_buffer) 
appsink.connect('new-preroll', on_new_preroll) 

pipeline.set_state(gst.STATE_PAUSED) 

data = open(r'D:\Musics\Fiona Fung - Proud Of You.mp3', 'rb').read() 
buf = gst.Buffer(data) 
appsrc.emit('push-buffer', buf) 
appsrc.emit('end-of-stream') 

bus = pipeline.get_bus() 
while True: 
    msg = bus.poll(gst.MESSAGE_ANY, -1) 
    on_msg(msg) 

我沒有使用filesrc作爲源,我使用appsrc來代替。我想從互聯網而不是文件讀取流式數據。奇怪的是,作爲結果,輸出時間爲-1

.... 
new buffer 315 
new buffer 320 
new buffer 335 
new buffer 553 
Duration (-1L, <enum GST_FORMAT_TIME of type GstFormat>) 

如果我切換到appsrc filesrc,那麼持續時間是正確的

import logging 

import pygst 
pygst.require('0.10') 
import gst 

# this is very important, without this, callbacks from gstreamer thread 
# will messed our program up 
import gobject 
gobject.threads_init() 


def on_new_buffer(appsink): 
    buf = appsink.emit('pull-buffer') 
    print 'new buffer', len(buf) 

def on_new_preroll(appsink): 
    buf = appsink.emit('pull-preroll') 
    print 'new preroll', len(buf) 

def on_pad_added(decoder, pad): 
    print 'Pad added' 
    decoder.link(converter) 
    pipeline.set_state(gst.STATE_PLAYING) 

def on_msg(msg): 
    if msg.type == gst.MESSAGE_ERROR: 
     error, debug = msg.parse_error() 
     print error, debug 
    elif msg.type == gst.MESSAGE_EOS: 
     duration = pipeline.query_duration(gst.FORMAT_TIME) 
     print 'Duration', duration 

pipeline = gst.Pipeline('pipeline') 

filesrc = gst.element_factory_make('filesrc', 'src') 
decoder = gst.element_factory_make('decodebin2', 'decoder') 
converter = gst.element_factory_make('audioconvert', 'converter') 
lame = gst.element_factory_make('lamemp3enc', 'lame') 
appsink = gst.element_factory_make('appsink', 'sink') 

pipeline.add(filesrc, decoder, lame, converter, appsink) 
gst.element_link_many(filesrc, decoder) 
gst.element_link_many(converter, lame, appsink) 

# -- setup filesrc -- 
filesrc.set_property('location', r'D:\Musics\Fiona Fung - Proud Of You.mp3') 

# -- setup decoder -- 
decoder.connect('pad-added', on_pad_added) 

# -- setup mp3 encoder -- 
lame.set_property('bitrate', 128) 

# -- setup appsink -- 
# this makes appsink emit singals 
appsink.set_property('emit-signals', True) 
# turns off sync to make decoding as fast as possible 
appsink.set_property('sync', False) 
appsink.connect('new-buffer', on_new_buffer) 
appsink.connect('new-preroll', on_new_preroll) 

pipeline.set_state(gst.STATE_PAUSED) 

bus = pipeline.get_bus() 
while True: 
    msg = bus.poll(gst.MESSAGE_ANY, -1) 
    on_msg(msg) 

正如你可以看到,現在的結果是正確的。

new buffer 322 
new buffer 323 
new buffer 315 
new buffer 320 
new buffer 549 
Duration (189459000000L, <enum GST_FORMAT_TIME of type GstFormat>) 

所以,我的問題是 - 如何從appsrc獲得正確的音頻流數據持續時間?

謝謝。

回答

1

不幸的是,與appsrc不可能獲得流的確切持續時間,儘管有一些固定比特率的格式可以基於文件長度來估計它,但是其他格式使用可變比特率報告未知長度。

因爲appsrc工作在傳入的緩衝區(推或拉模型),通過它接收一塊數據,使用它,然後要麼或提供下一塊數據,因此使估計的媒體時間差不多不可能。另外,在推送模式中,不可能尋找媒體。