CCCPaste

nvenc_fix_shadowplay

@echo off
SetLocal EnableDelayedExpansion
set title1=H.264 NVENC VBR
title %title1%

if "%~1"=="" ( goto :MakeShortcut ) else ( title %title1%^: "%~nx1")

:: you can override exe paths here. for example, set "ffmpeg=C:\ffmpeg\bin\ffmpeg.exe"
set "ffmpeg=ffmpeg"
set "ffprobe=ffprobe"

:: note: if you put ffmpeg.exe/ffprobe.exe and this script in the same folder, that would also work


:: only these file extensions will be processed by the script
set supported_formats=avi,mp4,mkv,mov,mts,m2ts,xmf,wmv

:: whether to play a chime sound after completion
set playsound=true

:: the sound to play. you can change
set "chime=C:\Windows\Media\tada.wav"

:: whether to open the output folder after completion
set open_folder=true

:: whether to add suffix to output files. for example, set "suffix=_fixed"
set suffix=

:: optional default subfolder to output to. for example, set "subfolder=converted"
set subfolder=

:: load override settings from optional settings.ini located in the same folder as this script
if exist "%~dp0settings.ini" ( for /f "tokens=* eol=;" %%L in ('type "%~dp0settings.ini"') do set "%%~L")

:CheckSubfolderVar
if not "%subfolder%"=="" (
set subfolder=%subfolder: =%
for %%A in ("!subfolder!") do ( set "subfolder=%%~A" & goto :CheckFFMPEG)
)
set subfolder=

:CheckFFMPEG
if not exist "%ffmpeg%" (
if exist "%~dp0ffmpeg.exe" set "ffmpeg=%~dp0ffmpeg.exe" & goto :CheckFFPROBE
ffmpeg>nul 2>&1
if !errorlevel!==9009 CALL :PrintMessage "ERROR: FFMPEG NOT FOUND / INSTALLED. EXITING." & echo  & pause & goto :eof
)

:CheckFFPROBE
if not exist "%ffprobe%" (
if exist "%~dp0ffprobe.exe" set "ffprobe=%~dp0ffprobe.exe" & goto :CountFiles
ffprobe>nul 2>&1
if !errorlevel!==9009 CALL :PrintMessage "ERROR: FFPROBE NOT FOUND / INSTALLED. EXITING." & echo  & pause & goto :eof
)

:CountFiles
:: replace bad characters for batch
set files=%*
set files=%files:,=\comma\%
set files=%files:(=\obr\%
set files=%files:)=\cbr\%

:: count files
set total=0
for %%F in (%files%) do (
if "%%~xF"=="" (
CALL :CountFolder "%%~F"
) else (
for %%A in (%supported_formats%) do ( if /i %%~xF==.%%A set /a total=!total!+1)
)
)
if %total%==0 echo  & CALL :PrintMessage "NO FILES TO PROCESS" "EXITING" & pause & goto :eof
if %total% GTR 1 title %title1%^: %total% files

:EnterPath
if "%subfolder%"=="" ( set "msg=output path = ") else ( set "msg=output path (default %subfolder%) ")
set p=
echo.
set /p p="%msg%"
if not "%p%"=="" (
for %%F in ("!p!") do (
set "outfolder=%%~F"
goto :ConformPath
)
)

:ConformPath
echo.
if not "!outfolder!"=="" (
if not "!outfolder:~-1!"=="\" (
if "!outfolder:~-1!"=="/" set "outfolder=!outfolder:~0,-1!"
set "outfolder=!outfolder!\"
for %%A in ("%outfolder%") do (
echo "%%~dA"| find /i "%~d1" > nul 2>&1
if not !ErrorLevel!==0 ( set openfolder=true & goto :BatchProcess)
)
for %%A in ("%outfolder%") do (
echo "%%~dpA"| find /i "%~dp1" > nul 2>&1
if not !ErrorLevel!==0 ( set openfolder=true & goto :BatchProcess)
)
)
)

