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

FFmpeg视频剪辑合并:音频交叉淡入淡出功能实现求助

问题:实现part2.mp4与pip.mp4之间的音频交叉淡入淡出效果

本文已更新

提前感谢各位提供的帮助!

我正在处理4个规格一致的立体声音频视频素材:

  • intro
  • mainvideo
  • midroll_video(广告)
  • endboard

我需要在代码生成的part2.mp4和pip.mp4之间添加仅音频的交叉淡入淡出效果。已按照@Баяр Гончикжапов的指导修改代码,但仍无法正常工作,以下是我使用的代码,恳请协助排查问题。

感谢各位的帮助!

# Input parameters
mainvideo=mezzfile.mp4
endboard=endboard.mp4
intro=sting.mp4
midroll_video=midroll.mp4

tailtime=20
fadelength=0.2
midroll_edit_value=00:11:31.600

# Time calculations to define cut point
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $mainvideo)
endboard_cut_point=$(echo "scale=2;$duration-$tailtime" | bc)

duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $mainvideo)
midroll_cut_point=$(echo "scale=2;$duration-$midroll_edit_value" | bc)

# Safety check
tbn_main=$(ffprobe -v error -select_streams v -show_entries stream=time_base -of default=noprint_wrappers=1:nokey=1 $mainvideo)
tbn_main=${tbn_main#*/}
tbn_intro=$(ffprobe -v error -select_streams v -show_entries stream=time_base -of default=noprint_wrappers=1:nokey=1 $intro)
tbn_intro=${tbn_intro#*/}
tbn_end=$(ffprobe -v error -select_streams v -show_entries stream=time_base -of default=noprint_wrappers=1:nokey=1 $endboard)
tbn_end=${tbn_end#*/}

if [[ $(( ($tbn_intro+$tbn_main+$tbn_end)/3 )) -ne $tbn_main ]]; then
  echo "WARNING: source video files have the different timebase."
  echo "The use of the concat demuxer will produce incorrect output."
  echo "Re-encoding is highly recommended."
  read -s -k $'?Press any key to exit.\n'
  exit 1
fi

# Trim the main part of mainvideo
ffmpeg -hide_banner -y -i $mainvideo -to $midroll_edit_value -c copy part1.mp4

ffmpeg -hide_banner -y -i $mainvideo -ss $midroll_edit_value -to $endboard_cut_point -c copy part2.mp4

ffmpeg -hide_banner -y -i $mainvideo -ss $midroll_edit_value -to $duration -c copy part2av.mp4


# Trim the tail of mainvideo and overlay it onto endboard
ffmpeg -hide_banner -y \
  -i $mainvideo \
  -i $endboard \
  -filter_complex \
    "[0:v]select='gt(t,$duration-$tailtime)',scale=w=iw/2.03:h=ih/2.03,setpts=PTS-STARTPTS[v_tail]; \
     [0:a]aselect='gt(t,$duration-$tailtime)',asetpts=PTS-STARTPTS[a_out]; \
     [1:v][v_tail]overlay=format=auto[v_out]" \
  -map "[v_out]" \
  -map "[a_out]" \
  -video_track_timescale $tbn_main \
  pip.mp4

ffmpeg -hide_banner -y -i "part2.mp4" -i "part2av.mp4" -i "pip.mp4" \
  -filter_complex \
     -map "[0:v];" 
     -map "[1:a];" 
     -map "[2:v]" 
     -c copy "part2pip.mp4" \

# Pass all parts through the concat demuxer
[ -f filelist.txt ] && rm filelist.txt
for f in $intro part1.mp4 $midroll_video part2pip.mp4; do echo "file '$PWD/$f'" >> filelist.txt; done
ffmpeg -hide_banner -y -f concat -safe 0 -i filelist.txt -c copy TEST_FILE.mp4

# Sweep the table
rm pip.mp4 part1.mp4 part2.mp4 filelist.txt

问题排查与修正方案

1. 核心语法错误

你生成part2pip.mp4的ffmpeg命令存在致命语法问题:

  • -filter_complex参数后直接跟-map属于非法写法,-map是全局选项,不能嵌套在滤镜链中
  • 完全没有实现音频淡入淡出的滤镜逻辑

2. 音频交叉淡入淡出的实现逻辑

要实现part2.mp4音频淡出、pip.mp4音频淡入的交叉效果,需要:

  1. 对part2.mp4的音频应用afade=t=out:d=$fadelength实现淡出
  2. 对pip.mp4的音频应用afade=t=in:d=$fadelength实现淡入
  3. 用amix滤镜混合两个处理后的音频,同时用concat拼接两段视频

3. 修正后的关键代码片段

替换原脚本中生成part2pip.mp4的命令:

# 实现音频交叉淡入淡出并合并视频
ffmpeg -hide_banner -y \
  -i "part2.mp4" \
  -i "pip.mp4" \
  -filter_complex \
    "[0:a]afade=t=out:d=$fadelength[a_out]; \
     [1:a]afade=t=in:d=$fadelength[a_in]; \
     [a_out][a_in]amix=inputs=2:duration=first[a_mix]; \
     [0:v][1:v]concat=n=2:v=1:a=0[v_concat]" \
  -map "[v_concat]" \
  -map "[a_mix]" \
  -c:v libx264 -c:a aac "part2pip.mp4"

4. 其他冗余优化

  • 删除未使用的midroll_cut_point变量计算逻辑
  • 移除冗余的part2av.mp4生成步骤,直接使用pip.mp4的原音频即可

完整修正后的脚本

# Input parameters
mainvideo=mezzfile.mp4
endboard=endboard.mp4
intro=sting.mp4
midroll_video=midroll.mp4

tailtime=20
fadelength=0.2
midroll_edit_value=00:11:31.600

# Time calculations to define cut point
duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $mainvideo)
endboard_cut_point=$(echo "scale=2;$duration-$tailtime" | bc)

# Safety check
tbn_main=$(ffprobe -v error -select_streams v -show_entries stream=time_base -of default=noprint_wrappers=1:nokey=1 $mainvideo)
tbn_main=${tbn_main#*/}
tbn_intro=$(ffprobe -v error -select_streams v -show_entries stream=time_base -of default=noprint_wrappers=1:nokey=1 $intro)
tbn_intro=${tbn_intro#*/}
tbn_end=$(ffprobe -v error -select_streams v -show_entries stream=time_base -of default=noprint_wrappers=1:nokey=1 $endboard)
tbn_end=${tbn_end#*/}

if [[ $(( ($tbn_intro+$tbn_main+$tbn_end)/3 )) -ne $tbn_main ]]; then
  echo "WARNING: source video files have the different timebase."
  echo "The use of the concat demuxer will produce incorrect output."
  echo "Re-encoding is highly recommended."
  read -s -k $'?Press any key to exit.\n'
  exit 1
fi

# Trim the main part of mainvideo
ffmpeg -hide_banner -y -i $mainvideo -to $midroll_edit_value -c copy part1.mp4

ffmpeg -hide_banner -y -i $mainvideo -ss $midroll_edit_value -to $endboard_cut_point -c copy part2.mp4

# Trim the tail of mainvideo and overlay it onto endboard
ffmpeg -hide_banner -y \
  -i $mainvideo \
  -i $endboard \
  -filter_complex \
    "[0:v]select='gt(t,$duration-$tailtime)',scale=w=iw/2.03:h=ih/2.03,setpts=PTS-STARTPTS[v_tail]; \
     [0:a]aselect='gt(t,$duration-$tailtime)',asetpts=PTS-STARTPTS[a_out]; \
     [1:v][v_tail]overlay=format=auto[v_out]" \
  -map "[v_out]" \
  -map "[a_out]" \
  -video_track_timescale $tbn_main \
  pip.mp4

# 实现音频交叉淡入淡出并合并视频
ffmpeg -hide_banner -y \
  -i "part2.mp4" \
  -i "pip.mp4" \
  -filter_complex \
    "[0:a]afade=t=out:d=$fadelength[a_out]; \
     [1:a]afade=t=in:d=$fadelength[a_in]; \
     [a_out][a_in]amix=inputs=2:duration=first[a_mix]; \
     [0:v][1:v]concat=n=2:v=1:a=0[v_concat]" \
  -map "[v_concat]" \
  -map "[a_mix]" \
  -c:v libx264 -c:a aac "part2pip.mp4"

# Pass all parts through the concat demuxer
[ -f filelist.txt ] && rm filelist.txt
for f in $intro part1.mp4 $midroll_video part2pip.mp4; do echo "file '$PWD/$f'" >> filelist.txt; done
ffmpeg -hide_banner -y -f concat -safe 0 -i filelist.txt -c copy TEST_FILE.mp4

# Sweep the table
rm pip.mp4 part1.mp4 part2.mp4 filelist.txt

内容的提问来源于stack exchange,提问作者3EK

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 17:10:40