You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中FFmpeg为叠加图片添加淡入淡出动画报错求助

问题解决:FFmpeg命令报错及图片淡入淡出实现

错误原因

你的命令违反了FFmpeg核心语法规则:所有输入文件(-i)必须放在输出选项(如-filter_complex、-map)和输出文件之前。ChatGPT生成的代码把-filter_complex和-map放在了图片输入的循环里,导致FFmpeg将这些输出选项误判为输入文件的参数,触发报错。同时原滤镜逻辑重复处理同一图片的fade效果,不符合实际需求。

修正后的代码

以下是符合FFmpeg语法规则、实现图片淡入淡出叠加的完整代码:

ArrayList<String> cmd2 = new ArrayList<>();
cmd2.add("-y");

// 添加视频模板输入
cmd2.add("-i");
if (video_temp_path != null) {
    cmd2.add(video_temp_path);
} else {
    cmd2.add(Environment.getExternalStorageDirectory().getPath() + "/Download/happy.mp4");
}

// 批量添加图片输入,每个图片启用循环(避免仅显示一帧)
for (String path : paths) {
    cmd2.add("-loop");
    cmd2.add("1");
    cmd2.add("-i");
    cmd2.add(path);
}

// 构建滤镜链:为每张图片添加淡入淡出+时间控制的叠加逻辑
StringBuilder filterComplex = new StringBuilder();
String currentStream = "[0:v]"; // 初始流为视频模板

// 自定义每张图片的显示时间段:[开始时间, 结束时间],Integer.MAX_VALUE表示持续到视频结束
int[][] timeRanges = {{3, 8}, {10, 15}, {17, Integer.MAX_VALUE}};

for (int i = 0; i < paths.length; i++) {
    int imgIdx = i + 1;
    int startTime = timeRanges[i][0];
    int endTime = timeRanges[i][1];

    // 为图片添加淡入淡出滤镜:淡入1秒,淡出1秒(结束前1秒开始)
    String fadePart;
    if (endTime == Integer.MAX_VALUE) {
        fadePart = String.format("[%d:v]fade=in:st=%d:d=1[img%d];", imgIdx, startTime, imgIdx);
    } else {
        fadePart = String.format("[%d:v]fade=in:st=%d:d=1,fade=out:st=%d:d=1[img%d];", imgIdx, startTime, endTime - 1, imgIdx);
    }
    filterComplex.append(fadePart);

    // 将处理后的图片叠加到当前视频流,控制显示时间段
    String overlayPart;
    if (endTime == Integer.MAX_VALUE) {
        overlayPart = String.format("%s[img%d]overlay=x=100:y=200:enable='gt(t,%d)'[v%d];", currentStream, imgIdx, startTime, i + 1);
    } else {
        overlayPart = String.format("%s[img%d]overlay=x=100:y=200:enable='between(t,%d,%d)'[v%d];", currentStream, imgIdx, startTime, endTime, i + 1);
    }
    filterComplex.append(overlayPart);

    // 更新当前流为最新叠加后的视频流
    currentStream = String.format("[v%d]", i + 1);
}

// 移除末尾多余分号(FFmpeg兼容,但更规范)
if (filterComplex.length() > 0 && filterComplex.charAt(filterComplex.length() - 1) == ';') {
    filterComplex.setLength(filterComplex.length() - 1);
}

// 添加滤镜选项
cmd2.add("-filter_complex");
cmd2.add(filterComplex.toString());

// 指定输出流:视频用最后一次叠加后的流,音频保留原视频音频
cmd2.add("-map");
cmd2.add(currentStream);
cmd2.add("-map");
cmd2.add("0:a");

// 设置输出文件路径
cmd2.add(Environment.getExternalStorageDirectory().getPath() + "/Download/output.mp4");

关键修正点

  1. 语法合规:所有输入文件放在最前,输出选项(滤镜、映射)放在输入之后,输出文件路径最后,彻底解决原报错。
  2. 图片循环:每个图片输入前添加-loop 1,确保图片持续显示(FFmpeg默认仅读取图片一帧)。
  3. 动画同步:淡入动画与图片显示开始时间同步,淡出动画在显示结束前1秒启动,保证过渡自然。
  4. 动态适配:通过循环构建滤镜链,支持任意数量的图片,只需修改timeRanges数组即可自定义每张图片的显示时间段。

内容的提问来源于stack exchange,提问作者Pavan Ghanate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 14:55:04