Posts

Creating a Batch File for Compressing Older Videos (Code Inside)

0 comments·0 reblogs
ahmadmanga
75
·
0 views
·
min-read

In this article I'll talk about the Batch file I created to convert my Videos to the AV1 encoding.

Image from thread

My external HDD was getting full, so I spent a day to delete files I don't need anymore, but that wasn't enough. So, with what I learned from my earlier research on AV1 Encoding, I figured I could compress the older videos of my Let's Play game footage with AV1 encoding... I won't need most of them again, but I want to keep them all just in case.

So, I did some research (hint: conversations with AI) and guided AI to crate a batch code to do the job for me.

This code converts .mp4 files to .mkv files and vice-versa. The generated AV1 file does have less quality, but the size tradeoff for videos I probably won't need again, it wasn't a bad compromise.

Since this is just a batch code there are limits to how complex it can be. If I knew it'll become this long, I would've used python, but at least for now it does the job. The conversion on my PC takes about 9 minutes for an hour long video (at 720p) and twice as long in larger videos (1080p.) As I said above the quality is compromised, so I'll probably update this code to generate better quality.

What do you think?


The Code:

@echo off 
setlocal enabledelayedexpansion 
 
:: ============================================ 
:: Parse Command Line Arguments 
:: ============================================ 
set "qvbr_quality=30" 
set "resolution=" 
set "scale_filter=" 
 
:parse_args 
if "%~1"=="" goto :done_args 
if /i "%~1"=="-q" ( 
    set "qvbr_quality=%~2" 
    shift 
    shift 
    goto :parse_args 
) 
if /i "%~1"=="--qvbr" ( 
    set "qvbr_quality=%~2" 
    shift 
    shift 
    goto :parse_args 
) 
if /i "%~1"=="-r" ( 
    set "resolution=%~2" 
    shift 
    shift 
    goto :parse_args 
) 
if /i "%~1"=="--resolution" ( 
    set "resolution=%~2" 
    shift 
    shift 
    goto :parse_args 
) 
shift 
goto :parse_args 
:done_args 
 
:: Build scale filter if resolution specified 
if defined resolution ( 
    set "scale_filter=scale=-2:%resolution%," 
) 
 
:: ============================================ 
:: Setup Log File 
:: ============================================ 
for %%I in (.) do set "foldername=%%~nxI" 
 
:: Use WMIC for locale-independent date/time 
for /f "tokens=2 delims==" %%a in ('wmic os get localdatetime /value ^| find "="') do set "dt=%%a" 
set "logfile=VidConvert-Log-!foldername!-!dt:~0,4!-!dt:~4,2!-!dt:~6,2!-!dt:~8,2!-!dt:~10,2!.txt" 
 
:: Initialize log file with header 
>> "%logfile%" echo ============================================ 
>> "%logfile%" echo    AV1 Batch Converter Log 
>> "%logfile%" echo ============================================ 
>> "%logfile%" echo Date: !dt:~0,4!-!dt:~4,2!-!dt:~6,2! !dt:~8,2!:!dt:~10,2!:!dt:~12,2! 
>> "%logfile%" echo Quality Level: %qvbr_quality% 
if defined resolution >> "%logfile%" echo Resolution: %resolution%p 
>> "%logfile%" echo. 
 
echo ============================================ 
echo    AV1 Batch Converter for MKV/MP4 Files 
echo ============================================ 
echo. 
echo Settings: 
echo   QVBR Quality: %qvbr_quality% 
if defined resolution ( 
    echo   Resolution:   %resolution%p (scaled) 
) else ( 
    echo   Resolution:   Original 
) 
echo   Log File:     %logfile% 
echo. 
 
:: Initialize counters and totals 
set /a completed=0 
set /a remaining=0 
set /a current=0 
set /a skipped=0 
set /a errors=0 
set /a total_input_size=0 
set /a total_output_size=0 
 
:: Count files that need conversion 
for %%f in (*.mkv) do ( 
    if not exist "%%~nf.mp4" set /a remaining+=1 
) 
for %%f in (*.mp4) do ( 
    if not exist "%%~nf.mkv" set /a remaining+=1 
) 
 
set /a total=%remaining% 
 
if %total%==0 ( 
    echo No files need conversion. All MKV/MP4 pairs already exist. 
    >> "%logfile%" echo No files need conversion. All MKV/MP4 pairs already exist. 
    goto :end 
) 
 
echo Files to convert: %total% 
echo. 
 
