Page 1 of 1

Help with automated powershell script

Posted: Mon Mar 28, 2016 6:27 am
by FuSiOn
I am working on a PS script to monitor a folder for large video files if detected it will auto convert the file.
I learned a bit of PS for the soul purpose of making this automating script so I am a big nub at PS

this is the code so far:

Code: Select all

$Folder               = "E:\Series"                                   #Folder to be monitored for large video files.
$global:Output        = "E:\Encoded"                                  #Folder where encoding jobs go to, and that will be monitored for completed jobs to replace the original file with.
$global:MaxMB         = 15                                             #Max MB a minute
$global:Elapsed       = 0                                             #Variabel to store elapesed time of the convertion process.
$global:CurrentEncode = ""                                            #Loction to the current encoding job
$global:EstimateSize  = ""                                            #Estimeated file size
$global:LastSizeCheck = ""                                            #Last time the file size whas checked
$global:Rep_Source    = $true                                         #whether or not to replace the source with the output.
$global:MI_CLI        = "C:\Program Files\MediaInfoCLI\MediaInfo.exe" #Location of MediaInfoCLI
$global:HB_CLI        = "C:\Program Files\Handbrake\HandBrakeCLI.exe" #Location of HandBrakeCLI
$global:HB_Container  = "Copy"                                        #HandBrake container output(Copy,mp4,mkv) copy only works when the source is mp4 or mkv
$global:HB_Audio      = "Copy"                                        #Audio format for the output file
$global:HB_aBitRate   = 192                                           #Audio Bitrate
$global:HB_Width      = "Copy"                                        #The Width for the video to be converted.
$global:HB_ConstQ     = 20                                            #Constant Quality value 
$global:HB_Codec      = "x265"                                        #Codec used to convert file(Copy,x264,x265) copy only works when the source is x264 or x265
$global:Kodi_URI      = "http://127.0.0.1:8080/jsonrpc"               #URL of kodi webserver if password protected then add to url ex. "http://USERNAME:PASSWORD@127.0.0.1:8080/jsonrpc"
$global:Kodi_Notify   = $true                                         #Wheter or not script should send a notification on new and completed converions to kodi
$global:kodi_IMG      = "https://handbrake.fr/img/logo.png"           #Image displayed in the notification

