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

问题描述 投票:2回答:1

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

c# .net ffmpeg process
1个回答
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();
        }
© www.soinside.com 2019 - 2024. All rights reserved.