对于没有音频的视频,一种简单的方法是添加音频(空音频源):
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=""
检查每个视频并做 2 件事:
-
检测不到音频
-
将 ffmpeg 参数串在一起
您可以将文件放入文件夹中,在文件名前添加数字以确定连接的顺序。不要在文件名中使用空格! "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
创建连接过滤器
# 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