Search code examples
pythongstreamervalagenieinterleave

I need help about of audio 'interleave' on gstreamer-0.10


I'm trying to program an video/audio dubbing editor. Trying to mix serveral audio files in vala/genie. Using adder or interleave.

I need traslate this gst-launch command to Genie or Vala code but using: 1.- Gst.Element.link 2.- Gst.ElementFactory.make 3.- request_pad and others... Please don't use parse_launch()

gst-launch-0.10 interleave name=i ! audioconvert ! wavenc ! filesink location=file.wav  filesrc location=file1.wav ! decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.   filesrc location=file2.wav !  decodebin ! audioconvert ! "audio/x-raw-int,channels=1" ! queue ! i.

I have this Genie code:

[indent=4]

uses
    Gst

pipeline: private Pipeline 
interleave: private Element
audioconvert: private Element
audioconvert2: private Element
audioconvert3: private Element
wavenc: private Element
decodebin2: private Element
decodebin3: private Element
capsfilter2: private Element
capsfilter3: private Element
filesink: private Element
src3:private Element
src2:private Element
queue2:private Element
queue3:private Element
capsfilter2a:private Element
capsfilter3a:private Element

init
    Gst.init (ref args)
    pipeline = new Pipeline ("mypipeline")

    interleave=ElementFactory.make ("interleave","inter")
    interleave.set ("name","i")
    audioconvert=ElementFactory.make ("audioconvert","audioconvert")
    wavenc=ElementFactory.make ("wavenc","wavenc")
    filesink=ElementFactory.make ("filesink","filesink")
    filesink.set("location","totalfinal.wav")

    // primer archivo
    src2=  ElementFactory.make ("filesrc", "filesrc2")
    src2.set ("location","file1.wav")
    decodebin2=  ElementFactory.make ("decodebin", "decodebin2")
    audioconvert2=  ElementFactory.make ("audioconvert", "audioconvert2")
    capsfilter2= ElementFactory.make ("capsfilter","capsfileter2")
    capsfilter2.set("caps", Gst.Caps.from_string("audio/x-raw-int,channels=1"))
    queue2= ElementFactory.make ("queue","queue2")
    capsfilter2a= ElementFactory.make ("capsfilter","capsfileter2a")
    capsfilter2a.set("caps", Gst.Caps.from_string("i.sink_0"))

    // segundo archivo
    src3=  ElementFactory.make ("filesrc", "filesrc3")
    src3.set ("location","file2.wav")
    decodebin3=  ElementFactory.make ("decodebin", "decodebin3")
    audioconvert3=  ElementFactory.make ("audioconvert", "audioconvert3")
    capsfilter3= ElementFactory.make ("capsfilter","capsfileter3")
    capsfilter3.set("caps", Gst.Caps.from_string("audio/x-raw-int,channels=1"))
    queue3= ElementFactory.make ("queue","queue3")
    capsfilter3a= ElementFactory.make ("capsfilter","capsfileter3a")
    capsfilter3a.set("caps", Gst.Caps.from_string("i.sink_1"))


    pipeline.add_many(interleave,wavenc,filesink,audioconvert);
    pipeline.add_many(src2,src3,decodebin2,decodebin3,audioconvert2,audioconvert3,capsfilter2,capsfilter2a,capsfilter3,capsfilter3a);
    pipeline.add_many(queue2,queue3);

    // basic line
    interleave.link(audioconvert)
    audioconvert.link(wavenc)
    wavenc.link(filesink)

    // first src
    src2.link(decodebin2)
    decodebin2.link(audioconvert2)
    audioconvert2.link(capsfilter2)
    capsfilter2.link(queue2)
    queue2.link(capsfilter2a)

    // second src
    src3.link(decodebin3)
    decodebin3.link(audioconvert3)
    audioconvert3.link(capsfilter3)
    capsfilter3.link(queue3)
    queue3.link(capsfilter3a)


    pipeline.set_state(Gst.State.PLAYING)

    new MainLoop().run();

I don't know what is going wrong.


