Skip to content

Commit

Permalink
Improve error handling for progress
Browse files Browse the repository at this point in the history
Moved Watch-ScriptTerminated to its own function as well
  • Loading branch information
patrickenfuego committed Aug 21, 2022
1 parent bc66ce7 commit 8f3c6bb
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 48 deletions.
58 changes: 20 additions & 38 deletions modules/FFTools/Private/Write-EncodeProgress.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -31,53 +31,35 @@ function Write-EncodeProgress {
[bool]$DolbyVision
)

<#
.SYNOPSIS
Watches for CTRL+C interrupts and clean exits all running jobs and scripts
#>
function Watch-ScriptTerminated ([string]$Message) {
if ($Host.UI.RawUI.KeyAvailable -and ($Key = $Host.UI.RawUI.ReadKey("AllowCtrlC,NoEcho,IncludeKeyUp"))) {
# If user hits Ctrl+C
if ([int]$Key.Character -eq 3) {
Write-Progress "Terminated" -Completed
Write-Warning "CTRL+C was detected - shutting down all running jobs before exiting the script"
# Clean up all running jobs before exiting
Get-Job | Stop-Job -PassThru | Remove-Job -Force -Confirm:$false

$psReq ? (Write-Host "$($aRed)$Message$($reset)") :
(Write-Host $Message @errColors)
$console.WindowTitle = $currentTitle
[console]::TreatControlCAsInput = $False
exit 77
}
# Flush the key buffer again for the next loop
$Host.UI.RawUI.FlushInputBuffer()
}
}

# Intercept ctrl+C for graceful shutdown of jobs
[console]::TreatControlCAsInput = $True
[console]::TreatControlCAsInput = $true
Start-Sleep -Milliseconds 500
$Host.UI.RawUI.FlushInputBuffer()

