Contents

FFmpeg处理视频的常见用法

20200713更新:这篇博文写于去年,最近进行了较大的调整重新发布。

FFmpeg是一个用处极为广泛的开源视频以及音频工具,官网上的介绍是“A complete, cross-platform solution to record, convert and stream audio and video.”,正如其言,很多下载、转码、剪辑音视频的软件都将FFmpeg作为基础的组成部分。FFmpeg的主要工具有ffmpeg,ffprobe以及ffplay,最近在处理音视频文件时经常用到ffmpeg,惊讶于其功能的强大,遂写下此博文来记录一下常用的基础操作。

1.基础操作

常用的命令行参数有

参数 含义
-c 指定编码器
-c copy 直接复制,不经过重新编码(这样比较快)
-vcodec/-c:v 指定视频编码器
-acodec/-c:a 指定音频编码器
-scodec/-c:s 指定字幕编码器
-i 指定输入文件
-an 去除音频流
-vn 去除视频
-preset 指定输出的视频质量,会影响文件的生成速度,有以下几个可用的值 ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow
-y 不经过确认,输出时直接覆盖同名文件

1.1 查看媒体文件信息

1
ffmpeg -i test.mp4

隐藏ffmpeg配置信息

1
ffmpeg -i video.mp4 -hide_banner

1.2 查看所有支持的编码

1
ffmpeg -formats

常见的容器默认编码样式为:

后缀 音频编码 视频编码
.avi: mp3 mpeg4
.mkv: ac3 H.264
.mov: AAC H.264
.mp4: AAC H.264
.mpg: mp2 mpeg1video
.mxf: pcm_s16le, mpeg2video
.wav: pcm_s16le

1.3 更换容器格式

不进行重新编码,因此比较迅速,使用map来保留所有的媒体流。

1
ffmpeg -i input.webm -c copy -map 0 output.mp4

1.4 更换编码方式

指定输出文件的编码器即可

1
ffmpeg -i [input.file] -c:v libx264 output.mp4

2. 选择输入媒体流

ffmpeg支持的媒体流的类型有5种:

  • a - audio
  • v - video
  • s - subtitle
  • d - data (including timecode tracks)
  • t - attachment

常用的有音频流、视频流和字幕流,不同的视频容器对于媒体流的数目和编码要求不尽相同。

2.1 自动选择

选择的规则如下

  • 视频:选择分辨率最高的流
  • 音频:选择最多channel的流
  • 字幕: 一般选择地一个字幕流,输出格式的默认字幕编码器可以为文字字幕和图形字幕,据此选择字幕流

默认情况下,ffmpeg每种类型只会选择一个流

2.2 手动选择

{{ figure src="/media/20200712-1.png" position=“center” >}}

使用-map参数选择输入视频中的流,基本语法如下:

-map file_number:stream_type[:stream_number]

一些特殊的参数如下:

参数 含义
-map 0 选择第一个文件的所有流
-map i:v 从文件序号i中获取所有视频流
-map i:a 获取所有音频流
-map i:s 获取所有字幕流
-an,-vn,-sn 分别排除所有的音频,视频,字幕流
-map 0:a? 如何选择的流不存在,则忽视
-map -0:a 不选择这个流

2.3 一个例子

有以下三个输入文件

input file 'A.avi'
      stream 0: video 640x360
      stream 1: audio 2 channels

input file 'B.mp4'
      stream 0: video 1920x1080
      stream 1: audio 2 channels
      stream 2: subtitles (text)
      stream 3: audio 5.1 channels
      stream 4: subtitles (text)

input file 'C.mkv'
      stream 0: video 1280x720
      stream 1: audio 2 channels
      stream 2: subtitles (image)

2.3.1 不经过滤镜处理

使用该命令进行处理

1
ffmpeg -i A.avi -i B.mp4 out1.mkv out2.wav -map 1:a -c:a copy out3.mov

out1.mkv的视频轨为B.mp4的stream 0,音轨为B.mp4的stream 3,字幕轨为B.mp4的stream 2
out2.wav只接受音轨,为B.mp4的stream 3
out3.mov 的音轨为A.avi的stream 1

2.3.1 无标签滤镜输出

1
ffmpeg -i A.avi -i C.mkv -i B.mp4 -filter_complex "overlay" out1.mp4 out2.srt

overlay滤镜是作用在视频轨上的,选取两个视频流即A.aviC.mkv中的视频流,生成没有标签的新视频流直接发送给第一个输出out1.mp4