Solution

  • The following Vala code works as long as the files are the same format (.wav or .mp3).

    using Gst;
    
    public class AudioFileSource : Gst.Bin {
    
        string filename;
        Gst.Caps outcaps;
        Gst.Element filesrc;
    
        Gst.Element dbin; 
        Gst.Element ident;
        Gst.Element audioconvert;
        Gst.Element volume;
    
        /**
         * AudioFileSource - creates an input source Bin from a filename
         * @param filename: The name of the audio file to load. 
         * @param volume: Volume level (fractional, may go above 1.0)
         * @param outcaps: Optional GStreamer capabilities object. A sensible
            default will be used if not given.
         */ 
        public AudioFileSource (string filename, double volume = 0.5, Gst.Caps? outcaps = null) {
    
            this.filename = filename;
    
            if (outcaps == null)
                this.outcaps = Gst.Caps.from_string("audio/x-raw,format=int,channels=2,rate=44100,depth=16");
            else
                this.outcaps = outcaps;
    
            filesrc = Gst.ElementFactory.make("filesrc", "src");
            filesrc.set("location", this.filename);
    
            dbin = Gst.ElementFactory.make("decodebin", null);
            ident = Gst.ElementFactory.make("identity", null);
            audioconvert = Gst.ElementFactory.make("audioconvert", null);
    
            this.volume = Gst.ElementFactory.make("volume", null);
            this.volume.set_property("volume", volume);
    
            add_many(filesrc, dbin, ident, audioconvert, this.volume);
            filesrc.link(dbin);
    
            audioconvert.link(this.volume);
            this.volume.link_filtered(ident, outcaps);
    
            // Create an output from this bin (the "src" of the ident instance
            // becomes the the "src" of this bin)
            var srcpad = new Gst.GhostPad("src", ident.get_static_pad("src"));
            add_pad(srcpad);
    
            dbin.pad_added.connect((e, p) => {
                p.link(audioconvert.get_static_pad("sink"));
            });
        }
    }
    
    public class SimpleMixer : GLib.Object {
        /*
        Simple class that mixes audio sources straight over the top of each other.
        */
    
        Gst.Pipeline pipeline;
        Gst.Element mixer;
        Gst.Element audioconvert;
        Gst.Element sink;
    
        AudioFileSource[] sources = {};
    
        public signal void finished();
    
        public SimpleMixer () {
            pipeline = new Gst.Pipeline("mypipeline");
            mixer = Gst.ElementFactory.make("adder", null);
        }
    
        public void stop(Message msg) {
            if (msg.type == Gst.MessageType.EOS) {
                pipeline.set_state(Gst.State.NULL);
                finished();
            }
        }
    
        public void add_source (string filename) {
            sources += new AudioFileSource(filename);
        }
    
        public void mix (string output) {
    
            audioconvert = Gst.ElementFactory.make("wavenc", null);
            sink = Gst.ElementFactory.make("filesink", "sink");
            sink.set("location", output);
    
            foreach (var source in sources)
                pipeline.add(source);
    
            pipeline.add(mixer);
    
            foreach (var source in sources)
                source.get_static_pad("src").link(mixer.get_request_pad("sink_%u"));
    
            pipeline.add(audioconvert);
            mixer.link(audioconvert);
            pipeline.add(sink);
            audioconvert.link(sink);
    
            var bus = pipeline.get_bus();
            bus.add_signal_watch(GLib.Priority.HIGH);
            bus.message.connect(stop);
    
            pipeline.set_state(Gst.State.PLAYING);
        }
    }
    
    static int main(string[] args) {
        Gst.init(ref args);
        var mainloop = new MainLoop();
    
        var mixer = new SimpleMixer();
        for (int i = 2; i < args.length; i++)
            mixer.add_source (args[i]);
    
        mixer.finished.connect(() => {
            mainloop.quit();
        });
    
        mixer.mix(args[1]);
    
        mainloop.run();
    
        return 0;
    }
    

    You should compile this with gstreamer-1.0:

    valac --pkg gstreamer-1.0 mixer.vala
    

    To use it:

    ./mixer totalfinal.wav file1.wav file2.wav
    

    Hope this helps get you started.