Welkom bij de Tweaking4All gemeenschapsforums!
Voor je gaat deelnemen, bekijk de Forum Regels!
Specifieke onderwerpen: Start het onderwerp met de naam van het programma of systeem.
Bijvoorbeeld “MacOS X – Jouw vraag“, of bijvoorbeeld “MS Word – Jouw Tip of Truc“.
Merk op: Omschakelen naar een andere taal zal niet werken als je een post aan het lezen bent aangezien er waarschijnlijk geen vertaling beschikbaar is.
[Opgelost] Lazarus - Hoe lees je de output van ffmpeg of ffprobe?
Delphi, Lazarus, Free Pascal
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
Topic starter
7 september 2013 21:06
Ik was aan het experimenteren met ffprobe (ffmpeg kan hetzelfde probleem hebben) waarbij ik ffprobe aanriep vanuit een Lazarus programma, m.b.v. TProcess, om vervolgens te ontdekken dat het maar geen output gaf.
Om de een of andere (onduidelijke) reden geeft ffprobe geen output via stdout maar via stderr!
Hieronder de code die ik gebruik om fprobe aan te roepen in mijn Lazarus programma:
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); // gebruik de Stderr property i.p.v. de Output property
end;
end;
Dit zou cross platform moeten zijn. Het kan natuurlijk nodig zijn om het pad van ffprobe in de fExec string aan te passen als je bijvoorbeeld Windows draait.
Vergeet niet Process aan de Uses clausule toe te voegen.
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
Topic starter
7 september 2013 22:02
Woops ... ik zie nu dat ik het mis had ...
1) De standaard ffprobe info (versie, libs etc) gaat via stderr.
2) De film informatie echter gaat via stdout.
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
Topic starter
7 september 2013 22:40
Omdat de output soms groot kan zijn van ffprobe, overweeg om regel 9 te veranderen naar:
Options := [poWaitOnExit,poUsePipes];
(@hans)
Famed Member Admin
Deelgenomen: 12 jaar geleden
Berichten: 2864
Topic starter
23 oktober 2013 22:10
Uiteindelijk gebruikte ik voor zowel MacOS X als 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;