TProcess.Output/Input (нестандартная консоль)

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

TProcess.Output/Input (нестандартная консоль)

Сообщение Voltag » 25.07.2021 03:31:59

Здравствуйте уважаемые!

Пытаюсь работать с ffmpeg.exe и ffplay.exe (http://ffmpeg.org/) цель - захват видео с экрана и потом проиграть. Думал что сделаю быстро(наивный).
Проблема с управлением через TProcess данного exe. Я написал маленькую серию тестов (попробую покороче)(проигрывание файла).
Система: Win10(64) lazarus32 (2.0.10) FPS: 3.2.0
Код: Выделить всё
  MyProc:=TProcess.Create(FormMain);
  MyProc.PipeBufferSize:=1024; //это значение по умолчанию, но я напишу т.к. важно для понимания
  MyProc.Options:= [poUsePipes];
 
  //я исполняю по 1 строчке, но для краткости, отставлю всё здесь
  MyProc.Executable:='calc'; //работает хорошо, как и должно, ничего в консоли не поймали (внизу код) ОК
  MyProc.Executable:='help'; //сработало поймали консоль в мемо, после отработки вышло один раз, прочитали 1024 (смотрите буфер) и вышли - ОК
  MyProc.Executable:='D:\vizion\test\test2.bat'; //это батник с паузами. Проверяю нормально ли работает ожидание, сумели ли словить
  //я подозреваю, что будет работать запись в стрим TProcess.Input (я не проверял, но вроде всё хорошо)
 
  //Внизу дам описание проблем следующего кода
  MyProc.Executable:=path_ffmpeg+'ffplay.exe';
  MyProc.Parameters.Add('D:\vizion\outfolder\output.mkv'); 
  MyProc.Execute();

  Application.ProcessMessages;

  while MyProc.Running do begin
     Label1.Caption:='run';
     Application.ProcessMessages;
     if MyProc.Output.NumBytesAvailable > 0 then
     begin
          MemoCmd.Lines.Add('can be read');
          MemoCmd.Lines.LoadFromStream(MyProc.Output);
     end;
  end;
  Label1.Caption:='not run';

  MyProc.Terminate(0);
  MyProc.Free;
                                               


Подаём экзешник с полным путём (ffplay.exe) и параметр к нему. Всё правильно исходи и из документации, и руками, когда я работаю с консолью всё хорошо
Но при указании [poUsePipes] я не получаю данных (код внизу) ни единого байтика, и само проигрывание не работает (чёрный экран консоли).
Execute без [poUsePipes] работает, а именно, вызывается консоль туда пишутся данные, открывается окно с проигрывателем и файл проигрывается.
ВАЖНО: Консоль там не простая, там отображено динамически данные типа FPS в реальном времени. Возможно поэтому захват консоли не работает, я не имел с таким дело.
При ошибках (например файла не существует) пайп работает как и должно, т.е. я могу всё уловить.
Примечание: Если Tprocess или TUTFProcess на форме как компоненты, т.е. они статические
то при вызове повторно, окошко с видео появляется, т.е. я один раз клацаю на кнопку, второй раз. Потом закрываю первое висящую консоль, и появляется проигрыватель(играет видео), вторая консоль видна, но данные я не могу с неё получить. Я проверил все настройки, но не понимаю почему так.
И последнее, проблема в том что мне надо прервать запись/проигрывание, для этого я должен в консоль написать пару чаров(насколько я понимаю), но,
1. Я не получил первичный ответ от процесса, может он занят, не знаю я
2. При попытки записи нет эффекта или ошибка памяти...
Вот ответ по поводу работы с ffmpeg, я могу плохо объяснять
https://stackoverflow.com/questions/797 ... eo-capture

Возможно, я должен был написать всё раньше т.к. плохо биться долго головой о стену.
Да, я мог бы скачать длл ки, и заголовочные, но я думал что через консоль то проще. + нет зависимости о заголовков + документация для EXE для всех языков с примерами + могу написать хоть автоматическое обновление
Пожалуйста подскажите, в чём может быть проблема.

upd:
пытался читать "нормальным методом" для больших данных в консоли, через TTimer(1000)
висит намертво вот на этой строке
Код: Выделить всё
  BytesRead    : longint;
  Buffer         : array[1..BUF_SIZE] of byte;
...
BytesRead := MyGlobalProc.Output.Read(Buffer, BUF_SIZE);

Величина буфера совпадает с PipeBufferSize
Поигрался с выводом логов. Нашёл настройку ffmpeg вывод статичных логов, читать их не получается (после любых операций остаётся 2 байта на чтение), хотя в консоли красным по чёрному написана ошибка =)))

