NeverJr
NeverJr

Reputation: 305

How can I read process getInputstream?

I use process builder and process ( with the ffmpeg), and I have to redirect the ffmpeg output to the java input. I wrote this short code, but the inputstream is empty anyways...

public class Ffmpegtest {
public static void main(String[] args) {
    String[] cmd = {"ffmpeg ","-i ","output2.mp4 ","-f ","mp4 ", "-"};
    InputStream stream;
    try {
        stream = new ProcessBuilder(Arrays.asList(cmd)).start().getInputStream();
        System.out.println(stream.available()); // still 0
        byte[] kilo = new byte[1024];
        int i = stream.read(kilo,0,1024);
        while(i != -1){
            System.out.println("read "+1024);
            i = stream.read(kilo,0,1024);
        }

    } catch (IOException ex) {
        System.out.println(ex.getMessage());
    }
}

Upvotes: 0

Views: 1424

Answers (2)

Ronald S. Bultje
Ronald S. Bultje

Reputation: 11184

When I run:

ffmpeg -i file -f mp4 -

stdout is empty. However, stderr says:

ffmpeg version N-74516-g99b9f01 Copyright (c) 2000-2015 the FFmpeg developers
  built with Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
  configuration: --enable-gpl --samples=/Users/ronaldbultje/Movies/fate-suite-ff --enable-libvpx
  libavutil      54. 31.100 / 54. 31.100
  libavcodec     56. 58.100 / 56. 58.100
  libavformat    56. 40.101 / 56. 40.101
  libavdevice    56.  4.100 / 56.  4.100
  libavfilter     5. 34.100 /  5. 34.100
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  2.101 /  1.  2.101
  libpostproc    53.  3.100 / 53.  3.100
Input #0, ivf, from 'file.ivf':
  Duration: 00:00:00.01, start: 0.002000, bitrate: 178292 kb/s
    Stream #0:0: Video: vp9 (Profile 0) (VP90 / 0x30395056), yuv420p(pc, bt470bg/unknown/unknown), 640x480, 1k tbr, 1k tbn, 1k tbc
[mp4 @ 0x7f95aa800000] muxer does not support non seekable output
Output #0, mp4, to 'pipe:':
  Metadata:
    encoder         : Lavf56.40.101
    Stream #0:0: Video: mpeg4 ( [0][0][0] / 0x0020), yuv420p, 640x480, q=2-31, 200 kb/s, 1k fps, 1k tbn, 1k tbc
    Metadata:
      encoder         : Lavc56.58.100 mpeg4
Stream mapping:
  Stream #0:0 -> #0:0 (vp9 (native) -> mpeg4 (native))
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument

The key here is "muxer does not support non seekable output". Choose a different output format that supports streaming (e.g. mpegts), or choose a file output instead of stdout. As a more general java rule, always check stdout as well as stderr when using Process.

Upvotes: 4

Raffaele
Raffaele

Reputation: 20885

It's always tricky to interface with other processes standard streams from Java. If you want to consume the output of ffmpeg you need your main thread to wait for the other process to end, and should always listen for both stdout and stderr. In the following demo two temporary files are used (don't forget to cleanup and check return code):

public class App {
  public static void main(String... args) throws Exception {
    File stdout = File.createTempFile("ffmpeg-out", ".txt");
    File stderr = File.createTempFile("ffmpeg-err", ".txt");
    int result = ProcessBuilder.command(args)
                  .redirectOutput(stdout)
                  .redirectError(stderr)
                  .start()
                  .waitFor();
    // Now examine result and use stdout/stderror
  }
}

Upvotes: 1

Related Questions