2.3.4 有标签滤镜输出

1
2
3
4
ffmpeg -i A.avi -i B.mp4 -i C.mkv -filter_complex "[1:v]hue=s=0,split=2[outv1][outv2];overlay;aresample" \
        -map '[outv1]' -an        out1.mp4 \
                                  out2.mkv \
        -map '[outv2]' -map 1:a:0 out3.mkv

B.mp4中的视频流发送给hue滤镜(),使用split滤镜复制输出,标签为[outv1][outv2],分别map到out1.mp4out3.mkv;
overlay滤镜接收两个没有使用的视频流,输出结果没有标签因此发送给第一个输出文件。
aresample滤镜接收两个没有使用的音频流,输出结果同样发送给第一个输出文件。
这两个默认的发送到第一个输出文件的媒体流排序在map的流的前面。

2.4 其它用法

2.4.1 选择所有流

单输入

1
ffmpeg -i input.avi -map 0 output.mkv

多输入

1
ffmpeg -i input0.mkv -i input1.mp4 -i input2.wav -map 0 -map 1 -map 2 output.mkv

2.4.2 只选择一种类型的流

使用map完成

1
2
ffmpeg -i input.mp4 -map 0:v output.mp4
ffmpeg -i input.mp4 -map 0:a output.mp4

更简洁的写法

1
ffmpeg -i input_file -map 0:v:0 video_output_file -map 0:a:0 audio_output_file

2.4.3 只去除一种类型的流

1
ffmpeg -i input.mp4 -map 0 -map -0:a output.mp4

其它写法

1
2
ffmpeg -i input.mp4 -c copy -an output.mp4
ffmpeg -i input.mp4 -c copy -vn output.mp4

2.4.2 选定特定语言

语言信息包含在流的meta中,中文一般为zho

1
ffmpeg -i input.mkv -map 0:v -map 0:m:language:zho output.mp4

2.4.3 选择滤镜输出

在以下例子中滤镜输出的视频流为[v],音频流为[a]

1
ffmpeg -i input.mp4 -i logo.png -i audio.mp3 -filter_complex "[0]scale=1280:-1[bg];[bg][1]overlay[v];[2:a]volume=-3dB[a]" -map "[v]" -map "[a]" output.mp4

2.4.4 多个输出

对于每个输出指定不同的map选项

1
ffmpeg -i input.mkv -map 0:v video.mp4 -map 0:a:1 audio_1.mp3 -map 0:a:3 audio_3.wav

2.4.5 修改流的顺序

map选择流的顺序就是输出文件中流的顺序

1
ffmpeg -i input.mp4 -map 0:v -map 0:a -c copy output.mp4

3. 常见选项参数

3.1 音频选项

Audio options:

参数 含义
-aframes number set the number of audio frames to output
-aq quality 设置音质
-ar rate 采样率
-ac channels 声道数目
-an 去除音频
-acodec codec 指定音频编码
-vol volume 改变音量 (256=normal)
-af filter_graph 设置audio filters

3.2 视频选项

参数 含义
-vframes number set the number of video frames to output
-r rate 指定视频的帧率
-s size 指定视频的尺寸
-aspect aspect 设置画面比例(4:3, 16:9 or 1.3333, 1.7777)
-bits_per_raw_sample number set the number of bits per raw sample
-vn 去除视频
-vcodec codec 指定视频编码
-timecode hh:mm:ss[:;.]ff set initial TimeCode value.
-pass n select the pass number (1 to 3)
-vf filter_graph set video filters
-ab bitrate audio bitrate (please use -b:a)
-b bitrate video bitrate (please use -b:v)
-dn disable data

3.3 字幕选项

Subtitle options:

参数 含义
-s size set frame size (WxH or abbreviation)
-sn disable subtitle
-scodec codec force subtitle codec (‘copy’ to copy stream)
-stag fourcc/tag force subtitle tag/fourcc
-fix_sub_duration fix subtitles duration
-canvas_size size set canvas size (WxH or abbreviation)
-spre preset set the subtitle options to the indicated preset
-dn disable data

4. 常见滤镜的使用

filter:单个滤镜
filter chain: 多个滤镜的组合使用,前一个的输出作为后一个输入,用,分开
filtergraph: 多个filter chain的组合,用;分开
-vf-filter:v的简写
当使用多个输入或者输出文件时,使用-filter_complex而不是-vf

                [main]
