ffmpeg 用法总结

总结 ffmpeg 的强大用法。

  • 官方说明:
    • https://ffmpeg.org/ffmpeg-all.html
    • https://trac.ffmpeg.org/wiki/Encode/MPEG-4
  • 其他好的总结:
    • https://rollingstarky.github.io/2019/03/10/ffmpeg-user-manual-and-practical-examples/
    • https://www.tecmint.com/ffmpeg-commands-for-video-audio-and-image-conversion-in-linux/

隐藏 ffmpeg 信息

如果你不想看 FFmpeg 标语和其它细节,而仅仅想看媒体文件信息,增加 -hide_banner参数,一般放在整个命令最后面。

将一组图片按顺序合成为一个视频

https://stackoverflow.com/questions/24961127/how-to-create-a-video-from-images-with-ffmpeg

ffmpeg -y -i room_view/frame%03d.png -pix_fmt yuv420p result.mp4

-i是获取视频细节信息(当然不只是用于这里)。frame%03d 是类似 printf 函数中的用法,指的是所有的文件名是 frameXXX 的文件,XXX 表示前面 pad 上 0 的数字,从 frame000 开始。3 的意思是数字的 digit 位数是 3 位。即,这里读取的文件就是 room_view/frame000.png, room_view/frame001.png …

注意,如果要合并的图片的文件名没有规律,那么直接把图片名改成类似*.png有可能会失败。此时经测试下面命令可行:

ffmpeg -framerate 30 -pattern_type glob -i '*.png' -c:v libx264 -pix_fmt yuv420p out.mp4

从视频中提取图片 Split Video into Images

最简单用法:

ffmpeg -i video.mp4 image%d.jpg

说明:

  • 支持多种视频格式(mp4, flv, mov, avi,…)和多种图片格式(png, bmp, jpg,…)。不过不同图片格式有压缩率的区别,可以通过其他参数设置。
  • 最后一个参数image%d.jpg会生成 image1.jpg, image2.jpg, …。如果要在图片 index 前增加 0 padding,可以这样:image%04d.jpg,这样就会生成 4 位数 index 的图片 image0001.jpg, image0002.jpg, ….。

设置帧率 FPS

增加参数 -r 24或者 -vf fps=24/1。前者就是设置 fps 数值,后者 24/1意思是 1 秒钟提取 24 张图片。后者的好处是,可以设置类似 3/2 这种数值。

保证提取图片质量高

首先,如果提取的是无损的 PNG 图片时,就无需设置额外参数了。这里主要针对的是 jpg 等压缩格式。

选择视频的 quality level 可以用 -qscale:v n,其中 n 是1-31的值,越小质量越高,例如 -qscale:v 1。同理,对于音频的 quality level 的选择,可以用 -qscale:a n。(参考:https://trac.ffmpeg.org/wiki/Encode/MPEG-4)。

不过,很多其他文档提到,使用原视频的最高质量可以直接用 -qscale 0这种(参考:https://zhuanlan.zhihu.com/p/67878761)。

这两种方法都可以提取视频最高的 quality。

我个人通过实验对比了一下使用 -qscale:v 1或者-qscale 0这两种方式,当都保存 jpg 图片时,结果似乎没什么区别。但是,它们得到的 jpg 图片结果都有一定程度的损失。这是因为,ffmpeg 压缩 jpg 时有默认的参数,并未调到最高。如果你想要最大程度的保留原视频信息到 jpg 图片中,需要按照下面的方法设置其他的参数。

提取图片为 jpg 时保持质量尽量高

参考:https://superuser.com/questions/1032503/ffmpeg-extract-lossless-image-from-video

增加这个参数:-q:v 1 -qmin 1 -qmax 1。这里 -q:v就是用来设置 JPEG 的压缩率的,1 是质量最高。后面的 qminqmax都设成 1,确保用最高品质。经测试,该方法的 jpg 结果要比上面使用 -qscale:v 1或者-qscale 0的结果都高。因此推荐该方法。

另一种方法是,可以先提取无损的 PNG,然后再使用第三方软件自行转换,增加相关参数。例如,在 Linux 中可以使用 imagemagick 提供的 convert命令直接转:

convert img.png img.jpg

详细可以参考:http://ubuntuhandbook.org/index.php/2013/07/how-to-convert-png-to-jpg-on-ubuntu-via-command/

自定义提取图片的 resolution

参考:

  • https://trac.ffmpeg.org/wiki/Scaling
  • https://stackoverflow.com/questions/17657718/how-to-specify-size-of-output-image-in-ffmpeg-command

其实就是在 -vf 后面增加 -vf scale=320:240类似这样。

如果只想指定一个 width 或者 height,那么不指定的那个值用 -1,比如设定 width = 320 是这样:-vf scale=320:-1。此时ffmpeg 会自动计算 height 的值,并保持视频中图片的 aspect ratio 宽高比。

裁剪图片 Crop Image

参考:https://www.bogotobogo.com/FFMpeg/ffmpeg_cropping_video_image.php

增加类似 -vf "crop=w:h:x:y"的参数。其中,w 和 h 是输出视频/图片的宽和高,x 和 y 则是输出视频/图片最左上角的点在原始视频中的位置。如果不指定 x,y 的值(即类似 crop=w:h这样),那 默认有 x = (in_w - w) / 2,y = (in_h - h) / 2,即默认裁剪结果就是视频正中间。

例如,下面是裁剪一个视频的完整命令:

ffmpeg -i before.mp4 -vf "crop=w:h:x:y" after.mp4

将两个视频左右或者上下放置合并成一个

最简单的是:

ffmpeg -i left.mp4 -i right.mp4 -filter_complex hstack output.mp4

不过上面这个命令得到的合并视频中,左右视频中间没有 padding。如果要加上 padding,参考上面第一个链接。如果要垂直合并两个视频,将 hstack改成 vstack就行了,具体参见第二个链接

旋转视频

参考:https://stackoverflow.com/questions/3937387/rotating-videos-with-ffmpeg

Rotate 90 clockwise:

ffmpeg -i in.mov -vf "transpose=1" out.mov

For the transpose parameter you can pass:

0 = 90CounterCLockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90CounterClockwise
3 = 90Clockwise and Vertical Flip

Use -vf "transpose=2,transpose=2" for 180 degrees.

将 mov 转换为 mp4

  • https://stackoverflow.com/questions/12026381/ffmpeg-converting-mov-files-to-mp4

The command to just stream it to a new container (mp4) needed by some applications like Adobe Premiere Pro without encoding (fast) is:

ffmpeg -i movie.mov -vcodec copy -acodec copy out.mp4

Alternative as mentioned in the comments, which re-encodes with best quaility (-qscale 0):

ffmpeg -i input.mov -q:v 0 output.mp4

还有其他参数,例如 scale 视频等。

Search

    Table of Contents