::######################################
:: Usage: ffmpeg_grid 8 8 160 90 "-c:v libx264 -an" output.mp4 input1.mp4 ...
::######################################
@echo off
setlocal enabledelayedexpansion
:: Copy mandatory args into named vars
set cols=%1
set rows=%2
set w=%3
set h=%4
set extra_args=%~5
set output=%6
:: Load all remaining args into array 'inputs'
for /l %%i in (1,1,6) do shift
set i=0
:args_loop
if "%1"=="" goto args_done
set inputs[%i%]=%1
set /a i+=1
shift
goto args_loop
:args_done
del %output% 2>nul
set /a w_total=%w% * %cols%
set /a h_total=%h% * %rows%
set /a max_x=%cols%-1
set /a max_y=%rows%-1
set /a cnt=%cols% * %rows%
set ffmpeg_cmd=ffmpeg -hide_banner
del %tmp%\~ffscr1 2>nul
del %tmp%\~ffscr2 2>nul
set i=0
set input=%1
:: Loop over all videos in grid
for /l %%y in (0,1,%max_y%) do (
for /l %%x in (0,1,%max_x%) do (
call set test=%%inputs[!i!]%%
if not "!test!"=="" set input=!test!
set ffmpeg_cmd=!ffmpeg_cmd! -i !input!
echo [!i!:v] setpts=PTS-STARTPTS, scale=%w%x%h% [%%x%%y];>>%tmp%\~ffscr1
set /a j=!i!+1
set /a x=%%x * %w%
set /a y=%%y * %h%
echo [tmp!i!][%%x%%y] overlay=shortest=1:x=!x!:y=!y!>>%tmp%\~ffscr2
set /a i=!i!+1
if !i! lss %cnt% echo [tmp!j!];>>%tmp%\~ffscr2
)
)
:: Create filter_complex_script
echo nullsrc=size=%w_total%x%h_total% [tmp0];>%tmp%\~ffscr
type %tmp%\~ffscr1>>%tmp%\~ffscr
type %tmp%\~ffscr2>>%tmp%\~ffscr
:: Run FFmpeg command
!ffmpeg_cmd! -filter_complex_script %tmp%\~ffscr %extra_args% %output%
:: Clean up tmp files
del %tmp%\~ffscr 2>nul
del %tmp%\~ffscr1 2>nul
del %tmp%\~ffscr2 2>nul
endlocal