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

  1. Read the 'FFmpeg 合成失败: {}' log line for the actual ffmpeg stderr.
  2. Verify ffmpegPath with `ffmpeg -version` and that both input files exist before calling (see autoAddVoiceover's existing Files.exists logging).
  3. If -c:v copy fails due to codec mismatch, re-encode instead: replace "copy" with "libx264" for -c:v.
  4. 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

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


AI-assisted analysis of jeecgboot/JeecgBoot@96fb33f5ec (2026-08-14). Data as JSON: /api/errors/0c9b0f7e8863a59c. Report an issue: GitHub.