:: ============================================ 
:: Convert MKV to MP4 
:: ============================================ 
for %%f in (*.mkv) do ( 
    set "input=%%f" 
    set "basename=%%~nf" 
    set "output=%%~nf.mp4" 
     
    if exist "!output!" ( 
        echo [SKIP] !output! already exists 
        set /a skipped+=1 
    ) else ( 
        set /a current+=1 
         
        :: Get input file size in bytes 
        for %%a in ("!input!") do set /a input_size=%%~za 
         
        echo. 
        echo ============================================ 
        echo [!current!/%total%] Converting: !input! 
        echo ============================================ 
        echo Input size: !input_size! bytes 
        echo Encoding in progress... 
        echo. 
         
        :: Log start of conversion 
        >> "%logfile%" echo [%date% %time%] START: !input! 
         
        :: Run FFmpeg with AMF AV1 encoder (output to terminal only) 
        ffmpeg -y -xerror -i "!input!" -c:v av1_amf -rc qvbr -qvbr_quality_level %qvbr_quality% -preset high_quality -aq_mode caq -preencode true -preanalysis true -pa_lookahead_buffer_depth 40 -pa_taq_mode 2 -pa_adaptive_mini_gop true -bf 3 -g 180 -vf "!scale_filter!hqdn3d=2:2:0:0" -c:a copy "!output!" 
         
        if errorlevel 1 ( 
            echo. 
            echo [ERROR] FFmpeg failed on !input! 
            if exist "!output!" del "!output!" 
            set /a errors+=1 
            >> "%logfile%" echo [%date% %time%] ERROR: !input! - Conversion failed 
            >> "%logfile%" echo. 
        ) else ( 
            :: Get output file size 
            for %%a in ("!output!") do set /a output_size=%%~za 
             
            :: Calculate compression ratio (fixed point math with 2 decimals) 
            set /a ratio_num=input_size*100/output_size 
            set /a ratio_whole=ratio_num/100 
            set /a ratio_dec=ratio_num%%100 
            set /a saved_percent=100-(output_size*100/input_size) 
             
            :: Apply creation date from input to output 
            powershell -command "try { $src = Get-Item '!input!'; $dst = Get-Item '!output!'; $dst.CreationTime = $src.CreationTime } catch {}" 
             
            set /a completed+=1 
            set /a total_input_size+=input_size 
            set /a total_output_size+=output_size 
             
            echo. 
            echo ---------------------------------------- 
            echo [DONE] !input! -^> !output! 
            echo ---------------------------------------- 
            echo Input:  !input_size! bytes 
            echo Output: !output_size! bytes 
            echo Ratio:  !ratio_whole!.!ratio_dec!x (!saved_percent%% smaller) 
            echo ---------------------------------------- 
             
            :: Log successful conversion 
            >> "%logfile%" echo [%date% %time%] DONE: !input! -^> !output! 
            >> "%logfile%" echo   Input:  !input_size! bytes 
            >> "%logfile%" echo   Output: !output_size! bytes 
            >> "%logfile%" echo   Ratio:  !ratio_whole!.!ratio_dec!x (!saved_percent%% smaller) 
            >> "%logfile%" echo. 
        ) 
         
        set /a remaining=total-completed-skipped-errors 
        echo Progress: Completed=%completed% Remaining=!remaining! Errors=%errors% 
         
        if !completed! GTR 0 ( 
            set /a mod=completed%%3 
            if !mod!==0 ( 
                echo. 
                echo **************************************** 
                echo  STATUS: %completed% done, !remaining! remaining, %errors% errors 
                echo **************************************** 
                echo. 
            ) 
        ) 
    ) 
) 
 
