实时管道和过滤 bash 输出

实时管道和过滤 bash 输出

我正在 bash 中运行一些命令(基本上是一些ffmpeg命令),我正在使用这些命令grepawk过滤出结果。该命令需要一些时间,并在视频播放过程中不断输出一些结果。管子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 [...]

此外,您可以将grepand合并awk为一个运算:

而不是:

[...] | grep freezedetect | awk '{print $4,$5}' | tr -d , | grep lavfi

相反,您可以:

[...] | awk '/freezedetect/ && ( $4 /lavfi/ || $5 /lavfi/ ) {print $4,$5}' | tr -d ,

相关内容