如何使用ffmpeg从视频文件中提取高质量的JPEG图像?

170

目前我正在使用这个命令来提取图片:

ffmpeg -i input.mp4 output_%03d.jpeg

但是我该如何提高JPEG图像的质量?


1
除了它不够“好”之外,当前质量有什么问题? - bjoernz
3个回答

315

使用-qscale:v控制视频质量

可以使用-qscale:v(或别名-q:v)作为输出选项。

  • JPEG的正常范围为2-31,其中31是最低质量。
  • 比例尺是线性的,双倍的qscale大约相当于一半的比特率。
  • 建议尝试2-5的值。
  • 您可以使用1的值,但必须添加-qmin 1输出选项(因为默认值为-qmin 2)。

要输出一系列图像:

ffmpeg -i input.mp4 -qscale:v 2 output_%03d.jpg

请查看图像混合器文档以获取有关图像输出的更多选项。

输出单个图像,持续时间约为60秒:

ffmpeg -ss 60 -i input.mp4 -qscale:v 4 -frames:v 1 output.jpg

持续地将视频流保存为单个图片

使用-update 1图像多路复用器 (image muxer)选项。例如,对于每秒从直播流输入更新一次的情况:

ffmpeg -i rtmp://input.foo -q:v 4 -r 1 -update 1 output.jpg

另请参阅


1
对我来说,除了添加“-q:v 1”外,再加上“-qmin 1 -qmax 1”会使文件大小翻倍。而且我似乎也能看到一点点改善。 - complistic
1
@complistic:-qmin 1 -qmax 1导致文件变大,但给了我完全相同的图像。我通过Photoshop进行了验证,使用了2个图层和差异滤镜。像素是一样的。 - cherouvim
@Kostanos 您可以尝试使用“-qmin 1 -q:v 1”。 - llogan
1
最好先提取.png文件,然后使用具有更好JPEG算法的mozjpeg。 - Валерий Заподовников
1
ffmpeg -i MVI_5624.MP4 -r 1 images/thumb%04d.png - Nasser Ali Karimi
显示剩余7条评论

17

以无损格式(如PNG)输出图片:

mkdir stills
ffmpeg -i my-film.mp4 -vsync 0 -f image2 stills/my-film-%06d.png

然后使用另一个程序(例如GIMP),在其中更精确地指定质量、子采样和DCT方法,将您想要的PNG转换为JPEG。

通过使用这种方式,可以获得比使用-qmin 1 -q:v 1并直接从ffmpeg输出为JPEG格式略微更清晰的图像。

如果您只想提取关键帧(这些关键帧在编辑后可能具有更高的质量),则可以使用类似于以下内容的东西:

ffmpeg -skip_frame nokey -i my-film.mp4 -vsync 0 -f image2 stills/my-film-%06d.png
-vsync 0参数避免了需要使用-r来指定帧率的问题,并且意味着输入文件中的所有帧都被视为一个帧。

3
我使用这种方法提取的PNG文件都是24位的(即使某些帧少于256种颜色,而其他帧则有更多)。我在Windows上使用了版本4.2.1 x64。此外,在这里还写道:“如果我使用此 [ffmpeg] 命令从mp4中提取png文件,则会得到与原始视频完全相同质量的高质量png文件。”请问您使用的 ffmpeg 版本输出了 PNG8 文件,并且输入格式是什么? - Jake
1
@DonnyV。您的评论不会被踩(只会被标记为不当)。很高兴这有所帮助。谢谢您提醒我发布了这个问题。我已经重新检查了我给出的示例命令,并更新了我的答案,提供了一些更好的替代方案,更符合我现在对ffmpeg的了解。 - Jake
1
我发现你的解决方案可以生成高质量的关键帧,但是我认为它需要以更清晰的方式进行排列。 - BalrogOfMoria
2
@pouya 在播放过程中暂停视频,你能得到更好的东西吗?如果不能,那么你没有足够高质量的原始视频副本来完成你想做的事情。我看过源代码,其中 ffmpeg 将 JPEG 压缩质量设置为 90(而不是 70),如果你设置了 -q2,但这仍然比我通常使用的要低。还要注意,它正在重新压缩已经被压缩过的电影中的静止画面,并且“关键帧”的质量会更好。但是,虽然 MPEG 是基于 JPEG 的,但似乎不可能直接将关键帧作为 JPEG 图像提取出来。 - Jake
2
我在尝试将.mp4视频拆分成帧时,尝试了-qscale:v参数。从.jpg更改为.png的简单更改产生了最大的质量改进。 - Radespy
显示剩余7条评论

0
记下特定帧的编号
mpv --osd-msg1='${estimated-frame-number} / ${estimated-frame-count}' vid1.mp4

将帧编号保存在一个文件中,每个编号占一行,例如frm.txt,然后运行:
sed -i 's/^/eq(n\\,/' frm.txt; sed -i 's/$/)\+/'  frm.txt; sed -i '$ s/.$//' frm.txt;        #adds eq(n\, #adds )+ at the end of each line #remove + in lastline (last digit)

然后将它们提取为bmp或png格式。
frms=$(cat frm.txt); ffmpeg -i vid_1.mp4  -vf "select='$frms'" -fps_mode drop "frames_%03d.bmp"

然后转换为jpg - 差别太大了,350kb(使用最佳质量的ffmpeg jpg)与2MB(将bmp转换为jpg)相比简直天壤之别!!!
for pic in *.bmp; do convert  -units PixelsPerInch -density 300 -quality 100  "$pic" "${pic//}_j.jpg"; done

(当然,你需要安装ImageMagick的convert工具)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接