Взаимодействовать с 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");
}