Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Lazarus - How to read the output from ffmpeg or ffprobe?

4 Posts
1 Users
0 Reactions
4,945 Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2858
Topic starter  

I was dabbling with ffprobe (ffmpeg might be affected as well) calling it from the command-line in a Lazarus program, using TProcess, only to notice that I didn't get any output back from the command-line call.

Low and behold, for some reason odd ffprobe actually doesn't use stdout but stderr.
The code below shows how I call ffprobe and catch it's output in Lazarus:

procedure TForm1.Button1Click(Sender: TObject);
var fExec, Args : string;
begin
fExec := './ffprobe';
Args := '';
with TProcess.Create(self) do
begin
CurrentDirectory := '.';
Options := [poUsePipes];
CommandLine := fExec + ' ' + Args;
Execute;
Memo1.Lines.LoadFromStream(Stderr); // use the Stderr property instead of the Output property
end;
end;

This should be cross platform, with the exception of course on how ffprobe is called in the fExec string (patch and such).

Don't forget to add Process to your Uses clause.


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2858
Topic starter  

I stand corrected:

1) The default info from ffprobe (version, libs, etc) goes through stderr.

2) The movie informatie however comes through stdout.


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2858
Topic starter  

Note: Output can be pretty extensive. If that's the case consider having Lazarus wait by changing line 9 to:

Options := [poWaitOnExit,poUsePipes];

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2858
Topic starter  

In the end I used this for both MacOS X and Windows:

{$IFDEF DARWIN} // Mac
fExec := ProgramDirectory+'ffprobe';
{$ENDIF}
{$IFDEF WINDOWS} // Windows
fExec := 'ffprobe.exe';
{$ENDIF}
MyShell := TProcess.Create(self);
ShellResult := TStringList.Create;
MemStream := TMemoryStream.Create;
BytesRead := 0;
with MyShell do
begin
Options:=[poUsePipes];
ShowWindow:=swoHIDE;
Executable:=fExec;
Parameters.Add('-show_format');
Parameters.Add('-show_streams');
Parameters.Add('-v');
Parameters.Add('quiet');
Parameters.Add('-print_format');
Parameters.Add('ini');
Parameters.Add(movieFile);
Execute;
end;
while MyShell.Running do
begin
MemStream.SetSize(BytesRead + READ_BYTES);
NumBytes := MyShell.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
if NumBytes > 0 then
begin
Inc(BytesRead, NumBytes);
end
else
begin
Sleep(100);
end;
end;
repeat
// make sure we have room
MemStream.SetSize(BytesRead + READ_BYTES);
// try reading it
NumBytes := MyShell.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
if NumBytes > 0 then
begin
Inc(BytesRead, NumBytes);
end;
until NumBytes <= 0;
MemStream.SetSize(BytesRead);
ShellResult.LoadFromStream(MemStream);
MemStream.Free;
MyShell.Free;      

   
ReplyQuote
Share: