C# Process StandardInput 和 StandardOutput 与 FFmpeg 卡住

标签 c# .net ffmpeg process

我正在尝试将一些流通过管道传输到 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 的吗?

最佳答案

我不得不异步写入和读取标准输入和标准输出以避免死锁。来自 Wiz 和 this post 的评论带我走向正确的方向!谢谢! 关闭 StandardInput 以使流程结束也很重要。 否则它仍然会等待更多的输入并且 stdout 保持打开并且永远不会完成复制。 以下代码在我的场景中工作得很好:

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# Process StandardInput 和 StandardOutput 与 FFmpeg 卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50680393/

相关文章:

c# - 如何使用 FFMPEG 传递参数

c# - TabControl 上下文菜单

c# - 我的 web api 2 Controller 需要路由

c# - 规范模式和性能

c# - 如何使用图形库 C# 在图像上绘制小图像?

python - 如何从无尽的音频流中获取和划分音频

c# - 将参数作为对象传递[]

c# - 如何以不可变的方式实现缓存?

c# - 为什么更改 ListView 的 HeaderStyle 会挂起应用程序?

php - 在一个人无法完全控制的主机上安装 ffmpeg?+