微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

FFMpeg 无法开始使用 Process API

如何解决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”。
  • cancellationTokenNone 用于测试用例。

但这没有用。输出始终为空。 所以我使用非提升的 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 举报,一经查实,本站将立刻删除。