如何 read/write ProcessBuilder 流并最终在 ffmpeg 中创建输出文件
How to read/write streams of ProcessBuilder and finally create a output file in ffmpeg
我正在尝试使用带有 java.ProcessBuilder 的 ffmpeg 对视频进行转码。我阅读了与此相关的其他主题,但它并没有真正解决我的问题。
我认为在进程 p=pb.start() 之前一切顺利。我知道我必须读取一些 ProcessBuilder 流并将其转换为 byte[] 并将其写入文件。我认为 ffmpeg 会为我做所有这些,因为我正在传递 "inputFile" 和 OutputFile 路径。无论如何,我 post 我到这里为止所拥有的。我该如何修复此代码,以便在结果后看到完全转码的视频文件?
目前所有代码执行无误,输出文件已创建,但其大小为 0KB。我是 运行 来自 windows 服务器的 Java (.jar) 程序中的代码。
这是程序的一个片段
try {
File encodingFile = new File("c:\ffmpeg\bin\output.mp4");
File errorFile = new File("c:\ffmpeg\bin\error.txt");
errorFile.createNewFile();
encodingFile.createNewFile();
ProcessBuilder pb = new ProcessBuilder("c:\ffmpeg\bin\ffmpeg.exe", "-i", "c:\ffmpeg\bin\input.mp4", "-y", "-s", "360" + "480" + "-1", "-vcodec", "libx264", "c:\ffmpeg\bin\output.mp4"); //or other command....
pb.redirectErrorStream(true);
pb.redirectError(errorFile);
//pb.redirectOutput(encodingFile);
Process p=pb.start();
byte[] videoIn;
File file = new File("c:\ffmpeg\bin\input.mp4");
videoIn = new byte[(int)file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(videoIn);
*/
gui.textArea1.append("\n+++++++Finished while converting!++++++++\n");
}catch(IOException ex){
gui.textArea1.append("\nIOException converting: "+ex.getMessage());
}finally{
try{
if(is!=null){
is.close();
}
if(fos!=null){
fos.close();
}
}catch(IOException ioe){
gui.textArea1.append("\nClosing streams while converting:"+ioe.getMessage());
}
}
gui.textArea1.append("converting finished!");
你的问题在这里:
pb.redirectErrorStream(true);
pb.redirectError(errorFile);
//pb.redirectOutput(encodingFile);
你在这里做的是将stderr重定向到stdout;并且都被重定向到 errorFile
.
而您的 encodingFile
是刚刚创建的:
encodingFile.createNewFile();
甚至不能保证成功。
修复:
final Path videoIn = Paths.get("c:\ffmpeg\bin\input.mp4");
final Path encodingFile = Paths.get("c:\ffmpeg\bin\output.mp4");
final Path errorFile = Paths.get("c:\ffmpeg\bin\error.txt");
int retCode;
try {
Files.deleteIfExists(encodingFile);
Files.deleteIfExists(errorFile);
final ProcessBuilder pb
= new ProcessBuilder("c:\ffmpeg\bin\ffmpeg.exe",
"-i", videoIn.toString(),
"-y",
"-s", "360x480", // stripped the extraneous "-1"
"-vcodec", "libx264",
"c:\ffmpeg\bin\output.mp4"
); //or other command....
pb.redirectError(errorFile.toFile());
pb.redirectOutput(encodingFile.toFile());
final Process p = pb.start();
// CHECK FOR THIS!
retcode = p.waitFor();
// Reproduced here; not sure this is anything useful,
// since the old code, just like this one, just reads the contents
// from the video file to be converted... Huh?
final byte[] videoIn = Files.readAllBytes(videoIn);
} catch (IOException e) {
// deal with e here
}
原代码注意事项:
- 为什么要阅读原始视频文件的内容?这没有意义;
- 您没有检查
.createNewFile()
的 return 值;它可能会失败;这里我使用 java.nio.file,这将在错误时抛出异常;
- 您没有检查进程的 return 代码;这里它在一个
retCode
变量中,你必须在之后检查它。有关可能的错误代码,请参阅 ffmpeg 手册页。
我正在尝试使用带有 java.ProcessBuilder 的 ffmpeg 对视频进行转码。我阅读了与此相关的其他主题,但它并没有真正解决我的问题。
我认为在进程 p=pb.start() 之前一切顺利。我知道我必须读取一些 ProcessBuilder 流并将其转换为 byte[] 并将其写入文件。我认为 ffmpeg 会为我做所有这些,因为我正在传递 "inputFile" 和 OutputFile 路径。无论如何,我 post 我到这里为止所拥有的。我该如何修复此代码,以便在结果后看到完全转码的视频文件?
目前所有代码执行无误,输出文件已创建,但其大小为 0KB。我是 运行 来自 windows 服务器的 Java (.jar) 程序中的代码。
这是程序的一个片段
try {
File encodingFile = new File("c:\ffmpeg\bin\output.mp4");
File errorFile = new File("c:\ffmpeg\bin\error.txt");
errorFile.createNewFile();
encodingFile.createNewFile();
ProcessBuilder pb = new ProcessBuilder("c:\ffmpeg\bin\ffmpeg.exe", "-i", "c:\ffmpeg\bin\input.mp4", "-y", "-s", "360" + "480" + "-1", "-vcodec", "libx264", "c:\ffmpeg\bin\output.mp4"); //or other command....
pb.redirectErrorStream(true);
pb.redirectError(errorFile);
//pb.redirectOutput(encodingFile);
Process p=pb.start();
byte[] videoIn;
File file = new File("c:\ffmpeg\bin\input.mp4");
videoIn = new byte[(int)file.length()];
FileInputStream fileInputStream = new FileInputStream(file);
fileInputStream.read(videoIn);
*/
gui.textArea1.append("\n+++++++Finished while converting!++++++++\n");
}catch(IOException ex){
gui.textArea1.append("\nIOException converting: "+ex.getMessage());
}finally{
try{
if(is!=null){
is.close();
}
if(fos!=null){
fos.close();
}
}catch(IOException ioe){
gui.textArea1.append("\nClosing streams while converting:"+ioe.getMessage());
}
}
gui.textArea1.append("converting finished!");
你的问题在这里:
pb.redirectErrorStream(true);
pb.redirectError(errorFile);
//pb.redirectOutput(encodingFile);
你在这里做的是将stderr重定向到stdout;并且都被重定向到 errorFile
.
而您的 encodingFile
是刚刚创建的:
encodingFile.createNewFile();
甚至不能保证成功。
修复:
final Path videoIn = Paths.get("c:\ffmpeg\bin\input.mp4");
final Path encodingFile = Paths.get("c:\ffmpeg\bin\output.mp4");
final Path errorFile = Paths.get("c:\ffmpeg\bin\error.txt");
int retCode;
try {
Files.deleteIfExists(encodingFile);
Files.deleteIfExists(errorFile);
final ProcessBuilder pb
= new ProcessBuilder("c:\ffmpeg\bin\ffmpeg.exe",
"-i", videoIn.toString(),
"-y",
"-s", "360x480", // stripped the extraneous "-1"
"-vcodec", "libx264",
"c:\ffmpeg\bin\output.mp4"
); //or other command....
pb.redirectError(errorFile.toFile());
pb.redirectOutput(encodingFile.toFile());
final Process p = pb.start();
// CHECK FOR THIS!
retcode = p.waitFor();
// Reproduced here; not sure this is anything useful,
// since the old code, just like this one, just reads the contents
// from the video file to be converted... Huh?
final byte[] videoIn = Files.readAllBytes(videoIn);
} catch (IOException e) {
// deal with e here
}
原代码注意事项:
- 为什么要阅读原始视频文件的内容?这没有意义;
- 您没有检查
.createNewFile()
的 return 值;它可能会失败;这里我使用 java.nio.file,这将在错误时抛出异常; - 您没有检查进程的 return 代码;这里它在一个
retCode
变量中,你必须在之后检查它。有关可能的错误代码,请参阅 ffmpeg 手册页。