:BatchProcess
set current=
for %%F in (%files%) do (
set "file=%%~F"
set "file=!file:\comma\=,!"
set "file=!file:\cbr\=)!"
set "file=!file:\obr\=(!"
if "%%~xF"=="" (
CALL :ProcessFolder "!file!"
) else (
for %%A in (%supported_formats%) do ( if /i %%~xF==.%%A CALL :ProcessFile "!file!")
)
)
title Finished
if defined openfolder if %open_folder%==true explorer "%outfolder%"
if %playsound%==true powershell -c (New-Object Media.SoundPlayer "%chime%").PlaySync();
goto :eof

:: SUBROUTINES
:CountFolder
set "f=%~1"
set "f=!f:\comma\=,!"
set "f=!f:\cbr\=)!"
set "f=!f:\obr\=(!"
for /f "tokens=*" %%F in ('dir "!f!" /s /b /a:-d') do ( for %%A in (%supported_formats%) do ( if /i %%~xF==.%%A set /a total=!total!+1))
goto :eof

:ProcessFolder
for /f "tokens=*" %%F in ('dir "%~1" /s /b /a:-d') do (
for %%A in (%supported_formats%) do (
if /i %%~xF==.%%A (
if not "%outfolder%"=="" ( set "foldertree=%%~dpF" & set "foldertree=!foldertree:%~dp1=!")
CALL :ProcessFile "%%~F"
)
)
)
set foldertree=
goto :eof

:: MAIN ROUTINE
:ProcessFile
if "!current!"=="" ( set current=1) else ( set /a current=!current!+1)
if %total% GTR 1 set "ratio= !current!/!total!"
title %title1%^:!ratio! "%~nx1"
if not "%cd%\"=="%~dp1" cd /d "%~dp1"

:CheckBitrate
set bitrate=
for /f "tokens=*" %%L in ('""%ffprobe%" -hide_banner -show_streams -select_streams v -show_entries stream^=bit_rate "%~1""') do (
echo "%%L"| find /i "bit_rate" > nul 2>&1
if !ErrorLevel!==0 for /f "tokens=2 delims==" %%C in ("%%L") do set "bitrate=%%C"
)

:CalcRates
set /a bitrate=!bitrate! / 1000000
set /a halfrate=!bitrate! / 2
set /a maxrate=!halfrate! + !bitrate!
set /a bufsize=!maxrate! * 2
title %title1%^:!ratio! "%~nx1" Target bitrate^: !bitrate!Mb/s

:CheckFramerate
if not "%customgop%"=="" goto :SetAudio
set framerate=
set gsize=
set lookahead=
for /f "tokens=*" %%L in ('""%ffprobe%" -hide_banner -show_streams -select_streams v -show_entries stream^=r_frame_rate^,avg_frame_rate "%~1""') do (
echo "%%L"| find /i "r_frame_rate" > nul 2>&1
if !ErrorLevel!==0 for /f "tokens=2 delims==" %%C in ("%%L") do ( set /a "framerate=%%C" & echo %%C)
if "!framerate!"=="" (
echo "%%L"| find /i "avg_frame_rate" > nul 2>&1
if !ErrorLevel!==0 for /f "tokens=2 delims==" %%D in ("%%M") do ( set /a "framerate=%%D" & echo %%D)
)
)
if not "!framerate!"=="" (
set /a "gop=!framerate!/2"
set gsize=-g !gop!
set lookahead=-rc-lookahead !gop!
) else ( CALL :PrintMessage "WARNING^: COULD NOT IDENTIFY FRAMERATE." "GOP AND LOOKAHEAD WILL NOT BE DEFINED." & pause)


:SetAudio
for /f "tokens=*" %%L in ('""%ffprobe%" -hide_banner -show_streams -select_streams a -show_entries stream^=codec_name "%~1""') do (
echo "%%L"| find /i "codec_name" >nul 2>&1
if !ErrorLevel!==0 for /f "tokens=2 delims==" %%C in ("%%L") do set "audiocodec=%%C"
)
if "!audiocodec!"=="aac" ( set "audiosettings=-c:a copy") else ( set "audiosettings=-c:a aac -b:a 320k")