input --> split ---------------------> overlay --> output
            |                             ^
            |[tmp]                  [flip]|
            +-----> crop --> vflip -------+

实现命令如下:

1
ffmpeg -i INPUT -vf "split [main][tmp]; [tmp] crop=iw:ih/2:0:0, vflip [flip]; [main][flip] overlay=0:H/2" OUTPUT

4.1 缩放视频

scale滤镜改变视频尺寸

1
ffmpeg -i input -vf scale=iw/2:-1 output

iw为表示输入的宽度(ih表示高度),-1表示维持原来的宽高比例

保持原来的比例,缩放到一个固定的宽高内

1
ffmpeg -i input.jpg -vf scale=w=320:h=240:force_original_aspect_ratio=decrease output_320.png

更详细的选项参考官网wiki

4.2 加速减速

4.2.1 加速视频流

setpts滤镜控制视频播放速度。将播放速度加速到原来的两倍的语句如下:

1
ffmpeg -i input.mkv -filter:v "setpts=0.5*PTS" output.mkv

减速

4.2.2 ​加速音频流

atempo滤镜控制音频播放速度,注意该滤镜的参数限定为0.5-2

1
ffmpeg -i input.mkv -filter:a "atempo=2.0" -vn output.mkv

如果想达到其他速度的效果,可以重复使用

1
ffmpeg -i input.mkv -filter:a "atempo=2.0,atempo=2.0" -vn output.mkv

4.2.3 同时加速

使用复合滤镜,注意音频和视频的参数互为倒数,但是表示的含义是相同的。

1
ffmpeg -i input.mkv -filter_complex "[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]" -map "[v]" -map "[a]" output.mkv

4.3 提升视频流畅度

使用minterpolate进行插值算法,默认的帧率为60

1
ffmpeg -i input.mkv -filter:v "minterpolate='mi_mode=mci:mc_mode=aobmc:vsbmc=1:fps=120'" output.mkv

4.4 改变音量

1
2
3
4
5
6
# 调整音量倍数到原来的一半
ffmpeg -i input.wav -filter:a "volume=0.5" output.wav
# 增加10分贝
ffmpeg -i input.wav -filter:a "volume=10dB" output.wav
# 降低分贝
ffmpeg -i input.wav -filter:a "volume=-5dB" output.wav

标准化音量

1
ffmpeg -i input.wav -filter:a volumedetect -f null /dev/null

更详细的选项参考官网wiki

4.5 视频裁减画面

crop=width:height:x:y,其中 width 和 height 表示裁剪后的尺寸,x:y 表示裁剪区域的左上角坐标

1
ffmpeg -i inputname.mp4 -vf crop=1280:720:0:120 -threads 5 -preset ultrafast -strict -2 outputname.mp4

裁减和缩放同时进行

1
ffmpeg -i IMG_4940.MOV -strict -2 -vf scale=853:480,crop=480:480:186:0 out.mp4

4.6 其它常用滤镜

hflip,vflip 视频翻转
colormatrix,colorspace 视频色调

5. 其它常见的用法

5.1 音画不同步问题

推迟音轨

1
ffmpeg -i "movie.mp4" -itsoffset 3.84 -i "movie.mp4" -map 0:v -map 1:a -c copy "movie-audio-delayed.mp4"

推迟视频轨

1
ffmpeg -i "movie.mp4" -itsoffset 3.84 -i "movie.mp4" -map 1:v -map 0:a -c copy "movie-video-delayed.mp4"

5.2 视频转换gif

1
ffmpeg -ss 00:00:20 -i sample.mp4 -to 10 -r 10 -b 2048k -vf scale=200:-1 sixthtry.gif
参数 含义
-ss GIF起始时间
-to GIF终止时间
-r 帧率,值越大,GIF质量越好
-vf 设置图像的大小,此处宽度为200px,高度按比例压缩
-b 比特率
设置调色板进一步优化
1
2
ffmpeg -ss 2.6 -t 1.3 -i sample.mp4  -filter_complex "fps=10,scale=500:-1:flags=lanczos,palettegen" palette.png
ffmpeg -ss 2.6 -t 1.3 -i sample.mp4  -i palette.png -filter_complex "[0:v]fps=10, scale=500:-1:flags=lanczos[v], [v][1:v]paletteuse" -loop 6 sixthtry.gif

使用 ImageMagick 来优化图片的大小

