Imports System.Text Imports StaxRip.CommandLine Public Class ffmpegEnc Inherits BasicVideoEncoder Property ParamsStore As New PrimitiveStore Public Overrides ReadOnly Property DefaultName As String Get Return "ffmpeg | " + Params.Codec.OptionText End Get End Property Sub New() Muxer = New ffmpegMuxer("AVI") End Sub Private ParamsValue As EncoderParams Property Params As EncoderParams Get If ParamsValue Is Nothing Then ParamsValue = New EncoderParams ParamsValue.Init(ParamsStore) End If Return ParamsValue End Get Set(value As EncoderParams) ParamsValue = value End Set End Property Overrides Sub ShowConfigDialog() Dim newParams = New EncoderParams Dim store = DirectCast(ObjectHelp.GetCopy(ParamsStore), PrimitiveStore) newParams.Init(store) Using form As New CommandLineForm(newParams) Dim a1 = Sub() Dim enc = ObjectHelp.GetCopy(Of ffmpegEnc)(Me) Dim params2 As New EncoderParams Dim store2 = DirectCast(ObjectHelp.GetCopy(store), PrimitiveStore) params2.Init(store2) enc.Params = params2 enc.ParamsStore = store2 SaveProfile(enc) End Sub form.cms.Add("Save Profile...", a1) Dim a2 = Sub() Dim codecText = newParams.Codec.OptionText Dim consoleHelp = ProcessHelp.GetConsoleOutput(Package.ffmpeg.Path, "-hide_banner -h encoder=" + newParams.Codec.ValueText) Dim helpDic As New Dictionary(Of String, String) From { {"x264", "https://trac.ffmpeg.org/wiki/Encode/H.264"}, {"x265", "https://trac.ffmpeg.org/wiki/Encode/H.265"}, {"XviD", "https://trac.ffmpeg.org/wiki/Encode/MPEG-4"}, {"VP9", "https://trac.ffmpeg.org/wiki/Encode/VP9"}, {"FFV1", "https://trac.ffmpeg.org/wiki/Encode/FFV1"}, {"Intel H.264", "https://trac.ffmpeg.org/wiki/Hardware/QuickSync"}, {"Intel H.265", "https://trac.ffmpeg.org/wiki/Hardware/QuickSync"}, {"AV1", "https://trac.ffmpeg.org/wiki/Encode/AV1"}} Dim help = $"

ffmpeg Online Help

" + "

ffmpeg Online Help

" If helpDic.ContainsKey(codecText) Then help += $"

ffmpeg {codecText} Online Help

" + $"

ffmpeg {codecText} Online Help

" End If help += $"

ffmpeg {codecText} Console Help

