video-in-place-hevc-converter/convert_Videos.ps1

290 lines
13 KiB
PowerShell
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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:\1_movies\_main.movies'
$videoPath = 'M:\2_serien\_main.series'
#$videoPath = 'M:\3_dokus'
#-----------------------------------------------------------------------
# HEVC profiles: main, main10, main444
$hevc_profile = 'main10'
$forceReviewAll = $false # If set to $true all failed conversions are reviewed even those that are obviously corrupt.
$NVEncoder = "$PSScriptRoot\encoder\NVEncC64.exe"
$fileTester = "$PSScriptRoot\mediainfo.exe"
$reviewPlayer = "C:\Program Files\VideoLAN\VLC\vlc.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 = 0
$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("yyyy-MM-dd") + ' - [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
# Pre-file-check if "HEVC" exist in filename skip filechecking:
if ($video -match "HEVC") {
$codec = "HEVC"
}
else {
# 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
}
# 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 + 1) 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,3,4 --sub-copy 1,2,3,4 --profile $hevc_profile --output `"$outputFile`""
Start-Process $NVEncoder -ArgumentList $arguments -WindowStyle Minimized
$processName = 'NVEncC64'
Start-Sleep -Seconds 1
# 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 2
# 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 {
if (($StreamSize_new -eq $($StreamSize_old - 1)) -or ($($StreamSize_new - 1) -eq $StreamSize_old)) {
# Newly converted file does not match exactly the old duration. But diffrence its not more than 1 sec!
Write-Host "Conversion Done! - Streamsize is not exactly the same. But still OK - Ignoring!"
Write-Host
Write-Host "------------------------------------------------------------------------------------------------"
Remove-Item -LiteralPath $inputFile
$convertedVideos = $convertedVideos + 1
$Logfile = "$PSScriptRoot\logs\$logFolderName\successfully_converted.log"
LogWrite "$outputFile"
}
elseif (($StreamSize_new -ge $($StreamSize_old - 20)) -or ($($StreamSize_new - 20) -ge $StreamSize_old)) {
# New converted file has been converted but with up to max 20 seconds deviation!
Write-Host "Conversion Done! - But streamsize is not the same. - Please review!"
Write-Host
Write-Host "------------------------------------------------------------------------------------------------"
$review = $true
$convertedVideos = $convertedVideos + 1
$Logfile = "$PSScriptRoot\logs\$logFolderName\review_needed.log"
LogWrite "$inputFile,$outputFile"
}
else {
if ($forceReviewAll) {
# Mark probably corrupted file for review
Write-Host "Conversion Failed! - Marked for review! because it is desired."
Write-Host
Write-Host "------------------------------------------------------------------------------------------------"
$review = $true
$convertedVideos = $convertedVideos + 1
$Logfile = "$PSScriptRoot\logs\$logFolderName\review_needed.log"
LogWrite "$inputFile,$outputFile"
}
else {
# Delete obviously 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,$StreamSize_new,$StreamSize_old,"
}
}
}
}
}
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 #
#############################################################################################################
if ($review) {
$reviewFiles = Get-content -LiteralPath "$PSScriptRoot\logs\$logFolderName\review_needed.log" | Measure-Object Line
$ReviewCount = $reviewFiles.Lines
Write-Host "There are $ReviewCount files to review.." -ForegroundColor Yellow
Read-Host -Prompt "Press Enter to start reviewing first file"
Write-Host
Write-Host "################################################################################################"
$review_count = 1
foreach ($review_pair in Get-Content -LiteralPath "$PSScriptRoot\logs\$logFolderName\review_needed.log") {
$oldFile, $newFile = $review_pair.split(',')
Write-Host "Playing $review_count converted file: $newFile"
Write-Host
# Starting VLC Player with the file to review
Start-Process $reviewPlayer -ArgumentList `"$newFile`"
Start-Sleep -Seconds 6
# Wait until player is closed.
$processID = (Get-Process "vlc").id
Wait-Process -Id $processID
$msg = 'Do you want to keep the newly converted file and delete the old? (N for deleting NEW-file) [Y/N]'
do {
$response = Read-Host -Prompt $msg
} until (($response -eq 'n') -or ($response -eq 'y'))
if ($response -eq 'y') {
Write-Host "delete old file, keep newly converted.."
$to_delete = $oldFile
}
else {
Write-Host "delete newly converted, keep old file"
$to_delete = $newFile
$failedVideos = $failedVideos + 1
$convertedVideos = $convertedVideos - 1
}
Write-Host "DELETED: $to_delete" -ForegroundColor Red
Remove-Item -LiteralPath $to_delete
Write-Host "------------------------------------------------------------------------------------------------"
Start-Sleep -Seconds 2
}
}
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