Home > front end >  how to capture continuous Realtime progress stream of output (from ffmpeg)
how to capture continuous Realtime progress stream of output (from ffmpeg)

Time:12-06

I am having trouble showing the progress of ffmpeg through my script. I compile my script to exe with ps2exe and ffmpeg output on standard error instead of outputting on standard out So I used to pipe 1 option

my script.ps1 now is:

# $nb_of_frames= #some_int
& $ffmpeg_path -progress pipe:1 -i input.mp4 -c:v libx264 -pix_fmt yuv420p -crf 25 -preset fast -an output.mp4

then I compile it with ps2exe. (to reproduce you don't need the compile, just use the above command with pipe:1 directly in cmd or PowerShell you will get the same behavior)

Normally with ffmpeg you get a progress reporting (that is interactive), one line containing the information and it keeps getting updated as 1 single line without spamming the console with 100s of lines, it looks like this.

frame= 7468 fps=115 q=22.0 size=   40704kB time=00:05:10.91 bitrate=1072.5kbits/s speed= 4.8x

But this does not appear in the compiled version of my script, so after digging I added -progress pipe:1 to get the progress to appear on std out

Now I get a continuous output every second that looks like this:

frame=778
fps=310.36
stream_0_0_q=16.0
bitrate= 855.4kbits/s
total_size=3407872
progress=continue
...
frame=1092
fps=311.04
stream_0_0_q=19.0
bitrate= 699.5kbits/s
total_size=3932160
progress=continue 

I would like to print some sort of updatable percentage out of this, I can compute a percentage easily if I can capture that frame number, but in this case, I don't know how to capture a real-time output like this and how to make my progress reporting update 1 single line of percentage in real-time (or some progress bar via symbols) instead of spamming on many lines

(or if there is a way to make the default progress of FFmpeg appear in the compiled version of my script that would work too)

edit: a suggestion based on the below answer

#use the following lines instead of write-progress if using with ps2exe
            #$a=($frame * 100 / $maxFrames)
            #$str = "#"*$a
            #$str2 = "-"*(100-$a)
            #Write-Host -NoNewLine "`r$a% complete | $str $str2|"

Thanks

CodePudding user response:

Here is an example how to capture current frame number from ffmpeg output, calculate percentage and pass it to Write-Progress:

$maxFrames = 12345

& $ffmpeg_path -progress pipe:1 -i input.mp4 -c:v libx264 -pix_fmt yuv420p -crf 25 -preset fast -an output.mp4 |
    Select-String 'frame=(\d )' | ForEach-Object {
        $frame = [int] $_.Matches.Groups[1].Value
        Write-Progress -Activity 'ffmpeg' -Status 'Converting' -PercentComplete ($frame * 100 / $maxFrames)
    }

Remarks:

  • Select-String parameter is a regular expression that captures the frame number by the group (\d ) (where \d means a digit and requires at least one digit). See this Regex101 demo.
  • ForEach-Object runs the given script block for each match of Select-String. Here $_.Matches.Groups[1].Value extracts the matched value from the first RegEx group. Then we convert it to integer to be able to use it for calculations.
  • Finally calculate the percentage and pass it to Write-Progress.
  • Related