如何解决FFMpeg 无法开始使用 Process API
所以我正在尝试使用 FFProbe 来使用 Process API 检索媒体信息,我在 Net 5 上并希望保持跨平台兼容。
在我开始摆弄之前,我尝试了 FFMpeg Core 来检索元数据,但它仅适用于 Windows,并且无法处理多行标签,只能解析最后一行。
所以我尝试手动将输出通过管道传输到我的应用程序。
最初,我使用 CliWrap 将输出整齐地通过管道传输到 StringBuilder
,就像我通常在其他存储库中所做的那样。
var output = new StringBuilder();
var args = new[] { "-i",filePath };
var pResult = await Cli.Wrap(GetFFProbeFilePath())
.WithArguments(args)
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(output))
.ExecuteAsync(cancellationToken);
-
filePath
:任何媒体文件。 -
GetFFProbeFilePath()
:为 ffmpeg 清理 %PATH%,返回“C:\ProgramData\chocolatey\bin\ffprobe.exe”。 -
cancellationToken
:None
用于测试用例。
但这没有用。输出始终为空。
所以我使用非提升的 cmd 运行以下命令:C:\\ProgramData\\chocolatey\\bin\\ffprobe.exe -i my/lovely/file.mp3
并且控制台完全显示输出,没有错误。
自然是 CliWrap 的错,因为我很完美;这就是为什么我用一个普通的 Process API 调用替换它:
var output = new StringBuilder();
using (var p = new Process())
{
p.StartInfo.FileName = "C:\\ProgramData\\chocolatey\\bin\\ffprobe.exe";
p.StartInfo.Arguments = String.Join(' ',args);
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
output.Append(await p.StandardOutput.ReadToEndAsync());
await p.WaitForExitAsync(cancellationToken);
}
using var p = new Process();
p.StartInfo.FileName = "C:\\ProgramData\\chocolatey\\bin\\ffprobe.exe";
p.StartInfo.Arguments = " -i \"" + filePath + "\" 2> " + "\"C:\\temp\\Metadata.log\"";
if (!p.Start())
throw new Exception();
await p.WaitForExitAsync(cancellationToken);
-
C:\temp\
:777
未创建临时文件,由此我得出结论,该进程未成功退出。即使没有抛出异常(我也尝试管道错误:没有)。
然后我继续运行这个命令 20 倍,并想知道为什么它在 ps & cmd 中有效,而在 C# 中无效:
C:\ProgramData\chocolatey\bin\ffprobe.exe -i my/lovely/file.mp3 2> "C:\temp\Metadata.log"
直到我使用 [Win]+[R] 运行它,并且我得到一个图形故障和 Windows 错误报告而不是进程完成,文件没有被创建。经过一些实验,我发现 start
+ cmd 中的命令具有相同的行为。
为什么在(插入偏好的神)名称中 [Win]+[R] 和 cmd 有区别,为什么从 C# 运行时会崩溃?我如何克服这种奇怪的行为,同时仍然跨平台兼容?
顺便说一下,这整个事情在 linux 中运行得很好。
编辑:
手动启动 cmd 进程时,FFProbe 被正确调用,但我仍然没有在输出管道上检索任何数据,因为 cmd.exe
没有写入任何内容,而且我无法通过管道传输 FFProbe。
var output = new StringBuilder();
_ = await Cli.Wrap("cmd.exe")
.WithArguments("/C ffprobe -i \"my/lovely/file.mp3\" 2> \"C:\\temp\\Metadata.log\"")
.WithStandardOutputPipe(PipeTarget.ToStringBuilder(output))
.ExecuteAsync(cancellationToken);
这实际上创建了 Metadata.log
文件,但没有输出,因为我只重定向了 cmd.exe
的输出,而不是 ffprobe
。
我目前的想法是,我可以打开一个 conhost
并通过在命令参数中显式提供管道来手动将 ffprobe
输出通过管道传输到控制台输入,这在 linux 中也不会以相同的方式工作,即有点违背目的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。