嗨,我需要从视频中提取帧使用ffmpeg..还有比这更快的方法吗:

ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg

?


当前回答

我试过了。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被淹没了。

如果你确切地知道要提取哪些帧,例如1、200、400、600、800、1000,尝试使用:

select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)' \
       -vsync vfr -q:v 2

我使用这个管道Imagemagick的蒙太奇从任何视频得到10帧预览。显然,帧数需要使用ffprobe来计算

ffmpeg -i myVideo.mov -vf \
    select='eq(n\,1)+eq(n\,200)+eq(n\,400)+eq(n\,600)+eq(n\,800)+eq(n\,1000)',scale=320:-1 \
    -vsync vfr -q:v 2 -f image2pipe -vcodec ppm - \
  | montage -tile x1 -geometry "1x1+0+0<" -quality 100 -frame 1 - output.png

.

小的解释:

在ffmpeg表达式中,+代表OR, *代表and \只是转义,字符 没有-vsync vfr -q: v2,它似乎不工作,但我不知道为什么-有人吗?

与@makeworld的回答相同,但也解决了这里提到的关于帧数不一致和需要垂直同步的问题,以及关于垂直同步的使用:

// reliably works for jpg output (and probably png too)
ffmpeg -i rgb.mov -vf setpts=N/FR/TB -vsync 0 ./images/%05d.jpg

// reliably works for png output only
ffmpeg -i rgb.mov -vsync 0 ./images/%05d.png

我试过了。3600帧32秒。你的方法太慢了。你应该试试这个。

ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg

如果JPEG编码步骤过于性能密集,您可以始终将未压缩的帧存储为BMP图像:

ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp

这样做的另一个优点是,通过将代码转换为JPEG进行量化,不会导致更多的质量损失。(PNG也是无损的,但编码时间往往比JPEG长得多。)