Progress-report line need be constrained to 80 characters at maximum
|Reported by:||blit2z||Owned by:|
|Blocking:||Reproduced by developer:||no|
|Analyzed by developer:||no|
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.