使用java调用ffmpeg进行视频转码,适合windows和linux环境
测试结论
可以使用多线程调用ffmpeg命令执行转码,但不推荐。因为使用多线程并不能提高视频转码效率,相反,它会导致单个的视频转码效率成比例的降低,虽然总体耗时差不多。 综述,推荐使用有且只有一个线程用于调用ffmpeg命令执行视频转码。详情见 https://gitee.com/springboot_learning/springboot-ffmpeg/blob/master/HELP.md 的"性能消耗情况如何?"一节
关键代码块
@Async("ffmpegExecutor")
@Override
public void execVideoTranscode(File ffmpegCmd, boolean isWindows, String sourceFile, String targetFile) {
Runtime runtime = null;
try {
log.info("<<开始视频转码>> 文件名:{}", sourceFile);
runtime = Runtime.getRuntime();
long startTime = System.currentTimeMillis();
String cmd = ffmpegCmd.getAbsolutePath() + " -y -i " + sourceFile + " -vcodec libx264 -vf scale=\"iw/1:ih/1\" " + targetFile;
log.info("<<命令>> {}", cmd);
Process process = null;
if(isWindows){
process = runtime.exec(cmd);
}else{
process = runtime.exec(new String[]{"sh", "-c", cmd});
}
// 通过读取进程的流信息,可以看到视频转码的相关执行信息,并且使得下面的视频转码时间贴近实际的情况
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while((line = br.readLine()) != null){
log.debug("<<视频执行信息>> {}", line);
}
br.close();
log.info("<<开始关闭进程相关流>>");
process.getOutputStream().close();
process.getInputStream().close();
process.getErrorStream().close();
long endTime = System.currentTimeMillis();
log.info("<<视频转码完成>> 耗时 {}ms", (endTime - startTime));
} catch (IOException e) {
log.error("<<视频转码失败,原因:发生IO异常>>");
} finally {
if(Objects.nonNull(runtime)){
runtime.freeMemory();
}
}
}
完整代码
https://gitee.com/springboot_learning/springboot-ffmpeg.git
tip: 请先阅读项目中根目录下的HELP.md文件