Capturing progress, snapshots and returns from ffmpeg command line on windows lazarus / 21-General ---------------------------------------------------------------------- Mig.BR · 2022-07-17 06:22 For some time I have been looking for ways to mainly capture the progress of a conversion using the ffmpeg.exe command line but have found little. I decided to create something along these lines myself based on what I learned. I hope it will be useful to some and that others, more advanced, will suggest improvements. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i unit untFFMpeg; {$mode ObjFPC}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ComCtrls, StdCtrls, Process, Pipes,  StrUtils, DateUtils, FileUtil, ExtCtrls; type   { TFFMpegProcess }  TFFMpegProcess = class(TProcess)  private    fsErrorString : String;   procedure ProcessEvent(Sender, Context: TObject; Status: TRunCommandEventCode; const Message: String);  public    flMemo: TMemo;    flPBar: TProgressBar;    flFrame: TImage;    fiBytesProcessed: Integer;    fiStringsAdded: Integer;    fiDuration: Integer;    fiProgress: Integer;    fiPosition: Integer;  fsDuration: String;    fsProgress: String;    fsInputFile: String;  fsOutputFile: String;    fnDuration: TTime;    fnProgress: TTime;    function ReadInputStream(lBuf: TInputPipeStream; var iBytesRead: Integer; var iDataLength: Integer; var sData: String; iMaxLoops: Integer = 10): Boolean; override;  end;   function RunFFMpegProcess(const sExeName: TProcessString; const aCommands: array of TProcessString; out sOutputString: string; oProcOptions: TProcessOptions = []; eWinShowOption: TShowWindowOptions = swoNone; lMemo: TMemo = nil; lPBar: TProgressBar = nil; lFrame: TImage = nil; lRunRefresh: TOnRunCommandEvent = nil): Boolean;  implementation  function RunFFMpegProcess(const sExeName: TProcessString; const aCommands: array of TProcessString; out sOutputString: string; oProcOptions: TProcessOptions = []; eWinShowOption: TShowWindowOptions = swoNone; lMemo: TMemo = nil; lPBar: TProgressBar = nil; lFrame: TImage = nil; lRunRefresh: TOnRunCommandEvent = nil): Boolean;var vlProc: TFFMpegProcess;    viCnt, viExitStatus: Integer;begin  vlProc := TFFMpegProcess.Create(nil);  vlProc.fiDuration := 0;  vlProc.fiProgress := 0;  vlProc.fsDuration := '';  vlProc.fsProgress := '';  vlProc.fnDuration := EncodeTime(0,0,0,0);  vlProc.fnProgress := EncodeTime(0,0,0,0);  vlProc.flMemo := lMemo;  vlProc.flPBar := lPBar;  vlProc.flFrame := lFrame;  if vlProc.flMemo <> nil then    vlProc.flMemo.Clear;  if vlProc.flPBar <> nil then  begin    vlProc.flPBar.Max := 100;    vlProc.flPBar.Position := 0;  end;  if vlProc.flFrame <> nil then    vlProc.flFrame.Picture.Clear;  if lRunRefresh <> nil then    vlProc.OnRunCommandEvent := lRunRefresh  else    vlProc.OnRunCommandEvent := @vlProc.ProcessEvent;   if oProcOptions <> [] then    vlProc.Options := oProcOptions - [poRunSuspended, poWaitOnExit];  vlProc.Options := vlProc.Options + [poRunIdle];  vlProc.ShowWindow := eWinShowOption;  vlProc.Executable := sExeName;  if High(aCommands) >= 0 then   for viCnt := Low(aCommands) to High(aCommands) do     vlProc.Parameters.Add(aCommands[viCnt]);   try    Result := vlProc.RunCommandLoop(sOutputString, vlProc.fsErrorString, viExitStatus) = 0;  finally    vlProc.Free;  end;   if viExitStatus <> 0 then    Result := False;end; { TFFMpegProcess }function TFFMpegProcess.ReadInputStream(lBuf: TInputPipeStream; var iBytesRead: Integer; var iDataLength: Integer; var sData:String; iMaxLoops: Integer = 10): Boolean;var viLFPos : Integer;    viCRCorrectedPos:Integer;    viEPos, viELen: Integer;    vsFndExpr: String;    viStrAdded: Integer;    vsNewStr: String;    viHH, viNN, viSS, viMS: Word;begin  Result := inherited ReadInputStream(lBuf, iBytesRead, iDataLength, sData, iMaxLoops);  sData := StringReplace(sData, ' time=', LineEnding+'time=', []);  if (Result) and (iBytesRead > fiBytesProcessed)then  begin    viStrAdded := 0;    viLFPos := pos(#10, sData, fiBytesProcessed+1);    while (viLFPos <> 0) and (viLFPos <= iBytesRead) do    begin      viCRCorrectedPos := viLFPos;      if (viCRCorrectedPos > 0) and (sData[viCRCorrectedPos-1] = #13) then        Dec(viCRCorrectedPos);      vsNewStr := Copy(sData, fiBytesProcessed+1, viCRCorrectedPos - fiBytesProcessed-1);      ////--Memo, PBar, Duration, Progress--////      if Trim(vsNewStr) <> '' then      begin        //Add vsNewStr To Memo        if flMemo <> nil then          flMemo.Lines.Add(Trim(vsNewStr));        //Get Duration in vsNewStr        if fsDuration = '' then        begin        vsFndExpr := 'Duration: ';          viEPos := Pos(vsFndExpr, vsNewStr);          if viEPos > 0 then          begin            viELen := Length(vsFndExpr);            fsDuration := Copy(vsNewStr, viEPos+viELen, Pos('.', vsNewStr, viEPos)-(viEPos+viELen)+3);          fnDuration := StrToTimeDef(Copy(fsDuration, 1, Length(fsDuration)-3), EncodeTime(0,0,0,0));            DecodeTime(fnDuration, viHH, viNN, viSS, viMS);            fiDuration := viHH*3600 + viNN*60 + viSS;            if flPBar <> nil then            flPBar.Max := fiDuration;          end;        end;        //Get InputFile in vsNewStr        if fsInputFile = '' then        begin        vsFndExpr := 'Input #0,';          viEPos := Pos(vsFndExpr, vsNewStr);          if viEPos > 0 then          begin            vsFndExpr := 'from ''';            viEPos := Pos(vsFndExpr, vsNewStr);            if viEPos > 0 then            begin            viELen := Length(vsFndExpr);              fsInputFile := Copy(vsNewStr, viEPos+viELen, Pos(''':', vsNewStr, viEPos)-(viEPos+viELen));            end;          end;        end;      //Get InputFile in vsNewStr        if fsOutputFile = '' then      begin          vsFndExpr := 'Output #0,';          viEPos := Pos(vsFndExpr, vsNewStr);          if viEPos > 0 then          begin          vsFndExpr := 'to ''';            viEPos := Pos(vsFndExpr, vsNewStr);            if viEPos > 0 then            begin            viELen := Length(vsFndExpr);              fsOutputFile := Copy(vsNewStr, viEPos+viELen, Pos(''':', vsNewStr, viEPos)-(viEPos+viELen));            end;          end;        end;      //Get Progress in vsNewStr        vsFndExpr := 'time=';        viEPos := Pos(vsFndExpr, vsNewStr);        if viEPos > 0 then        begin          viELen := Length(vsFndExpr);          fsProgress := Copy(vsNewStr, viEPos+viELen, Pos('.', vsNewStr, viEPos)-(viEPos+viELen)+3);          fnProgress := StrToTimeDef(Copy(fsProgress, 1, Length(fsProgress)-3), EncodeTime(0,0,0,0));          DecodeTime(fnProgress, viHH, viNN, viSS, viMS);          fiProgress := viHH*3600 + viNN*60 + viSS;        if flPBar <> nil then            flPBar.Position := fiProgress;      end;        if OnRunCommandEvent <> @ProcessEvent then          Application.ProcessMessages;      end;      Inc(viStrAdded);      fiBytesProcessed := viLFPos;      viLFPos := pos(#10, sData, fiBytesProcessed+1);    end;    Inc(fiStringsAdded, viStrAdded); //Check Idle Event.  end;end; procedure TFFMpegProcess.ProcessEvent(Sender, Context: TObject; Status: TRunCommandEventCode; const Message: String);begin  if Status = RunCommandFinished then  begin    if flMemo <> nil then    begin      if Trim(fsErrorString) = '' then        flMemo.Lines.Add('... Process finished! Conversion failed: ' + fsErrorString)      else      if fiProgress < fiDuration then        flMemo.Lines.Add('... Process finished! Incomplete Conversion!')      else        flMemo.Lines.Add('... Process finished! Conversion completed.');    end;    if flPBar <> nil then    begin      flPBar.Max := 100;      flPBar.Position := 0;    end;    if flFrame <> nil then      if Pos('.png', LowerCase(fsOutputFile)) > 0 then        if FileExists(fsOutputFile) then        begin          try            flFrame.Picture.Clear;            flFrame.Picture.PNG.LoadFromFile(fsOutputFile);            DeleteFile(fsOutputFile);          except            flFrame.Picture.Clear;          end;        end;  end;  Sleep(10);  Application.ProcessMessages;end; end. ---------------------------------------------------------------------- mosquito · 2022-07-17 09:55 thx a lot for share !! I will try sure.