总结 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 -vf fps=24/1
说明:
- 支持多种视频格式(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 是质量最高。后面的 qmin
和 qmax
都设成 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/
自定义提取图片分辨率
参考:
- 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
类似这样。也可以用 -s 600x400
这样。
如果只想指定一个 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
将两个视频左右或者上下放置合并成一个
-
Merge two video clips into one, placing them next to each other
-
Vertically or horizontally stack (mosaic) several videos using ffmpeg?
最简单的是:
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 视频等。
将视频转换为 gif
-
https://gist.github.com/vitorleal/563771e821cef668eef5
-
https://medium.com/acronis-design/ffmpeg-imagemagick-convert-video-to-gif-using-the-terminal-app-in-macos-657948adf900
Mac 中可以结合 ffmpeg 和 gifsicle(用 brew install gifsicle
安装):
ffmpeg -i movie-name.mp4 -s 600x400 -pix_fmt rgb24 -r 10 -f gif - | gifsicle --optimize=0 --delay=3 > movie-name.gif
Options:
-
-r 10
tells ffmpeg to reduce the frame rate from 25 fps to 10 -
-s 600x400
tells ffmpeg the max-width and max-height -
--delay=7
tells gifsicle to delay 70ms between each gif -
--optimize=3
requests that gifsicle use the slowest/most file-size optimization
和 ffmpeg 相关的 options 都可以用。例如,-s 600x400
是 rescale 图片为制定分辨率,并未保持图片宽高比。可以用-vf scale=600:-1
来控制图片宽高比。