C#使用FFmpeg冻结处理StandardInput和StandardOutput

时间:2018-06-04 12:15:14

标签: 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吗?

1 个答案:

答案 0 :(得分:3)

我必须异步地从stdin和stdout写入和读取以避免死锁。 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();
        }