1. Overview

In this tutorial, we’ll learn how to join two videos side-by-side into a unified video. For that purpose, we’ll make use of FFmpeg‘s hstack and overlay complex filters. Then, we’ll dive into merging the audio streams of the videos.

Finally, we’ll add enhancements such as padding and borders to the video streams.

2. Stitching Videos

In FFmpeg, we can use a combination of filters to appropriately place videos side by side. For that purpose, we can use filter_complex. Specifically, filter_complex lets us combine multiple complex filters for audio and video streams simultaneously.

There are two such complex filters that we use to stitch videos together: hstack and overlay. We can use either filter and the end result should be the same.

In the next sections, we’ll use both filters to demonstrate how to join videos together. For our example, we’ve chosen two small videos that are 10 seconds long with the same resolution.

2.1. hstack

hstack stands for “horizontal stack”. Specifically, it lets us stitch two or more videos together in a horizontal manner. Therefore, the output video will have multiple videos placed side by side.

As an example, let’s use the hstack filter to stitch two videos:

$ ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex "[0:v][1:v]hstack[out]" -map "[out]" output.mp4

Let’s break this down:

  • v1.mp4 and v2.mp4 are two input video files
  • filter_complex specifies the filters to use:
    • [0:v] and [1:v] refer to the first and second “video” streams from the first and second inputs
    • hstack specifies the hstack filter that would combine these video streams horizontally
    • [out] is the label we assign to the output video stream
  • -map “[0]” selects the output stream to encode
  • output.mp4 is the resulting video file

Here is the output video:

In addition, the resulting video is re-encoded because we can’t copy the contents from the streams when we’re using a complex filtergraph.

Alternatively, if we have two videos, we can make the command simpler:

$ ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex hstack output.mp4

Furthermore, for more than two videos, we can use hstack=inputs=N, where N is the number of inputs:

$ ffmpeg -i v1.mp4 -i v2.mp4 -i v3.mp4 -filter_complex hstack=inputs=3 output.mp4

2.2. overlay

The overlay filter overlays one video on top of another as well as manipulates attributes like transparency, size, and position of the overlaid stream.

Here’s the general syntax for overlay filter:

[base][overlay]overlay=x:y[out]

Let’s see what this means:

  • [base] is the base video stream
  • [overlay] is the video to be overlaid on the base stream
  • overlay=x:y specifies the position of the overlaid video relative to the top-left corner of the base video
  • [out] is the label for the output video stream

So, if we have two videos, we can simply overlay the second input on the first input:

$ ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex '[0:v]pad=iw*2:ih[res];[res][1:v]overlay=W/2:0[out]' -map '[out]' output.mp4

Let’s break down the filter:

  • [0:v]pad=iw*2:ih[int] takes the first stream and pads it:
    • iw*2 doubles the original width
    • ih maintains the original height
    • [res] stores the intermediate result
  • [res][1:v]overlay=W/2:0 takes the [res] stream from the previous step and overlays the second input
  • [out] is the label that we assigned to the output video stream

Once we run the command, FFmpeg encodes the resulting video:

3. Merging Audio

In addition to video streams, we can also combine audio streams from all inputs into a single, multi-channel audio stream using the amerge filter:

$  ffmpeg -i v1.mp4 -i v2.mp4 \
    -filter_complex "[0:v][1:v]hstack=inputs=2[v]; \
    [0:a][1:a]amerge[a]" \
    -map "[v]" -map "[a]" -ac 2 output.mp4

Let’s dive into this:

  • [0:v][1:v]hstack=inputs=2[v] stacks the video streams and labels it “v
  • [0:a][1:a]amerge[a] takes the audio streams from both inputs and merges them into a single audio stream called “a
  • -map “[v]” -map “[a]” combines the two streams
  • -ac 2 creates two audio channels to make it stereo

If we omit -ac 2, the resulting audio stream will have four channels, preserving the channels from both inputs. Alternatively, we can add -an to completely remove the audio streams from the output.

4. Background Enhancements

In addition to stitching videos, we can also add padding and borders to the joined videos. It makes the video more clear and appealing.

4.1. Padding

We add padding to the videos using the pad filter:

$ ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex \
  "[0:v]pad=iw+10:ih+20:10:10[v1]; \
   [1:v]pad=iw+20:ih+20:10:10[v2]; \
   [v1][v2]hstack=inputs=2[v]" -map "[v]" output.mp4

Here is a breakdown of the pad filter:

  • [0:v]pad=iw+10:ih+20:10:10 adds padding to the first video:
    • iw+10 adjusts the width of the video by adding 10 pixels to the original input width
    • ih+20 adjusts the height of the video by adding 20 pixels to the original input height
    • 10:10 adds 10 pixels padding to the left, top, and bottom of the video
  • [1:v]pad=iw+10:ih+20:10:10[v2] adds 10px padding to the left, top, and bottom of the second video

After executing the command, we get a video with the given padding:

Now, if we look closely, we can see that the videos are padded 10px from all sides. However, the padded area is colored in black, which we’ll change in the next section.

4.2. Borders

We can go further by adding color to the padded area, creating a border-like appearance:

$ ffmpeg -i v1.mp4 -i v2.mp4 -filter_complex \
  "[0:v]pad=iw+10:ih+20:10:10:yellow[v1]; \
   [1:v]pad=iw+20:ih+20:10:10:yellow[v2]; \
   [v1][v2]hstack=inputs=2[v]" -map "[v]" output.mp4

In the command, we specified to the pad filter to color the padded area “yellow“. Alternatively, we can also specify color codes in the form of hex codes or RGB values.

Here is the final result:

5. Conclusion

In the article, we discussed how we can stack multiple videos horizontally using FFmpeg. We learned how to use the hstack and overlay complex filters as well as the amerge audio filter to merge the audio streams.

Lastly, we saw how to add simple enhancements to the stacked videos.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.