我正在 bash 中运行一些命令(基本上是一些ffmpeg
命令),我正在使用这些命令grep
并awk
过滤出结果。该命令需要一些时间,并在视频播放过程中不断输出一些结果。管子grep
是一样的。但是awk
管道会等到命令完成并立即打印所有内容,这不太好。我想让它输出立刻它找到了一个匹配项。
如何更改此命令以在执行过程中实时输出结果?
ffmpeg -i freeze.mp4 -vf "freezedetect=n=-60dB:d=2" -map 0:v:0 -f null - 2>&1 | grep freezedetect | awk '{print $4,$5}' | tr -d , | grep lavfi
答案1
使用标准工具,尝试
ffmpeg -i freeze.mp4 -vf "freezedetect=n=-60dB:d=2" -map 0:v:0 -f null - 2>&1 | stdbuf -o 0 grep freezedetect | stdbuf -o 0 awk '{print $4,$5}' | stdbuf -o 0 tr -d , | stdbuf -o 0 grep lavfi
答案2
expect
提供了一个工具unbuffer
,您可以用它来解决这个问题。它将使用伪终端连接到长时间运行的ffmpeg
进程,这使得系统的行为就像是交互式的,而不是使用管道通常包含的 4K 缓冲区:
$ unbuffer ffmpeg [...] | grep [...] | awk [...]
此外,您可以将grep
and合并awk
为一个运算:
而不是:
[...] | grep freezedetect | awk '{print $4,$5}' | tr -d , | grep lavfi
相反,您可以:
[...] | awk '/freezedetect/ && ( $4 /lavfi/ || $5 /lavfi/ ) {print $4,$5}' | tr -d ,