# Converts videos to HEVC for given path:
# https://github.com/rigaya/NVEnc/releases

#-----------------------------------------------------------------------
# Edit the $videoPath variable to point to your video-files folder:

$videoPath = 'M:\2_serien\_main.series\'

#-----------------------------------------------------------------------
# HEVC profiles: main, main10, main444
$profile = 'main10'

$NVEncoder = "$PSScriptRoot\encoder\NVEncC64.exe"
$fileTester = "$PSScriptRoot\mediainfo.exe"


#############################################################################################################
#                                    Testing and conversion preparations 									#
#############################################################################################################
if(!(Test-Path $NVEncoder -PathType leaf))
{
    Write-Host "NVEncC64.exe not found, please check path in `"$NVEncoder`"." -ForegroundColor Yellow
	Read-Host -Prompt "Press Enter to exit"
    exit
}

# Get video list from provided path:
$videos = Get-ChildItem -LiteralPath $videoPath -Name -Recurse -Include ('*.mp4', '*.mkv') #('*.avi', '*.mp4', '*.mkv') - avi currently doesn't work.

# Instantiating used variables:
$videoID = 1
$convertedVideos = 1
$notConvertedVideos = 0
$failedVideos = 0
# Square brackets are used as wildcards in Powershell. 
# To recognize this as normal text, the LogWite function uses the -LiteralPath parameter instead of the -Path parameter.
$logFolderName = $((Get-Date).tostring("dd-MM-yyyy") + ' - [run started at ' + (Get-Date).tostring("HH-mm") + ']')
$count = $videos.Count

if($videos.Count -lt 1)
{
    Write-Host "No videos found in: $videoPath" -ForegroundColor Red
    Read-Host -Prompt "Press Enter to exit"
	exit
}
# Log write function:
Function LogWrite
{
   Param ([string]$logstring)
   Add-content -LiteralPath $Logfile -value $logstring
}
# Create new log directory:
New-Item -itemType Directory -Path $PSScriptRoot\logs\ -Name $logFolderName > $null
# Calculates the total size of the given directory in GB:
Write-Host "Inizialization in progress.."
$folderSizeInGB = "{0:N2} GB" -f ((Get-ChildItem $videoPath -Recurse | Measure-Object -Property Length -Sum -ErrorAction Stop).Sum / 1GB)
Clear-Host # Clears the upper message from the window
#############################################################################################################
# END - Testing and conversion preparations



#############################################################################################################
#                                          Main conversion process											#
#############################################################################################################
Write-Host "Found $count videos with a total size of $folderSizeInGB - starting converter.." -ForegroundColor Cyan
Write-Host
Write-Host
Write-Host "------------------------------------------------------------------------------------------------"

foreach($video in $videos)
{
    
    $video = $video.Replace("`"", "")
    $inputFile = $videoPath + $video
	
	# Get and check File info for codec, if it's already HEVC: - JSON query: (['media']['track'][1]['Format'])
	$fileDetails = cmd /c $fileTester $inputFile --Output=JSON | ConvertFrom-Json
	$codec = $fileDetails.media.track[1].Format
	#echo $codec
	
	# If not already HEVC, convert video using NVEncC64:
	if($codec -ne "HEVC")
	{
		# Configure new file naming:
		if ($video -match "264")
		{
			$outputFile = $videoPath + $video.Replace("264", "265")
		} else {
			$outputFile = $videoPath + $video.Insert(($video.Length - 4), '-HEVC')
		}
		Write-Host "Analyzing video ($videoID of $count), starting convertion of number: $convertedVideos please wait.." -ForegroundColor Magenta
		Write-Host "$video `nto:`n$outputFile" -ForegroundColor White
		Write-Host
		
		# If the Subtitles should not be copied, delete the "--sub-copy 1,2" argument.
		$arguments = "--input `"$inputFile`" --codec hevc --audio-copy 1,2 --sub-copy 1,2 --profile $profile --output `"$outputFile`""
		
		Start-Process $NVEncoder -ArgumentList $arguments -WindowStyle Minimized

		$processName = 'NVEncC64'
		Start-Sleep -Seconds 8
		# Sets to use 3 cores (always set to one less core that your CPU has)
		# 2 Cores = 3, 3 Cores = 7, 4 cores = 15, 5 cores = 31, 6 cores = 63
		# Code to calculate for your CPU:
		# $noOfCores = Get-WmiObject Win32_Processor | Measure-Object NumberOfLogicalProcessors -Sum
		# $noOfCores.Sum = $noOfCores.Sum - 1
		# [math]::Pow(2,$($noOfCores).Sum) - 1
		#
		$process = Get-Process $processName; $process.ProcessorAffinity=7
		Start-Sleep -Seconds 8
		# Sets priorty to High
		# Values: High, AboveNormal, Normal, BelowNormal, Low
		$process = Get-Process -Id $process.Id
		$process.PriorityClass = 'High'

		# Waits for process to complete
		$processID = (Get-Process $processName).id
		Wait-Process -Id $processID
		
		
		if(Test-Path -LiteralPath $outputFile)
		# Specifies a path to be tested. Unlike Path, the value of the LiteralPath parameter is used exactly as it is typed. 
		#No characters are interpreted as wildcard characters.
		{
			Write-Host "CONVERSION DONE! FILE: `"$outputFile`" FOUND" -ForegroundColor Yellow
			Start-Sleep -Seconds 4
			
			# Check if File is valid; the duration of video must be the same! (['media']['track'][0]['Duration']):
			$fileDetails_new = cmd /c $fileTester $outputFile --Output=JSON | ConvertFrom-Json
			
			# This code gets the duration and splits it in two parts, only the part before the "." is needed:
			$StreamSize_old,$notused = $($fileDetails.media.track[0].Duration).split('.')
			$StreamSize_new,$notused = $($fileDetails_new.media.track[0].Duration).split('.')
			
			Write-Host
			Write-Host "Old Duration was: $StreamSize_old `nnew Duration is: $StreamSize_new" -ForegroundColor White
			Write-Host
		
			if ($StreamSize_new -eq $StreamSize_old)
			{
				# Delete old video File!
				Write-Host "Conversion Successful! - Deleting old file.."
				Write-Host
				Write-Host "------------------------------------------------------------------------------------------------"
				Remove-Item -LiteralPath $inputFile
				$convertedVideos = $convertedVideos + 1
				$Logfile = "$PSScriptRoot\logs\$logFolderName\successfully_converted.log"
				LogWrite "$outputFile"
			} else
			{
				# Delete corrupt File!
				Write-Host "Conversion Failded! - Deleting new converted file.." -ForegroundColor Red
				Write-Host
				Write-Host "------------------------------------------------------------------------------------------------"
				Remove-Item -LiteralPath $outputFile
				$failedVideos = $failedVideos + 1
				$notConvertedVideos = $notConvertedVideos + 1
				$Logfile = "$PSScriptRoot\logs\$logFolderName\error_during_conversion.log"
				LogWrite "$inputFile"
			}
		}
		#Start-Sleep -Seconds 4
	} else 
	{
		# Alert if video doesn't need conversion:
		Write-Host "Analyzing video ($videoID of $count) - skip" -ForegroundColor Magenta
		Write-Host "$video is already in correct format!" -ForegroundColor Green
		Write-Host
		Write-Host "------------------------------------------------------------------------------------------------"
		# Increments not converted video counter:
		$notConvertedVideos = $notConvertedVideos + 1
		$Logfile = "$PSScriptRoot\logs\$logFolderName\skipped_files.log"
		LogWrite "$inputFile"
	}
	# Increments video counter:
	$videoID = $videoID + 1
	$outputFile = "" # Resets the variable to nothing, that in case of an error the old file is not affected.
}
#############################################################################################################
# END - Main conversion process



#############################################################################################################
#                                  Evaluation part of the conversion script									#
#############################################################################################################
Write-Host "Final calculations are in progress.."
$folderSizeInGB2 = "{0:N2} GB" -f ((Get-ChildItem $videoPath -Recurse | Measure-Object -Property Length -Sum -ErrorAction Stop).Sum / 1GB)
if($notConvertedVideos -eq 0)
{
	Write-Host "Finished converted $convertedVideos out of $count videos." -ForegroundColor Green
} else 
{
	if($failedVideos -eq 0)
	{
		Write-Host "Finished converted $convertedVideos out of $count videos. - $notConvertedVideos where not converted because of already correct codec!" -ForegroundColor Green
	} else
	{
		Write-Host "Finished converted $convertedVideos out of $count videos. - $notConvertedVideos where not converted because error or already correct codec!!" -ForegroundColor Green
		Write-Host "$failedVideos have failed!" -ForegroundColor Red

	}
}
Write-Host "Directory size before conversion: $folderSizeInGB"
Write-Host "Directory size after conversion: $folderSizeInGB2"

Read-Host -Prompt "Press Enter to exit"
#############################################################################################################
# END - conversion script