我的最终目标是在使用 fdkaac 编码时获得 zenity 进度对话框。
我首先从一些代码开始,当我用 lame 将“aa.wav”编码为“aa.mp3”时,这些代码可以正常工作。这会导致进度条从 0 平滑更新到 100%:
lame -m auto -V 4 aa.wav aa.mp3 | awk -vRS='\r' '(NR>3){gsub(/[()%|]/," ");print $2; fflush();}' | zenity --progress --title="Title" --text="encoding" --auto-close
现在我使用 fdkaac 运行此代码:
fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac
这会导致编码结束时的屏幕输出:
[100%] 05:31.227/05:31.227 (43x), ETA 00:00.000
14607096/14607096 在 00:07.689 中处理的样本
在编码过程中,会打印第一行,并且 [100%] 在编码过程中从 0 平滑更新到 100。在编码的最后打印第二行。
基于此,我修改了 gsub 搜索并替换为: gsub(/[[%]/," ") 来挑选数据。
我现在运行这段代码:
fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac 2>&1 | awk -vRS='\r' '(NR>3){gsub(/[\[%]/," ");print $1; fflush();}' | zenity --progress --title="Title" --text="Encoding" --auto-close
结果不是我所期望的。进度对话框显示为 0% ...,然后一段时间后跳至 50% ...,然后在编码完成时消失。
因此,我使用以下代码查看了进入 zenity 的数据:
fdkaac --profile 2 --bitrate-mode 5 aa.wav -o aa.aac 2>&1 | awk -vRS='\r' '(NR>3){gsub(/[\[%]/," ");print $1; fflush();}'
屏幕输出不是我所期望的。 1 到 50 全部同时打印,但在连续行上,然后当编码完成时,50 到 100 分别打印在连续行上:
1
2
3
4
5
...
48
49
50
并继续到 50。然后输出继续在单独的行上从 50 到 100(再次同时打印):
50
51
52
..
98
99
100
所以,问题很明显......输出数据分两批打印(正如在对话框中看到的那样)。并且数据出现在连续的行上。 (awk过滤器之后的lame输出全部打印在同一行上并且平滑更新)。
我怀疑问题与额外的回车符有关,但我不知道如何摆脱它们。我尝试删除 -vRS='\r 命令..但这根本没有输出。
我不明白替换:RS='\r'。变量RS出现在哪里?
我也很奇怪,数据打印出来时正好是 50% 和 100%。为什么不是 38% 或 67%? ..所以数据告诉了我一些事情,但我不确定它是什么。
答案1
问题可能是当fdkaac
它的输出到管道时缓冲它的输出。尝试在命令前加上前缀:
stdbuf -o 0 -e 0 fdkaac ... 2>&1 | ...
其中 -o 代表 stdout,-e 代表 stderr。
如果您想尝试 awk 的替代方案,可以使用 shell 脚本。确保你的 shell 是 bash
stdbuf -o 0 -e 0 fdkaac ... 2>&1 |
(IFS="$IFS%[]"
while read -d$'\r' junk1 percent junk2
do echo "$percent"
done) |
zenity --progress --title="Title" --text="encoding" --auto-close
通过设置 IFS(bash 字段分隔符)以包含另外 3 个字符“%[]”,它们实际上变得像输入中的空格一样,因此read
带有分隔符回车符 (-d) 应该将行的第一个单词放入 var垃圾 1,百分比第二,其余的垃圾 2。然后我们可以只回显应该只保存数字的变量。
注意:您需要在没有 zenity 位的情况下尝试此操作,看看是否获得了数字字段。我不知道为什么我必须使用第一个 var junk1,因为百分比应该是该行中的第一个字段,但如果您没有得到想要的数字,请尝试从读取中删除 junk1 变量。
答案2
让我们分解一下 awk 命令:
awk -vRS='\r' '(NR>3){gsub(/[()%|]/," ");print $1; fflush();}'
记录分隔符是\r,字段分隔符是[\t]+。字符 ()%|将被替换为空格。您正在占据第一个字段。
基于此格式:[100%] 05:31.227/05:31.227 (43x), ETA 00:00.000
以下内容将传递给 zenity:[100]
也许你的 awk 应该更像是:
awk -vRS='\r' '(NR>3){gsub(/[()%|[]]/," ");print $1; fflush();}'
或者更好地删除位置参数:gawk -vRS='\r' 'match($0, /([0-9]+)%/, ary) {print ary[1]}'