ffmpeg concat两个带有可选音频的来源

时间:2020-02-09 00:25:05

标签: ffmpeg

我想使用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始终不具有音频,因此ffm​​peg抛出无效的输入流。 我对ffmpeg缺乏经验,并且对文档不了解。 是否有可能在一个命令中就可以很好地理解的可能方法?

总结:我想合并两个包含音频的视频文件,但是第二个文件可能有也可能没有音频层。

2 个答案:

答案 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=""

遍历每个视频并做两件事:

  1. 不检测音频

    • 识别没有音频的视频

    • 向这些视频添加空音频

  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检查输入以告诉您输入是否有音频:

然后您可以使用首选的脚本/编码语言来使用结果来执行适当的命令。