0

Currently running a batch script to mass convert media clips to save some storage space. I'd like to also add automation to the script that after the conversion will delete which ever ends up being the larger file. Not entirely sure how to best set that up at the end of each conversion.

pushd "%2"

::Default variables
SET paths=paths.txt
::paths lets you put a bunch of folder paths in a text file and run this across those, instead of individually. I use this to run overnight on a LOT of footage folders at once. Thanks to Aayla for a lot of these upgrades
::Fun tip - select your folders (15 max at a time) and shift+right-click and click "copy as paths"
SET /A ffmpeg_qv=24
::change CQP value here so you only have to type it once. 22 is lossless for HEVC.

::for /R %%A in (*.mp4, *.avi, *.mov, *.wmv, *.ts, *.m2ts, *.mkv, *.mts) do (
::    echo Processing %%A
::    ffmpeg -hwaccel auto -i "%%A" -pix_fmt p010le -map 0:v -map 0:a -c:v hevc_nvenc -rc constqp -qp 21 -b:v 0K -c:a libfdk_aac -vbr 5 -movflags +faststart "%%A~dnpA_CRF%ffmpeg_qv%_HEVC.mp4"
::    echo Processed %%A
::)
::pause
::Test if the paths file exists and iterate through it
if EXIST %paths% (
    for /f "tokens=*" %%a in (%paths%) do (
        echo Changing to directory %%a
        pushd "%%a"
        CALL :ffmpeg
    )
) else (
    ::It doesn't exist
    CALL :ffmpeg
)
pause
EXIT /B %ERRORLEVEL%
::Don't run the function when they're first defined because that's a thing Batch does for some reason???
:ffmpeg
    for /R %%A in (*.mp4, *.avi, *.mov, *.wmv, *.ts, *.m2ts, *.mkv, *.mts) do (
        echo Processing "%%A"
        ffmpeg -hwaccel auto -i "%%A" -pix_fmt yuv420p -map 0:v -map 0:a -map_metadata 0 -c:v hevc_nvenc -rc constqp -qp %ffmpeg_qv% -b:v 0K -c:a aac -b:a 128k -movflags +faststart -movflags use_metadata_tags "%%A~dnpA_CRF%ffmpeg_qv%_HEVC.mp4"
        :: "-map_metadata 0" copies all metadata from source file
        :: "-movflags +faststart" helps with audio streaming
        echo Processed %%A
        :: echo inFile %%A outFile %%A~dnpA_CRF%ffmpeg_qv%_HEVC.mp4
        :: code here to check if A>B or B<A 
        :: then delete the larger of the two
    )
GOTO :EOF
PolarBear
  • 3
  • 2
  • For other people's knowledge and future reference I have found a GUI that does exactly what I need here [link](https://stackoverflow.com/a/50018786/12325404) – PolarBear Nov 06 '19 at 15:03

1 Answers1

0

This will do the needful.

Note since you are playing with Video files they have a good chance of being larger than the 32 bit integer limit so I needed to code in checking the files against each other in a way that gets around that issue.

@( SETLOCAL EnableDelayedExpansion
  ECHO OFF
  REM Default variables
  SET "_eLvl=0"
  SET "_Media_Extentions*.mp4, *.avi, *.mov, *.wmv, *.ts, *.m2ts, *.mkv, *.mts"
  SET /A "ffmpeg_qv=24" & REM change CQP value here so you only have to type it once. 22 is lossless for HEVC.
  SET "paths=C:\Folder\paths.txt" & REM File Containing several paths to work on, allows running many footage folders at once.
  REM SET "paths=C:\Jobs\paths.txt" & REM File Containing several paths to work on, allows running many footage folders at once.
  REM NOTE: - In Windows Explorer you can select as many folders as you like, then hold shift and right-click on them, this will give the option "copy as paths".
  REM NOTE: - you can also just put the list of paths directly into the FOR Loop section below instead of using a separate file.
  REM   Thanks to Aayla for a lot of these upgrades
)

REM Call main function, pass any arguments provided to the script.
CALL :Main %*

( ENDLOCAL
  EXIT /B %_eLvl%
)


:Main
  REM Test if the paths file exists and iterate through it
  IF NOT EXIST "%paths%" (
    ECHO=  "%paths%" Does Not Exist Adding either "%~2" or "%~dp0"
    IF /I "%~2" NEQ "" (
      ECHO=  "%~2" Was provided, adding that value.
      ECHO=%~2>"%paths%"
    ) ELSE (
      ECHO=  "%~2" Was blank, adding "%~dp0".
      ECHO="%~dp0">"%paths%"
    )
  )
  IF NOT EXIST "%paths%" (
    ECHO= ERROR!  Somehow the Paths File could not be created at "%paths%"
    ECHO= Exiting!
    SET "eLvl=100"
  ) ELSE (
    FOR /F "Tokens=*" %%_ in ('
      type "%paths%"
    ') DO (
      IF EXIST "%%~_" (
        ECHO Checking Media in Path "%%~_"
        CALL :ffmpeg "%%~_"
      ) ELSE (
        ECHO= This Path does Not Exist!
        SET "eLvl=110"
      )
    )
  )