if ($PSBoundParameters['TestFrames']) {
$frameCount = $TestFrames
$frame['FrameCount'] = $TestFrames
}
# Gather total frame count without demuxing
else {
if (!$SecondPass) {
Write-Progress "Gathering frame count for progress display..."
$frameStr = ffmpeg -hide_banner -i $InputFile -map 0:v:0 -c:v copy -f null - 2>&1
}
elseif (!$SecondPass -or ($frame['FrameCount'] -le 0)) {
Write-Progress "Gathering frame count for progress display..."
$frameStr = ffmpeg -hide_banner -i $InputFile -map 0:v:0 -c:v copy -f null - 2>&1

# Select-String does not work on this output for some reason?
$tmp = $frameStr | Select-Object -Index ($frameStr.Count - 2)
[int]$frameCount = $tmp |
[int]$frame['FrameCount'] = $tmp |
Select-String -Pattern '^frame=\s*(\d+)\s.*' |
ForEach-Object { $_.Matches.Groups[1].Value }

if (!$frameCount) {
Write-Progress "Could not retrieve frame count" -Completed
return
if (!$frame['FrameCount']) {
Write-Progress "Error" -Completed
$msg = "Failed to parse frame count from string"
$PSCmdlet.ThrowTerminatingError(
[System.Management.Automation.ErrorRecord]::new(
([System.ArgumentNullException]$msg),
'frame',
[System.Management.Automation.ErrorCategory]::InvalidResult,
$frame['FrameCount']
)
)
}
}

Expand Down Expand Up @@ -123,9 +105,9 @@ function Write-EncodeProgress {
}

if ($currentFrame -and $fps) {
$progress = ($currentFrame / $frameCount) * 100
$progress = ($currentFrame / $frame['FrameCount']) * 100
$status = '{0:N1}% Complete' -f $progress
$activity = "Encoding Frame $currentFrame of $frameCount, $('{0:N2}' -f $fps) FPS"
$activity = "Encoding Frame $currentFrame of $($frame['FrameCount']), $('{0:N2}' -f $fps) FPS"

$params = @{
PercentComplete = $progress
Expand Down
86 changes: 76 additions & 10 deletions modules/FFTools/Public/Invoke-FFMpeg.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,10 @@ function Invoke-FFMpeg {
[switch]$DisableProgress
)

# Writes the banner information during encoding
<#
.SYNOPSIS
Writes the banner information during encoding
#>
function Write-Banner {
if ($TestFrames) {
$startStr = switch -Wildcard ($TestStart) {
Expand Down Expand Up @@ -247,6 +250,31 @@ function Invoke-FFMpeg {
}
}

<#
.SYNOPSIS
Wait for encode jobs to finish if progress bar returns an error
.DESCRIPTION
If the progress bar function returns an error, this function will wait for the job
to complete while intercepting CTRL+C and gracefully exiting if needed
#>
function Wait-Completed ($JobName, $Exception) {
Write-Host "ERROR: The progress bar failed to initialize`n" @errColors
Write-Verbose "ERROR: $($Exception.Message)"
Write-Verbose "LINE: $($Exception.InvocationInfo.ScriptLineNumber)"

# Intercept ctrl+C for graceful shutdown of jobs
[console]::TreatControlCAsInput = $true
Start-Sleep -Milliseconds 500
$Host.UI.RawUI.FlushInputBuffer()

while ((Get-Job -Name $JobName).State -ne 'Completed') {
Watch-ScriptTerminated -Message $exitBanner
Start-Sleep -Milliseconds 750
}

return
}

# Infer primary language based on streams (for muxing) - NOT always accurate, but pretty close
$streams = ffprobe $Paths.InputFile -show_entries stream=index:stream_tags=language `
-select_streams a -v 0 -of compact=p=0:nk=1
Expand Down Expand Up @@ -279,7 +307,8 @@ function Invoke-FFMpeg {
$HDR = Get-HDRMetadata @params
}
catch [System.ArgumentNullException] {
Write-Host "`u{203C} Failed to get HDR metadata: $($_.Exception.Message). Metadata will not be copied" @errColors
$err = $_.Exception.Message
Write-Host "`u{203C} Failed to get HDR metadata: $err. Metadata will not be copied" @errColors
$HDR = $null
}
}
Expand Down Expand Up @@ -397,7 +426,13 @@ function Invoke-FFMpeg {
RCLookahead = $RCLookahead
}
# Set preset based arguments based on user input
$presetParams = Set-PresetParameters -Settings $presetArgs -Preset $Preset -Encoder $Encoder -Verbose:$setVerbose
$params = @{
Settings = $presetArgs
Preset = $Preset
Encoder = $Encoder
Verbose = $setVerbose
}
$presetParams = Set-PresetParameters @params
Write-Verbose "PRESET PARAMETER VALUES:`n$($presetParams | Out-String)`n"

<#
Expand Down Expand Up @@ -558,7 +593,12 @@ function Invoke-FFMpeg {
DolbyVision = $dovi
Verbose = $setVerbose
}
Write-EncodeProgress @params
try {
Write-EncodeProgress @params
}
catch {
Wait-Completed -JobName '1st Pass' -Exception $_.Exception
}
}

Write-Host
Expand All @@ -584,7 +624,12 @@ function Invoke-FFMpeg {
DolbyVision = $dovi
Verbose = $setVerbose
}
Write-EncodeProgress @params
try {
Write-EncodeProgress @params
}
catch {
Wait-Completed -JobName '2nd Pass' -Exception $_.Exception
}
}
}
# CRF/One pass x265 encode
Expand Down Expand Up @@ -625,7 +670,12 @@ function Invoke-FFMpeg {
DolbyVision = $dovi
Verbose = $setVerbose
}
Write-EncodeProgress @params
try {
Write-EncodeProgress @params
}
catch {
Wait-Completed -JobName 'crf' -Exception $_.Exception
}
}
}
# Mux/convert audio and subtitle streams separately from elementary hevc stream
Expand Down Expand Up @@ -727,7 +777,12 @@ function Invoke-FFMpeg {
Verbose = $setVerbose
DolbyVision = $dovi
}
Write-EncodeProgress @params
try {
Write-EncodeProgress @params
}
catch {
Wait-Completed -JobName 'ffmpeg 1st Pass' -Exception $_.Exception
}
}
}

Expand All @@ -753,7 +808,12 @@ function Invoke-FFMpeg {
Verbose = $setVerbose
DolbyVision = $dovi
}
Write-EncodeProgress @params
try {
Write-EncodeProgress @params
}
catch {
Wait-Completed -JobName 'ffmpeg 2nd Pass' -Exception $_.Exception
}
}
}
# CRF encode
Expand Down Expand Up @@ -792,8 +852,9 @@ function Invoke-FFMpeg {
}
# Should be unreachable. Throw error and exit script if rate control cannot be detected
else {
$msg = 'Rate control method could not be determined from input parameters'
$params = @{
Exception = [System.FieldAccessException]::new('Rate control method could not be determined from input parameters')
Exception = [System.FieldAccessException]::new($msg)
Category = 'InvalidResult'
TargetObject = $RateControl
ErrorId = 101
Expand Down Expand Up @@ -821,7 +882,12 @@ function Invoke-FFMpeg {
DolbyVision = $dovi
Verbose = $setVerbose
}
Write-EncodeProgress @params
try {
Write-EncodeProgress @params
}
catch {
Wait-Completed -JobName 'ffmpeg' -Exception $_.Exception
}
}

# Remove ffmpeg jobs
Expand Down

0 comments on commit 8f3c6bb

Please sign in to comment.