$Filter        = '*.*'
$fsw = New-Object IO.FileSystemWatcher $Folder, $Filter 
$fsw.IncludeSubdirectories = $true
$fswOnChange = Register-ObjectEvent $fsw Changed -SourceIdentifier FileUpdated -Action {
    Start-Sleep -s 2
    $FilePath =  $EventArgs.FullPath
    $DirPath  =  $FilePath.Split('\')
    $DirPath  =  $DirPath[0..($DirPath.Length - 2)] -join "\" 
    $FileName =  $FilePath.Split('\')[-1]
    if($FilePath -imatch '\.(?:mp4|mkv)$'){
        $Converted = if(Test-Path -LiteralPath "$Output\Converted.log"){Get-Content "$Output\Converted.log"}
        if((Test-Path -LiteralPath $filePath) -and -not ((Test-Path -LiteralPath "$Output\$FileName") -or $Converted -contains $FileName)){
            if(Test-FileReady $FilePath){
                $MediaInfo  = Get-MediaInfo $FilePath
                $Size       = $MediaInfo.General.FileSize
                $SizeString = $MediaInfo.General.FileSizeString4
                $Duration   = $MediaInfo.General.Duration
                $TimeFormat = if($Duration -ge 36e5){"hh\h\mm\mss\s"}else{"mm\mss\s"}
                $Resolution = $MediaInfo.Video.Width + "x" + $MediaInfo.Video.Height
                $Source_MBm = [math]::Round(($Size / ($Duration / 6e4)) / 1MB, 2)
                if($Source_MBm -gt $MaxMB){
                    $global:CurrentEncode = "$Output\$FileName"
                    Set-CrusorPosistionX 0
                    Write-Host  "Large Video Detected: `"$($FileName)`""
                    Write-Host  "`t$((Get-Date).DateTime)"
                    Write-Color "`tSource:::White $SizeString | $(Format-Time $Duration $TimeFormat) | $Source_MBm MiB/m | $Resolution::Gray"
                    Write-Host  "`tSending To HandBrake..."
                    if($Kodi_Notify){Notify-Kodi -Title "New Convertion Started." -Message $FileName -IMG $kodi_IMG -URI $Kodi_URI}
                    HB-Convert $FilePath $Output
                    $Completed = (Get-Content $Output\$($FileName -replace `"\[|\]`", `"`").log) -match 'encoded.*?'
                    if($Completed){
                        $time       = [int]((([regex]::matches($completed, "\d+(?:\.\d+)?s") | %{$_.value}) -replace "[s.]","")) * 10
                        $time       = Format-Time $time $(if($time -eq 36e5){"hh\hmm\mss\s"}else{"mm\mss\s"})
                        $Completed  = $Completed -replace "\d+(?:\.\d+)?s" , $time -replace "^e", "E"
                        $MediaInfo  = Get-MediaInfo "$Output\$FileName"
                        $Size       = $MediaInfo.General.FileSize
                        $SizeString = $MediaInfo.General.FileSizeString4
                        $Duration   = $MediaInfo.General.Duration
                        $TimeFormat = if($Duration -ge 3600000){"hh\h\mm\mss\s"}else{"mm\mss\s"}
                        $Resolution = $MediaInfo.Video.Width + "x" + $MediaInfo.Video.Height
                        $MBm        = [math]::Round(($MediaInfo.General.FileSize / ($MediaInfo.General.Duration / 6e4)) / 1MB,2)
                        $FileName >> "$Output\Converted.log"
                        $global:CurrentEncode = ""
                        $global:EstimateSize  = ""
                        $global:LastSizeCheck = ""   
                        Set-CrusorPosistionX 0
                        Write-Host  "`t$Completed$(`" `" * 30)"
                        Write-Color "`tOutput:::White $SizeString | $(Format-Time $Duration $TimeFormat) | $MBm MiB/m | $Resolution::Gray"
                        Write-Host  "`tReplacing source with output..."
                        if($Rep_Source){Move-Item   "$Output\$FileName" $DirPath -force}
                        Write-Host  "`tConversion Completed!`n" -ForegroundColor White
                        if($Kodi_Notify)  {Notify-Kodi -Title "Convertion Completed." -Message $FileName -IMG $kodi_IMG -URI $Kodi_URI}
                    }else{ 
                        $global:CurrentEncode = ""
                        $global:EstimateSize  = ""
                        $global:LastSizeCheck = ""   
                        Write-Host  "`n`tFailed to convert file!!! Check log for more details.`n" -ForegroundColor DarkRed
                        if($Kodi_Notify){Notify-Kodi -Title "Convertion Failed." -Message $FileName -IMG $kodi_IMG -URI $Kodi_URI}
                    }
                }
            }#else{Set-CrusorPosistionX 0;write-host "File IS LOCKED"}
        }
    }
}

function global:HB-Convert{
    param ( [parameter(Mandatory=$true)][string]$source,
            [parameter(Mandatory=$true)][string]$dest )
    if(-not (Test-Path -LiteralPath $source) -or -not (Test-Path -LiteralPath $dest)) {return}
    $FileName =  $source.split('\')[-1]
    $LogFile  = "$dest\$($FileName -replace `"\[|\]`", `"`").log"
    & $HB_CLI -i `"$source`" -o `"$dest\$FileName`" -f mkv -w 1280 --crop 0:0:0:0 --loose-anamorphic --modulus 2 -e $HB_Codec -q $HB_ConstQ --vfr -a 1 -E $HB_Audio -6 dpl2 -R Auto -B $HB_aBitRate -D 0 --gain 0 --audio-fallback ac3 --encoder-preset=faster --verbose=0 2> "$LogFile" | HB-UpdateProgress
}

function global:HB-UpdateProgress{
  Process{
    $Progress   = @($input)[0]
    $Percentage = ([regex]"(\d+(?:\.\d+)?)\s%").Matches($Progress) | select Groups
    if($Percentage -and $CurrentEncode){
        $Percentage  = $Percentage.Groups[1].Value
        $Round       = [Math]::Floor($Percentage)
        if(($Round %5 -eq 0) -and ($Round -ne 0) -and ($LastSizeCheck -ne $Round)){
            if(Test-Path -LiteralPath $CurrentEncode){
                $EFS  = [math]::Round((((Get-Item $CurrentEncode).length / 1MB) / $Percentage) * 100, 2)
                if($EFS -ge 1GB){
                    $EFS = [string]([math]::Round($EFS / 1GB, 2)) + " GiB"
                }else{
                    $EFS = ", EFS $EFS MiB"
                }
                $global:EstimateSize  = $EFS
                $global:LastSizeCheck = $Round
            }
        }
    }
    $Progress   = ($Progress -replace "00h|00m|task 1 of 1, ", "") -replace "\)", "$EstimateSize)"
    $CharCount  = $Progress.length
    $WhiteSpace = " " * (80 - $CharCount)
    Set-CrusorPosistionX 0
    Write-Host "`t$Progress$WhiteSpace" -NoNewline -ForegroundColor White
  }
}

function global:Set-CrusorPosistionX{
    Param([parameter(Mandatory=$true)][int]$X)
    $position = $host.ui.rawui.cursorposition
    $position.X = $X
    $host.ui.rawui.cursorposition = $position
}

function global:Set-CrusorPosistionY{
    Param([parameter(Mandatory=$true)][int]$Y)
    $position = $host.ui.rawui.cursorposition
    $position.Y = $Y
    $host.ui.rawui.cursorposition = $position
}

function global:Test-FileReady {
    Param([parameter(Mandatory=$true)]$path)
    if (Test-Path  -LiteralPath $path) {
      trap {
        return $false
      }
      $stream = New-Object system.IO.StreamReader $path
      if ($stream) {
        $stream.Close()
        return $true
      }
    }
}

function global:Notify-Kodi{
    param( [parameter(Mandatory=$true)][string]$Title,
           [parameter(Mandatory=$true)][string]$Message,
           [parameter(Mandatory=$true)][string]$IMG,
           [parameter(Mandatory=$true)][string]$URI )
    $body = "[{`"jsonrpc`": `"2.0`", `"params`": {`"image`": `"$IMG`", `"title`": `"$Title`" , `"message`": `"$Message`"}, `"method`": `"GUI.ShowNotification`", `"id`": `"HandBrake`"}]"
    Invoke-RestMethod -Method Post -Uri $URI -Body $body -Header @{"Content-Type"="application/json"}
}

Function global:Format-Time {
    param ( [parameter(Mandatory=$true)][int]$MilliSeconds,
            [Parameter(Mandatory=$false)][string]$Format ='hh\:mm\:ss' )
    Return [timespan]::FromMilliseconds($MilliSeconds).ToString($Format)
}

function global:Get-MediaInfo{
    param ([parameter(Mandatory=$true)][string]$source)
    if(-not (Test-Path -LiteralPath $source)){return ""}
    $rawInfo   = & $MI_CLI `"$source`"  --Language=raw --Full
    if(-not $rawInfo){return ""}
    $rawInfo   = $rawInfo -split '[\r\n]'
    $MediaInfo = @{}
    $type      = ""
    for ($i=0; $i -lt $rawInfo.length; $i++) {
	    $info = $rawInfo[$i] -split ':'
        if($info.length -eq 1){
            $type = $info[0].trim()
            if(-not $type){continue}
            $MediaInfo[$type] = @{}
            continue
        }
        $words = $info[0].trim() -split "[\s(/)]"
        if($words.length -gt 1){
            $info[0] = ''
            foreach($word in $words){
               if($word -and $word.length -gt 1){
                   $info[0] += $word.substring(0,1).toupper() + $word.substring(1).tolower() 
               }elseif($word -and $word.length -eq 1){
                   $info[0] += $word
               }
            }
        }
        $MediaInfo[$type][$info[0].trim()] = $info[1].trim()
    }
    return $MediaInfo
}

function global:Write-Color{
       param ([parameter(Mandatory=$true)][string]$Message)
       $MessageArray =  $Message -split("::\w+")
       $ColorsArray  =  ([regex]"::\w+").Matches($Message) | select value
       if($MessageArray.Length -gt 1){
           for($i=0; $i -le $ColorsArray.Length - 1; $i++){
              write-host $MessageArray[$i]  -ForegroundColor ($ColorsArray[$i].value -replace "::","") -NoNewline
           }
           Write-Host
       }
}

Write-Host "When HandBrake is converting hit 'p' to pauze and 'r' to resume."
Write-Host "Monitoring folder `"$Folder`" for large video files...`n"

the script works like it should the problem is when HandBrakeCLI is called it outputs all info not just the progress of the encoding.
Anyone that can help me on what I am doing wrong here? It would be much appreciated .

Re: Help with automated powershell script

Posted: Wed Mar 30, 2016 5:41 pm
by FuSiOn
ok i got it to work now.


Adding this to the script.

Code: Select all

function global:HB-UpdateProgress{
  Process{
    $Progress   = @($input)[0]
    $CharCount  = $Progress.length
    $WhiteSpace = " " * (80 - $CharCount)
    Set-CrusorPosistionX 0
    Write-Host "`t$Progress$WhiteSpace" -NoNewline -ForegroundColor DarkCyan
  }
}

And then calling handbrakeCLI with "&" will display only the progress.

Re: Help with automated powershell script

Posted: Wed Apr 06, 2016 2:52 pm
by virgilfox
Have you considered using the Write-Progress cmdlet in Powershell?

http://discoposse.com/2012/10/07/its-al ... ss-cmdlet/