我想让一个Perl程序处理ffmpeg编码的输出,但我的测试程序似乎只能以定期块接收ffmpeg的输出,因此我假设存在某种缓冲。如何使其实时处理?
我的测试程序(
当使用上述脚本时,我会看到每秒的输出情况。使用
我尝试在命令调用中在
非常感谢您的帮助。
如果您不熟悉ffmpeg的输出,它会将一堆文件信息和其他东西输出到
我的测试程序(
tr
命令在那里,是因为我认为ffmpeg的回车符可能会导致perl看到一个很长的行或其他东西):#!/usr/bin/perl
$i = "test.mkv"; # big file, long encode time
$o = "test.mp4";
open(F, "-|", "ffmpeg -y -i '$i' '$o' 2>&1 | tr '\r' '\n'")
or die "oh no";
while(<F>) {
print "A12345: $_"; # some random text so i know the output was processed in perl
}
当我用这个脚本替换ffmpeg
命令时,一切都正常工作:
#!/bin/bash
echo "hello";
for i in `seq 1 10`; do
sleep 1;
echo "hello $i";
done
echo "bye";
当使用上述脚本时,我会看到每秒的输出情况。使用
ffmpeg
时,需要等待大约5-10秒才会有输出,并且有时会输出100行左右。我尝试在命令调用中在
ffmpeg
之前使用程序unbuffer
,但似乎没有效果。也许是2>&1
导致了缓冲?非常感谢您的帮助。
如果您不熟悉ffmpeg的输出,它会将一堆文件信息和其他东西输出到
STDOUT
,然后在编码期间输出类似以下的行:frame= 332 fps= 93 q=28.0 size= 528kB time=00:00:13.33 bitrate= 324.2kbits/s speed=3.75x
这里的tr
指的是以回车符而非换行符开头的文本,它出现在STDERR
上(因此使用了2>&1
)。
ffmpeg
很熟悉,但是在你的问题中并没有告诉我为什么你需要实时看到输出。那个输出是用来控制台使用的,而且如果你通过程序运行转换,那么你肯定只需要知道每个文件是否成功转换了吧? - Borodin<>
,他们就不能使用<>
。(没关系,他们可以使用read
代替。)// 这不是使用unbuffer
的方式。 - ikegamiunbuffer
不能被管道传输,正确的用法是unbuffer <bin> <args>
。当我这样做时,我可以实时输出,直到回车符号部分,此时我将不再有输出,直到编码完成。这就是为什么我使用了tr
,但现在我们看起来问题好像并不在那里。 - Sebastian Kingstdbuf -i0 -o0 -eL
替换了unbuffer -p
(-eL
使其现在是行缓冲,我认为稍微更有效),以消除对相当大的expect
包的依赖。 - Sebastian King