嗨,我需要从视频中提取帧使用ffmpeg..还有比这更快的方法吗:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
嗨,我需要从视频中提取帧使用ffmpeg..还有比这更快的方法吗:
ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
?
当前回答
遇到了这个问题,这里有一个快速的比较。比较以下两种从38m07秒长的视频中每分钟提取一帧的方法:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1 m36.029s
这需要很长时间,因为ffmpeg解析整个视频文件以获得所需的帧。
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0 m4.689s
这要快20倍。我们使用快速查找到所需的时间索引并提取一帧,然后为每个时间索引调用ffmpeg几次。注意-accurate_seek是默认值 ,并确保在input video -i选项之前添加-ss。
注意,最好使用-filter:v -fps=fps=…而不是-r,因为后者可能不准确。虽然机票被标记为固定,但我还是遇到了一些问题,所以最好谨慎行事。
其他回答
如果JPEG编码步骤过于性能密集,您可以始终将未压缩的帧存储为BMP图像:
ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
这样做的另一个优点是,通过将代码转换为JPEG进行量化,不会导致更多的质量损失。(PNG也是无损的,但编码时间往往比JPEG长得多。)
我试过了。3600帧32秒。你的方法太慢了。你应该试试这个。
ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
在我的情况下,我需要帧至少每秒钟。我使用了上面的“寻求”方法,但不知道我是否可以并行完成任务。我在这里使用了先进先出的N个进程: https://unix.stackexchange.com/questions/103920/parallelize-a-bash-for-loop/216475#216475
open_sem(){
mkfifo /tmp/pipe-$$
exec 3<>/tmp/pipe-$$
rm /tmp/pipe-$$
local i=$1
for((;i>0;i--)); do
printf %s 000 >&3
done
}
run_with_lock(){
local x
read -u 3 -n 3 x && ((0==x)) || exit $x
(
"$@"
printf '%.3d' $? >&3
)&
}
N=16
open_sem $N
time for i in {0..39} ; do run_with_lock ffmpeg -ss `echo $i` -i /tmp/input/GOPR1456.MP4 -frames:v 1 /tmp/output/period_down_$i.jpg & done
从本质上讲,我用&派生了进程,但将并发线程的数量限制为N。
在我的例子中,这将“寻求”方法从26秒提高到16秒。唯一的问题是主线程不能干净地退出到终端,因为stdout被淹没了。
遇到了这个问题,这里有一个快速的比较。比较以下两种从38m07秒长的视频中每分钟提取一帧的方法:
time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
1 m36.029s
这需要很长时间,因为ffmpeg解析整个视频文件以获得所需的帧。
time for i in {0..39} ; do ffmpeg -accurate_seek -ss `echo $i*60.0 | bc` -i input.mp4 -frames:v 1 period_down_$i.bmp ; done
0 m4.689s
这要快20倍。我们使用快速查找到所需的时间索引并提取一帧,然后为每个时间索引调用ffmpeg几次。注意-accurate_seek是默认值 ,并确保在input video -i选项之前添加-ss。
注意,最好使用-filter:v -fps=fps=…而不是-r,因为后者可能不准确。虽然机票被标记为固定,但我还是遇到了一些问题,所以最好谨慎行事。
这对我很有效
Ffmpeg -i file.mp4 -vf fps= 1% d.jpg