使用ffmpeg提取帧的最快方法?

Stp*_*tpn 97 video ffmpeg

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

ffmpeg -i file.mpg -r 1/1 $filename%03d.jpg
Run Code Online (Sandbox Code Playgroud)

Mul*_*ike 124

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

ffmpeg -i file.mpg -r 1/1 $filename%03d.bmp
Run Code Online (Sandbox Code Playgroud)

这还具有通过转码为JPEG而不会通过量化而导致更多质量损失的优点.(PNG也是无损的,但往往需要比JPEG更长的时间来编码.)

  • @ Evi1M4chine只需删除-r参数,这将提取所有帧 (30认同)
  • 你的意思是 `ffmpeg -r 1 -i file.mp4 -r 1 "$filename%03d.png`,对吗?(你错过了 `-i`) (15认同)
  • 我想补充一点,虽然JPEG在CPU上并不是很难,但是未压缩的Bitmaps在存储上真的很难,所以我怀疑与JPEG相比,你会获得更高的BMP吞吐量. (11认同)
  • 这导致我的机器上丢失了很多*帧.我可以告诉ffmpeg渲染一切吗? (7认同)
  • 要提取所有帧:`ffmpeg -r 1 file.mp4 -r 1"$ filename%03d.png"` (3认同)

mak*_*rld 57

这比迄今为止所有其他命令更简单:

ffmpeg -i input.mp4 '%04d.png'
Run Code Online (Sandbox Code Playgroud)

更改04为容纳所有帧所需的数字。确保0数字前始终有一个 ,以便输出帧名称用零填充。


blu*_*nge 51

遇到这个问题,所以这里是一个快速比较.比较这两种不同的方式从38m07s长的视频中每分钟提取一帧:

time ffmpeg -i input.mp4 -filter:v fps=fps=1/60 ffmpeg_%0d.bmp
Run Code Online (Sandbox Code Playgroud)

1m36.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
Run Code Online (Sandbox Code Playgroud)

0m4.689s

这大约快20倍.我们使用快速搜索来转到所需的时间索引并提取一个帧,然后为每个时间索引多次调用ffmpeg.请注意,这-accurate_seek 是默认设置 ,并确保-ss在输入视频-i选项之前添加.

请注意,这是更好地使用-filter:v -fps=fps=...,而不是-r作为后者可能是不准确的.虽然机票被标记为固定,但我仍然遇到了一些问题,所以最好安全地玩.

  • 2016年2月:从ffmpeg 2.1开始,准确的搜索选项现在默认 - https://trac.ffmpeg.org/wiki/Seeking (5认同)
  • `bc` 不是本机 Ubuntu 软件包,而是可以使用 bash:`let "i = $i * 60"`。顺便说一句-好主意 (4认同)
  • 在`-i`之前添加`-ss`的好技巧。否则,整个视频将被解码,不需要的帧将被丢弃 (2认同)
  • 由于这是谷歌的顶级,我想指出,在 2018 年,这仍然是一种产生红利的方法。最好的结果似乎是在主机的每个内核上运行一个 `ffmpeg` - 这(对于 bmp)会产生近乎线性的速度提升(直到遇到其他瓶颈,例如磁盘)。 (2认同)

Kis*_*ela 8

这对我有用

ffmpeg -i file.mp4 -vf fps=1 %d.jpg


小智 7

Output one image every minute, named img001.jpg, img002.jpg, img003.jpg, etc. The %03d dictates that the ordinal number of each output image will be formatted using 3 digits.

ffmpeg -i myvideo.avi -vf fps=1/60 img%03d.jpg
Run Code Online (Sandbox Code Playgroud)

Change the fps=1/60 to fps=1/30 to capture a image every 30 seconds. Similarly if you want to capture a image every 5 seconds then change fps=1/60 to fps=1/5

SOURCE: https://trac.ffmpeg.org/wiki/Create a thumbnail image every X seconds of the video


Voy*_*Voy 6

如果您确切知道要提取哪些帧,例如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
Run Code Online (Sandbox Code Playgroud)

我正在使用这个管道来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\,100)',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
Run Code Online (Sandbox Code Playgroud)

.

小解释:

  1. 在ffmpeg中,表达式+代表OR和*AND
  2. \,只是逃避,角色
  3. 没有-vsync vfr -q:v 2它似乎没有工作,但我不知道为什么 - 任何人?

  • `-q:v` 是 `-qscale:v` (https://trac.ffmpeg.org/wiki/Encode/MPEG-4) 的别名,用于控制图像质量。`-vsync vfr` 是视频同步方法(您首先需要了解 `-vf` 是一个过滤器图)。根据文档,“vfr”的意思是“帧通过其时间戳传递或丢弃,以防止 2 个帧具有相同的时间戳。”*我认为*这是为了避免默认选项“cfr”,如此处所述 https: //ffmpeg.org/ffmpeg.html (2认同)

Küb*_*bra 5

我尝试过这个。32 秒 3600 帧。你的方法真的很慢。你应该试试这个。

ffmpeg -i file.mpg -s 240x135 -vf fps=1 %d.jpg
Run Code Online (Sandbox Code Playgroud)

  • 当然,将它们缩放到很小的尺寸会使速度更快,但这不是他所要求的。 (2认同)