我想使用ffmpeg将两个视频文件合并在一起。我已经找到以下命令:
ffmpeg -i INPUT1 -i INPUT2 -filter_complex \"[0:v][0:a][1:v][1:a]concat=n=2:v=1:a=1[v][a]\" -map \"[v]\" -map \"[a]\" OUTPUT
问题是,INPUT2始终不具有音频,因此ffmpeg抛出无效的输入流。 我对ffmpeg缺乏经验,并且对文档不了解。 是否有可能在一个命令中就可以很好地理解的可能方法?
总结:我想合并两个包含音频的视频文件,但是第二个文件可能有也可能没有音频层。
答案 0 :(得分:0)
对于没有音频的视频,一种简单的方法是添加音频(空音频源):
ffmpeg -f lavfi \
-i anullsrc=channel_layout=stereo:sample_rate=44100 \
-i "videoWithoutAudio.mp4" \
-shortest -c:v copy -c:a aac "videoWithAudio.mp4"
如果您想走得更远,这是我的shell脚本
设置目标尺寸
targetWidth=1920
targetHeight=1080
创建比例表达式,必要时根据来源放大
slhck为ffmpeg提出了一个很棒的比例表达式。无论您使用哪种尺寸或纵横比,该表达式都可以根据需要缩放和填充。
smartScale="scale=iw*min($targetWidth/iw\,$targetHeight/ih):ih*min($targetWidth/iw\,$targetHeight/ih), pad=$targetWidth:$targetHeight:($targetWidth-iw*min($targetWidth/iw\,$targetHeight/ih))/2:($targetHeight-ih*min($targetWidth/iw\,$targetHeight/ih))/2:color=black, setdar=ratio=16/9, setfield=tff"
进行计数并设置变量
c=0
ffmpegInput=""
filter_complex_params_1=""
filter_complex_params_2=""
遍历每个视频并做两件事:
不检测音频
识别没有音频的视频
向这些视频添加空音频
将ffmpeg参数串在一起
将每个视频添加为ffmpeg输入
为每个新输入扩展ffmpegs filter_complex
您可以将文件放入文件夹中,在文件名之前添加数字以确定连接顺序。不要在文件名中使用空格!“ 01_SummerVacation_2020.mkv
”
for i in *
do
# Use file command to recognize the type of data contained in a file
bashFileCommand=$(file "$i")
# parts of the file command output for many files that are not a video
regexPattern="image|Image|IMAGE|bitmap|text|Text|TEXT|ocument|DOCUMENT|Microsoft|rchive|empty|directory"
# detect if file is a video or not
# if the file contains no string of the above regexPattern it is likely a video
if [[ ! $bashFileCommand =~ $regexPattern ]]; then
# Concatenation works only if all videos contain audio
# detect videos without audio using ffprobe
# store command arguments for ffprobe query in array: codec_type for audio
command_audioCodec_type=(ffprobe -v quiet -select_streams a:0 -show_entries stream=codec_type -of default=nw=1:nk=1 "$i")
# execute command in array and store result variables
result_audioCodec_type=$("${command_audioCodec_type[@]}" | tail -1)
if [[ ! $result_audioCodec_type =~ "audio" ]]; then
# Add dummy audio to video
# Since we cannot overwrite the source file we have to create a temporary file
# ffmpeg chooses the right format according to the extension. Therefore we add "tmp" in front of the filename. Otherwise we would mess up the extension.
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -i "$i" \
-shortest -c:v copy -c:a aac "tmp_${i}"
# remove original
rm "${i}"
# renaming new file to appear as the original
mv "tmp_${i}" "${i}"
fi
# iterate over all videos (e.g. 3) and add the parameters to the previous parameters:
# Scale videos to set size
# 1st iteration: [0:v]${smartScale}[scaled_v0];
# 2nd iteration: [0:v]${smartScale}[scaled_v0];[1:v]${smartScale}[scaled_v1];
# 3rd iteration: [0:v]${smartScale}[scaled_v0];[1:v]${smartScale}[scaled_v1];[3:v]${smartScale}[scaled_v2];
filter_complex_params_1="$filter_complex_params_1[${c}:v]${smartScale}[scaled_v${c}]; "
# Scale videos to set size
# 1st iteration: [scaled_v0][0:a]
# 2nd iteration: [scaled_v0][0:a][scaled_v1][1:a]
# 3rd iteration: [scaled_v0][0:a][scaled_v1][1:a][scaled_v2][2:a]
filter_complex_params_2="$filter_complex_params_2[scaled_v${c}][${c}:a]"
# Add inputs
# 1st iteration: -i video1.mp4
# 2nd iteration: -i video1.mp4 -i video2.mp4
# 3rd iteration: -i video1.mp4 -i video2.mp4 -i video3.mp4
ffmpegInput="$ffmpegInput -i ${i}"
# increment counter for filter
c=$((c+1))
fi
done
创建concat过滤器
# 3rd (last) iteration: concat=n=3:v=1:a=1[v][a]
filter_complex_params_3="concat=n=${c}:v=1:a=1[v][a]"
将所有变量组合到最终的ffmpeg命令
# concatenate videos
ffmpeg ${ffmpegInput} -filter_complex "${filter_complex_params_1}${filter_complex_params_2}${filter_complex_params_3}" -map "[v]" -map "[a]" -c:v libx264 -crf 23 -c:a aac concatenated.mkv
答案 1 :(得分:0)
所有要连接的段必须具有相同数量和类型的流。因此,如果input1.mp4
有音频,而input2.mp4
没有音频,则您需要忽略input1.mp4
的音频或为input2.mp4
添加音频。一种方法是使用anullsrc过滤器添加无声音频,如下所示:
没有选项可以自动添加丢失的音频,因此您必须使用ffprobe
检查输入以告诉您输入是否有音频:
然后您可以使用首选的脚本/编码语言来使用结果来执行适当的命令。