51

我有两个完全相同长度的视频,我想使用 ffmpeg 将它们堆叠成一个视频文件。

我怎样才能做到这一点?

4

3 回答 3

209

使用vstack(垂直)、hstack(水平)或xstack(自定义布局)过滤器。它比其他方法更容易和更快。

合并/堆叠两个视频或图像

垂直的

使用vstack过滤器。

在此处输入图像描述

ffmpeg -i input0 -i input1 -filter_complex vstack=inputs=2 output

视频必须具有相同的宽度。

水平的

使用hstack过滤器。

在此处输入图像描述

ffmpeg -i input0 -i input1 -filter_complex hstack=inputs=2 output

视频必须具有相同的高度。

带边框

使用过滤器。此示例在两侧之间创建一个 5px 的黑色边框。

在此处输入图像描述

ffmpeg -i input0 -i input1 -filter_complex "[0]pad=iw+5:color=black[left];[left][1]hstack=inputs=2" output

带音频

缩混并使用原始频道位置

在此处输入图像描述

添加amerge 过滤器以组合来自两个输入的音频通道:

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v];[0:a][1:a]amerge=inputs=2[a]" -map "[v]" -map "[a]" -ac 2 output
  • 这假设每个输入都包含一个立体声音频流。

  • -ac 2如果两个输入都包含多声道音频,则包含缩混为立体声。例如,如果两个输入都是立体声,如果省略-ac 2.

将来自每个输入的所有音频放入单独的通道中

在此处输入图像描述

使用amerge(或amix)和pan过滤器:

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v];[0:a][1:a]amerge=inputs=2,pan=stereo|c0<c0+c1|c1<c2+c3[a]" -map "[v]" -map "[a]"  output
  • 这假设每个输入都包含一个立体声音频流。

使用来自一个特定输入的音频

此示例将使用来自的音频input1

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v]" -map "[v]" -map 1:a output

添加静音音频/如果一个输入没有音频

如果您混合有音频的输入和没有音频的输入,则 amerge 将失败,因为每个输入都需要音频。您可以使用anullsrc 过滤器添加静音音频来防止这种情况:

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v];anullsrc[silent];[0:a][silent]amerge=inputs=2[a]" -map "[v]" -map "[a]" -ac 2 output.mp4

3 个视频或图像

在此处输入图像描述

ffmpeg -i input0 -i input1 -i input2 -filter_complex "[0:v][1:v][2:v]hstack=inputs=3[v]" -map "[v]" output

如果你想垂直使用 vstack 而不是 hstack。


2x2 网格

在此处输入图像描述

使用xstack

ffmpeg -i input0 -i input1 -i input2 -i input3 -filter_complex "[0:v][1:v][2:v][3:v]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v]" -map "[v]" output

使用hstackvstack

ffmpeg -i input0 -i input1 -i input2 -i input3 -filter_complex "[0:v][1:v]hstack=inputs=2[top];[2:v][3:v]hstack=inputs=2[bottom];[top][bottom]vstack=inputs=2[v]" -map "[v]" output

这种语法更容易理解,但比使用上面显示的 xstack 效率低。


带文本的 2x2 网格

在此处输入图像描述

使用drawtext过滤器:

ffmpeg -i input0 -i input1 -i input2 -i input3 -filter_complex
"[0]drawtext=text='vid0':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v0];
 [1]drawtext=text='vid1':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v1];
 [2]drawtext=text='vid2':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v2];
 [3]drawtext=text='vid3':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v3];
 [v0][v1][v2][v3]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v]"
-map "[v]" output

4x4

使用xstack 过滤器。总共 16 个视频的示例:

ffmpeg -i input0 -i input1 -i input2 -i input3 -i input4 -i input5 -i input6 -i input7 -i input8 -i input9 -i input10 -i input11 -i input12 -i input13 -i input14 -i input15 -i input16 -filter_complex "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v][9:v][10:v][11:v][12:v][13:v][14:v][15:v]xstack=inputs=16:layout=0_0|w0_0|w0+w1_0|w0+w1+w2_0|0_h0|w4_h0|w4+w5_h0|w4+w5+w6_h0|0_h0+h4|w8_h0+h4|w8+w9_h0+h4|w8+w9+w10_h0+h4|0_h0+h4+h8|w12_h0+h4+h8|w12+w13_h0+h4+h8|w12+w13+w14_h0+h4+h8" output.mp4

