Reputation: 305
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
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
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