@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