首页 > 解决方案 > FFMpeg 无法开始使用 Process API

问题描述

所以我正在尝试使用 FFProbe 来使用 Process API 检索媒体信息,我在 Net 5 上并希望保持跨平台兼容。在我开始摆弄之前,我尝试了 FFMpeg Core来检索元数据,但它只适用于 Windows,并且不能处理多行标签,只解析最后一行。所以我尝试手动将输出通过管道传输到我的应用程序。最初,我使用CliWrap将输出巧妙地通过管道传输到 a StringBuilder,就像我通常在其他存储库中所做的那样。

var output = new StringBuilder();
var args = new[] { "-i", filePath };
var pResult = await Cli.Wrap(GetFFProbeFilePath())
    .WithArguments(args)
    .WithStandardOutputPipe(PipeTarget.ToStringBuilder(output))
    .ExecuteAsync(cancellationToken);

但这没有用。输出始终为空。所以我使用非提升的 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);

临时文件没有创建,因此我断定进程没有成功退出。即使没有抛出异常(我也尝试过管道错误:什么都没有)。

然后我继续运行这个命令 20x 并想知道为什么它在 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. 我目前的想法是,我可以通过在命令参数中显式提供管道来打开 aconhost并手动将ffprobe输出通过管道传输到控制台输入,这在 linux 中也不能以同样的方式工作,这违背了目的。

标签: c#ffmpegprocessipc

解决方案


推荐阅读