More development, added more robustness and error checking and cleaned output
This commit is contained in:
parent
4dce237600
commit
81ed27cd05
1 changed files with 48 additions and 17 deletions
65
spav1an.ps1
65
spav1an.ps1
|
@ -2,13 +2,14 @@ param (
|
||||||
[String] $EncoderPath = "aomenc-3.0.0-335.exe",
|
[String] $EncoderPath = "aomenc-3.0.0-335.exe",
|
||||||
[String] $FFmpegPath = "ffmpeg.exe",
|
[String] $FFmpegPath = "ffmpeg.exe",
|
||||||
[String] $FFprobePath = "ffprobe.exe",
|
[String] $FFprobePath = "ffprobe.exe",
|
||||||
|
[Switch] $PrintCommands,
|
||||||
[int] $EncoderType = 1, # Encoder type. 1 = aomenc, 2 = SVT-AV1
|
[int] $EncoderType = 1, # Encoder type. 1 = aomenc, 2 = SVT-AV1
|
||||||
[int] $Renderer = 1, # Frame type, 1 = ffmpeg native, 2 = avisynth
|
[int] $Renderer = 1, # Frame type, 1 = ffmpeg native, 2 = avisynth
|
||||||
[int] $MinChunkSec = 10,
|
[int] $MinChunkSec = 10,
|
||||||
[int] $Threads = 0,
|
[int] $Threads = 0,
|
||||||
[String] $Framerate = "auto",
|
[String] $Framerate = "auto",
|
||||||
[String] $AnalyzeVidSize = "848x480",
|
[String] $AnalyzeVidSize = "848x480",
|
||||||
[String] $AnalyzeVidEnc = "-hide_banner -loglevel info -i {0} -map 0:0 -vf zscale={1}:f=spline36 -vcodec libx264 -preset veryfast -crf 40 -x264-params keyint={2}:min-keyint=5:scenecut=40 -y -pix_fmt yuv420p {3}",
|
[String] $AnalyzeVidEnc = "-hide_banner -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] $AvisynthScript = "LSMASHVideoSource({0})",
|
||||||
[String] $EncoderOptions = "--cpu-used=8 --passes=1 --cq-level=10 --rt -o {0} -",
|
[String] $EncoderOptions = "--cpu-used=8 --passes=1 --cq-level=10 --rt -o {0} -",
|
||||||
[parameter(Position=0)] [String] $InputFile = ""
|
[parameter(Position=0)] [String] $InputFile = ""
|
||||||
|
@ -21,6 +22,7 @@ public struct KeyFrameData {
|
||||||
public int start;
|
public int start;
|
||||||
public int end;
|
public int end;
|
||||||
public decimal startstamp;
|
public decimal startstamp;
|
||||||
|
public int length;
|
||||||
}
|
}
|
||||||
"@
|
"@
|
||||||
|
|
||||||
|
@ -37,8 +39,6 @@ public class ProjectChunkData {
|
||||||
}
|
}
|
||||||
"@
|
"@
|
||||||
|
|
||||||
Write-Host ""
|
|
||||||
|
|
||||||
function Write-OurHelp {
|
function Write-OurHelp {
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "S. Powershell variant of av1an"
|
Write-Host "S. Powershell variant of av1an"
|
||||||
|
@ -60,6 +60,7 @@ function Write-OurHelp {
|
||||||
Write-Host " -Framerate auto Frame rate of the video. Auto will use ffprobe"
|
Write-Host " -Framerate auto Frame rate of the video. Auto will use ffprobe"
|
||||||
Write-Host " to autodect. Otherwise you can specify it using"
|
Write-Host " to autodect. Otherwise you can specify it using"
|
||||||
Write-Host " rate/scale"
|
Write-Host " rate/scale"
|
||||||
|
Write-Host " -PrintCommands Print all ffmpeg/ffprobe commands run and arguments"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "Analyze options:"
|
Write-Host "Analyze options:"
|
||||||
Write-Host "The analyze file will be used to generate scenecut changes as well as other"
|
Write-Host "The analyze file will be used to generate scenecut changes as well as other"
|
||||||
|
@ -83,6 +84,31 @@ function Assert-OurParameters {
|
||||||
Install-Module -Name ThreadJob -Scope CurrentUser
|
Install-Module -Name ThreadJob -Scope CurrentUser
|
||||||
Write-Host "Install complete"
|
Write-Host "Install complete"
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
$gobble = Invoke-NativeCommand -FilePath 'cmd' -ArgumentList ('/c', 'echo test') | Receive-RawPipeline
|
||||||
|
} catch {
|
||||||
|
Write-Host "Use-RawPipeline was not found, automatically installing for scope local user"
|
||||||
|
Install-Module -Name Use-RawPipeline -Scope CurrentUser
|
||||||
|
Write-Host "Install complete"
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$gobble = Invoke-NativeCommand -FilePath $FFprobePath -ArgumentList ('-loglevel', 'quiet', '-version') | Receive-RawPipeline
|
||||||
|
} catch {
|
||||||
|
Write-Error ("Error, unable to run or find $FFprobePath, make sure path or program exists. Error: " + $_.Exception.Message)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$gobble = Invoke-NativeCommand -FilePath $FFmpegPath -ArgumentList ('-loglevel', 'quiet', '-version') | Receive-RawPipeline
|
||||||
|
} catch {
|
||||||
|
Write-Error ("Error, unable to run or find $FFmpegPath, make sure path or program exists. Error: " + $_.Exception.Message)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$gobble = Invoke-NativeCommand -FilePath $EncoderPath -ArgumentList ('--help') | Receive-RawPipeline
|
||||||
|
} catch {
|
||||||
|
Write-Error ("Error, unable to run or find $EncoderPath, make sure path or program exists. Error: " + $_.Exception.Message)
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
$writehelp = $false
|
$writehelp = $false
|
||||||
|
|
||||||
if ($inputfile -eq "") {
|
if ($inputfile -eq "") {
|
||||||
|
@ -156,9 +182,12 @@ function Write-ProjectFile {
|
||||||
|
|
||||||
# Check if framerate is auto and grab it from the source file
|
# Check if framerate is auto and grab it from the source file
|
||||||
if ($Framerate -eq 'auto') {
|
if ($Framerate -eq 'auto') {
|
||||||
|
Write-Host "Framerate is auto, checking framerate from source"
|
||||||
$fpsPropeArgs = "-v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate $identifier1".Split(' ')
|
$fpsPropeArgs = "-v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate $identifier1".Split(' ')
|
||||||
$fpsPropeArgs = Rename-ArrayIdentifiers $fpsPropeArgs $identifier1 $InputFile
|
$fpsPropeArgs = Rename-ArrayIdentifiers $fpsPropeArgs $identifier1 $InputFile
|
||||||
|
if ($PrintCommands) { Write-Host "[Running] $FFprobePath $fpsPropeArgs" }
|
||||||
$Framerate = Invoke-NativeCommand -FilePath $FFprobePath -ArgumentList $fpsPropeArgs | Receive-RawPipeline
|
$Framerate = Invoke-NativeCommand -FilePath $FFprobePath -ArgumentList $fpsPropeArgs | Receive-RawPipeline
|
||||||
|
Write-Host "Framerate is: $Framerate"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Split the framerate (rate/scale) to their respective values and calculate
|
# Split the framerate (rate/scale) to their respective values and calculate
|
||||||
|
@ -180,25 +209,22 @@ function Write-ProjectFile {
|
||||||
$analyzeffmpegSplitted = Rename-ArrayIdentifiers $AnalyzeVidEnc.Split(' ') $identifier1 $InputFile $identifier2 $analyzefilename
|
$analyzeffmpegSplitted = Rename-ArrayIdentifiers $AnalyzeVidEnc.Split(' ') $identifier1 $InputFile $identifier2 $analyzefilename
|
||||||
|
|
||||||
Write-Host "Creating $analyzefilename to generate keyframe split data from"
|
Write-Host "Creating $analyzefilename to generate keyframe split data from"
|
||||||
Write-Host ""
|
|
||||||
Write-Host "$FFmpegPath $analyzeffmpegSplitted"
|
|
||||||
Write-Host ""
|
|
||||||
|
|
||||||
# Create our analyze file
|
# Create our analyze file
|
||||||
# Reason we use Invoke-NativeCommand is "ffmpeg.exe" if located in the same
|
# Reason we use Invoke-NativeCommand is "ffmpeg.exe" if located in the same
|
||||||
# folder as script will make the Invoke-Expression fail as it requires .\ in
|
# folder as script will make the Invoke-Expression fail as it requires .\ in
|
||||||
# front of it. Invoke-NativeCommand allows us to specify filepath and it will
|
# front of it. Invoke-NativeCommand allows us to specify filepath and it will
|
||||||
# run regardless
|
# run regardless
|
||||||
|
if ($PrintCommands) { Write-Host "[Running] $FFmpegPath $analyzeffmpegSplitted" }
|
||||||
# Invoke-NativeCommand -FilePath $FFmpegPath -ArgumentList $analyzeffmpegSplitted | Receive-RawPipeline
|
# Invoke-NativeCommand -FilePath $FFmpegPath -ArgumentList $analyzeffmpegSplitted | Receive-RawPipeline
|
||||||
Write-Host ""
|
|
||||||
|
|
||||||
Write-Host "Reading keyframe data from $analyzefilename"
|
Write-Host "Reading keyframe data from $analyzefilename"
|
||||||
Write-Host ""
|
|
||||||
$analyzekeyframefilename = $workproject + '_kf.txt'
|
$analyzekeyframefilename = $workproject + '_kf.txt'
|
||||||
|
|
||||||
# Start probing and analyzing our analyze file
|
# Start probing and analyzing our analyze file
|
||||||
$analyzePropeArgs = "-hide_banner -show_entries packet=pts_time,flags -select_streams v:0 -of csv=print_section=0 $identifier1".Split(' ')
|
$analyzePropeArgs = "-loglevel error -hide_banner -show_entries packet=pts_time,flags -select_streams v:0 -of csv=print_section=0 $identifier1".Split(' ')
|
||||||
$analyzePropeArgs = Rename-ArrayIdentifiers $analyzePropeArgs $identifier1 $InputFile
|
$analyzePropeArgs = Rename-ArrayIdentifiers $analyzePropeArgs $identifier1 $analyzefilename
|
||||||
|
if ($PrintCommands) { Write-Host "[Running] $FFprobePath $analyzePropeArgs" }
|
||||||
$videodata = Invoke-NativeCommand -FilePath $FFprobePath -ArgumentList $analyzePropeArgs | Receive-RawPipeline
|
$videodata = Invoke-NativeCommand -FilePath $FFprobePath -ArgumentList $analyzePropeArgs | Receive-RawPipeline
|
||||||
|
|
||||||
# Invoke-Expression ".\$FFprobePath -hide_banner -show_entries packet=pts_time,flags -select_streams v:0 -of csv=print_section=0 $analyzefilename > $analyzekeyframefilename"
|
# Invoke-Expression ".\$FFprobePath -hide_banner -show_entries packet=pts_time,flags -select_streams v:0 -of csv=print_section=0 $analyzefilename > $analyzekeyframefilename"
|
||||||
|
@ -210,7 +236,9 @@ function Write-ProjectFile {
|
||||||
for ($i = 0; $i -lt $videodata.Length; $i++) {
|
for ($i = 0; $i -lt $videodata.Length; $i++) {
|
||||||
$split = $videodata[$i].Split(',')
|
$split = $videodata[$i].Split(',')
|
||||||
if ($split.Count -gt 1 -and $split[1][0] -eq 'K') {
|
if ($split.Count -gt 1 -and $split[1][0] -eq 'K') {
|
||||||
$keyframes.Add((New-Object KeyFrameData -Property @{ start = $i; startstamp = [convert]::ToDecimal($split[0]) }))
|
$keyframes.Add((New-Object KeyFrameData -Property @{
|
||||||
|
start = $i;
|
||||||
|
startstamp = [convert]::ToDecimal($split[0]) }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,9 +258,11 @@ function Write-ProjectFile {
|
||||||
if ($length -gt $maxkeyint) {
|
if ($length -gt $maxkeyint) {
|
||||||
if ($keyframes[$i - 1].start - 1 -gt $start.start) {
|
if ($keyframes[$i - 1].start - 1 -gt $start.start) {
|
||||||
$start.end = $keyframes[$i - 1].start - 1
|
$start.end = $keyframes[$i - 1].start - 1
|
||||||
|
$start.length = $start.end - $start.start
|
||||||
$next = $keyframes[$i - 1]
|
$next = $keyframes[$i - 1]
|
||||||
if ($start.end - $start.start -lt $maxkeyint / 2) {
|
if ($start.end - $start.start -lt $maxkeyint / 2) {
|
||||||
$start.end = $keyframes[$i].start - 1
|
$start.end = $keyframes[$i].start - 1
|
||||||
|
$start.length = $start.end - $start.start
|
||||||
$next = $keyframes[$i]
|
$next = $keyframes[$i]
|
||||||
}
|
}
|
||||||
$project.Add($start)
|
$project.Add($start)
|
||||||
|
@ -245,14 +275,15 @@ function Write-ProjectFile {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$start.end = $videodata.Length - 1
|
$start.end = $videodata.Length - 1
|
||||||
|
$start.length = $start.end - $start.start
|
||||||
$project.Add($start)
|
$project.Add($start)
|
||||||
|
|
||||||
$projectoutput = '{'
|
$projectoutput = '{'
|
||||||
$projectoutput += "`n `"fps`":`"" + $Framerate + "`","
|
$projectoutput += "`n `"fps`":`"" + $Framerate + "`","
|
||||||
$projectoutput += "`n `"chunks`": ["
|
$projectoutput += "`n `"chunks`": ["
|
||||||
$projectoutput += "`n [" + $project[0].start + ", " + $project[0].end + ", " + $project[0].startstamp + "]"
|
$projectoutput += "`n [" + $project[0].start + ", " + $project[0].end + ", " + $project[0].startstamp + ", " + $project[0].length + "]"
|
||||||
for ($i = 1; $i -lt $project.Count; $i++) {
|
for ($i = 1; $i -lt $project.Count; $i++) {
|
||||||
$projectoutput += ",`n [" + $project[$i].start + ", " + $project[$i].end + ", " + $project[$i].startstamp + "]"
|
$projectoutput += ",`n [" + $project[$i].start + ", " + $project[$i].end + ", " + $project[$i].startstamp + ", " + $project[$i].length + "]"
|
||||||
}
|
}
|
||||||
$projectoutput += "`n ]"
|
$projectoutput += "`n ]"
|
||||||
$projectoutput += "`n}"
|
$projectoutput += "`n}"
|
||||||
|
@ -265,6 +296,10 @@ function Write-ProjectFile {
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
#>
|
#>
|
||||||
function Start-OurEncoding {
|
function Start-OurEncoding {
|
||||||
|
if ($Threads -lt 1) {
|
||||||
|
$Threads = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors
|
||||||
|
}
|
||||||
|
|
||||||
Write-Host "Starting our chunk encoder with maximum $Threads workers"
|
Write-Host "Starting our chunk encoder with maximum $Threads workers"
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
$encodefile = $workproject + '_output'
|
$encodefile = $workproject + '_output'
|
||||||
|
@ -404,10 +439,6 @@ function Start-OurEncoding {
|
||||||
try {
|
try {
|
||||||
Assert-OurParameters
|
Assert-OurParameters
|
||||||
|
|
||||||
if ($Threads -lt 1) {
|
|
||||||
$Threads = (Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors
|
|
||||||
}
|
|
||||||
|
|
||||||
$workproject = [io.path]::GetFileNameWithoutExtension($InputFile)
|
$workproject = [io.path]::GetFileNameWithoutExtension($InputFile)
|
||||||
$projectfile = $workproject + '_spav1an.json'
|
$projectfile = $workproject + '_spav1an.json'
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue