視頻上傳場景常需「轉統一格式(FLV/MP4)+ 生成封面縮略圖」。本文提供基於 ProcessBuilder 調用 FFmpeg 與 Mencoder 的完整實現,涵蓋參數調優、同步執行控制與常見坑點規避。
public class VideoProcessor {
public boolean transcodeAndCapture(String srcPath, String flvPath, String thumbPath) {
List mencoderCmd = Arrays.asList(
"D:/tools/mencoder/mencoder.exe", srcPath,
"-o", flvPath,
"-of", "lavf",
"-oac", "mp3lame", "-lameopts", "abr:br=32:vol=1",
"-srate", "22050",
"-ovc", "lavc", "-lavcopts", "vcodec=flv:vbitrate=480:mbd=2:v4mv:turbo",
"-vf", "scale=400:226"
);
List ffmpegCmd = Arrays.asList(
"D:/tools/ffmpeg/ffmpeg.exe", "-i", srcPath,
"-y", "-f", "image2", "-ss", "8", "-t", "0.001",
"-s", "100x100", thumbPath
);
try {
execSync(mencoderCmd);
execSync(ffmpegCmd);
return true;
} catch (IOException | InterruptedException e) {
log.error("Video processing failed", e);
return false;
}
}
private void execSync(List cmd) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process p = pb.start();
// 消費輸出流防止阻塞
try (BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) log.debug(line);
}
int exit = p.waitFor();
if (exit != 0) throw new IOException("Command exited with " + exit);
}
}
| 參數 | 說明 | 調優方向 |
|---|---|---|
-vbitrate=480 | 視頻碼率 kbps | 根據清晰度需求調整,720p 建議 1500-2500 |
-ss 8 | 截圖時間點(秒) | 避開片頭黑屏/字幕,可改為總時長 10% 處 |
-s 100x100 | 縮略圖尺寸 | 保持原視頻長寬比,防止變形;建議加 -aspect 強制比例 |
-t 0.001 | 截取時長 | 極短時間僅抓單幀,確保輸出單張圖片 |
vbitrate 或改用 H.264 (libx264) 提高壓縮效率-ss 定位非關鍵幀導致黑屏,加 -keyint_min 或改用 -vf select='eq(pict_type,I)'ProcessBuilder 自動處理參數列表無需轉義,但確保系統默認編碼為 UTF-8,或額外設置 pb.environment().put("LANG", "zh_CN.UTF-8")ffprobe 先探測視頻時長/編碼,動態計算截圖時間點p.waitFor(30, TimeUnit.MINUTES) 防止掛起完整可運行 Demo 見文末附件,已在 Windows/Linux 雙平台驗證通過。