使用java調(diào)用ffmpeg進(jìn)行視頻轉(zhuǎn)碼,適合windows和linux環(huán)境
測(cè)試結(jié)論
可以使用多線程調(diào)用ffmpeg命令執(zhí)行轉(zhuǎn)碼退子,但不推薦。因?yàn)槭褂枚嗑€程并不能提高視頻轉(zhuǎn)碼效率,相反鲸拥,它會(huì)導(dǎo)致單個(gè)的視頻轉(zhuǎn)碼效率成比例的降低,雖然總體耗時(shí)差不多僧免。 綜述刑赶,推薦使用有且只有一個(gè)線程用于調(diào)用ffmpeg命令執(zhí)行視頻轉(zhuǎn)碼。詳情見 https://gitee.com/springboot_learning/springboot-ffmpeg/blob/master/HELP.md 的"性能消耗情況如何懂衩?"一節(jié)
關(guān)鍵代碼塊
@Async("ffmpegExecutor")
@Override
public void execVideoTranscode(File ffmpegCmd, boolean isWindows, String sourceFile, String targetFile) {
Runtime runtime = null;
try {
log.info("<<開始視頻轉(zhuǎn)碼>> 文件名:{}", 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});
}
// 通過讀取進(jìn)程的流信息撞叨,可以看到視頻轉(zhuǎn)碼的相關(guān)執(zhí)行信息,并且使得下面的視頻轉(zhuǎn)碼時(shí)間貼近實(shí)際的情況
BufferedReader br = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String line = null;
while((line = br.readLine()) != null){
log.debug("<<視頻執(zhí)行信息>> {}", line);
}
br.close();
log.info("<<開始關(guān)閉進(jìn)程相關(guān)流>>");
process.getOutputStream().close();
process.getInputStream().close();
process.getErrorStream().close();
long endTime = System.currentTimeMillis();
log.info("<<視頻轉(zhuǎn)碼完成>> 耗時(shí) {}ms", (endTime - startTime));
} catch (IOException e) {
log.error("<<視頻轉(zhuǎn)碼失敗浊洞,原因:發(fā)生IO異常>>");
} finally {
if(Objects.nonNull(runtime)){
runtime.freeMemory();
}
}
}
完整代碼
https://gitee.com/springboot_learning/springboot-ffmpeg.git
tip: 請(qǐng)先閱讀項(xiàng)目中根目錄下的HELP.md文件