Gstreamer+python:运行时添加和移除音频源
我正在做一个示例的python脚本,最初是在这里找到的:在运行时向GStreamer管道添加和移除音频源。这个脚本的目的是让它能够在管道运行时插入和移除音频源,但在源和添加器之间加一个audioconvert元素。这样做是因为在更一般的情况下,Adder希望接收到的音频流格式是一样的。
下面是代码;我们创建了两个生成器(发声器)。第一个发出1000Hz的音调,并等待回车键。第二个是500Hz的音调,在按下回车键后会和第一个音调合成。再次按下回车键时,只有第二个生成器的声音能被听到。
#!/usr/bin/python
import gobject;
gobject.threads_init()
import gst
# THE FOLLOWING FUNCTION IS A REWORK OF THE ORIGINAL, STILL DOING THE JOB
def create_raw_audiotest_signal(pipe, freq, adder):
# create buzzer of a given freq
buzzer = gst.element_factory_make("audiotestsrc","buzzer%d" % freq)
buzzer.set_property("freq",freq)
pipe.add(buzzer)
buzzersrc=buzzer.get_pad("src")
# Gather a request sink pad on the mixer
sinkpad=adder.get_request_pad("sink%d")
# .. and connect it to the buzzer
buzzersrc.link(sinkpad)
return buzzer, buzzersrc, sinkpad
# THIS IS A MODIFIED VERSION, NOT WORKING, THAT JUST PUTS AN AUDIOCONVERT
# ELEMENT BETWEEN THE GENERATOR AND THE ADDER.
def create_audiotest_signal_with_converter(pipe, freq, adder):
# create buzzer of a given freq
buzzer = gst.element_factory_make("audiotestsrc","buzzer%d" % freq)
buzzer.set_property("freq",freq)
# add a converter because adder wants inputs with the same format.
ac = gst.element_factory_make("audioconvert", "ac%d" % freq)
pipe.add(buzzer, ac)
# link the buzzer with the converter ...
buzzer.link(ac)
buzzersrc=buzzer.get_pad("src")
# Gather a request sink pad on the mixer
sinkpad=adder.get_request_pad("sink%d")
# and then the converter to the adder
ac.get_pad('src').link(sinkpad)
return buzzer, buzzersrc, sinkpad
if __name__ == "__main__":
# First create our pipeline
pipe = gst.Pipeline("mypipe")
# Create a software mixer with "Adder"
adder = gst.element_factory_make("adder","audiomixer")
pipe.add(adder)
# Create the first buzzer..
#buzzer1, buzzersrc1, sinkpad1 = create_raw_audiotest_signal(pipe, 1000, adder)
buzzer1, buzzersrc1, sinkpad1 = create_audiotest_signal_with_converter(pipe, 1000, adder)
# Add some output
output = gst.element_factory_make("autoaudiosink", "audio_out")
pipe.add(output)
adder.link(output)
# Start the playback
pipe.set_state(gst.STATE_PLAYING)
raw_input("1kHz test sound. Press <ENTER> to continue.")
# Get another generator
#buzzer2, buzzersrc2, sinkpad2 = create_raw_audiotest_signal(pipe, 500, adder)
buzzer2, buzzersrc2, sinkpad2 = create_audiotest_signal_with_converter(pipe, 500, adder)
# Start the second buzzer (other ways streaming stops because of starvation)
buzzer2.set_state(gst.STATE_PLAYING)
raw_input("1kHz + 500Hz test sound playing simoultenously. Press <ENTER> to continue.")
# Before removing a source, we must use pad blocking to prevent state changes
buzzersrc1.set_blocked(True)
# Stop the first buzzer
buzzer1.set_state(gst.STATE_NULL)
# Unlink from the mixer
buzzersrc1.unlink(sinkpad2)
# Release the mixers first sink pad
adder.release_request_pad(sinkpad1)
# Because here none of the Adder's sink pads block, streaming continues
raw_input("Only 500Hz test sound. Press <ENTER> to stop.")
如果在两个调用中用create_raw_audiotest_signal替换create_audiotest_signal_with_converter,当然是可以正常工作的。如果混合使用这两者,也能工作,但会有不必要的额外延迟。最有趣的情况是,当在两个调用中都使用audioconvert时,gtk在第一次按下回车键时会阻塞。
有没有人有什么建议?我哪里做错了?谢谢大家。
1 个回答
2
我自己找到了答案,其实很简单…… 我添加了其他组件,但它们在管道中运行,保持独立的播放状态。所以解决办法是把整个管道设置为播放状态,这样就会把所有子组件的状态也设置为播放。
pipe.set_state(gst.STATE_PLAYING)
而不是:
buzzer2.set_state(gst.STATE_PLAYING)
这样就又能正常工作了。