如果您需要先缩放输入:

ffmpeg -i input0 -i input1 -i input2 -i input3 -i input4 -i input5 -i input6 -i input7 -i input8 -i input9 -i input10 -i input11 -i input12 -i input13 -i input14 -i input15 -i input16 -filter_complex "[0:v]scale=iw/4:-1[v0];[1:v]scale=iw/4:-1[v1];[2:v]scale=iw/4:-1[v2];[3:v]scale=iw/4:-1[v3];[4:v]scale=iw/4:-1[v4];[5:v]scale=iw/4:-1[v5];[6:v]scale=iw/4:-1[v6];[7:v]scale=iw/4:-1[v7];[8:v]scale=iw/4:-1[v8];[9:v]scale=iw/4:-1[v9];[10:v]scale=iw/4:-1[v10];[11:v]scale=iw/4:-1[v11];[12:v]scale=iw/4:-1[v12];[13:v]scale=iw/4:-1[v13];[14:v]scale=iw/4:-1[v14];[15:v]scale=iw/4:-1[v15];[v0][v1][v2][v3][v4][v5][v6][v7][v8][v9][v10][v11][v12][v13][v14][v15]xstack=inputs=16:layout=0_0|w0_0|w0+w1_0|w0+w1+w2_0|0_h0|w4_h0|w4+w5_h0|w4+w5+w6_h0|0_h0+h4|w8_h0+h4|w8+w9_h0+h4|w8+w9+w10_h0+h4|0_h0+h4+h8|w12_h0+h4+h8|w12+w13_h0+h4+h8|w12+w13+w14_h0+h4+h8" output.mp4

调整/缩放输入

由于两个视频都需要与 vstack 相同,并且 hstack 的高度相同,因此您可能需要缩放其他视频之一以匹配另一个:

简单的缩放过滤器示例,将 input0 的宽度设置为 640,并在保留纵横比的同时自动设置高度:

ffmpeg -i input0 -i input2 -filter_complex "[0:v]scale=640:-1[v0];[v0][1:v]vstack=inputs=2" output

延迟/暂停视频

此示例将播放左上角的视频,同时暂停其他视频。一旦左上角的视频结束,右上角的视频就会播放,依此类推。

使用tpadadelayxstackamix过滤器:

ffmpeg -i top-left.mp4 -i top-right.mp4 -i bottom-left.mp4 -i bottom-right.mp4 -filter_complex "[1]tpad=start_mode=clone:start_duration=5[tr];[2]tpad=start_mode=clone:start_duration=10[bl];[3]tpad=start_mode=clone:start_duration=15[br];[0][tr][bl][br]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v];[1:a]adelay=5s:all=true[a1];[2:a]adelay=10s:all=true[a2];[3:a]adelay=15s:all=true[a3];[0:a][a1][a2][a3]amix=inputs=4[a]" -map "[v]" -map "[a]" output.mp4
  • 此示例假定每个输入的持续时间为 5 秒。根据需要调整start_durationadelay值。

  • 此命令需要 FFmpeg 4.3 或更高版本。

  • 如果您不喜欢 xstack 的复杂性,您可以使用多个 hstack/vstack 来代替,如示例 4:2x2 grid所示。

于 2015-11-17T18:59:51.413 回答
29

请参阅此问题的答案以获得更新、更简单的方法。


旧版本:
您应该可以使用FFmpeg 中的padmovieoverlay过滤器来做到这一点。该命令将如下所示:

ffmpeg -i top.mov -vf 'pad=iw:2*ih [top]; movie=bottom.mov [bottom]; \
  [top][bottom] overlay=0:main_h/2' stacked.mov

首先,应该在顶部的电影被填充到其高度的两倍。然后加载底部电影。然后底部电影以填充电影高度的一半的偏移量覆盖在填充顶部电影上。

于 2012-07-19T02:32:44.507 回答
0

对于 2 个视频:

ffmpeg -i 1.mp4 -i 2.mp4 -filter_complex hstack out.mp4

更多视频(本例中为 3 个):

ffmpeg -i 1.mp4 -i 2.mp4 -i 3.mp4 -filter_complex hstack=3 out.mp4
于 2020-04-15T10:36:09.240 回答