我正在尝试将一些流通过管道传输到 ffmpeg 并捕获它的输出,以便我可以在我的代码中传递另一个流。
这是一个代码示例,它只是在我写入其 StandardInput.BaseStream
后停止进程继续。
internal class Program
{
private static void Main(string[] args)
{
var inputFile = @"C:\Temp\test.mp4";
var outputFile = @"C:\Temp\test.mp3";
var process = new Process
{
StartInfo = new ProcessStartInfo
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
Arguments = "-i - -f mp3 -",
FileName = "ffmpeg.exe"
},
EnableRaisingEvents = true
};
process.ErrorDataReceived += (sender, eventArgs) => Console.WriteLine(eventArgs.Data);
process.Start();
process.BeginErrorReadLine();
using (var input = new FileStream(inputFile, FileMode.Open))
using (var output = new FileStream(outputFile, FileMode.Create))
{
input.CopyTo(process.StandardInput.BaseStream);
process.StandardOutput.BaseStream.CopyTo(output);
}
process.WaitForExit();
Console.WriteLine("done");
Console.ReadLine();
}
}
这个例子与这个问题的答案几乎相同:https://stackoverflow.com/a/8999542/2277280
我究竟做错了什么?
为什么这个过程没有继续?
它是 ffmpeg 特定的吗?
最佳答案
我不得不异步地从 stdin 和 stdout 写入和读取以避免死锁。 Wiz 和 this post 的评论将我带向了正确的方向!谢谢!
关闭 StandardInput 以使进程结束也很重要。
否则它仍然会等待更多输入并且标准输出保持打开状态并且永远不会完成复制。
以下代码在我的场景中工作得很好:
private static void Main(string[] args)
{
var inputFile = @"C:\Temp\test.mp4";
var outputFile = @"C:\Temp\test.mp3";
var process = new Process
{
StartInfo = new ProcessStartInfo
{
RedirectStandardInput = true,
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
Arguments = "-i - -f mp3 -",
FileName = "ffmpeg.exe"
},
EnableRaisingEvents = true
};
process.ErrorDataReceived += (sender, eventArgs) =>
{
Console.WriteLine(eventArgs.Data);
};
process.Start();
process.BeginErrorReadLine();
var inputTask = Task.Run(() =>
{
using (var input = new FileStream(inputFile, FileMode.Open))
{
input.CopyTo(process.StandardInput.BaseStream);
process.StandardInput.Close();
}
});
var outputTask = Task.Run(() =>
{
using (var output = new FileStream(outputFile, FileMode.Create))
{
process.StandardOutput.BaseStream.CopyTo(output);
}
});
Task.WaitAll(inputTask, outputTask);
process.WaitForExit();
Console.WriteLine("done");
Console.ReadLine();
}
关于C# 使用 FFmpeg 处理 StandardInput 和 StandardOutput 卡住,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50680393/