1
 convert -layers Optimize output.gif output_optimized.gif

5.3 加水印

加在左上角(10px,10px)坐标

1
ffmpeg -i birds.mp4 -i watermark.png -filter_complex "overlay=10:10" birds1.mp4

加在正中间

1
ffmpeg -i birds.mp4 -i watermark.png -filter_complex "overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2" birds2.mp4
参数 含义
main_h the video’s height
main_w the video’s width
overlay_h the overlay’s height
overlay_w the overlay’s width

不遮挡视频

1
ffmpeg -i birds.mp4 -i watermark2.png -filter_complex "pad=height=ih+40:color=#71cbf4,overlay=(main_w-overlay_w)/2:main_h-overlay_h" birds3.mp4

移动水印

1
ffmpeg -i birds.mp4 -i watermark.png -filter_complex "overlay='if(gte(t,1), -w+(t-1)*200, NAN)':(main_h-overlay_h)/2" birds4.mp4

文字水印

1
ffmpeg -i input_file -vf drawtext="fontfile=font_path:fontsize=font_size:text=watermark_text:fontcolor=font_color:alpha=0.4:x=(w-text_w)/2:y=(h-text_h)/2" output_file

5.4 添加时间标签

1
ffmpeg -i input_file -vf drawtext="fontfile=font_path:fontsize=font_size:timecode=starting_timecode:fontcolor=font_colour:box=1:boxcolor=box_colour:rate=timecode_rate:x=(w-text_w)/2:y=h/1.2" output_file

5.4 加字幕

字幕流

1
ffmpeg -i input.mp4 -i subtitle.srt -c copy -c:s mov_text output.mp4

字幕压制进视频流

1
2
3
4
5
6
7
8
# srt字幕
ffmpeg -i video.avi -vf subtitles=subtitle.srt out.avi
# mkv内嵌字幕
ffmpeg -i video.mkv -vf subtitles=video.mkv out.avi
# ass字幕
ffmpeg -i video.avi -vf "ass=subtitle.ass" out.avi
# 转换字幕格式
ffmpeg -i subtitle.srt subtitle.ass

同时添加字幕和水印

1
ffmpeg -i ganguan.mkv -c:v libx264 -vf "movie=logo.png[wm];[i][wm]overlay=0:0,subtitles=ganguan.srt[out]" ganguan.mp4

5.5 修改视频显示比例

1
ffmpeg -i input_file -c:v copy -aspect 4:3 output_file

5.6 剪辑与合并

5.6.1 剪辑

指定开始时间和结束时间

1
ffmpeg -ss 00:02:00 -to 00:55:00 -accurate_seek -i test.mp4 -codec copy -avoid_negative_ts 1 cut.mp4

指定开始时间和持续时间

1
ffmpeg -i input_file -ss 00:05:00 -t 10 -c copy output_file

从开始提取5秒

1
ffmpeg -i input_file -t 5 -c copy -map 0 output_file

从结尾提取5秒

1
ffmpeg -sseof -5 -i input_file -c copy -map 0 output_file

从制定位置到结尾

1
ffmpeg -i input_file -ss 5 -c copy -map 0 output_file

5.6.2 合并

合并多个文件

