我必须使用VB.NET运行此命令行:
" H:\ videotest \ test.vpy" - -y | " H:\发布\数据\ bin64适用\ ffmpeg.exe" -hwaccel auto -y -i - -map 0:v:0 -c:v libx265 -crf 20.0 -preset 5 -x265-params level = 0:profile = undefined:pmode:no-pme:pme:no-high-层:REF = 3:B-帧= 4:开放式GOP:在keyint = 250:分钟-在keyint = 25:b-适应= 2:b帧偏置= 0:RC-先行= 20:无场景切换:b-金字塔:我=十六进制:次亚= 2:merange = 57:颞MVP:weightp:无weightb:最大合并= 2:无weightb:无RECT:没有放:VBV-BUFSIZE = 0:VBV-MAXRATE = 0:VBV-INIT = 0.9:无严格-CBR:qcomp为= 0.6:QSTEP = 4:AQ-模式= 1:AQ-强度= 1.0:cutree:无早期跳过命令min-Cu系大小= 8: CTU = 64:无快速-CFB:ipratio = 1.4:pbratio = 1.3:cbqpoffs = 0:crqpoffs = 0:RD = 3:PSY-RD = 0.3:PSY-RDOQ = 1:无b-帧内:NO-快速帧内:RDOQ级别= 1:无tskip:无tskip快速:CU-无损:TU-帧内深度= 1:TU-间深度= 1:强帧内平滑:无constrained-帧内:NR-帧内= 0:NR-间= 0:qblur = 0.5:cplxblur = 20:signhide:SAR = 16 " H:\ videotest \ outputawdwd.mkv"
vspipe.exe
运行test.vpy
脚本并对视频输入应用过滤器或调整视频输入大小,然后输出通过管道传输到ffmpeg以进行编码。
如果我在vspipe中使用正常的Process声明,则会出现以下错误:
未知参数:|
从命令行,脚本运行良好。我怀疑这意味着我必须在vspipe
和ffmpeg
之间手动管道。
是否可以手动将输出从一个流程输送到另一个流程?我必须手动完成吗?
这是我启动流程的功能:
executablepath = "H:\Project\VapourSynth\core64\vspipe.exe"
params = "H:\videotest\test.vpy" - -y | "H:\Release\data\bin64\ffmpeg.exe" -hwaccel auto -y -i - -map 0:v:0 -c:v libx265 -crf 20.0 -preset 5 -x265-params level=0:profile=undefined:pmode:no-pme:pme:no-high-tier:ref=3:bframes=4:open-gop:keyint=250:min-keyint=25:b-adapt=2:bframe-bias=0:rc-lookahead=20:no-scenecut:b-pyramid:me=hex:subme=2:merange=57:temporal-mvp:weightp:no-weightb:max-merge=2:no-weightb:no-rect:no-amp:vbv-bufsize=0:vbv-maxrate=0:vbv-init=0.9:no-strict-cbr:qcomp=0.6:qstep=4:aq-mode=1:aq-strength=1.0:cutree:no-early-skip:min-cu-size=8:ctu=64:no-fast-cfb:ipratio=1.4:pbratio=1.3:cbqpoffs=0:crqpoffs=0:rd=3:psy-rd=0.3:psy-rdoq=1:no-b-intra:no-fast-intra:rdoq-level=1:no-tskip:no-tskip-fast:cu-lossless:tu-intra-depth=1:tu-inter-depth=1:strong-intra-smoothing:no-constrained-intra:nr-intra=0:nr-inter=0:qblur=0.5:cplxblur=20:signhide:sar=16 "H:\videotest\outputawdwd.mkv"
Private Sub CreateJobProcess(ByVal Name, ByVal executablepath, ByVal params)
Try
If Not jobs_processes.ContainsKey(Name) Then
Dim Proc As New Process
Proc.StartInfo.UseShellExecute = False
Proc.StartInfo.CreateNoWindow = True
Proc.StartInfo.RedirectStandardError = True
Proc.StartInfo.FileName = "" & executablepath & ""
Proc.StartInfo.Arguments = params
'start process
Proc.Start()
'add new process to dictionary
jobs_processes.Add(Name, Proc)
'TEMP
My.Settings.giobbe -= 1
'start background workers for statistics
If Not ConversionStats.IsBusy Then
ConversionStats.WorkerSupportsCancellation = True
ConversionStats.RunWorkerAsync()
End If
If Not UpdateListJob.IsBusy Then
UpdateListJob.WorkerSupportsCancellation = True
UpdateListJob.RunWorkerAsync()
End If
End If
Catch ex As Exception
Me.Invoke(New MethodInvoker(Sub() Logbox.AppendText(Environment.NewLine & ">Program exception:" & Environment.NewLine & ex.Message & Environment.NewLine)))
MsgBox(ex.Message)
End Try
End Sub
更新
这是我更改的块,此函数获取需要创建的作业的作业名称和参数,然后将该过程保存在字典中。
Dim Proc As New Process
Proc.StartInfo.UseShellExecute = False
Proc.StartInfo.CreateNoWindow = True
Proc.StartInfo.RedirectStandardError = True
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = params
'start process
Proc.Start()
'add new process to dictionary
jobs_processes.Add(Name, Proc)
'TEMP
My.Settings.giobbe -= 1
'start background workers for statistics
If Not ConversionStats.IsBusy Then
ConversionStats.WorkerSupportsCancellation = True
ConversionStats.RunWorkerAsync()
End If
If Not UpdateListJob.IsBusy Then
UpdateListJob.WorkerSupportsCancellation = True
UpdateListJob.RunWorkerAsync()
End If
然后我有一个backgroundworker(ConversionStats)从字典中的每个进程获取stderr并将它们打印到文本框中:
'take current selected process and set streamreader
Dim tmpproc As Process = jobs_processes(CurrentJob)
Dim ffmpeg_stats As StreamReader
Dim stdoutput As String = ""
'something that verify if the job is started
If statejob = 1 Then 'if job is working
'take stderr from ffmpeg
ffmpeg_stats = tmpproc.StandardError
stdoutput = ffmpeg_stats.ReadLine()
If stdoutput IsNot Nothing Then 'if ffmpeg stderr is not nothing
'IF FFMPEG IS RETURNING STATS
If stdoutput.Contains("frame=") Or stdoutput.Contains("size=") Then
所以这是我的代码...... 但是现在cmd得到了带有streamreader的standarderror导致了一个字符串" Invalid Handle。"这是cmd stderr的错误或者流读取器有问题吗?
更新2
我甚至尝试启动一个干净的cmd进程,只声明参数,但结果只是带有主信息的控制台。
Microsoft Windows [Versione 6.3.9600] (c)2013 Microsoft Corporation。 Tutti i diritti riservati。
H:\项目\ BIN \推出>
这是澄清的代码:
Dim Proc As New Process
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = params
'start process
Proc.Start()
所以,有人可以指导我如何将STDOUTPUT从一个进程(vspipe.exe)管理/重定向到另一个进程(ffmpeg.exe)?
答案 0 :(得分:0)
由于您知道命令字符串在命令行上有效,因此最简单的方法是让cmd.exe
为您运行代码。正如Plutonix在his comment中建议的那样,在this answer中,Mark提供了一个如何在C#代码中执行此操作的示例。
Process test = new Process();
test.StartInfo.FileName = "cmd";
test.StartInfo.Arguments = @"/C ""echo testing | grep test""";
test.Start();
根据您的目的调整此内容,并转换为VB.net可能看起来像这样(使用您在代码中声明的相同变量):
Dim Proc As New Process()
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = "/C """ & executablepath & " " & params & """
Proc.Start()
这与您之前的做法有何不同?您使用Process.Start
运行vspipe.exe
,然后将params
传递给您。上面的这段新代码使用Process.Start
代替运行cmd.exe
,基本上打开命令提示符窗口,然后输入完整的命令行字符串。
接收stdout
和stderr
需要两个步骤。首先,您必须设置'重定向'每个属性为True
,然后在启动过程后,手动检索所需的输出。
Dim Proc As New Process()
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = executablepath & " " & params
'Capture stdio & stderr:
Proc.StartInfo.RedirectStandardOutput = True
Proc.StartInfo.RedirectStandardError = True
Proc.Start()
'Read stdio & stderr:
Dim StdIO As String = Proc.StandardOutput.ReadToEnd()
Dim StdErr As String = Proc.StandardError.ReadToEnd()
RE:更新2 :
在这个特定情况下的问题是Arguments
字符串是一堆双引号,必须进行转义。在vb.net中,这是通过双引号(""
)完成的,它可以显示为"三重双引号" ("""
)如果它们位于字符串的开头或结尾,或者如果有许多需要转义的话,甚至更长的双引号倍数。
虽然我的系统上没有必要的特定软件来测试,但以下情况应该有效:
Dim Proc As New Process
Proc.StartInfo.CreateNoWindow = True
Proc.StartInfo.UseShellExecute = False
Proc.StartInfo.FileName = "cmd"
Proc.StartInfo.Arguments = "/C ""H:\Project\VapourSynth\core64\vspipe.exe ""H:\videotest\test.vpy"" - -y | ""H:\Release\data\bin64\ffmpeg.exe"" -hwaccel auto -y -i - -map 0:v:0 -c:v libx265 -crf 20.0 -preset 5 -x265-params level=0:profile=undefined:pmode:no-pme:pme:no-high-tier:ref=3:bframes=4:open-gop:keyint=250:min-keyint=25:b-adapt=2:bframe-bias=0:rc-lookahead=20:no-scenecut:b-pyramid:me=hex:subme=2:merange=57:temporal-mvp:weightp:no-weightb:max-merge=2:no-weightb:no-rect:no-amp:vbv-bufsize=0:vbv-maxrate=0:vbv-init=0.9:no-strict-cbr:qcomp=0.6:qstep=4:aq-mode=1:aq-strength=1.0:cutree:no-early-skip:min-cu-size=8:ctu=64:no-fast-cfb:ipratio=1.4:pbratio=1.3:cbqpoffs=0:crqpoffs=0:rd=3:psy-rd=0.3:psy-rdoq=1:no-b-intra:no-fast-intra:rdoq-level=1:no-tskip:no-tskip-fast:cu-lossless:tu-intra-depth=1:tu-inter-depth=1:strong-intra-smoothing:no-constrained-intra:nr-intra=0:nr-inter=0:qblur=0.5:cplxblur=20:signhide:sar=16 ""H:\videotest\outputawdwd.mkv"""
Proc.StartInfo.RedirectStandardOutput = True
Proc.StartInfo.RedirectStandardError = True
Proc.Start()
Dim so As String = Proc.StandardOutput.ReadToEnd
Dim se As String = Proc.StandardError.ReadToEnd
Proc.WaitForExit()