@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