upd:
Можно настроить вывод ffmpeg более дружелюбнее, я перенаправил весь вывод в файл
можно это делать как стандартными способами операционных систем(наверно), так и сам ffmpeg имет систему репортов, необходимо указать параметр в Environment (TProcess)
К примеру:
Код: Выделить всё
  MyGlobalProc.Environment.Add('FFREPORT=file='''+path_ffmpeg+'fflog.log'':level=24');  //24 - уровень лога в файл

А вывод логов на уровне консоли отключить:
Код: Выделить всё
ffplay.exe output.mkv -loglevel +quiet

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

upd:
Стена оказалась сильнее =))). Я всё сделал через консоль, но при указании [poNoConsole] в TProcess я не могу корректно закрыть консольное приложение. on_close/exit не отрабатывается у процесса без консоли, например надо закончить захват экрана, и при выходе ffmpeg(в onclose) завершает концовку файла и закрывает медиа контейнер.
Terminate пробовал , пробовал PostMessage - говорит что WM_CLOSE для окон, хотя бы консольных. Пробовал через taskkill, не хочет работать без ключа /f который принудительно kill приложение.
[poNoConsole] - это WinApi CreateProcess с параметром CREATE_NO_WINDOW (как то так). А начиналось всё не так плохо...
Последний раз редактировалось Voltag 27.07.2021 03:21:41, всего редактировалось 2 раз(а).
Voltag
новенький
 
Сообщения: 29
Зарегистрирован: 02.04.2008 03:49:33

Re: TProcess.Output/Input проблемы

Сообщение zoltanleo » 26.07.2021 13:32:27

Написано очень много. Хорошо бы суть вопроса излагать в 2-3 строках. А подробности отдельно :)

Если посмотреть на код, то ты просто плохо изучил документацию. Вкратце - на каждый исполняемый файл -один TProcess. Либо запускаешь экзешники последовательно. Пока могу только отравить к документации, особенно обрати на комментарий переводчика
https://wiki.freepascal.org/Executing_E ... 0.B4.D0.B0

У меня все робит, консольный вывод идет в TMemo на форме
Аватара пользователя
zoltanleo
постоялец
 
Сообщения: 457
Зарегистрирован: 17.10.2013 10:55:01

Re: TProcess.Output/Input проблемы

Сообщение Voltag » 27.07.2021 03:20:25

to zoltanleo
Если я запускаю bat, например с последовательным выводом, то всё нормально работает.
Проблема в том, что при вызове определённых программ (ffmpeg.exe ffplay.exe) по какой-то причине консольный вывод у них не ловиться, происходит ошибка на каком-то уровне.
Некоторые процессы вывода в консоль этих файлов идут с динамичеки/интерактивно 1 строкой, в которой всё меняется (как раз я не могу получить текст из консоли).
Представьте себе архив который распоковываеться в консоли и 1 строкой пишет %(от 1-100) распаковки, (1 строкой - это не переходя на новую строку). В 1 строке меняются значения от 1 до 100.
И в процессе я не могу прочитать данные.
Это отдельный вопрос, как такое сделать и главный вопрос можно ли такое читать и как.
Спасибо за ответ =)

Я стараюсь не только получить ответ, но и чтобы проблема была решена, чтобы было видно как она может быть решена, а если нет, то почему.
На нестандартные вещи уходит очень много времени. И я очень радуюсь, когда нахожу решения, которые были оставлены другими людьми.

p/s подправил заголовок темы, теперь он более понятен
Voltag
новенький
 
Сообщения: 29
Зарегистрирован: 02.04.2008 03:49:33

Re: TProcess.Output/Input (нестандартная консоль)

Сообщение zoltanleo » 27.07.2021 06:19:38

TProcess - это одноразовое действие исполняемого файла. Боюсь, что ни о какой интерактивности речи быть не может. Батник - это вообще запуск системного шелла. И немного из другой области.

На мой взгляд, наверное стоит как-то пересмотреть способы решения задач.
Аватара пользователя
zoltanleo
постоялец
 
Сообщения: 457
Зарегистрирован: 17.10.2013 10:55:01

