我正在通过执行ffmpeg
并将其输出捕获到标准输出来用 Java 编写视频应用程序。我决定使用 Apache Commons-Exec 而不是 Java Runtime
,因为它看起来更好。但是,我很难捕获所有输出。
我认为使用管道将是可行的方法,因为它是进程间通信的标准方式。但是,我使用PipedInputStream
and的设置PipedOutputStream
是错误的。它似乎有效,但仅适用于流的前 1042 个字节,奇怪的是恰好是PipedInputStream.PIPE_SIZE
.
我不喜欢使用管道,但我想避免使用磁盘 I/O(如果可能的话),因为速度和数据量(512x384 分辨率的 1m 20s 视频会产生 690M
个管道数据)。
关于处理来自管道的大量数据的最佳解决方案的想法?我的两个课程的代码如下。(是的,sleep
很糟糕。对此有什么想法? wait()
和notifyAll()
?)
WriteFrames.java
public class WriteFrames {
public static void main(String[] args) {
String commandName = "ffmpeg";
CommandLine commandLine = new CommandLine(commandName);
File filename = new File(args[0]);
String[] options = new String[] {
"-i",
filename.getAbsolutePath(),
"-an",
"-f",
"yuv4mpegpipe",
"-"};
for (String s : options) {
commandLine.addArgument(s);
}
PipedOutputStream output = new PipedOutputStream();
PumpStreamHandler streamHandler = new PumpStreamHandler(output, System.err);
DefaultExecutor executor = new DefaultExecutor();
try {
DataInputStream is = new DataInputStream(new PipedInputStream(output));
YUV4MPEGPipeParser p = new YUV4MPEGPipeParser(is);
p.start();
executor.setStreamHandler(streamHandler);
executor.execute(commandLine);
} catch (IOException e) {
e.printStackTrace();
}
}
}
YUV4MPEGPipeParser.java
public class YUV4MPEGPipeParser extends Thread {
private InputStream is;
int width, height;
public YUV4MPEGPipeParser(InputStream is) {
this.is = is;
}
public void run() {
try {
while (is.available() == 0) {
Thread.sleep(100);
}
while (is.available() != 0) {
// do stuff.... like write out YUV frames
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}