@echo off
SetLocal EnableDelayedExpansion
title %~n0

:: only process these input files
set supported_formats=avi,bik,flv,m2ts,m4p,m4v,mkv,mov,mp2,mp4,mpg,mpeg,mpe,mpv,mts,qt,swf,wmv,xmf,webm

:: temporary created txt file for concat list
set filelist=temp_concat.txt

set playsound=true

:: check for input files
if "%~1"=="" ( echo ERROR: NO INPUT & echo  & pause & goto :eof ) else (
if "%~2"=="" ( echo ERROR: only ONE input file & pause & goto :eof )
if NOT "%cd%\"=="%~dp1" cd /d "%~dp1"
)

:: delete filelist is exists
if exist %filelist% del %filelist%

:: iterate_files
FOR %%A IN (%*) DO CALL :LogFile "%%~A"
if exist %filelist% goto :ffmpeg
goto :eof

:LogFile
for %%G in (%supported_formats%) do (
	if /i %~x1==.%%G (
		if "!first!"=="" (
			set "first=%~n1"
			set "extension=%~x1"
			if /i !extension!==.mp4 CALL :check_audio_mp4 "%~1"
		) else (
			set "last=%~n1"
		)
		echo ^file '%~nx1'>>%filelist%
		goto :eof
	)
)
echo ERROR: %~1 - extension not supported & goto :eof

:: if audio stream is not supported in mp4 container, switch to mov (Quicktime). So far I included conditionals for uncompressed pcm, flac and alac audio.
:check_audio_mp4
for /f "tokens=*" %%L in ('ffprobe.exe -hide_banner -show_streams -select_streams a -show_entries stream^=codec_name -loglevel quiet "%~1"') do (
	echo "%%L"| find /i "codec_name" > nul 2>&1
	if !ErrorLevel!==0 (
		for /f "tokens=2 delims==" %%C in ("%%L") do (
			echo "%%C"| find /i "pcm" && ( set "extension=.mov" & goto :eof)
			if /i "%%C"=="flac" set "extension=.mov" & goto :eof
			if /i "%%C"=="alac" set "extension=.mov" & goto :eof
		)
	)
)
goto :eof

:ffmpeg
title Concat %first% - %last%  ^>   %first%-%last%_merged%extension%"
set "output=%first%-%last%_merged%extension%"
ffmpeg.exe -f concat -safe 0 -i %filelist% -map 0:v -map 0:a? -c copy "%output%"
if not !errorlevel!==0 CALL :ErrorSubroutine %output%
del %filelist%
if defined goterror ( pause & goto :eof)
if %playsound%==true powershell -c (New-Object Media.SoundPlayer "C:\Windows\Media\tada.wav").PlaySync();
goto :eof

:: if output file is empty, deletes it. prints some messages. stores goterror var.
:ErrorSubroutine
title ERROR ^^! ^^! ^^!
if "%~z1"=="0" del %1
CALL :Message "ERROR: FILE OUTPUT FAILED"
set goterror=true
echo 
goto :eof

:: prints simple message
:Message
echo.
echo ----------------------------------
echo %~1
if not "%~2"=="" echo %~2
if not "%~3"=="" echo %~3
echo ----------------------------------
goto :eof
