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()
|