jeecgboot/JeecgBoot · error · RuntimeException
FFmpeg 合成失败,退出码: {exitCode}
Error message
FFmpeg 合成失败,退出码: {exitCode} What it means
Thrown by VideoGenerationServiceImpl.mergeVideoAudio() when the ffmpeg subprocess (which muxes a silent video and an audio track with -c:v copy -c:a aac -shortest) exits non-zero. The captured combined stdout/stderr is logged separately but omitted from the thrown message.
Source
Thrown at jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/video/service/impl/VideoGenerationServiceImpl.java:634
*/
private void mergeVideoAudio(Path videoPath, Path audioPath, Path outputPath) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(
ffmpegPath,
"-i", videoPath.toAbsolutePath().toString(),
"-i", audioPath.toAbsolutePath().toString(),
"-c:v", "copy",
"-c:a", "aac",
"-shortest",
"-y",
outputPath.toAbsolutePath().toString()
);
pb.redirectErrorStream(true);
Process process = pb.start();
String output = new String(process.getInputStream().readAllBytes());
int exitCode = process.waitFor();
if (exitCode != 0) {
log.error("FFmpeg 合成失败: {}", output);
throw new RuntimeException("FFmpeg 合成失败,退出码: " + exitCode);
}
}
/**
* 将 size(如 "1920x1080")转为 vidu2 的 aspect_ratio 格式(如 "16:9")
* 支持的比例:16:9、9:16、1:1,无法识别时默认 16:9
*/
private String convertSizeToAspectRatio(String size) {
if (size == null || size.isBlank()) {
return "16:9";
}
// 已经是比例格式则直接返回
if (size.matches("\\d+:\\d+")) {
return size;
}
// 解析 WxH 格式
String[] parts = size.toLowerCase().split("x");
if (parts.length == 2) {View on GitHub (pinned to 96fb33f5ec)
Solutions
- Read the 'FFmpeg 合成失败: {}' log line for the actual ffmpeg stderr.
- Verify ffmpegPath with `ffmpeg -version` and that both input files exist before calling (see autoAddVoiceover's existing Files.exists logging).
- If -c:v copy fails due to codec mismatch, re-encode instead: replace "copy" with "libx264" for -c:v.
- Confirm the output directory is writable and has disk space.
Example fix
// before "-c:v", "copy", // after - fall back to re-encode when stream copy is incompatible "-c:v", "libx264", "-preset", "fast",
Defensive patterns
Strategy: validation
Validate before calling
private void ensureFfmpegInputs(Path video, Path audio, Path out) throws IOException {
if (ffmpegPath == null) { throw new IllegalStateException("ffmpeg 未配置"); }
if (!Files.exists(video)) { throw new FileNotFoundException(video.toString()); }
if (!Files.exists(audio)) { throw new FileNotFoundException(audio.toString()); }
Files.createDirectories(out.getParent());
} Try / catch
// mergeVideoAudio is only called from autoAddVoiceover, which already wraps in try/catch // and degrades to a silent video -- retain that fallback rather than rethrowing.
Prevention
- Pre-validate ffmpegPath with `ffmpeg -version` during app startup.
- Log Files.exists() for both inputs right before invoking ffmpeg (already done in autoAddVoiceover).
- Prefer re-encoding (-c:v libx264) when stream-copy compatibility is uncertain.
When it happens
Trigger: mergeVideoAudio() runs ffmpegPath against silentVideoFile + audioPath. Non-zero exit when: ffmpegPath invalid/missing; either input file absent; video stream copy fails because the source container/codec is incompatible; the audio sample format is unsupported by aac; output directory not writable.
Common situations: ffmpeg not installed or ffmpegPath misconfigured; upstream silent video never written (so -i points at nothing); wav audio that ffmpeg cannot decode; permission denied on the upload/video output dir.
Related errors
- edge-tts 执行失败,退出码: {exitCode}
- Specified file not found
- The file name can not null
- 存储路径校验失败: {storePath}
- 语音生成异常: {message}
AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14).
Data as JSON: /api/errors/0c9b0f7e8863a59c.
Report an issue: GitHub.