3
# vi:si:et:sw=4:sts=4:ts=4
6
# takes in one or more audio files and creates one audio file of the combination
8
# Uses the gnonlin elements (http://gnonlin.sf.net/)
15
from gstfile import Discoverer, time_to_string
17
class AudioSource(gst.Bin):
18
"""A bin for audio sources with proper audio converters"""
20
def __init__(self, filename, caps):
21
gst.Bin.__init__(self)
22
self.filename = filename
25
self.filesrc = gst.element_factory_make("filesrc")
26
self.filesrc.set_property("location", self.filename)
27
self.dbin = gst.element_factory_make("decodebin")
28
self.ident = gst.element_factory_make("identity")
29
self.audioconvert = gst.element_factory_make("audioconvert")
30
self.audioscale = gst.element_factory_make("audioscale")
32
self.add_many(self.filesrc, self.dbin, self.ident,
33
self.audioconvert, self.audioscale)
34
self.filesrc.link(self.dbin)
35
self.audioconvert.link(self.audioscale)
36
self.audioscale.link(self.ident, caps)
37
self.add_ghost_pad(self.ident.get_pad("src"), "src")
39
self.dbin.connect("new-decoded-pad", self._new_decoded_pad_cb)
41
def _new_decoded_pad_cb(self, dbin, pad, is_last):
42
if not "audio" in pad.get_caps().to_string():
44
pad.link(self.audioconvert.get_pad("sink"))
46
gobject.type_register(AudioSource)
48
class AudioConcat(gst.Thread):
49
"""A Gstreamer thread that concatenates a series of audio files to another audio file"""
51
def __init__(self, infiles, outfile, audioenc="rawvorbisenc", muxer="oggmux"):
52
gst.Thread.__init__(self)
53
self.infiles = infiles
54
self.outfile = outfile
55
self.audioenc = gst.element_factory_make(audioenc)
57
raise NameError, str(audioenc + " audio encoder is not available")
58
self.muxer = gst.element_factory_make(muxer)
60
raise NameError, str(muxer + " muxer is not available")
61
self.filesink = gst.element_factory_make("filesink")
62
self.filesink.set_property("location", self.outfile)
64
self.timeline = gst.element_factory_make("gnltimeline")
65
self.audiocomp = gst.element_factory_make("gnlcomposition", "audiocomp")
67
self.audioconvert = gst.element_factory_make("audioconvert")
68
self.add_many(self.timeline, self.audioconvert,
69
self.audioenc, self.muxer, self.filesink)
71
## identity perfect stream check !
72
identity = gst.element_factory_make("identity")
73
identity.set_property("check-perfect", True)
76
#self.audioconvert.link(self.audioenc)
77
if not self.audioconvert.link(identity):
78
print "couldn't link audioconv -> ident"
79
if not identity.link(self.audioenc):
80
print "couldn't link ident -> audioenc"
81
self.audioenc.link(self.muxer)
82
self.muxer.link(self.filesink)
84
self.timeline.add(self.audiocomp)
86
caps = gst.caps_from_string("audio/x-raw-int,channels=2,rate=44100,depth=16")
88
for infile in self.infiles:
89
d = Discoverer(infile)
92
print "file", infile, "has length", time_to_string(d.audiolength)
93
asource = AudioSource(infile, caps)
94
gnlsource = gst.element_factory_make("gnlsource")
95
gnlsource.set_property("element", asource)
96
gnlsource.set_property("media-start", 0L)
97
gnlsource.set_property("media-stop", d.audiolength)
98
gnlsource.set_property("start", pos)
99
gnlsource.set_property("stop", pos + d.audiolength)
100
self.audiocomp.add(gnlsource)
103
self.timeline.get_pad("src_audiocomp").link(self.audioconvert.get_pad("sink"))
104
timelineprobe = gst.Probe(False, self.timelineprobe)
105
self.timeline.get_pad("src_audiocomp").add_probe(timelineprobe)
107
def timelineprobe(self, probe, data):
108
if isinstance(data, gst.Buffer):
109
print "timeline outputs buffer", data.timestamp, data.duration
111
print "timeline ouputs event", data.type
114
gobject.type_register(AudioConcat)
116
def eos_cb(pipeline):
119
if __name__ == "__main__":
120
if len(sys.argv) < 3:
121
print "Usage : %s <input file(s)> <output file>" % sys.argv[0]
122
print "\tCreates an ogg file from all the audio input files"
124
if not gst.element_factory_make("gnltimeline"):
125
print "You need the gnonlin elements installed (http://gnonlin.sf.net/)"
127
concat = AudioConcat(sys.argv[1:-1], sys.argv[-1])
128
concat.connect("eos", eos_cb)
129
concat.set_state(gst.STATE_PLAYING)