Create a 3x3 Video Grid Using FFmpeg xstack

This guide demonstrates how to use the FFmpeg xstack filter to merge nine separate video files into a single 3x3 grid layout. You will learn the exact command-line syntax, how to define the custom grid coordinates, and how to manage the accompanying audio tracks for a clean and professional final render.

The 3x3 Grid Command

To combine nine videos into a 3x3 grid, you must pass all nine videos as inputs and use the xstack filter. The filter requires you to define the number of inputs and specify the exact coordinate placement for each video stream.

Here is the standard command assuming all nine input videos have the exact same dimensions (width and height):

ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 \
       -i input4.mp4 -i input5.mp4 -i input6.mp4 \
       -i input7.mp4 -i input8.mp4 -i input9.mp4 \
       -filter_complex \
       "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v]xstack=inputs=9:layout=0_0|w0_0|w0+w1_0|0_h0|w0_h0|w0+w1_h0|0_h0+h3|w0_h0+h3|w0+w1_h0+h3[v]" \
       -map "[v]" output.mp4

Understanding the Coordinates Layout

The layout parameter in xstack uses a grid of X_Y coordinates separated by pipe (|) characters. The coordinates correspond to each input video in the order they are listed (from index 0 to 8).

Assuming each video has a width (w) and height (h):

Handling Different Input Sizes

The xstack filter requires all input streams to have identical pixel formats, and the layout math is much simpler if they are the exact same size. If your source videos have different resolutions, you should scale them first within the filtergraph.

The command below scales all nine inputs to 640x360 before passing them to the xstack filter, resulting in a perfectly aligned 1920x1080 output:

ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 \
       -i input4.mp4 -i input5.mp4 -i input6.mp4 \
       -i input7.mp4 -i input8.mp4 -i input9.mp4 \
       -filter_complex \
       "[0:v]scale=640:360[v0]; \
        [1:v]scale=640:360[v1]; \
        [2:v]scale=640:360[v2]; \
        [3:v]scale=640:360[v3]; \
        [4:v]scale=640:360[v4]; \
        [5:v]scale=640:360[v5]; \
        [6:v]scale=640:360[v6]; \
        [7:v]scale=640:360[v7]; \
        [8:v]scale=640:360[v8]; \
        [v0][v1][v2][v3][v4][v5][v6][v7][v8]xstack=inputs=9:layout=0_0|w0_0|w0+w1_0|0_h0|w0_h0|w0+w1_h0|0_h0+h3|w0_h0+h3|w0+w1_h0+h3[v]" \
       -map "[v]" output.mp4

Adding Audio

By default, the above commands only output video. To manage audio, you have two primary options:

Option 1: Use Audio from One Specific Video

To use the audio from the first input video (input1.mp4), map its audio channel using -map 0:a:

ffmpeg -i input1.mp4 -i input2.mp4 ... [inputs] ... \
       -filter_complex "[0:v]...xstack...[v]" \
       -map "[v]" -map 0:a output.mp4

Option 2: Mix All Audio Tracks Together

To mix the audio tracks of all nine inputs so they play simultaneously, use the amix filter:

ffmpeg -i input1.mp4 -i input2.mp4 -i input3.mp4 \
       -i input4.mp4 -i input5.mp4 -i input6.mp4 \
       -i input7.mp4 -i input8.mp4 -i input9.mp4 \
       -filter_complex \
       "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v]xstack=inputs=9:layout=0_0|w0_0|w0+w1_0|0_h0|w0_h0|w0+w1_h0|0_h0+h3|w0_h0+h3|w0+w1_h0+h3[v]; \
        [0:a][1:a][2:a][3:a][4:a][5:a][6:a][7:a][8:a]amix=inputs=9[a]" \
       -map "[v]" -map "[a]" output.mp4