我正在使用 EndeavourOS,如果我使用命令播放音频ffmpeg -i test.flac -f alsa default
,终端会显示这种输出:
size=N/A time=00:00:21.31 bitrate=N/A speed=1.22x
我想在那里获取“time=”参数及其值。我知道 ffmpeg 输出到 STDERR,所以我知道重定向 2>1,所以我尝试:
ffmpeg -i test.flac -f alsa default 2>&1 | grep time
…此时终端保持完全空白(但音乐播放正常)。
我也尝试过:
ffmpeg -i test.flac -f alsa default 2>test.txt
…在第二个终端会话中:
tail -f test.txt | grep time
...仍然是空白的,但如果我只是 tail 文件而不使用 grep 部分,我就会看到相关的文本行,其中 time= 值不断增加。
我知道会建议使用 ffplay,但我正在使用 ffmpeg 处理大量代码,切换不是一种选择。我更想知道为什么 grep 似乎无法在 ffmpeg STDERR 输出上工作,无论它重定向到哪里!几乎是次要的:有没有办法只使用 ffmpeg 来提取“流中的当前位置”时间值?
鉴于以下评论:
ffmpeg -v
ffmpeg version n7.1 Copyright (c) 2000-2024 the FFmpeg developers
built with gcc 14.2.1 (GCC) 20240910
仅播放音乐的截断输出,没有重定向:
TAGDATE : 1623718801
encoder : Lavf61.7.100
Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
Metadata:
encoder : Lavc61.19.100 pcm_s16le
size=N/A time=00:00:15.36 bitrate=N/A speed=1.34x
下面是一些我可以和不能从该输出中找到的示例:
[zelenka Desktop]$ ffmpeg -i test.flac -f alsa default 2>&1 | grep Duration
Duration: 00:21:10.00, start: 0.000000, bitrate: 690 kb/s
^C^C^C
[zelenka Desktop]$ ffmpeg -i test.flac -f alsa default 2>&1 | grep Audio
Stream #0:0: Audio: flac, 44100 Hz, stereo, s16
Stream #0:0: Audio: pcm_s16le, 44100 Hz, stereo, s16, 1411 kb/s
^C^C^C
[zelenka Desktop]$ ffmpeg -i test.flac -f alsa default 2>&1 | grep time=
^C^C^C
(此时我必须按Ctrl+C来中断,因为屏幕上什么都没有出现)。 查找“静态”数据有效;查找size=N/A time=00:00:15.36 bitrate=N/A speed=1.34x
行输出的动态部分无效。
编辑以提供有效答案:
在会话 1 中,我现在可以发出以下命令:
ffmpeg -stats_period 1 -i test.flac -f alsa default |& awk -v RS="\r" -v FS='[= ]' 'NR > 1 && /time/ {print $4; fflush("/dev/stdout")}' | tee test.txt
这意味着 ffmpeg 每 1 秒输出一次进度计数。进度输出随后被传递到 awk,搜索进度的“out_time=”行。然后刷新并写入 test.txt 文件。
然后,在第二个终端中,我发出以下命令:
tail -f test.txt | cut -c-8
...产生如下输出:
[zelenka Desktop]$ tail -1 test.txt | grep --line-buffered ":" |cut -c-8
00:00:04
00:00:05
00:00:06
00:00:07
00:00:08
00:00:09
...我可以用它!
如果你只想看到
time
字段:如果你不想看
time=
部分:如果您仍想将输出重定向到另一个文件,您可以按照 awk 中的刷新输出操作进行操作,但请记住,在管道中执行的操作越多,速度就越慢:
ffmpeg -i test.flac -f alsa default 2>&1 | grep time
不起作用,因为 grep 是面向行的,但它的换行符意味着\n
(ASCII 0xa,您可以看到它man ascii
),但 ffmpeg 使用\r
(ASCII 0xd) 转到行首并清除它,以便时间信息始终显示在同一行。您可以使用 strace 看到它:它是 awk 记录分隔符,您可以在 GNU awk 手册中了解更多有关它的信息。
ffmpeg 有一个选项
-progress
可以将输出进度写入文件(或任何 URL 或管道)。所以跑
ffmpeg -i test.flac -progress myfile.txt -f alsa default
进而
grep "time=" myfile.txt | tail -1