:Checkoutfolder
if not "%outfolder%"=="" (
set "outpath=%outfolder%!foldertree!"
) else (
if "%subfolder%"=="" ( set "outpath=%~dp1") else ( set "outpath=%~dp1%subfolder%\")
)
if not exist "!outpath!" mkdir "!outpath!"

:Add_Postfix
if exist "!outpath!%~n1%suffix%.mp4" (
for /L %%N in (1,1,1000) do (
if not exist "!outpath!%~n1%suffix%_%%N.mp4" ( set "postfix=_%%N" & goto :FFmpeg)
)
)

:FFmpeg
"%ffmpeg%" -hide_banner -hwaccel_output_format cuda -i "%~1" -map 0:v -map 0:a:? -c:v h264_nvenc -preset slow -profile:v high -bf 2 !gsize! !lookahead! -rc vbr -b:v !bitrate!M -maxrate !maxrate!M -bufsize !bufsize!M !audiosettings! -movflags +faststart "!outpath!%~n1%suffix%!postfix!.mp4"
goto :eof

:: UTILITIES

:PrintMessage
echo.
echo ---------------------------------------------------------------
echo %~1
if not "%~2"=="" echo %~2
if not "%~3"=="" echo %~3
if not "%~4"=="" echo %~4
echo ---------------------------------------------------------------
goto :eof

::SETUP

:MakeShortcut
title Generate Shortcut
if exist "%ProgramFiles%\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA GeForce Experience.exe" ( set icon=$s.IconLocation='%ProgramFiles%\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA GeForce Experience.exe,0';) else ( set icon=$s.IconLocation='%windir%\system32\shell32.dll,115';)
powershell "$s=(New-Object -COM WScript.Shell).CreateShortcut('%appdata%\Microsoft\Windows\SendTo\Fix Shadowplay Color.lnk');$s.TargetPath='%~dpn0';%icon%$s.Save()"
if %errorlevel%==0 CALL :PrintMessage "The shortcut has been created." "If you wish to rename or remove it, do it yourself at" "%appdata%\Microsoft\Windows\SendTo" "or just type sendto in explorer address bar to get there"


:check_permissions
title "Fix shadowplay" script^: Add/Remove context menu entry
echo. & echo Checking permissions for adding/removing context menu entry in registry...
net session >nul 2>&1
if not %errorLevel% == 0 echo  & echo Error: For adding the context menu entry, you must run this script as administrator. & pause>nul & goto :FinishSetup
echo.

:CheckRegistry
reg query "HKCR\SystemFileAssociations\.mp4\Shell\fix_shadowplay">nul 2>&1
if %errorlevel%==0 ( set isinstalled=true) else ( set isinstalled=false)

:Prompt
title "Fix shadowplay" script^: Add/Remove context menu entry. Enter Y or N
if %isinstalled%==true ( set "msg=Context menu entry found. Delete it" ) else ( set "msg=Install context menu entry")
set proceed=
set /p "proceed=%msg% (Y/N)?"
if not "!proceed!"=="" (
set "proceed=!proceed: =!"
for /f "delims=yYnN" %%A in ('echo !proceed!') do goto :Prompt
)
if /i !proceed!==y ( if %isinstalled%==true ( goto :DeleteKey) else ( goto :AddKey))
if /i !proceed!==n goto :FinishSetup
goto :Prompt

:AddKey
title "Fix shadowplay" script^: Adding context menu entry to registry
if exist "%ProgramFiles%\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA GeForce Experience.exe" ( set "icon=%ProgramFiles%\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA GeForce Experience.exe" & set "icon2=0") else ( set "icon=%windir%\system32\shell32.dll" & set "icon2=115")
reg add "HKCR\SystemFileAssociations\.mp4\Shell\fix_shadowplay" /f /v "" /t REG_SZ /d "Fix Shadowplay Color"
reg add "HKCR\SystemFileAssociations\.mp4\Shell\fix_shadowplay" /f /v "Icon" /t REG_SZ /d "\"%icon%\",%icon2%"
reg add "HKCR\SystemFileAssociations\.mp4\Shell\fix_shadowplay\command" /f /v "" /t REG_SZ /d "\"%~dpnx0\" \"%%1\""
goto :FinishSetup

:DeleteKey
title "Fix shadowplay" script^: Removing context menu entry from registry
reg delete "HKCR\SystemFileAssociations\.mp4\Shell\fix_shadowplay" /f
goto :FinishSetup

:FinishSetup
title Done
explorer "%appdata%\Microsoft\Windows\SendTo"
goto :eof