GOTO :EOF


:ffmpeg
  ECHO= Entered %0, Path Found: "%~1"
  FOR /R "%~1" %%_ IN ( %_Media_Extentions% ) DO (
    echo Processing "%%~_"
    ffmpeg -hwaccel auto -i "%%~_" -pix_fmt yuv420p -map 0:v -map 0:a -map_metadata 0 -c:v hevc_nvenc -rc constqp -qp %ffmpeg_qv% -b:v 0K -c:a aac -b:a 128k -movflags +faststart -movflags use_metadata_tags "%%~dpn__CRF%ffmpeg_qv%_HEVC.mp4"
    echo Processed "%%~_"
    ECHO= Outer Loop - Checking if "%%~_" is Larger or Smaller than "%%~dpn__CRF%ffmpeg_qv%_HEVC.mp4"
    FOR %%# IN ("%%~dpn__CRF%ffmpeg_qv%_HEVC.mp4") DO (
      SET "_Deleted="
      ECHO=
      ECHO= Inner Loop - Checking if "%%~n_" is Larger or Smaller than "%%~n#"
      ECHO= Old FILE: "%%~nx_" Size: "%%~z_"
      ECHO= New FILE: "%%~nx#" Size: "%%~z#"
      IF /I "%%~z_" EQU "%%~z#" (
        SET "eLvl=200"
        ECHO= Size of the files are equal...  Deleting "%%~f#"
        DEL /F /Q "%%~f#"
      ) ELSE (
        ECHO= Sizes are Different, Checking Which is Larger.
        SET "_TmpSize_=%%~z_"
        SET "_TmpSize#=%%~z#"
        FOR %%A IN (0 1 2 3 4 5 6 7 8 9) DO (
          SET "_TmpSize_=!_TmpSize_:%%A=%%A !"
          SET "_TmpSize#=!_TmpSize#:%%A=%%A !"
        )
        FOR %%A IN (!_TmpSize_!) DO (
          CALL SET /A "_TmpSize_Count+=1"  )
        FOR %%A IN (!_TmpSize#!) DO (
          CALL SET /A "_TmpSize#Count+=1"  )
        ECHO= Checking the length of Each Number:
        IF !_TmpSize_Count! LSS !_TmpSize#Count! (
          ECHO= Smaller File is the Old File...  Deleting "%%~f#"
          DEL /F /Q "%%~f#"
        ) ELSE (
          IF !_TmpSize_Count! GTR !_TmpSize#Count! (
            ECHO= Smaller File is the New File...  Deleting "%%~f_"
            DEL /F /Q "%%~f_"
          ) ELSE (
            ECHO= File Sizes are the Same Number of Characters.  Need to try advanced checking.
            SET "_TmpSize_=!_TmpSize_: =!"
            SET "_TmpSize#=!_TmpSize#: =!"
            FOR /L %%L IN (1,1,!_TmpSize_Count!) DO (
              IF NOT DEFINED _Deleted (
                SET /A "_Tst_=!_TmpSize_:~%%L,1!"
                SET /A "_Tst#=!_TmpSize#:~%%L,1!"
                IF !_Tst_! NEQ !_Tst#! (
                  IF !_Tst_! LSS !_Tst#! (
                    ECHO= Smaller File is the Old File...  Deleting "%%~f#"
                    DEL /F /Q "%%~f#"
                  ) ELSE (
                    ECHO= Smaller File is the New File...  Deleting "%%~f_"
                    DEL /F /Q "%%~f_"
                  )
                  SET "_Deleted=1"
                )
              )
            )
          )
        )
      )
    )
    ECHO Finished Check
  )
  SET "eLvl=!ERRORLEVEL!"
GOTO :EOF
Ben Personick
  • 2,666
  • 1
  • 16
  • 22
  • Thanks for the input! I hadn't even thought of the 4GB limit, which would have given me trouble. Really I'm okay copying this script to the parent directory and running it right there and letting it go recursively down. However still getting an error : `Checking Media in Path "F:\Test_h265" ( was unexpected at this time. F:\Test_h265> IF LSS ( ` – PolarBear Nov 06 '19 at 10:22
  • @PolarBear Glad to help. The 32bit integer is Signed, so its around 2 Gb that it becomes an issue. As for the error, it Looks like I accidentally used `%` to surround some of the variables when they needed `!` instead as we were inside the loop. I have amended the script and posted in replacement of the original for you. – Ben Personick Nov 06 '19 at 15:32
  • @PolarBear and I ran some tests on it to check the logic as I woe this quickly originally, there were a couple mior syntax errors, I fixed them and the above script should be good to go. – Ben Personick Nov 06 '19 at 16:57