I'm trying to write a simple music player using GStreamer. I want to play any arbitrary music file ABS_FILE_PATH
, store the samples for other purposes and later loop over these indefinitely, once the original end of stream is reached.
Now playing the music works fine until short after the last sample of the track was played. Most of the time there's just silence, but sometimes there are one or two audible samples indicating, that the track just started playing again. The same holds for the terminal output. It shows, that a few samples after looping was started, the need-data
signal is sent more frequently than before.
I've used fakesink
for dumping the data, which seemed to work perfectly fine. The data was just looped, like it was intended.
So what happens here? Why don't the samples play a second (third, fourth, ...) time? I've run out of ideas.
Following I added a minimal example of what I'm doing without any UI, but with the same problem:
import itertools, signal
signal.signal(signal.SIGINT, signal.SIG_DFL)
from gi.repository import Gst, GstApp, Gtk
Gst.init(None)
# read samples with Gst.AppSink from a playbin
playbin = Gst.ElementFactory.make("playbin")
playbin.props.uri = "file://" + ABS_FILE_PATH # only works with absolute paths
playbin.props.audio_sink = GstApp.AppSink(sync=False, emit_signals=True)
playbin.set_state(Gst.State.PLAYING)
# loop over all samples
def samples(app_sink):
samples = []
sample = app_sink.pull_sample()
while sample:
yield sample
samples.append(sample)
sample = app_sink.pull_sample()
print('looping')
for sample in itertools.cycle(samples):
yield sample
# write samples with Gst.AppSrc
def need_data(appsrc, length, samples):
print('sample')
sample = next(samples)
appsrc.set_caps(sample.get_caps())
appsrc.push_buffer(sample.get_buffer())
src = GstApp.AppSrc(format=Gst.Format.TIME, emit_signals=True)
src.connect('need-data', need_data, samples(playbin.props.audio_sink))
# to the autoaudiosink or just a fakesink
sink = Gst.ElementFactory.make("autoaudiosink")
#sink = Gst.ElementFactory.make("fakesink")
#sink.props.dump = True # dump contents of fakesink
# playback
play = Gst.Pipeline()
play.add(src)
play.add(sink)
src.link(sink)
play.set_state(Gst.State.PLAYING)
Gtk.main()
gst-plugins-base: 1.4.4
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…