:: ============================================ 
:: Convert MP4 to MKV 
:: ============================================ 
for %%f in (*.mp4) do ( 
    set "input=%%f" 
    set "basename=%%~nf" 
    set "output=%%~nf.mkv" 
     
    if exist "!output!" ( 
        echo [SKIP] !output! already exists 
        set /a skipped+=1 
    ) else ( 
        set /a current+=1 
         
        :: Get input file size in bytes 
        for %%a in ("!input!") do set /a input_size=%%~za 
         
        echo. 
        echo ============================================ 
        echo [!current!/%total%] Converting: !input! 
        echo ============================================ 
        echo Input size: !input_size! bytes 
        echo Encoding in progress... 
        echo. 
         
        :: Log start of conversion 
        >> "%logfile%" echo [%date% %time%] START: !input! 
         
        :: Run FFmpeg with AMF AV1 encoder (output to terminal only) 
        ffmpeg -y -xerror -i "!input!" -c:v av1_amf -rc qvbr -qvbr_quality_level %qvbr_quality% -preset high_quality -aq_mode caq -preencode true -preanalysis true -pa_lookahead_buffer_depth 40 -pa_taq_mode 2 -pa_adaptive_mini_gop true -bf 3 -g 180 -vf "!scale_filter!hqdn3d=2:2:0:0" -c:a copy "!output!" 
         
        if errorlevel 1 ( 
            echo. 
            echo [ERROR] FFmpeg failed on !input! 
            if exist "!output!" del "!output!" 
            set /a errors+=1 
            >> "%logfile%" echo [%date% %time%] ERROR: !input! - Conversion failed 
            >> "%logfile%" echo. 
        ) else ( 
            :: Get output file size 
            for %%a in ("!output!") do set /a output_size=%%~za 
             
            :: Calculate compression ratio (fixed point math with 2 decimals) 
            set /a ratio_num=input_size*100/output_size 
            set /a ratio_whole=ratio_num/100 
            set /a ratio_dec=ratio_num%%100 
            set /a saved_percent=100-(output_size*100/input_size) 
             
            :: Apply creation date from input to output 
            powershell -command "try { $src = Get-Item '!input!'; $dst = Get-Item '!output!'; $dst.CreationTime = $src.CreationTime } catch {}" 
             
            set /a completed+=1 
            set /a total_input_size+=input_size 
            set /a total_output_size+=output_size 
             
            echo. 
            echo ---------------------------------------- 
            echo [DONE] !input! -^> !output! 
            echo ---------------------------------------- 
            echo Input:  !input_size! bytes 
            echo Output: !output_size! bytes 
            echo Ratio:  !ratio_whole!.!ratio_dec!x (!saved_percent%% smaller) 
            echo ---------------------------------------- 
             
            :: Log successful conversion 
            >> "%logfile%" echo [%date% %time%] DONE: !input! -^> !output! 
            >> "%logfile%" echo   Input:  !input_size! bytes 
            >> "%logfile%" echo   Output: !output_size! bytes 
            >> "%logfile%" echo   Ratio:  !ratio_whole!.!ratio_dec!x (!saved_percent%% smaller) 
            >> "%logfile%" echo. 
        ) 
         
        set /a remaining=total-completed-skipped-errors 
        echo Progress: Completed=%completed% Remaining=!remaining! Errors=%errors% 
         
        if !completed! GTR 0 ( 
            set /a mod=completed%%3 
            if !mod!==0 ( 
                echo. 
                echo **************************************** 
                echo  STATUS: %completed% done, !remaining! remaining, %errors% errors 
                echo **************************************** 
                echo. 
            ) 
        ) 
    ) 
) 
 
:end 
echo. 
echo ============================================ 
echo  CONVERSION COMPLETE 
echo ============================================ 
echo  Files converted: %completed% 
echo  Files skipped:   %skipped% 
echo  Files failed:    %errors% 
echo. 
 
if %completed% GTR 0 ( 
    :: Calculate total compression stats 
    set /a total_ratio_num=total_input_size*100/total_output_size 
    set /a total_ratio_whole=total_ratio_num/100 
    set /a total_ratio_dec=total_ratio_num%%100 
    set /a total_saved_percent=100-(total_output_size*100/total_input_size) 
     
    echo  TOTAL COMPRESSION SUMMARY 
    echo  ---------------------------------------- 
    echo  Input size:  %total_input_size% bytes 
    echo  Output size: %total_output_size% bytes 
    echo  Ratio:       !total_ratio_whole!.!total_ratio_dec!x 
    echo  Space saved: !total_saved_percent!%% 
    echo ============================================ 
     
    :: Write final summary to log 
    >> "%logfile%" echo ============================================ 
    >> "%logfile%" echo  FINAL SUMMARY 
    >> "%logfile%" echo ============================================ 
    >> "%logfile%" echo Files converted: %completed% 
    >> "%logfile%" echo Files skipped:   %skipped% 
    >> "%logfile%" echo Files failed:    %errors% 
    >> "%logfile%" echo Input size:  %total_input_size% bytes 
    >> "%logfile%" echo Output size: %total_output_size% bytes 
    >> "%logfile%" echo Ratio:       !total_ratio_whole!.!total_ratio_dec!x 
    >> "%logfile%" echo Space saved: !total_saved_percent!%% 
    >> "%logfile%" echo ============================================ 
) 
 
echo Log saved to: %logfile% 
echo. 
echo Press any key to close... 
pause >nul 

Posted Using INLEO