c# - 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);
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
临时文件没有创建,因此我断定进程没有成功退出。即使没有抛出异常(我也尝试过管道错误:什么都没有)。
然后我继续运行这个命令 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 中也不能以同样的方式工作,这违背了目的。
解决方案
推荐阅读
- openedge - 如何在 Progress Developer Studio 中的现有 *.w 文件上打开可视化设计器?
- java - 如何使用 dom4j 添加默认名称空间?
- excel - 将数据透视表从一个数据模型导入到另一个数据模型
- computer-vision - .SMOTE 库问题
- visual-studio - 我不能在编辑器区域打开更多 3 个文件
- sql - SQL Inner join 如何只显示一次组合
- python - 创建数据透视表时出现关键错误
- php - 使用选项数组在 php 7.4 版中未设置 Cookie?
- c++ - for (int i = 2; i < n; i = i*i) 的时间复杂度是多少?
- python - 如何单击 recaptchaV2 的使用 Selenium 和 Python 解决挑战按钮