1
2
for f in ./*.mp4; do echo "file '$f'" >> mylist.txt; done
ffmpeg -f concat -safe 0  -i mylist.txt -c copy myvideo.mp4

每60s切割一个文件

1
ffmpeg -i input_file -c copy -map 0 -f segment -segment_time 60 -reset_timestamps 1 output_file-%03d.mkv

5.7 截图

thumbmail

1
ffmpeg -y -i input.mp4 -ss 00:00:20 -vframes 1 thumb.png

每秒一张图

1
ffmpeg -i input.mov -vf fps=1 -q:v 2 output%03d.png

每秒截图,大小为原视频的一半,输出一张 10x3 的网格图

1
ffmpeg -y -i input.mp4 -vf "fps=1,scale=iw/2:-1,tile=10x3" -an output.jpg
参数 含义
-y 覆盖
-f 生成图片格式
-ss 开始截图时间 seconds or in hh:mm:ss[.xxx] 如果截图开始时间越接近篇尾,所花费的时间就会越长
-vframes 截图帧数 或者 使用 -t : 截图时长 seconds, or hh:mm:ss[.xxx]
-s 图片宽高比
b-%3d.jpg 格式化文件命名,会生成 b-001.jpg,b-002.jpg等。

5.8 为音频添加封面

有两个输入文件,一个是封面图片cover.jpg,另一个是音频文件input.mp3。-loop 1参数表示图片无限循环,-shortest参数表示音频文件结束,输出视频就结束

1
ffmpeg -r 1 -loop 1 -i image_file -i audio_file -acodec copy -shortest -vf scale=1280:720 output_file

5.9 录屏

1
2
3
ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i :0.0+100,200 -f alsa -ac 2 -i hw:0 output.mkv
或者(pulse input device):
ffmpeg -video_size 1024x768 -framerate 25 -f x11grab -i :0.0+100,200 -f pulse -ac 2 -i default output.mkv

5.10 视频和音频淡入淡出

1
ffmpeg -i input_file -filter:v "fade=in:st=IN_POINT:d=DURATION, fade=out:st=OUT_POINT:d=DURATION" -filter:a "afade=in:st=OUT_POINT:d=DURATION, afade=out:st=IN_POINT:d=DURATION" -c:v libx264 -c:a aac output_file

IN_POINT, OUT_POINT, DURATION 都为以秒表示的时间

5.11 去除音频的静音

去除开头的静音

1
ffmpeg -i input_file -af silenceremove=start_threshold=-57dB:start_duration=1:start_periods=1 -c:a your_codec_choice -ar your_sample_rate_choice output_file

去除结尾的静音

1
ffmpeg -i input_file -af areverse,silenceremove=start_threshold=-57dB:start_duration=1:start_periods=1,areverse -c:a your_codec_choice -ar your_sample_rate_choice output_file

5.12 音视频倒放

1
ffmpeg -i inputfile.mp4 -vf reverse -af areverse -preset superfast reversed.mp4

预设(preset),预设会影响编码的速度和压缩比。慢的预设会给出一个较好的压缩比

总结

整理了一大堆命令,希望之后使用的时候能够更加方便。除此之外,ffmpeg还可以用来做直播推流等,这个网站上面有很多常见的例子以及具体的参数解释:ffmprovisr,可以用于参考。

最近好想学习剪辑视频,然而linux系统的剪辑软件选择范围不多,多学点命令行处理视频,感觉还是很有用的。

参考

  1. https://ffmpeg.org/
  2. https://zh.wikipedia.org/wiki/FFmpeg
  3. ffmpeg 入门笔记 http://einverne.github.io/post/2015/12/ffmpeg-first.html
  4. [总结]FFMPEG视音频编解码零基础学习方法 https://blog.csdn.net/leixiaohua1020/article/details/15811977
  5. 20+ FFmpeg Commands For Beginners https://www.ostechnix.com/20-ffmpeg-commands-beginners/
  6. High Quality Gifs with FFMPEG https://medium.com/@colten_jackson/doing-the-gif-thing-on-debian-82b9760a8483
  7. Watermarking Videos from the Command Line with FFMPEG Filters http://ksloan.net/watermarking-videos-from-the-command-line-using-ffmpeg-filters/
  8. https://trac.ffmpeg.org/wiki/HowToBurnSubtitlesIntoVideo
  9. 分类:如何使用 FFmpeg 进行视频转码 https://wiki.fiveyellowmice.com/wiki/%E5%88%86%E7%B1%BB:%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8_FFmpeg_%E8%BF%9B%E8%A1%8C%E8%A7%86%E9%A2%91%E8%BD%AC%E7%A0%81
  10. https://trac.ffmpeg.org/wiki/Capture/Desktop
  11. FFmpeg 视频处理入门教程 http://www.ruanyifeng.com/blog/2020/01/ffmpeg.html
  12. FFmpeg filter简介 https://www.cnblogs.com/tocy/p/ffmpeg-filter-intro.html
  13. FFmpeg Map命令 https://trac.ffmpeg.org/wiki/Map
  14. ffmpeg命令行map参数的使用 https://blog.csdn.net/xiaoluer/article/details/81136478
  15. ffmpeg滤镜wiki的使用 https://trac.ffmpeg.org/wiki/FilteringGuide
  16. macOS 下 FFmpeg 视频转码入门及进阶使用教程 https://segmentfault.com/a/1190000013425769
  17. ffmpeg wiki上面滤镜的有趣例子 https://trac.ffmpeg.org/wiki/FancyFilteringExamples
  18. ffmprovisr https://amiaopensource.github.io/ffmprovisr/