diff --git a/spav1an.ps1 b/spav1an.ps1 index dadddac..72ec5d5 100644 --- a/spav1an.ps1 +++ b/spav1an.ps1 @@ -12,7 +12,7 @@ param ( [String] $AnalyzeVidSize = "848x480", [String] $AnalyzeVidEnc = "-hide_banner -loglevel error -stats -i {0} -map 0:0 -vf zscale={1}:f=spline36 -vcodec libx264 -preset veryfast -crf 40 -x264-params keyint={2}:min-keyint=5:scenecut=60 -y -pix_fmt yuv420p {3}", [String] $AvisynthScript = "LSMASHVideoSource({0})", - [String] $EncoderOptions = "--cpu-used=8 --passes=1 --target-bitrate=20000 --rt --limit={1} --fps={2} -o {0} -", + [String] $EncoderOptions = "--cpu-used=8 --passes=1 --target-bitrate=1000 --rt", [parameter(Position=0)] [String] $InputFile = "" ) $ErrorActionPreference = "Stop" @@ -384,7 +384,7 @@ function Start-ProcessJobItem([ProjectContext] $context, [ProjectChunkData] $pro } $identifier1 = '5BdMoB52CQyrNYEof3gARsbLgsTjZCdqF9' - $encoderparameters = $EncoderOptions -f $identifier1, ($projectitem.end - $projectitem.start + 1), $context.fps + $encoderparameters = ($EncoderOptions + " --limit={1} --fps={2} -o {0} -") -f $identifier1, ($projectitem.end - $projectitem.start + 1), $context.fps $encoderargs = Rename-ArrayIdentifiers $encoderparameters.Split(' ') $identifier1 $projectitem.filename # Write-Host ("Encoding chunk " + ($chunkformat -f $projectitem.index, $project.Count) + " " + $projectitem.start + ' - ' + $projectitem.end + ' (' + ($projectitem.end - $projectitem.start + 1) + ')') @@ -413,10 +413,12 @@ function Watch-JobsUntilFinishes([ProjectContext] $context, [System.Collections. throw "Error during muxing" } + $consolewidth = [Math]::Max($Host.UI.RawUI.WindowSize.Width, 0) [Console]::SetCursorPosition(0, [Math]::Max($Host.UI.RawUI.CursorPosition.Y - $activeworkers.Count - 2, 0)) for ($x = 0; $x -lt $activeworkers.Count; $x++) { if ($null -eq $activeworkers[$x].job) { + Write-Host (("{0,-" + [Math]::Max($Host.UI.RawUI.WindowSize.Width - 1, 0) + "}") -f ("Worker {0} done" -f ($x + 1))) continue } @@ -458,19 +460,29 @@ function Watch-JobsUntilFinishes([ProjectContext] $context, [System.Collections. $howisitgoing = ("{0:" + $framechunk + "}/{1:" + $framechunk + "}") -f $context.framesfinished, $context.framestotal - $howisitgoing += " [{0,-30}]" -f ('#' * [Math]::Floor(($context.framesfinished/$context.framestotal) * 30)) + $howisitgoing += " [{0,-30}]" -f ('#' * [Math]::Floor(($context.framesfinished/$context.framestotal) * 30)) - $howisitgoing += (" Muxed {0:" + $context.countformat + "}/{1:" + $context.countformat + "}") -f $context.muxernextindex, $context.chunkstotal + $howisitgoing += (" Muxed {0:" + $context.countformat + "}/{1:" + $context.countformat + "}") -f $context.muxernextindex, $context.chunkstotal if ($context.muxerjob.State -ne 'Completed') { - $howisitgoing += " Muxing " + $context.muxerjob.State + ": " + ($context.muxerjob.Output | Select-Object -Last 3) + $lastmessage = $context.muxerjob.Output | Select-Object -Last 1 + if ($lastmessage) { + $howisitgoing += " Muxing " + $lastmessage + } + } + + if ($howisitgoing.Length -gt ($consolewidth - 1)) { + $howisitgoing = $howisitgoing.Substring(0, $consolewidth - 1) } - Write-Host (("{0,-" + [Math]::Max($Host.UI.RawUI.WindowSize.Width - 1, 0) + "}") -f " ") - Write-Host (("{0,-" + [Math]::Max($Host.UI.RawUI.WindowSize.Width - 1, 0) + "}") -f $howisitgoing) + Write-Host (("{0,-" + $consolewidth + "}") -f " ") + Write-Host (("{0,-" + $consolewidth + "}") -f $howisitgoing) if ($workerFinished) { break } + if ($context.muxerjob.State -eq 'Completed' -and $context.muxernextindex -ge $project.Count) { + break + } Start-Sleep 1 } return $finishedForMuxing @@ -479,8 +491,11 @@ function Watch-JobsUntilFinishes([ProjectContext] $context, [System.Collections. function Start-Muxing([ProjectContext] $context, [System.Collections.Generic.List[ProjectChunkData]] $project) { [System.Collections.ArrayList]$segmentstomux = @() + $lastmuxed = $null + if ($context.muxernextindex -gt 0) { - $segmentstomux.Add(("{0}[{1}].webm" -f $context.fileprefix, $context.muxernextindex)) | Out-Null + $segmentstomux.Add((("{0}({1:" + $context.countformat + "}).webm") -f $context.fileprefix, $context.muxernextindex)) | Out-Null + $lastmuxed = $segmentstomux[0] } for ($i = $context.muxernextindex; $i -lt $project.Count; $i++) { @@ -494,14 +509,19 @@ function Start-Muxing([ProjectContext] $context, [System.Collections.Generic.Lis } } - $targetfile = "{0}[{1}].webm" -f $context.fileprefix, $context.muxernextindex + $targetfile = ("{0}({1:" + $context.countformat + "}).webm") -f $context.fileprefix, $context.muxernextindex - $context.muxerjob = Start-ThreadJob -ArgumentList @($targetfile, $segmentstomux) -ScriptBlock { + $context.muxerjob = Start-ThreadJob -ArgumentList @($targetfile, $segmentstomux, $lastmuxed) -ScriptBlock { cmd.exe /C ("mkvmerge.exe -w --flush-on-close -o `"" + $args[0] + "`" [ " + $args[1] + " ]") if ($lastExitCode -gt 0) { throw } - Start-Sleep 5 + if ($args[2]) { + Remove-Item -Force $args[2] + } + for ($x = 0; $x -lt $args[1].Count; $x++) { + Remove-Item -Force $args[1][$x] + } } } @@ -538,6 +558,12 @@ function Start-OurEncoding { } $context.framestotal = $project[$project.Count - 1].end + 1 + $context.fps = $projectraw.fps + $context.nextchunkindex = 0 + $context.muxernextindex = 0 + $context.muxerinqueue = 0 + $context.chunkstotal = $project.Count + $context.muxerjob = Start-ThreadJob -ScriptBlock {} $activeworkers = New-Object 'System.Collections.Generic.List[ProjectChunkData]' for ($i = 0; $i -lt $Threads; $i++) { @@ -545,13 +571,36 @@ function Start-OurEncoding { } Write-Host "Checking for existing files" + $removed = 0 $files = Get-ChildItem -Path './' for ($i = 0; $i -lt $files.Count; $i++) { if ($files[$i].Name.StartsWith($context.fileprefix + '_')) { - Write-Host "Removing:", $files[$i].Name - Remove-Item $files[$i] + $removed++ + Remove-Item -Force $files[$i] + } elseif ($files[$i].Name.StartsWith($context.fileprefix + '(')) { + try { + $mymatches = $files[$i].Name | Select-String -Pattern '\((\d+)\)' + $checkmuxerprevious = [int]$mymatches.Matches[0].Groups[1].Value + if ($context.muxernextindex -eq 0 -or $checkmuxerprevious -lt $context.muxernextindex) { + $context.muxernextindex = [int]$mymatches.Matches[0].Groups[1].Value + $context.nextchunkindex = $context.muxernextindex + Write-Host ("Continuing from previous session from {0}" -f $context.muxernextindex) + } else { + Write-Host ("Removing {0} as we found existing smaller index to continue from of {1}" -f $files[$i].Name, $context.muxernextindex) + $removed++ + Remove-Item -Force $files[$i].Name + } + } catch { + throw ("Unable to continue from previous run, unable to read " + $files[$i].Name) + } } } + if ($removed -gt 0) { + Write-Host ("Removed {0} existing files" -f $removed) + } + for ($i = 0; $i -lt $context.nextchunkindex; $i++) { + $context.framesfinished += ($project[$i].end - $project[$i].start) + 1 + } Write-Host "Starting our chunk encoder with maximum $Threads workers" for ($x = 0; $x -lt $activeworkers.Count; $x++) { @@ -559,13 +608,6 @@ function Start-OurEncoding { } Write-Host "" Write-Host "" - - $context.chunkstotal = $project.Count - $context.fps = $projectraw.fps - $context.nextchunkindex = 0 - $context.muxernextindex = 0 - $context.muxerinqueue = 0 - $context.muxerjob = Start-ThreadJob -ScriptBlock {} # repeat until done while ($true) { @@ -587,8 +629,14 @@ function Start-OurEncoding { # print progress until an item finishes Watch-JobsUntilFinishes $context $activeworkers + + if ($context.muxerjob.State -eq 'Completed' -and $context.muxernextindex -ge $project.Count) { + break + } } + Move-Item (("{0}({1:" + $context.countformat + "}).webm") -f $context.fileprefix, $context.muxernextindex) ("{0}_finished.webm" -f $context.fileprefix) + Write-Host "Finished" } diff --git a/test_output(121).webm b/test_output(121).webm new file mode 100644 index 0000000..b07d831 Binary files /dev/null and b/test_output(121).webm differ diff --git a/test_output_125.ivf b/test_output_125.ivf new file mode 100644 index 0000000..c6eff2a Binary files /dev/null and b/test_output_125.ivf differ