[FFmpeg-trac] #9589(undetermined:new): Progress-report line need be constrained to 80 characters at maximum

FFmpeg trac at avcodec.org
Fri Jan 7 22:19:48 EET 2022


#9589: Progress-report line need be constrained to 80 characters at maximum
-------------------------------------+-------------------------------------
             Reporter:  blit2z       |                     Type:  defect
               Status:  new          |                 Priority:  normal
            Component:               |                  Version:
  undetermined                       |  unspecified
             Keywords:  Progress-    |               Blocked By:
  report CR                          |
             Blocking:               |  Reproduced by developer:  0
Analyzed by developer:  0            |
-------------------------------------+-------------------------------------
 As you know, "ffmpeg" displays a progress-report line like the following.
 Note that there are four white spaces at the end.

 {{{
 frame=  315 fps=0.0 q=29.0 size=       0kB time=00:00:08.73 bitrate=
 0.0kbits/s speed=17.4x
 }}}

 The width of every progress-report line printed by "ffmpeg" is 97
 characters, and ends with a Carriage Return character (CR 0x0D \r).
 However, it is strongly advisable that the width of progress-report line
 ending with CR should be constrained to 80 characters at maximum.  Let me
 explain why.

 The problem that arises when the progress-report line is wider than 80
 characters is a generic problem that occurs with not only "ffmpeg" but any
 CLI program that uses CR to implement a progress-report line.  Thus,
 before I continue to talk about the progress-report line of "ffmpeg", let
 me expound the Carriage Return character (CR 0x0D \r) and a progress-
 report line in general which is NOT specific to "ffmpeg".

 As used by some command-line programs on Unix-like systems, the Carriage
 Return character (CR 0x0D \r) is useful to implement a progress-report
 line.

 To see what a progress-report line is, save the following code as
 "cr_test_progress.sh", and execute it on a terminal window whose width is
 80 characters or more.

 {{{
 #!/bin/bash

 printf %b 'processed=10%    speed=7.3mbits/s '; sleep 1; printf %b '\r'
 printf %b 'processed=20%    speed=7.0mbits/s '; sleep 1; printf %b '\r'
 printf %b 'processed=30%    speed=8.8mbits/s '; sleep 1; printf %b '\r'
 printf %b 'processed=40%    speed=7.3mbits/s '; sleep 1; printf %b '\r'
 printf %b 'processed=70%    speed=14.4mbits/s'; sleep 1; printf %b '\r'
 printf %b 'processed=80%    speed=7.1mbits/s '; sleep 1; printf %b '\r'
 printf %b 'processed=100%   speed=12.8mbits/s\n'
 }}}

 A progress-report line refreshes with new information, overwriting and
 deleting the old line.  The Carriage Return character (CR 0x0D \r) causes
 the carriage (or cursor or caret) to return to the first column on the
 current terminal row without advancing the carriage to the line below.
 Hence the current terminal row will be overwritten.  If each progress-
 report line ended with a newline character (LF 0x0A \n) instead of a
 carriage return character (CR 0x0D \r), then the line would not be
 overwritten, and each old line of the progress-report would persist where
 they are and would build up; thus, the terminal screen would be flooded
 with obsolete information.

 By the way, let me use the term "pseudo-line" for a line ending with CR,
 when it is desired to distinguish it from a full line ending with a
 newline character (LF 0x0A \n).  When it is unimportant to distinguish the
 two, I may call both kinds of line just a "line".  Also note that a
 "terminal line", that is, a line on a terminal screen, is sometimes should
 be distinguished from a line in a file or a line being sent to the
 terminal.

 If any line in general (regardlessly of whether containing CR or not) is
 longer than the width of the terminal window, then the terminal wraps the
 line.  Whether this wrap is hard or soft depends on the terminal program.

 In most cases, the factory default for the width of a terminal window is
 80.  Thus, suppose that the terminal window is 80 characters wide.
 Suppose also that a progress-report pseudo-line ending with CR is 90
 characters long.  Then, the terminal wraps it into two terminal lines (80
 and 10), and brings the cursor back to the beginning of the 10-character-
 long latter line.

 Do not expect as if the CR would cause the terminal to move the cursor
 back to the beginning of the 80-character-long first part.  In fact, only
 the 10-character-long latter part is deleted and overwritten; the 80
 -character-long first part is never deleted and hence persists there.
 Thus, the 80-character-long first part builds up, as the progress-report
 pseudo-line refreshes repeatedly.

 To see this behavior, save the following code as "cr_test_wide.sh", and
 execute it on a terminal window whose width is exactly 80 characters.
 When copying, pasting and saving the following code, make sure not to
 hard-wrap it.

 {{{
 #!/bin/bash

 echo      '         1         2         3         4         5         6
 7         8'
 echo
 '12345678901234567890123456789012345678901234567890123456789012345678901234567890'
 printf %b
 '11111111111111111111111111111111111111111111111111111111111111111111111111111111ABCDEFGHIJ';
 sleep 2; printf %b '\r'
 printf %b
 '22222222222222222222222222222222222222222222222222222222222222222222222222222222abcdefghij';
 sleep 2; printf %b '\r'
 printf %b
 '33333333333333333333333333333333333333333333333333333333333333333333333333333333QRSTUVWXYZ';
 sleep 2; printf %b '\r'
 printf %b
 '44444444444444444444444444444444444444444444444444444444444444444444444444444444qrstuvwxyz\n'

 }}}

 Each line consists of 80 digits followed by 10 alphabets, totaling 90
 visible characters.  The first three lines are pseudo-lines ending with
 CR.  The last line ends with LF.  Assuming the window width is 80
 characters, the terminal wraps each line into 80 digits and 10 alphabets.
 For each pseudo-line, only the 10 alphabets are deleted and overwritten;
 and all the digits persist and build up.

 Note that this behavior that CR causes the cursor to return to the
 beginning of the latter row is regardless of whether the wrap is hard or
 soft.  This behavior is reasonable for hardwrapped rows.  Upon
 encountering a CR, the terminal simply returns the cursor to the first
 column of the current terminal row.  For softwrapped rows, this behavior
 may be somewhat counter-intuitive.  Nevertheless, this is how terminals
 behave upon encountering a CR.  This is true for Linux (GNOME Terminal on
 Cinnamon desktop and MATE Terminal on MATE desktop) and macOS
 (Terminal.app).

 To reproduce the problem with "ffmpeg", set the width of the terminal
 window to 80 characters, and run any "ffmpeg" command (such as the
 following) that prints a progress-report line.  It seems that any
 progress-report line printed by "ffmpeg" is 97 characters long including
 trailing spaces.  The following command generates an mp4 video which is
 simply a black burst with no interesting pictures, and whose resolution is
 640x480 and whose duration is 240 seconds.  The file size of the resultant
 video is approximately 250 KB.  As it generates the video, it reports the
 progress.  Make sure that the width of the terminal window to 80
 characters.

 {{{
 ffmpeg -f lavfi -i color=s=640x480:r=30:d=240:c=0x000000 -f mp4
 black_480.mp4
 }}}


 It is common that the width of terminal window is 80 characters by default
 out of the box.  It is strongly advisable that the width of progress-
 report line ending with CR should be constrained to 80 characters at
 maximum.

 An exemplar program that conforms to this constraint is "curl".  "curl"
 wisely constrains the width of its progress-report line to 78 characters.

 The reason why the progress-report line of `ffmpeg` is very long and why
 that of `curl` is concise follows.  On each progress-report line, `ffmpeg`
 prints not only values but also field names.  On the other hand, `curl`
 prints only values on each progress-report line, and prints field names on
 the header only once, separating field names from values.

 Here is an example of progress report by `curl`.  The header with field
 names ends with LF, is printed only once, and stays there permanently.
 The values are on the pseudo-line ending with CR, and are repeatedly
 refreshed and updated.

 {{{
   % Total    % Received % Xferd  Average Speed   Time    Time     Time
 Current
                                  Dload  Upload   Total   Spent    Left
 Speed

  39  133M   39 52.1M    0     0  46.9M      0  0:00:02  0:00:01  0:00:01
 42.8M
 }}}


 It is desirable that "ffmpeg" should constrain the width of progress-
 report line to 80 characters at maximum as "curl" does.
-- 
Ticket URL: <https://trac.ffmpeg.org/ticket/9589>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list