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