C # Процесс StandardInput и StandardOutput с зависанием FFmpeg - PullRequest
0 голосов
/ 04 июня 2018

Я пытаюсь передать поток в 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 голосов
/ 05 июня 2018

Я должен был писать и читать из stdin и stdout асинхронно, чтобы избежать тупика.Комментарий от Wiz и этого поста привел меня в правильном направлении!Спасибо!Также было важно закрыть 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();
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...