Re: TProcess.Output/Input (нестандартная консоль)

Сообщение Снег Север » 27.07.2021 08:46:37

В делфи (под виндой, естественно) через использование функций API можно полностью перехватить и ввод, и вывод в запущенную из приложения стороннюю консольную программу. Через named pipes. Когда-то делал сам. Готовое решение несложно отыскать через гугл. Можно ли сделать подобное с TProcess не знаю.
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2995
Зарегистрирован: 27.11.2007 16:14:47

Re: TProcess.Output/Input (нестандартная консоль)

Сообщение Voltag » 27.07.2021 09:18:53

to zoltanleo
Да, я согласен с вами, что часто приходятся выполнять задачи одноразовый запуска, TProcess c этим справляется. TProcess есть так-же как визуальный компонент, я предполагаю, что его делали для многоразового использования, иначе он просто не нужен в панели. Так-же у TProcess есть задокументированный TProcess.Input (stream) который позволяет писать в консоль. Т.е. он подразумевает так-же интерактивность. И с этим тоже нет проблем. Если пользоваться стандартным выводом построчным, то всё хорошо(я не проверял прям основательно). Но, вывод файлов не стандартный, потому, что он не читается стандартными средствами, или я что-то пропускаю или не вижу строку в документации. Я решил эту проблему комбинацией логов самого ffmpeg и некоторой доступной логикой того же TProcess.

Т.е я решил проблему, сделал это с "другой" стороны. Но я нашёл ещё одну проблему, которую описал. О том, что флаг poNoConsole, не скрывает консоль так, чтобы её не было видно, оказалось что она лишает процесса "оконности", например ему нельзя послать postMessage потому, что "Ошибка: неверный дискрптор окна". Хотя, я считал наивно, что любой процесс - это окно. Видимо и очевидно, что я плохо знаю архитектуру ОС. и я запутался =)))

Добавлено спустя 11 минут 32 секунды:
to Снег Север
Спасибо за совет! Я взял TProcess как задел на кроссплатформенность, сижу экспериментирую. Стали понятны некоторые ограничения. Пытаюсь использовать систему сообщений виндовых, что как бы убивает всю идею, но по другому видимо никак. Если сдамся совсем, то перейду на винапи.
Voltag
новенький
 
Сообщения: 29
Зарегистрирован: 02.04.2008 03:49:33

Re: TProcess.Output/Input (нестандартная консоль)

Сообщение zoltanleo » 27.07.2021 10:05:25

Консольные окна не имеют хендла, если я правильно ошибаюсь. А значит никаких сообщений.

А TProcess - кроссплатформенный шелл. Если исходить из этих предпосылок, то все становится на свои места
Аватара пользователя
zoltanleo
постоялец
 
Сообщения: 457
Зарегистрирован: 17.10.2013 10:55:01

Re: TProcess.Output/Input (нестандартная консоль)

Сообщение Voltag » 27.07.2021 10:50:37

да, zoltanleo, вы правы. цитирую справку винды:
CREATE_NO_WINDOW
The process is a console application that is being run without a console window. Therefore, the console handle for the application is not set.
т.е. Консольное приложение запускается без окна консоли. Следовательно, хендл консоли для приложения не установлен.
TProcess вызывает CreatProcessW (я смотрел TProcessUTF8). Мне понятно почему меня не пускает, хотя on_close/exit есть.

не стал перфектничать (работа без консоли). Вместо [poNoConsole] сделал:
Код: Выделить всё
TProcess.ShowWindow := swoHide;

условно решил проблему, хотя в процессах виден "хост окна консоли"(win10), зато не буду голову ломать никому.

Спасибо всем за ответы.
Voltag
новенький
 
Сообщения: 29
Зарегистрирован: 02.04.2008 03:49:33

Re: TProcess.Output/Input (нестандартная консоль)

Сообщение Ichthyander » 30.07.2021 12:40:40

Много написано, все не осилю. Но смысл как я понял связь с приложением через cli интерфейс. Вот пример либы, которая подключается к внешнему приложению через консоль, отправляет команды и считывают информацию из него. Вообщем, полная интерактивность, работает через TProcess: https://github.com/Al-Muhandis/fp-youtube-dl
Аватара пользователя
Ichthyander
энтузиаст
 
Сообщения: 675
Зарегистрирован: 04.04.2007 08:32:43
Откуда: Астрахань


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и гости: 25

Рейтинг@Mail.ru