合并3个视频并匹配主视频帧率:脚本故障排查求助
视频拼接脚本问题排查与修复
有三个MP4视频:开场视频(sting.mp4)、主视频(mezzfile.mp4)、结尾视频(endboard.mp4),仅主视频帧率与另外两个不同,其余参数一致。尝试用ffprobe获取主视频帧率并统一输出帧率,但编写的bash脚本无法正常运行,原脚本如下:
#!/bin/bash mezzfile=mezzfile.mp4 tailtime=20 duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 $mezzfile) framerate=$(ffprobe -v 0 -of compact=p=0 -select_streams 0 \ -show_entries stream=r_frame_rate '$mezzfile') ffmpeg -hide_banner -y \ -i sting.mp4 \ -i $mezzfile \ -i endboard.mp4 \ -filter_complex \ "[0:v]setpts=PTS-STARTPTS,fps=${framerate}[v_intro]; \ [0:a]asetpts=PTS-STARTPTS,fps=${framerate}[a_intro]; \ [1:v]setpts=PTS-STARTPTS,split[v_main1][v_main2]; \ [1:a]asetpts=PTS-STARTPTS[a_main]; \ [2:v]setpts=PTS-STARTPTS,fps=${framerate}[v_endboard]; \ [v_main1]select='gt(t,$duration-$tailtime)',scale=w=iw/2:h=ih/2,setpts=PTS-STARTPTS[v_tail]; \ [v_endboard][v_tail]overlay[v_pip]; \ [v_main2]select='lte(t,$duration-$tailtime)',setpts=PTS-STARTPTS[v_mid]; \ [v_intro][v_mid][v_pip]concat=n=3:v=1:a=0[v_out]; \ [a_intro][a_main]concat=n=2:v=0:a=1[a_out]" \ -map "[v_out]" \ -map "[a_out]" \ output.mp4
问题分析
- ffprobe变量解析错误:获取帧率的命令中,
'$mezzfile'用单引号包裹,导致bash无法解析变量,会把$mezzfile当作字符串直接传入ffprobe,找不到目标文件。 - 音频滤镜误用参数:音频流不存在帧率(fps)属性,
[0:a]滤镜链中的fps是视频专属滤镜,应用在音频上会直接导致ffmpeg报错。 - 浮点数运算失败:
duration是ffprobe返回的浮点数(如125.8),bash默认仅支持整数算术运算,$duration-$tailtime会触发计算错误。 - concat参数不统一:concat滤镜要求所有输入视频流的分辨率、帧率、像素格式完全一致,原脚本未明确强制主视频流的帧率属性,存在兼容隐患。
修复后的脚本
#!/bin/bash mezzfile=mezzfile.mp4 tailtime=20 # 获取主视频帧率(修正变量引用,明确指定视频流) framerate=$(ffprobe -v error -of compact=p=0 -select_streams v:0 -show_entries stream=r_frame_rate "$mezzfile") # 获取主视频时长(保留浮点数格式) duration=$(ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "$mezzfile") # 用bc处理浮点数减法,计算截断时间点 cutoff_time=$(echo "$duration - $tailtime" | bc) ffmpeg -hide_banner -y \ -i sting.mp4 \ -i "$mezzfile" \ -i endboard.mp4 \ -filter_complex \ "[0:v]setpts=PTS-STARTPTS,fps=$framerate[v_intro]; \ [0:a]asetpts=PTS-STARTPTS[a_intro]; \ [1:v]setpts=PTS-STARTPTS,fps=$framerate,split[v_main1][v_main2]; \ [1:a]asetpts=PTS-STARTPTS[a_main]; \ [2:v]setpts=PTS-STARTPTS,fps=$framerate[v_endboard]; \ [v_main1]select='gt(t,$cutoff_time)',scale=w=iw/2:h=ih/2,setpts=PTS-STARTPTS[v_tail]; \ [v_endboard][v_tail]overlay[v_pip]; \ [v_main2]select='lte(t,$cutoff_time)',setpts=PTS-STARTPTS[v_mid]; \ [v_intro][v_mid][v_pip]concat=n=3:v=1:a=0[v_out]; \ [a_intro][a_main]concat=n=2:v=0:a=1[a_out]" \ -map "[v_out]" \ -map "[a_out]" \ -r "$framerate" \ output.mp4
修复说明
- 修正ffprobe的变量引用,将
'$mezzfile'改为"$mezzfile",同时用select_streams v:0明确指定读取视频流,避免误选音频流导致的帧率获取错误。 - 移除音频滤镜中的
fps参数,音频仅需调整时间基准(asetpts)即可同步。 - 使用
bc工具处理浮点数减法,解决bash无法计算小数的问题,得到准确的截断时间点。 - 为主视频流添加
fps=$framerate滤镜,确保concat的所有视频流帧率统一;输出时添加-r "$framerate"参数,强制指定输出文件的帧率。
内容的提问来源于stack exchange,提问作者3EK
相关产品推荐
相关产品推荐

