commons-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Edgar H <kaotix...@gmail.com>
Subject Re: [exec] Misconcepting PumpStreamHandler's way of working with streams?
Date Sun, 05 Feb 2017 20:46:43 GMT
Sure, here's a minimal example.

The following code belongs to a "MainApp" class, which is the basically the
application which starts the .jar responsible of capturing live audio data
from the system and sending it live to FFMPEG, which streams to an Icecast
Server, like a continuous stream using pipes.

public class MainApp {

    public static void main(String[] args) {
        initStream("Path to FFMPEG bin folder, which should include the
.jar of the second application that you need to copy and paste.");
    }

    public static void initStream(String path) {
        File file = new File(path);
        for (File s : file.listFiles()) {
            if (s.getName().equals("ffmpeg.exe")) {
                try {
                    DefaultExecutor executor = new DefaultExecutor();
                    executor.setWorkingDirectory(file);

                    CommandLine commandLine = new
CommandLine(s.getParentFile().getAbsolutePath());
                    System.out.println("Path: " + commandLine.toString());

                    String executeMe = "java -jar secondapp.jar"; //
Execute "SecondApp" .jar to start sending sound bytes to stdout.
                    commandLine = CommandLine.parse(executeMe);

                    PipedOutputStream output = new PipedOutputStream(); //
Fill this with bytes.
                    PipedInputStream input = new PipedInputStream();
                    output.connect(input); // Send audio bytes from output
to this input stream.

                    executor.setStreamHandler(new PumpStreamHandler(output,
null)); // Stream all the bytes to the output.
                    executor.execute(commandLine, new
DefaultExecuteResultHandler()); // Execute APP2 (The one which captures the
live audio bytes).

                    String feedMe = "ffmpeg -f s16le -ar 48000 -ac 2 -i -
-f ogg -content_type application/ogg icecast://source:hackme@localhost
:8000/stream";
                    commandLine = CommandLine.parse(feedMe);

                    executor.setStreamHandler(new PumpStreamHandler(null,
null, input)); // Send the bytes being received in real time to FFMPEG.
                    executor.execute(commandLine, new
DefaultExecuteResultHandler()); // Execute FFMPEG.
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Now, this is the code for the executable .jar which is the class
"SecondApp". This one just sends bytes to the Standard Output and it's
started by "MainApp".

public class SecondApp {

    public static void main(String[] args) throws ClassNotFoundException,
IOException {
        Mixer mixer =
AudioSystem.getMixer(AudioSystem.getMixerInfo()[Integer.parseInt(args[0])]);
        AudioFormat af = new AudioFormat(Encoding.PCM_SIGNED, 48000f, 16,
2, 4, 48000f, false);

        TargetDataLine line;
        DataLine.Info info = new DataLine.Info(TargetDataLine.class, af);
        if (!AudioSystem.isLineSupported(info))
            System.out.println("Line is not supported.");

        try {
            line = (TargetDataLine) mixer.getLine(info);
            line.open(af);

            int bytesRead, CHUNK_SIZE = 4096;
            byte[] data = new byte[line.getBufferSize() / 5];

            line.start();

            while (true) {
                bytesRead = line.read(data, 0, CHUNK_SIZE);
                System.out.write(data, 0, bytesRead);
                System.out.flush();
            }

        } catch (LineUnavailableException ex) {
            System.out.println("Line is unavailable.");
            ex.printStackTrace();
        }
    }
}

2017-02-05 16:31 GMT+01:00 Raymond DeCampo <ray@decampo.org>:

> Edgar, I didn't see anything obvious wrong with what you posted.  If you
> can distill it down to a minimal self-contained example that reproduces the
> behavior I can take a closer look.
>
> On Sat, Feb 4, 2017 at 1:47 PM, Edgar H <kaotixpro@gmail.com> wrote:
>
> > I've been struggling with this problem for quite some time now as it's my
> > very first time doing an application related to streaming and I just
> can't
> > figure out why. Here's the problem...
> >
> > What I'm trying to achieve is to send a command's output as an input for
> > the next one, which is basically what the pipe operator does. As I knew
> > this couldn't be executed directly with Exec library from Apache Commons
> I
> > started looking for ways to solve this. I've seen quite a few examples of
> > similar things to this but none of them covers my situation:
> >
> > I have two Java applications separated, one is the main application and
> the
> > second one is initialized by the first one. This second applications
> sends
> > to the Standard Output bytes, which FFMPEG should receive.
> >
> > The code that I have so far is the following one...
> >
> > public void initStream(String path) {
> >     File file = new File(path);
> >     for (File s : file.listFiles()) {
> >         if (s.getName().equals("ffmpeg.exe")) {
> >             try {
> >
> >                 // Second app, supposedly, writes here.
> >                 PipedOutputStream output = new PipedOutputStream();
> >
> >                 DefaultExecutor executor = new DefaultExecutor();
> >                 //DefaultExecutor executorFFMPEG = new DefaultExecutor();
> >                 executor.setWorkingDirectory(file);
> >                 //executor.setWorkingDirectory(file);
> >
> >                 CommandLine commandLine = new
> > CommandLine(s.getParentFile().getAbsolutePath());
> >                 System.out.println("Path: " + commandLine.toString());
> >
> >                 String executeMe = "java -jar streamer.jar";
> >                 commandLine = CommandLine.parse(executeMe);
> >
> >                 System.out.println("[testing] streamer about to
> launch.");
> >                 executor.setStreamHandler(new PumpStreamHandler(output,
> > null));
> >                 executor.execute(commandLine, new
> > DefaultExecuteResultHandler());
> >                 System.out.println("[testing] streamer started.");
> >
> >                 PipedInputStream input = new PipedInputStream();
> >                 output.connect(input);
> >
> >                 String feedMe = "ffmpeg"; // more attributes here
> >                 commandLine = CommandLine.parse(feedMe);
> >
> >                 System.out.println("[testing] ffmpeg about to launch.");
> >                 executor.setStreamHandler(new PumpStreamHandler(null,
> > null, input));
> >                 executor.execute(commandLine, new
> > DefaultExecuteResultHandler());
> >                 System.out.println("[testing] ffmpeg started.");
> >
> >             } catch (IOException e) {
> >                 e.printStackTrace();
> >             }
> >         }
> >     }}
> >
> > And the code for the second application (the zone where I send data to
> > the stdout) is the following one.
> >
> > static OutputStream stdout = System.out;
> >
> > (more code and other things around here)
> >
> > try {
> >         line = (TargetDataLine) mixer.getLine(info);
> >         line.open(format);
> >
> >         int bytesRead, CHUNK_SIZE = 4096;
> >         byte[] data = new byte[line.getBufferSize() / 5];
> >
> >         line.start();
> >
> >         while (true) {
> >             bytesRead = line.read(data, 0, CHUNK_SIZE);
> >             stdout.write(data, 0, bytesRead);
> >             stdout.flush();
> >         }
> >
> >     } catch (LineUnavailableException ex) {
> >         System.out.println("Line is unavailable.");
> >         ex.printStackTrace();
> >     }
> >
> > At the moment, no communication seems to be made between both commands as
> > ffmpeg isn't receiving anything.
> >
> > Hope you guys can tell what I'm missing out, or if I'm incorrectly
> working
> > with the library thinking it works in a way when it works in another one.
> >
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message