Взаимодействовать с ffmpeg из программы.NET - запись ввода

Что касается этого вопроса, то, как вы видите, мне удалось запустить и получить данные из программы.

Однако мне не удалось передать в него данные, например, при конвертации файла, нажав q немедленно прекратите конвертацию и остановите программу.
Мне нужно, чтобы мое приложение также поддерживало остановку процесса, и я думаю, что это должно быть сделано путем передачи этого параметра в приложение ffmpeg, так как я хочу, чтобы оно позаботилось обо всех невыбранных ресурсах или любой другой пыли, которую оно оставит, если я просто иди и используй process.Kill()

Вот что я попробовал:

static int lineCount = 0;
static bool flag;
static void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
  Console.WriteLine("Error ({1:m:s:fff}: {0})", lineCount++,
      DateTime.Now);

  if (e.Data != null && string.Equals(e.Data,"Press [q] to stop, [?] for help")) 
    flag = true;

  if (flag)
  {
    flag = false;
    Console.WriteLine("Stopping ({0:m:s:fff})...", DateTime.Now);
    process.CancelErrorRead();
    process.CancelOutputRead();
    process.StandardInput.WriteLine("q");
  }   

  Console.WriteLine(e.Data);
  Console.WriteLine();
}

Но он ничего не делает, кажется, что как только запрос на преобразование был запрошен, у меня больше нет контроля над ним, я могу только получать выходные данные от него. Запуск его в автономном режиме, конечно, позволяет мне взаимодействовать.

Чего мне здесь не хватает, это другой трюк при отправке вывода или код в предыдущем ответе неверный, или я должен был выбрать другой подход?

К вашему вниманию, RedirectStandardInput включен

ПРИМЕЧАНИЕ: как вы можете видеть в ответе на мой предыдущий вопрос, ffmpeg взаимодействует по-другому, я думаю, что тот, кто знает ответ, будет (возможно, я ошибаюсь) кто-то с опытом работы в ffmpeg.

2 ответа

Решение

Использование WriteLine('q'); вместо Write('q');,

:)

Я попытался запустить ffmpeg из оболочки Cygwin Bash и увидел, что я должен был ввести Enter после 'q', Так....

    static void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
    {
        Console.WriteLine("Error line: {0} ({1:m:s:fff})", lineCount++,
            DateTime.Now);
        Console.WriteLine(e.Data);
        Console.WriteLine();
        if (lineCount == 5)
            process.StandardInput.WriteLine("q");
    }

С запасом c:\Documents and Settings\All Users\Documents\My Music\Sample Music\Beethoven's Symphony No. 9 (Scherzo).wma

  • без process.StandardInput.WriteLine он печатает 61 строку на stderr, 1 строку на stdout и создает mp3-файл размером 1212457 байт.
  • добавьте выход и он напечатает меньше строк на stderr, ничего на stdout и намного меньший mp3-файл.

Обратите внимание, что он оставляет файл mp3 вокруг.

Так что.

РЕДАКТИРОВАТЬ

После просмотра вашего комментария вы уже попробовали это..

Я только что перепроверил. Поведение странное.

Сначала я повторил то, что имел, и увидел, что отправка "q\n" на 5-й строке для sterr создается файл намного меньшего размера, хотя в разных сериях он немного отличается - от 160К до 220К.

Далее я закомментировал Console.WriteLine надеясь, что это заставит ffmpeg выйти быстрее. Напротив, ffmpeg теперь вообще не останавливался и создал полный файл с точно таким же количеством байтов, 1212457 байт. Такое поведение согласуется с вашим наблюдением

Наконец, с WriteLines на месте я прокачал "q\n" на каждой строке stderr после пятого. Большой сюрприз! После регистрации 40 строк ошибок,

Unhandled Exception: System.InvalidOperationException: StandardIn has not been redirected.
   at System.Diagnostics.Process.get_StandardInput()
   at StandAlone.Program.process_ErrorDataReceived(Object sender, DataReceivedEventArgs e) in C:\[..]\StandAlone\Program.cs:line 171
   at System.Diagnostics.Process.ErrorReadNotifyUser(String data)

Не перенаправлен? И вы говорите мне после того, как я отправил 35 строк на его вход?

Что-то не совсем правильно... пахнет ошибкой.

Обновление от автора:

Обновление сборок Windows отсюда (статическое) решило мою проблему, я использовал несколько сборок с неофициального сайта.

Мне удалось, я использую глобальные переменные, как в процессе в моем коде:

private void RunProcessAsync(string FfmpegPath, string Parameters)
{
  //Create process info
  ProcessStartInfo oInfo = new ProcessStartInfo(FfmpegPath, Parameters);
  //Set process properties
  oInfo.UseShellExecute = false;
  oInfo.CreateNoWindow = true;
  oInfo.RedirectStandardOutput = false;
  oInfo.RedirectStandardError = true;
  oInfo.RedirectStandardInput = true;

  process.StartInfo = oInfo;

  process.EnableRaisingEvents = true;
  process.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
  process.Exited += new EventHandler(proc_Exited);

  process.Start();
  // this.pid = proc.Id;          
  process.BeginErrorReadLine();
}

public void stopProcess()
{
  process.StandardInput.WriteLine("q");
}
Другие вопросы по тегам