How to print Continuous output of Popen when reset character is used

Question:

I have a snippet of code that runs a video conversion using ffmpeg.

I read the output to analyze it later in the application, and also want to print it to console, for user feedback.

So I have

p = Popen(['ffmpeg', *args], stderr=STDOUT, stdout=PIPE)
while True:
    line = p.stdout.readline()
    if not line: 
        break
    print(line.decode('utf-8'), end='')

p.wait()
if p.returncode == 0:
    pass

Which works, somewhat. It prints the initial output of the ffmpeg command, as those are simple print statements.

But once the conversion starts, all the output is updated on one line, presumably using some reset character to move the cursor position back to the start of the line.

Is there a way to continue to print that output?

Edit:

Answer

p = subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE, universal_newlines=True)

with p.stdout:
    for line in iter(p.stdout.readline, None):
        if not line:
            break
        if line.startswith('frame'):
            print(f'33[2K{line.strip()}r', end='')
        else:
            print(line, end='')

This includes the cursor return, and clears the current line before printing to it again. And still prints the part I want on the same line, like it normally does.

Asked By: cclloyd

||

Answers:

Here’s an old code snippet of mine, which includes the universal_newlines=True option and then iterates over the stdout.

#!/usr/bin/env python3
from subprocess import Popen, PIPE, STDOUT
orig_file='V1.mp4'
new_file='V1.mkv'

command_line='ffmpeg -y -i '+orig_file+' '+new_file # -y Overwrite output files without asking
comm = Popen(command_line, shell=True, stdout=PIPE, stderr=STDOUT, universal_newlines=True)
with comm.stdout:
    for line in iter(comm.stdout.readline, b''):
        print(line.strip())
        if "Done" in line:
            break
        if line != '':
            pass
        else:
            break

Obviously, you can quiz the contents of line and decide which lines you wish to use, or define your output based on the contents.

Output snippet:

....
frame=    1 fps=0.0 q=0.0 size=       5kB time=00:00:00.11 bitrate= 334.6kbits/s speed=3.14x
frame=   54 fps=0.0 q=28.0 size=       5kB time=00:00:02.40 bitrate=  16.4kbits/s speed=4.16x
frame=   83 fps= 74 q=28.0 size=       5kB time=00:00:03.54 bitrate=  11.1kbits/s speed=3.18x
frame=  110 fps= 68 q=28.0 size=       5kB time=00:00:04.69 bitrate=   8.4kbits/s speed=2.91x
frame=  130 fps= 60 q=28.0 size=       5kB time=00:00:05.49 bitrate=   7.2kbits/s speed=2.53x
frame=  150 fps= 56 q=28.0 size=       5kB time=00:00:06.33 bitrate=   6.2kbits/s speed=2.37x
frame=  174 fps= 53 q=28.0 size=     256kB time=00:00:07.33 bitrate= 285.9kbits/s speed=2.25x
frame=  195 fps= 52 q=28.0 size=     256kB time=00:00:08.21 bitrate= 255.4kbits/s speed=2.18x
....
Answered By: Rolf of Saxony
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.