" + $"
{HelpDocument.ConvertChars(consoleHelp) + BR}
" form.HTMLHelpFunc = Function() help End Sub AddHandler form.BeforeHelp, a2 If form.ShowDialog() = DialogResult.OK Then Params = newParams ParamsStore = store OnStateChange() End If End Using End Sub Overrides ReadOnly Property OutputExt() As String Get Select Case Params.Codec.OptionText Case "Xvid", "MPEG-4", "UT Video", "FFV1" Return "avi" Case "ProRes", "R210", "V210" Return "mov" Case "VP8", "VP9" Return "webm" Case "x264" Return "h264" Case "x265" Return "h265" Case Else Return "mkv" End Select End Get End Property Overrides ReadOnly Property IsCompCheckEnabled() As Boolean Get Return False End Get End Property Overrides Sub Encode() p.Script.Synchronize() Params.RaiseValueChanged(Nothing) If Params.Mode.OptionText = "Two Pass" Then Encode(Params.GetCommandLine(True, False, 1)) Encode(Params.GetCommandLine(True, False, 2)) Else Encode(Params.GetCommandLine(True, False)) End If AfterEncoding() End Sub Overloads Sub Encode(args As String) Using proc As New Proc proc.Header = "Video encoding " + Params.Codec.OptionText proc.SkipStrings = {"frame=", "size="} proc.FrameCount = p.Script.GetFrameCount proc.Encoding = Encoding.UTF8 proc.Package = Package.ffmpeg proc.Arguments = args proc.Start() End Using End Sub Overrides Function GetMenu() As MenuList Dim ret As New MenuList ret.Add("Encoder Options", AddressOf ShowConfigDialog) ret.Add("Container Configuration", AddressOf OpenMuxerConfigDialog) Return ret End Function Overrides Property QualityMode() As Boolean Get Return Params.Mode.Value = EncodingMode.Quality End Get Set(Value As Boolean) End Set End Property Public Overrides ReadOnly Property CommandLineParams As CommandLineParams Get Return Params End Get End Property Public Class EncoderParams Inherits CommandLineParams Sub New() Title = "ffmpeg Options" End Sub Property Codec As New OptionParam With { .Switch = "-c:v", .Text = "Codec", .AlwaysOn = True, .Options = {"x264", "x265", "AV1", "XviD", "MPEG-4", "Theora", "ProRes", "R210", "V210", "UT Video", "FFV1", "VP | VP8", "VP | VP9", "Intel | Intel H.264", "Intel | Intel H.265", "Nvidia | Nvidia H.264", "Nvidia | Nvidia H.265"}, .Values = {"libx264", "libx265", "libaom-av1", "libxvid", "mpeg4", "libtheora", "prores", "r210", "v210", "utvideo", "ffv1", "libvpx", "libvpx-vp9", "h264_qsv", "hevc_qsv", "h264_nvenc", "hevc_nvenc"}} Property Mode As New OptionParam With { .Name = "Mode", .Text = "Mode", .VisibleFunc = Function() Not Codec.ValueText.EqualsAny("prores", "utvideo", "ffv1"), .Options = {"Quality", "One Pass", "Two Pass"}} Property Decoder As New OptionParam With { .Text = "Decoder", .Options = {"AviSynth/VapourSynth", "Software", "Intel", "DXVA2", "Nvidia"}, .Values = {"-", "sw", "qsv", "dxva2", "cuda"}} Property h264_nvenc_rc As New OptionParam With { .Name = "h264_nvenc rc", .Switch = "-rc", .Text = "Rate Control", .Options = {"Preset", "Constqp", "VBR", "CBR", "VBR_MinQP", "LL_2Pass_Quality", "LL_2Pass_Size", "VBR_2Pass"}, .VisibleFunc = Function() Codec.ValueText = "h264_nvenc"} Property Custom As New StringParam With { .Text = "Custom", .Quotes = QuotesMode.Never, .AlwaysOn = True} Overrides ReadOnly Property Items As List(Of CommandLineParam) Get If ItemsValue Is Nothing Then ItemsValue = New List(Of CommandLineParam) Add("Main", Decoder, Codec, Mode, New OptionParam With {.Name = "x264/x265 preset", .Text = "Preset", .Switch = "-preset", .Init = 5, .Options = {"Ultrafast", "Superfast", "Veryfast", "Faster", "Fast", "Medium", "Slow", "Slower", "Veryslow", "Placebo"}, .VisibleFunc = Function() Codec.OptionText.EqualsAny("x264", "x265")}, New OptionParam With {.Name = "x264/x265 tune", .Text = "Tune", .Switch = "-tune", .Options = {"None", "Film", "Animation", "Grain", "Stillimage", "Psnr", "Ssim", "Fastdecode", "Zerolatency"}, .VisibleFunc = Function() Codec.OptionText.EqualsAny("x264", "x265")}, New OptionParam With {.Switch = "-profile:v", .Text = "Profile", .VisibleFunc = Function() Codec.OptionText = "ProRes", .Init = 3, .IntegerValue = True, .Options = {"Proxy", "LT", "Normal", "HQ"}}, New OptionParam With {.Switch = "-speed", .Text = "Speed", .AlwaysOn = True, .VisibleFunc = Function() Codec.OptionText.EqualsAny("VP8", "VP9"), .Options = {"6 - Fastest", "5 - Faster", "4 - Fast", "3 - Medium", "2 - Slow", "1 - Slower", "0 - Slowest"}, .Values = {"6", "5", "4", "3", "2", "1", "0"}, .Value = 5}, New OptionParam With {.Switch = "-cpu-used", .Text = "CPU Used", .Init = 1, .VisibleFunc = Function() Codec.OptionText = "AV1", .IntegerValue = True, .Options = {"0 - Slowest", "1 - Very Slow", "2 - Slower", "3 - Slow", "4 - Medium", "5 - Fast", "6 - Faster", "7 - Very Fast", "8 - Fastest"}}, New OptionParam With {.Switch = "-aq-mode", .Text = "AQ Mode", .VisibleFunc = Function() Codec.OptionText = "VP9", .Options = {"Disabled", "0", "1", "2", "3"}, .Values = {"Disabled", "0", "1", "2", "3"}}, New OptionParam With {.Name = "h264_nvenc profile", .Switch = "-profile", .Text = "Profile", .Options = {"Baseline", "Main", "High", "High444p"}, .Init = 1, .VisibleFunc = Function() Codec.ValueText = "h264_nvenc"}, New OptionParam With {.Name = "h264_nvenc preset", .Switch = "-preset", .Text = "Preset", .Options = {"Default", "Slow", "Medium", "Fast", "HP", "HQ", "BD", "LL", "LLHQ", "LLHP", "Lossless", "Losslesshp"}, .Init = 2, .VisibleFunc = Function() Codec.ValueText = "h264_nvenc"}, New OptionParam With {.Name = "h264_nvenc level", .Switch = "-level", .Text = "Level", .Options = {"Auto", "1", "1.0", "1b", "1.0b", "1.1", "1.2", "1.3", "2", "2.0", "2.1", "2.2", "3", "3.0", "3.1", "3.2", "4", "4.0", "4.1", "4.2", "5", "5.0", "5.1"}, .VisibleFunc = Function() Codec.ValueText = "h264_nvenc"}, h264_nvenc_rc, New OptionParam With {.Name = "utVideoPred", .Switch = "-pred", .Text = "Prediction", .Init = 3, .Options = {"None", "Left", "Gradient", "Median"}, .VisibleFunc = Function() Codec.ValueText = "utvideo"}, New OptionParam With {.Name = "utVideoPixFmt", .Switch = "-pix_fmt", .Text = "Pixel Format", .Options = {"YUV420P", "YUV422P", "YUV444P", "RGB24", "RGBA"}, .VisibleFunc = Function() Codec.ValueText = "utvideo"}, New NumParam With {.Name = "Quality", .Text = "Quality", .Init = -1, .VisibleFunc = Function() Mode.Value = EncodingMode.Quality AndAlso Not Codec.ValueText.EqualsAny("prores", "utvideo", "ffv1"), .ArgsFunc = AddressOf GetQualityArgs, .Config = {-1, 63, 0.5, 1}}, New NumParam With {.Switch = "-threads", .Text = "Threads", .Config = {0, 64}}, New NumParam With {.Switch = "-tile-columns", .Text = "Tile Columns", .VisibleFunc = Function() Codec.OptionText = "VP9", .Value = 6, .DefaultValue = -1}, New NumParam With {.Switch = "-frame-parallel", .Text = "Frame Parallel", .VisibleFunc = Function() Codec.OptionText = "VP9", .Value = 1, .DefaultValue = -1}, New NumParam With {.Switch = "-auto-alt-ref", .Text = "Auto Alt Ref", .VisibleFunc = Function() Codec.OptionText = "VP9", .Value = 1, .DefaultValue = -1}, New NumParam With {.Switch = "-lag-in-frames", .Text = "Lag In Frames", .VisibleFunc = Function() Codec.OptionText = "VP9", .Value = 25, .DefaultValue = -1}, New BoolParam With {.Name = "h264_qsv Lookahead", .Text = "Lookahead", .Switch = "-look_ahead 1", .NoSwitch = "-look_ahead 0", .Value = False, .DefaultValue = True, .VisibleFunc = Function() Codec.ValueText = "h264_qsv"}, New BoolParam With {.Name = "h264_qsv VCM", .Text = "VCM", .Switch = "-vcm 1", .NoSwitch = "-vcm 0", .Value = False, .DefaultValue = True, .VisibleFunc = Function() Codec.ValueText = "h264_qsv"}, Custom) End If Return ItemsValue End Get End Property Overloads Overrides Function GetCommandLine( includePaths As Boolean, includeExecutable As Boolean, Optional pass As Integer = 1) As String Dim sourcePath = p.Script.Path Dim sb As New StringBuilder If includePaths AndAlso includeExecutable Then sb.Append(Package.ffmpeg.Path.Escape) End If Select Case Decoder.ValueText Case "sw" sourcePath = p.LastOriginalSourceFile Case "qsv" sourcePath = p.LastOriginalSourceFile sb.Append(" -hwaccel qsv") Case "dxva2" sourcePath = p.LastOriginalSourceFile sb.Append(" -hwaccel dxva2") Case "cuda" sourcePath = p.LastOriginalSourceFile sb.Append(" -hwaccel_output_format cuda") End Select If sourcePath.Ext = "vpy" Then sb.Append(" -f vapoursynth") End If If includePaths Then sb.Append(" -i " + sourcePath.Escape) End If Dim items = From i In Me.Items Where i.GetArgs <> "" AndAlso Not IsCustom(i.Switch) If items.Count > 0 Then sb.Append(" " + items.Select(Function(item) item.GetArgs).Join(" ")) End If If Calc.IsARSignalingRequired Then sb.Append(" -aspect " + Calc.GetTargetDAR.ToInvariantString.Shorten(8)) End If Select Case Mode.Value Case EncodingMode.TwoPass sb.Append(" -pass " & pass) sb.Append($" -b:v {p.VideoBitrate}k") If pass = 1 Then sb.Append(" -f rawvideo") End If If includePaths Then sb.Append(" -passlogfile " + (p.TempDir + p.TargetFile.Base + "_2pass").Escape) End If Case EncodingMode.OnePass sb.Append($" -b:v {p.VideoBitrate}k") End Select Select Case Codec.OptionText Case "XviD" sb.Append(" -tag:v xvid") Case "AV1" sb.Append(" -strict experimental") End Select Dim targetPath As String If Mode.OptionText = "Two Pass" AndAlso pass = 1 Then targetPath = "NUL" Else targetPath = p.VideoEncoder.OutputPath.ChangeExt(p.VideoEncoder.OutputExt).Escape End If If includePaths Then sb.Append(" -an -y -hide_banner " + targetPath) End If Dim ret = sb.ToString.Trim If ret.Contains("%") Then ret = Macro.Expand(ret) End If Return ret End Function Function IsCustom(switch As String) As Boolean If switch = "" Then Return False End If If Custom.Value?.Contains(switch + " ") OrElse Custom.Value?.EndsWith(switch) Then Return True End If End Function Public Overrides Function GetPackage() As Package Return Package.ffmpeg End Function Function GetQualityArgs() As String If Mode.Value = EncodingMode.Quality Then Dim param = GetNumParamByName("Quality") If param.Value <> param.DefaultValue Then If Codec.OptionText.EqualsAny("VP8", "VP9") Then Return "-crf " + param.Value.ToInvariantString & " -b:v 0" ElseIf Codec.OptionText.EqualsAny("x264", "x265", "AV1") Then Return "-crf " + param.Value.ToInvariantString ElseIf Codec.ValueText.EqualsAny("h264_nvenc") Then If h264_nvenc_rc.OptionText = "Constqp" Then Return "-qp " + param.Value.ToInvariantString Else Return "-cq " + param.Value.ToInvariantString End If ElseIf Codec.ValueText.EqualsAny("hevc_nvenc") Then Return "-cq " + param.Value.ToInvariantString Else Return "-q:v " + param.Value.ToInvariantString End If End If End If End Function End Class Enum EncodingMode Quality OnePass TwoPass End Enum End Class