计算机 · 2021年6月2日 0

FFmpeg从入门到精通读书笔记

第一章 FFmpeg简介

FFmpege的定义

FF:Fast Forward。
mpeg:Moving Picture Experts Group。

FFmpeg的历史

创始人:Fabrice Bellard。
负责人:Michael Niedermayer。

FFmpeg的构成

  • 封装模块AVFormat
    只要支持MP4,FLV,KV,TS等文件封装格式;RTMP,RTSP,NMS,HLS等网络协议封装格式。
  • 编解码模块AVCodec
    自带的媒体编解码格式:MPEG4,AAC,MJPEG;
    第三方的:使用X264编码器支持H.264(AVC);使用X265编码器支持H.265(HEVC);使用libmp3lame支持MP3(mp3lame)编码;
  • 滤镜模块(AVFilter)
    AVFilter提供了一个通用的音频、视频、字幕等滤镜处理框架。
  • 视频图像转换计算模块swscale
  • 音频转换计算模块swsample

FFmpeg的基础命令

转格式

ffmpeg -i input.mp4 output.avi

上面没有明确指定输出文件的容器格式,如果要明确指定,需要用-f参数指定:

ffmpeg -i input.mp4 -f avi output.dat

在ffmpeg的运行输出信息中的Input #0Output #0可以分别看到输入和输出的格式。

比如ffmpeg -i 2020-09-05-171930.webm 2020-09-05-171930.avi的输出信息如下:

ffmpeg version 4.1.3-0ppa1~18.04 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version='0ppa1~18.04' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-nonfree --enable-libfdk-aac --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, matroska,webm, from '2020-09-05-171930.webm':
  Metadata:
    encoder         : GStreamer matroskamux version 1.14.5
    creation_time   : 2020-09-05T09:19:30.000000Z
  Duration: 00:00:11.20, start: 0.000000, bitrate: 1145 kb/s
    Stream #0:0(eng): Video: vp8, yuv420p(progressive), 640x480, SAR 1:1 DAR 4:3, 30 fps, 30 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      title           : Video
    Stream #0:1(eng): Audio: vorbis, 44100 Hz, mono, fltp (default)
    Metadata:
      title           : Audio
Stream mapping:
  Stream #0:0 -> #0:0 (vp8 (native) -> mpeg4 (native))
  Stream #0:1 -> #0:1 (vorbis (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, avi, to '2020-09-05-171930.avi':
  Metadata:
    ISFT            : Lavf58.20.100
    Stream #0:0(eng): Video: mpeg4 (FMP4 / 0x34504D46), yuv420p, 640x480 [SAR 1:1 DAR 4:3], q=2-31, 200 kb/s, 30 fps, 30 tbn, 30 tbc (default)
    Metadata:
      title           : Video
      encoder         : Lavc58.35.100 mpeg4
    Side data:
      cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
    Stream #0:1(eng): Audio: mp3 (libmp3lame) (U[0][0][0] / 0x0055), 44100 Hz, mono, fltp (default)
    Metadata:
      title           : Audio
      encoder         : Lavc58.35.100 libmp3lame
frame=  335 fps=0.0 q=12.6 Lsize=     527kB time=00:00:11.20 bitrate= 385.7kbits/s speed=26.7x    
video:412kB audio:87kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 5.661337%

ffmpeg的主要工作流程:

  1. 解封装(Demuxing)
  2. 解码(Decoding)
  3. 编码(Encoding)
  4. 封装(Muxing)

封装解封装用libavformat,编解码用libavcodec,而中间解码之后的数据为YUV或PCM。

播放文件

ffplay 2020-09-05-171930.avi

多媒体分析器ffprobe

使用ffprobe可以获取媒体文件或者媒体流的编码格式、码率等信息。

ffprobe 2020-09-05-171930.mp4

ffmpeg的编译

第二章 FFmpeg工具使用基础

ffmpeg 常用命令

ffmpeg参数大概可以分为6种:

  • ffmpeg信息查询
  • ffmpeg公共操作
  • 文件操作
  • 视频操作
  • 音频操作
  • 字幕操作

信息查询

  1. 获取帮助信息
    ffmpeg --help
    ffmpeg --help long
    ffmpeg --help full
    这三个命令可以提供三个不同级别的帮助信息。
  2. 获取license支持信息
    ffmpeg -L
  3. 获取格式支持信息
    ffmpeg -formats
    ffmpeg会详细列出对每种格式的mux,demux支持。
  4. 获取编解码器支持信息
    ffmpeg -codecs查看编解码器信息
    ffmpeg --encoders只看编码器信息
    ffmpeg --decoders只看解码器信息
  5. 获取滤镜支持信息
    ffmpeg -filters
  6. 查看具体的某一种muxer/demuxer/encoder/decoder/filter支持信息
    ffmpeg -h muxer=flv
    ffmpeg -h demuxer=flv
    ffmpeg -h encoder=h264
    ffmpeg -h decoder=h264
    ffmpeg -h filter=colorkey

格式封装转换参数

参数类型说明
avioflags标记format的缓冲设置,默认为0,就是有缓冲
avioflagsdirect无缓冲状态
probesize整数在进行媒体数据处理前获得文件内容的大小,可用在预读取文件头时提高速度,也可以设置足够大的值来读取到足够多的音视频数据信息
fflags标记
fflagsflush_packets立即将packets数据刷新写入到文件中
fflagsgenpts输出时按照正常规则产生pts
fflagsnofillin不填写可以精确计算缺失的值
fflagsigndts忽略dts
fflagsdiscardcorrupt丢弃损坏的帧
fflagssortdts尝试以dts的顺序为标准输出
fflagskeepside不合并数据
fflagsfastseek快速seek(定位)操作,但是不够精确
fflagslatm设置RTP MP4_LATM生效
fflagsnobuffer直接读取或写出,不存入buffer,用于在直播采集时降低延迟
fflagsbitexact不写入随机或者不稳定的数据
seek2any整数支持随意位置seek,这个seek不以keyframe为参考
analyzeduration整数指定解析媒体所需要花销的时间,这里设置的值越高,解析越准确,如果在直播中为了降低延迟,这个值可以设置得低一些
codec_whitelist列表设置可以解析的codec的白名单
format_whitelist列表设置可以解析的format的白名单
output_ts_offset整数设置输出文件的起始时间

转码参数

参数类型说明
b整数设置音频与视频码率,可以认为是音视频加起来的码率,默认为200kbit/s 使用这个参数可以根据b:v设置视频码率,b:a设置音频码率
ab整数设置音频的码率,默认是128kbit/s
g整数设置视频GOP(可以理解为关键帧间隔)大小,默认是12帧一个GOP
ar整数设置音频采样率,默认为0
ac整数设置音频通道数,默认为0
bf整数设置连续编码为B帧的个数,默认为0
maxrate整数最大码率设置,与bufsize一同使用即可,默认为0
minrate整数最小码率设置,配合maxrate与bufsize可以设置为CBR模式,平时很少使用,默认为0
bufsize整数设置控制码率的buffer的大小,默认为0
keyint_min整数设置关键帧最小间隔,默认为25
sc_threshold整数设置场景切换支持,默认为0
mc_threshold整数设置运动估计阈值,默认为0
mb_threshold整数设置宏块阈值,默认为0
profile整数设置音视频的profile,默认为-99
level整数设置音视频的level,默认为-99
timecode_frame_start整数设置GOP帧的开始时间,需要在non-drop-frame默认情况下使用
channel_layout整数设置音频通道的布局格式
threads整数设置编解码工作的线程数

ffmpeg转码例子

ffmpeg -i 2020-09-05-171930.webm -vcodec mpeg4 -b:v 400k -r 15 -an  output.mp4

输出信息:

ffmpeg version 4.1.3-0ppa1~18.04 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version='0ppa1~18.04' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-nonfree --enable-libfdk-aac --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, matroska,webm, from '2020-09-05-171930.webm':
  Metadata:
    encoder         : GStreamer matroskamux version 1.14.5
    creation_time   : 2020-09-05T09:19:30.000000Z
  Duration: 00:00:11.20, start: 0.000000, bitrate: 1145 kb/s
    Stream #0:0(eng): Video: vp8, yuv420p(progressive), 640x480, SAR 1:1 DAR 4:3, 30 fps, 30 tbr, 1k tbn, 1k tbc (default)
    Metadata:
      title           : Video
    Stream #0:1(eng): Audio: vorbis, 44100 Hz, mono, fltp (default)
    Metadata:
      title           : Audio
File 'output.mp4' already exists. Overwrite ? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (vp8 (native) -> mpeg4 (native))
Press [q] to stop, [?] for help
Output #0, mp4, to 'output.mp4':
  Metadata:
    encoder         : Lavf58.20.100
    Stream #0:0(eng): Video: mpeg4 (mp4v / 0x7634706D), yuv420p, 640x480 [SAR 1:1 DAR 4:3], q=2-31, 400 kb/s, 15 fps, 15360 tbn, 15 tbc (default)
    Metadata:
      title           : Video
      encoder         : Lavc58.35.100 mpeg4
    Side data:
      cpb: bitrate max/min/avg: 0/0/400000 buffer size: 0 vbv_delay: -1
frame=  170 fps=0.0 q=2.3 Lsize=     655kB time=00:00:11.26 bitrate= 476.3kbits/s dup=0 drop=165 speed=54.2x    
video:653kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.244187%

解释:

  • 封装格式由webm变为mp4
  • 视频编码从vp8变为MPEG4
  • 原来没有单独指定视频的码率?但是输出的视频码率定为了400kbps
  • 视频帧率从30变为了15
  • 转码后的文件不包括音频(-an参数)

ffprobe常用命令

查看多媒体数据包

ffprobe -show_packets output.mp4

输出示例:

[PACKET]
codec_type=video
stream_index=0
pts=116736
pts_time=11.400000
dts=116736
dts_time=11.400000
duration=2048
duration_time=0.200000
convergence_duration=N/A
convergence_duration_time=N/A
size=2800
pos=368776
flags=__
[/PACKET]

packet字段说明:

字段说明
codec_type多媒体类型,如视频包,音频包等
stream_index多媒体的stream索引
pts多媒体的显示时间值
pts_time根据不同格式计算过后的多媒体的显示时间
dts多媒体解码时间值
dts_time根据不同格式计算过后的多媒体解码时间
duration多媒体包占用的时间值
duration_time根据不同格式计算过后的的多媒体包所占用的时间
size多媒体包的大小
pos多媒体包所在的文件偏移位置
flags多媒体包标记,如关键包与非关键包的标记

还可以把原始数据一起展示出来:

ffprobe -show_data -show_packets output.mp4

查看封装格式

ffprobe -show_format output.mp4

输出示例:

ffprobe version 4.1.3-0ppa1~18.04 Copyright (c) 2007-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu 7.3.0-27ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version='0ppa1~18.04' --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opengl --enable-sdl2 --enable-nonfree --enable-libfdk-aac --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 22.100 / 56. 22.100
  libavcodec     58. 35.100 / 58. 35.100
  libavformat    58. 20.100 / 58. 20.100
  libavdevice    58.  5.100 / 58.  5.100
  libavfilter     7. 40.101 /  7. 40.101
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  3.100 /  5.  3.100
  libswresample   3.  3.100 /  3.  3.100
  libpostproc    55.  3.100 / 55.  3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'output.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2mp41
    encoder         : Lavf58.20.100
  Duration: 00:00:11.60, start: 0.000000, bitrate: 257 kb/s
    Stream #0:0(eng): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 256 kb/s, 5 fps, 5 tbr, 10240 tbn, 5 tbc (default)
    Metadata:
      handler_name    : VideoHandler
[FORMAT]
filename=output.mp4
nb_streams=1
nb_programs=0
format_name=mov,mp4,m4a,3gp,3g2,mj2
format_long_name=QuickTime / MOV
start_time=0.000000
duration=11.600000
size=372678
bit_rate=257019
probe_score=100
TAG:major_brand=isom
TAG:minor_version=512
TAG:compatible_brands=isomiso2mp41
TAG:encoder=Lavf58.20.100
[/FORMAT]

format字段说明

字段说明
filename文件名
nb_streams媒体中包含的流的个数
nb_programs节目数
format_name使用的封装模块的名称
format_long_name封装的完整名称
start_time媒体文件的起始时间
duration媒体文件的总时间长度
size媒体文件的大小
bit_rate媒体文件的码率

ffprobe查看视频文件中的帧信息

ffprobe -show_frames output.mp4

示例输出:

[FRAME]
media_type=video
stream_index=0
key_frame=1
pkt_pts=0
pkt_pts_time=0.000000
pkt_dts=0
pkt_dts_time=0.000000
best_effort_timestamp=0
best_effort_timestamp_time=0.000000
pkt_duration=2048
pkt_duration_time=0.200000
pkt_pos=44
pkt_size=8378
width=640
height=480
pix_fmt=yuv420p
sample_aspect_ratio=1:1
pict_type=I
coded_picture_number=0
display_picture_number=0
interlaced_frame=0
top_field_first=0
repeat_pict=0
color_range=unknown
color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
[SIDE_DATA]
side_data_type=QP table data
[/SIDE_DATA]
[SIDE_DATA]
side_data_type=QP table properties
[/SIDE_DATA]
[/FRAME]

frame字段说明

属性说明
media_type帧的类型(视频、音频、字幕等)video
stream_index帧所在的索引区域0
key_frame是否为关键帧1
pkt_ptsFrame包的pts0
pkt_pts_timeFrame包的pts的时间显示0.000000
pkt_dtsFrame包的dts0
pkt_dts_timeFrame包的dts的时间显示0.000000
pkt_durationFrame包的时长2048
pkt_duration_timeFrame包的时长时间显示0.200000
pkt_posFrame包所在文件的偏移位置44
width帧显示的宽度680
height帧显示的高度480
pix_fmt帧的图像色彩格式yuv420p
pict_type帧类型I

ffprobe查看视频文件中的流信息

ffmpeg -show_streams output.mp4

示例输出:

[STREAM]
index=0
codec_name=mpeg4
codec_long_name=MPEG-4 part 2
profile=Simple Profile
codec_type=video
codec_time_base=1/5
codec_tag_string=mp4v
codec_tag=0x7634706d
width=640
height=480
coded_width=640
coded_height=480
has_b_frames=0
sample_aspect_ratio=1:1
display_aspect_ratio=4:3
pix_fmt=yuv420p
level=1
color_range=unknown
color_space=unknown
color_transfer=unknown
color_primaries=unknown
chroma_location=left
field_order=unknown
timecode=N/A
refs=1
quarter_sample=false
divx_packed=false
id=N/A
r_frame_rate=5/1
avg_frame_rate=5/1
time_base=1/10240
start_pts=0
start_time=0.000000
duration_ts=118784
duration=11.600000
bit_rate=256228
max_bit_rate=400000
bits_per_raw_sample=N/A
nb_frames=58
nb_read_frames=N/A
nb_read_packets=N/A
DISPOSITION:default=1
DISPOSITION:dub=0
DISPOSITION:original=0
DISPOSITION:comment=0
DISPOSITION:lyrics=0
DISPOSITION:karaoke=0
DISPOSITION:forced=0
DISPOSITION:hearing_impaired=0
DISPOSITION:visual_impaired=0
DISPOSITION:clean_effects=0
DISPOSITION:attached_pic=0
DISPOSITION:timed_thumbnails=0
TAG:language=eng
TAG:handler_name=VideoHandler
[/STREAM]

stream字段说明

属性说明
index流所在的索引区域0
codec_name编码名mpeg4
codec_long_name编码全名MPEG-4 part 2
profile编码的profileSimple Profile
level编码的level1
has_b_frames包含b帧信息0
codec_type编码类型video
codec_time_base编码的时间戳计算基础单位1/5
pix_fmt图像显示的色彩格式yuv420p
coded_width图i像的宽度640
coded_height图像的高度480
codec_tag_string编码的标签数据mp4v
r_frame_rate实际帧率5/1
avg_frame_rate平均帧率5/1
time_base时间基数(用来进行timestamp计算)1/10240
bit_rate码率200000
max_bit_rate最大码率400000
nb_frames帧数58

ffprobe设置输出格式

ffprobe可以换其他的格式输出上面查询的信息,并保存到相应文件。

ffprobe -of ini -show_streams output.mp4
ffprobe -of flag -show_streams output.mp4
ffprobe -of xml -show_streams output.mp4
ffprobe -of csv -show_streams output.mp4

ffprobe筛选stream

只看视频流:

ffprobe -show_frames -select_streams v -of xml output.mp4

ffplay常用命令

ffplay基础参数

参数说明
x强制设置视频显示窗口的宽度
y强制设置视频显示窗口的高度
s设置视频显示的宽高
fs强制全屏显示
an屏蔽音频
vn屏蔽视频
sn屏蔽字幕
ss根据设置的秒进行定位拖动
t设置播放视频/音频的长度
bytes设置定位拖动的策略,0为不可拖动,1为可拖动,-1为自动
nodisp关闭图形化显示窗口
f强制使用设置的格式进行解析
window_tile设置显示窗口的标题
af设置音频的滤镜
codec强制使用设置的codec进行解码
autorotate自动旋转视频
ast设置将要播放的音频流
vst设置将要播放的视频流
sst设置将要播放的字幕流
stats输出多媒体播放状态
fast非标准化规范的多媒体兼容优化
sync音视频同步设置可根据音频时间、视频时间或者外部扩展时间进行参考
autoexit多媒体播放完毕之后自动退出ffplay,ffplay默认播放完毕之后不退出播放器
exitonkeydown当有鼠标按下事件产生时退出ffplay
exitonmousedown当有鼠标按键事件产生时退出ffplay
loop设置多媒体文件循环播放的次数
framedrop当CPU资源占用过高时,自动丢帧
infbuf设置无极限的播放器buffer,这个选项常见于实时流媒体播放场景
vf视频滤镜设置
acodec强制使用设置的音频解码器
vcodec强制使用设置的视频解码器
scodec强制使用设置的字幕解码器
  • 从视频的第2秒开始播放,放5秒钟ffplay -ss 2 -t 5 ouput.mp4
  • 设置播放窗口的标题ffplay -window_title "hello my title" output.mp4
  • 播放rtmp流ffplay rtmp://xxx 可以配合nginx的rtmp模块搞着玩。
  • 对于广电行业的多节目流,需要指定音视频流编号ffplay -vst 4 -ast 5 xx.ts
  • 加载字幕文件
    需要使用滤镜ffplay -vf "subtitles=input.srt" output.mp4
  • 显示声音波形ffplay -showmode 1 output.mp3
  • 显示解码器如解码每个宏块
    下面这个命令应该已经过时了ffplay -debug vis_mb_type output.mp4 貌似可以用(我测试时一片绿色….):ffplay output.mp4 -vf codecview=qp=true
  • 显示B帧与P帧预测信息
    这个命令也过时了。。。ffplay -vismv pf output.mp4 应该使用:ffplay -flags2 +export_mvs output.mp4 -vf codecview=mv=pf+bf+bb

第三章 FFmpeg转封装

音视频文件转MP4格式

MP4格式标准:ISO-14496 Part12、ISO-14496 Part14
MP4的几个概念:

  • MP4文件由许多个Box与FullBox组成
  • 每个Box由Header和Data组成
  • FullBox是Box的扩展,其在Box结构的基础上,在Header中增加8位version标志和24位的flags标志
  • Header包含了整个Box的长度的大小(size)和类型(type),当size等于0时,代表这个Box是文件的最后一个Box。当size等于1时,说明Box长度需要更多的位来描述,在后面会定义一个64位的largesize来描述Box的长度。当type为uuid时,说明这个Box中的数据是用户自定义扩展类型。
  • Data为Box的实际数据,可以是纯数据,也可以是更多的子Box
  • 当一个Box中Data是一系列的子Box时,这个Box又可以称为Container(容器)Box

MP4常用参考标准排列方式
(赶时间,暂时懒得抄了。。。)

  1. moov容器
  2. mvhd子容器
  3. trak子容器
  4. tkhd容器
  5. mdia容器
  6. mdhd容器
  7. hdlr容器
  8. minf容器
  9. vmhd容器
  10. smhd容器
  11. dinf容器
  12. stbl容器
  13. edts容器

MP4分析工具

  1. Elecard streamEye
    貌似是款商业产品。。。
  2. mp4boxsudo apt install gpac 可以针对媒体文件进行合成、分解等操作。
    装好后命令名是MP4Box,基本操作:MP4Box -info output.mp4 示例输出:* Movie Info * Timescale 1000 - Duration 00:00:11.600 1 track(s) Fragmented File: no File Brand isom - version 512 Created: UNKNOWN DATE Modified: UNKNOWN DATE File has no MPEG4 IOD/OD iTunes Info: Encoder Software: Lavf58.20.100 1 UDTA types: meta (1) Track # 1 Info - TrackID 1 - TimeScale 10240 - Media Duration 00:00:11.600 Track has 1 edit lists: track duration is 00:00:11.600 Media Info: Language "eng (eng)" - Type "vide:mp4v" - 58 samples 1 UDTA types: name (1) Visual Track layout: x=0 y=0 width=640 height=480 MPEG-4 Config: Visual Stream - ObjectTypeIndication 0x20 MPEG-4 Visual Size 640 x 480 - Simple Profile @ Level 1 Pixel Aspect Ratio 1:1 - Indicated track size 640 x 480 Self-synchronized RFC6381 Codec Parameters: mp4v.20.1 Average GOP length: 11 samples 其他的使用例子
  3. mp4infosudo apt install mp4v2-utils 为啥我装的这个mp4info命令很弱鸡。。。
    原来书上说的mp4info是一个windows下的工具,linux下的应该可以用下这个[MediaParser][https://github.com/ksvc/MediaParser]。

MP4在FFmpeg中的Demuxer

ffmpeg解封装MP4常用参数

MP4在FFmpeg中的Muxer

ffmpeg封装MP4常用参数

  1. faststart参数
    正常情况下ffmpeg生产moov是在mdat写完成之后再写入,可以通过参数将moov容器移动至mdat的前面:ffmpeg -i input.flv -c copy -f mp4 output.mp4 ffmpeg -i input.flv -c copy -f mp4 -movflags faststart output.mp4 书中有讲过,如果是在互联网视频点播中,希望这个MP4文件被快速打开,那么需要将moov存放在mdat的前面,否则就只有将MP4文件下载完才可以进行播放。
  2. dash参数使用案例ffmpeg -i input.flv -c copy -f mp4 -movflags dash output.mp4
  3. isml参数使用案例
    从来没听说过的东西。。。

视频文件转FLV

FLV是Adobe发布的一种可以作为直播也可以作为点播的封装格式。

FLV格式标准

FLV文件格式分为两部分,一部分为FLV文件头,另一部分为FLV文件内容。

  1. FLV文件头格式解析
  2. FLV文件内容格式解析
  3. FLVTAG格式解析
  4. VideoTag格式解析
  5. AudioTag格式解析
  6. ScriptData格式解析

FFmpeg转flv参数

参数类型说明
flvflagsflag设置生成FLV时使用的flag
flvflagsaac_seq_header_detect添加AAC音频的Sequence Header
flvflagsno_sequence_end生成FLV结束时不写入sequence end
flvflagsno_metadata生成FLV时不写入metadata
flvflagsno_duration_filesize用于直播时不在metadata中写入duration与filesize
flvflagsadd_keyframe_index生成FLV时自动写入关键帧索引信息到metadata头

在生成FLV文件时,写入视频、音频数据均需要写入Sequence Header数据。

FFmpeg文件转FLV

FLV封装中可以支持的视频编码:

  • Sorenson H.263
  • Screen Video
  • On2 VP6
  • 带Alpha通道的On2 VP6
  • Screen Video 2
  • H.264(AVC)

FLV封装中支持的音频编码:

  • 线性PCM,大小端取决于平台
  • ADPCM音频格式
  • MP3
  • 线性PCM,小端
  • Nellymoser 16kHz Mono
  • Nellymoser 8kHz Mono
  • Nellymoser
  • G.711 A-law
  • G.711 mu-law
  • 保留(WTF?)
  • AAC
  • Speex
  • MP3 8kHz

如果封装flv时,内部的音频或者视频标准不是FLV支持的,那么就会报错,需要先进行专门:

ffmpeg -i input_ac3.mp4 -vcodec copy -acodec aac -f flv output.flv

从上面这个例子可以看出指定输出音频编码为FLV支持的标准即可。

FFmpeg生成带关键索引的FLV

对于网络点播视频,可以用yamdi工具为关键帧建立索引。也可以使用FFmpeg实现:

ffmpeg -i input.mp4 -c copy -f flv -flvflags add_keyframe_index output.flv

FLV文件格式分析工具

  • flvparse
  • FlvAnalyzer
  • ffprobeffprobe -v trace -i output.flv

视频文件转M3U8

M3U8格式标准

  • EXTM3U
  • EXT-X-VERSION
  • EXT-X-TARGETDURATION
  • EXT-X-MEDIA-SEQUENCE
  • EXTINF
  • EXT-X-ENDLIST
  • EXT-X-STREAM-INF

FFmpeg封装HLS参数

参数类型说明
start_number整数设置M3U8列表中的第一片的序列数
hls_time浮点数设置每一片时长
hls_list_size整数设置M3U8中分片的个数
hls_ts_options字符串设置TS切片的参数
hls_wrap整数设置切片索引回滚的边界值
hls_allow_cache整数设置M3U8中EXT-X-ALLOW-CACHE的标签
hls_base_url字符串设置M378中每一片的前置路径
hls_segment_filename字符串设置切片名模板
hls_key_info_file字符串设置M3U8加密的key文件路径
hls_subtitle_path字符串设置M3U8字幕路径
hls_flags标签(整数)设置M3U8文件列表的操作,具体如下:
sing_file:生成一个媒体索引与字节范围;
delete_segments:删除M3U8文件中不包含的过期的TS切片文件;
round_durations:生成的M3U8切片信息的duration为整数;
discont_start:生成M3U8的时候在列表前边加上discontinuity标签;
omit_endlist:在M3U8末尾不追加endlist标签;
use_localtime布尔设置M3U8文件序号为本地时间戳
use_localtime_mkdir布尔根据本地时间戳生成目录
hls_playlist_type整数设置M3U8列表为事件或者点播列表
method字符串设置HTTP属性

举例:

常规的从文件转换为HLS直播

ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb output.m3u8

-bsf:v h264_toannexb是说将MP4中的H.264数据转换为H.264 AnnexB标准的编码。

  1. 设置start_numberffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -start_number 300 output.m3u8
  2. hls_time参数ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_time 10 output.m3u8 因为ffmpeg这个命令是会从关键帧开始切片,所以这个10秒钟并不是严格的。
  3. hls_list_size参数ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_list_size 3 output.m3u8
  4. hls_wrap参数(据说有问题,在新版本中这个参数会被废弃?)ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_wrap 3 output.m3u8
  5. hls_base_url参数ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_base_url http://localhost output.m3u8
  6. hls_segment_filename参数ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_segment_filename test_output-%d.ts output.m3u8
  7. hls_flags参数
    • delete_segments
      需要配合hls_list_size使用。ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_flags delete_segments -hls_list_size 4 output.m3u8
    • round_durationsffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_flags round_durations output.m3u8 让m3u8文件里的切片时长信息显示为整型。
    • discont_start
      在m3u8文件里第一个TS信息前面加上#EXT-X-DISCONTINUITY表明切片不连续。ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_flags discont_start output.m3u8
    • omit_endlist
      在m3u8文件末尾不写上endlist标签。ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_flags omit_endlist output.m3u8
    • split_by_time
      配合hls_time一起使用,达到不按关键帧而是按照指定时间强行切片的效果。造成的问题就是如果你获得的第一个ts不是I帧开头的可能就会花屏或者显示慢。ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_time 2 -hls_flags split_by_time output.m3u8
  8. use_localtime参数ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_segment_filename -use_localtime output.m3u8
  9. method参数
    居然ffmpeg配合nginx的webdav模块可以直接把生成的m3u8和ts文件给直接推到服务器上去!

视频文件切片

  1. segment_format指定切片文件的格式ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 test_output-%d.mp4
  2. segment_list与segment_list_type指定切片索引列表
    • ffconcatffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type ffconcat -segment_list output.lst test_output-%d.mp4
    • flat格式ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type flat -segment_list filelist.txt test_output-%d.mp4
    • csv格式ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type csv -segment_list filelist.csv test_output-%d.mp4
    • m3u8格式ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type m3u8 -segment_list output.m3u8 test_output-%d.mp4
  3. reset_timestamps使切片时间戳归0ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -reset_timestamps 1 test_output-%d.mp4
  4. segment_times按照时间点剪切ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_times 3,9,12 test_output-%d.mp4

FFmpeg使用ss与t参数进行切片

  1. 使用ss指定剪切开头部分ffmpeg -ss 8 -i input.mp4 -c copy output.ts
  2. 使用t指定视频总长度ffmpeg -i input.mp4 -c copy -t 10 -copyts output.ts
  3. 使用output_ts_offset指定输出start_timeffmpeg -i input.mp4 -c copy -t 10 -output_ts_offset 120 output.mp4

音视频文件音视频流抽取

抽取AAC音频流

ffmpeg -i input.mp4 -vn -acodec copy output.aac

抽取H.264视频流

ffmpeg -i input.mp4 -vcodec copy -an output.h264

抽取音视频文件中的H.265数据

ffmpeg -i input.mp4 -vcodec copy -an -bsf hevc_mp4toannexb -f hevc output.hevc

第四章 FFmpeg转码

支持H.264的常见封装格式有:FLV,MP4,HLS(M3U8),MKV,TS等。FFmpeg本身不支持H.264编码,主要用x264和OpenH264编码器。使用ffmpeg -h encoder=libx264可以看到x264支持的像素格式。

x264编码参数

参数类型说明
preset字符串编码器预设参数
tune字符串调优编码参数
profile字符串编码profile档级设置
level字符串编码level层级设置
wpredp字符串P帧预测设置
x264opts字符串设置x264专有参数
crf浮点数选择质量恒定质量模式
crf_max浮点数选择质量恒定质量模式最大值
qp整数恒定量化参数控制
psy浮点数只用psychovisual优化
rc-lookahead整数设置预读帧设置
weightb浮点数B帧预测设置
weightp整数设置预测分析方法:none、simple、smart三种模式
ssim布尔计算打印SSIM状态
intra-refresh布尔定时刷I帧以替代IDR帧
bluray-compat布尔蓝光兼容参数
b-bias整数B帧使用频率设置
mixed-refs布尔每个partition一个参考,而不是每个宏块一个参考
8x8dct布尔8×8矩阵变换,用在high profile
aud布尔带AUD分隔标识
mbtree布尔宏块树频率控制
deblock字符串环路滤波参数
cplxblur浮点数减少波动QP参数
partitions字符串逗号分隔的partition列表,可以包含的值有p8x8,p4x4,b8x8,i8x8,i4x4,none,all
direct-pred整数运动向量预测模式
slice-max-size整数Slice的最大值
nal-hrd整数HRD信号信息设置:None,VBR,CBR设置
motion-est整数运动估计方法
forced-idr整数强行设置关键帧为IDR帧
coder整数编码器类型包括default、cavlc、cabac、vlc、ac
b_strategy整数I/P/B帧选择策略
chromaoffst整数QP色度和亮度之间的差异参数
sc_threshold整数场景切换阈值参数
noise_reduction整数降噪处理参数
x264-params字符串与x264opts操作相同

编码举例

编码器预设参数preset

  • ultrafast
  • superfast
  • veryfast
  • faster
  • fast
  • medium
  • slow
  • slower
  • veryslow
  • placebo
ffmpeg -i 2020-09-05-171930.mp4 -vcodec libx264 -preset ultrafast -b:v 100k output.mp4

在命令的输出中有显示:

frame= 336 fps=0.0 q=-1.0 Lsize= 245kB time=00:00:11.16 bitrate= 179.4kbits/s speed=29.9x

表示转码所花时间是视频本身时间的29.9分之一。

H.264编码优化参数tune

  • film
  • animation
  • grain
  • stillimage
  • psnr
  • ssim
  • fastdecode
  • zerolatency

在使用FFmpeg与x264进行H.264的直播编码推流时可以使用zerolatency模式降低因编码导致的延迟。

H.264的profile与level设置

profile:

  • Baseline
  • Extend
  • Main
  • High
  • High10
  • High422
  • High444

控制场景切换关键帧插入参数sc_threshold

设置x264内部参数x264opts

CBR恒定码率设置参数nal-hrd

硬件编解码

Nvidia GPU

Intel QSV

第五章 FFmpeg流媒体

发布与录制rtmp流

rtmp参数:

参数类型说明
rtmp_app字符串RTMP流发布点,又称为APP
rtmp_buffer整数客户端buffer大小(单位:毫秒),默认为3秒
rtmp_conn字符串在RTMP的Connect命令中增加自定义AMF数据
rtmp_flashver字符串设置模拟的flashplugin的版本号
rtmp_live整数指定RTMP流媒体播放类型,可以为any、live、recorded
rtmp_pageurl字符串RTMP在Connect命令中设置的PageURL字段,其为播放时所在的Web页面URL
rtmp_playpath字符串RTMP流播放的Stream地址,或者成为密钥,或者称为发布流
rtmp_subscribe字符串直播流名称,默认设置为rtmp_playpath的值
rtmp_swfhash二进制数据解压swf文件后的SHA256的hash值
rtmp_swfsize整数swf文件解压后的大小,用于swf认证
rtmp_swfurl字符串RTMP的Connect命令中设置的swfURL播放器的URL
rtmp_swfverify字符串设置swf认证时swf文件的URL地址
rtmp_tcurl字符串RTMP的Connect命令中设置的tcURL目标发布点地址,一般形如rtmp://xxx.xxx.xxx/app
rtmp_listen整数开启RTMP服务时所监听的端口
listen整数与rtmp_listen相同
timeout整数监听rtmpu端口时设置的超时时间,以秒为单位

推流:

ffmpeg -re -i input.mp4 -c copy -f flv -rtmp_app live -rtmp_playpath class rtmp://publish.chinaffmpeg.com
#可以省略掉rtmp_app参数与rtmp_playpath参数
ffmpeg -i input.mp4 -c copy -f flv rtmp://publish.chinaffmpeg.com/live/class

拉流:

ffmpeg -rtmp_app live -rtmp_playpath class -i rtmp://publish.chinaffmpeg.com -c copy -f flv output.flv
#同样的,命令可以简写
ffmpeg -i rtmp://publish.chinaffmpeg.com/live/class -c copy -f flv output.flv

录制rtsp流

通过ffmpeg -h demuxer=rtsp查看rtsp协议相关参数:

参数类型说明
initial_pause布尔建立廉洁后暂停播放
rtsp_transport标记设置rtsp的传输协议,可以为udp、tcp、udp_multicast、http
rtsp_flags标记可以为filter_src(只接收指定IP的流)、listen(设置为被动接受模式)、prefer_tcp(TCP可用情况下传输协议首选TCP)
allowed_media_types标记设置允许接受的数据模式(默认全部开启):video,audio,data,subtitle
min_port整数设置最小本地UDP端口,默认为5000
max_port整数设置最大本地UDP端口,默认为65000
timeout整数设置监听端口超时时间
reorder_queue_size整数设置录制数据Buffer的大小
buffer_size整数设置底层传输包Buffer的大小
user-agent字符串用户客户端标识

rtsp录制直播流:

ffmpeg -rtsp_transport tcp -i rtsp://47.90.47.25/test.ts -c copy -f mp4 output.mp4

添加User-Agent:

ffmpeg -user-agent "ChinaFFmpeg-Player" -i rtsp://input:554/live/1/stream.sdp -c copy -f mp4 -y output.mp4

录制http流

这节讲的所谓http直播,其实就是将视频文件用http方式提供出来,然后ffmpeg既可以作为http服务器,也可以作为http客户端。
ffmpeg支持的参数:

参数类型说明
seekable布尔设置HTTP链接为可以seek操作
chunked_post布尔使用Chunked模式post数据
http_proxy字符串设置HTTP代理传输数据
headers字符串自定义HTTP Header数据
content_type字符串设置POST的内容类型
user_agent字符串设置HTTP请求客户端信息
multiple_requests布尔HTTP长连接开启
post_data二进制数据设置将要POST的数据
cookies字符串设置HTTP请求时携带的Cookies
icy布尔设置ICY元数据,默认打开
anth_type整数HTTP验证类型设置
offset整数初始化HTTP请求时的偏移位置
method字符串发起HTTP请求时使用的HTTP的方法
reconnect布尔在EOF之前断开发起重连
reconnect_at_eof布尔在得到EOF时发起重连
reply_code整数作为HTTP服务时向客户端反馈状态码

举例:

seek操作:

ffmpeg -ss 30 -seekable 1 -i http://bbs.chinaffmpeg.com/test.ts -c copy -y output.mp4

headers参数设置:

ffmpeg -headers "referer: http://bbs.chinaffmpeg.com/index.html" -i http://play.chinaffmpeg.com/live/class.flv -c copy -f flv -y output.flv

user_agent参数设置:

ffmpeg -user_agent "LiuQi's Player" -i http://bbs.chinaffmpeg.com/1.flv

拉流录制:

ffmpeg -i http://bbs.chinaffmpeg.com/live.flv -c copy -f flv output.flv
ffmpeg -i http://bbs.chinaffmpeg.com/live.ts -c copy -f flv output.flv
ffmpeg -i http://bbs.chinaffmpeg.com/live.m3u8 -c copy -f flv output.flv

录制和发布UDP/TCP流

所谓录制和发布UDP/TCP流是ffmpeg通过自己的私有协议传输音视频流。

TCP参数:

参数类型说明
listen整数作为Server时监听TCP的端口
timeout整数获得数据超时时间(微妙)
listen_timeout整数作为Server时监听TCP端口的超时时间(毫秒)
send_buffer_size整数通过socket发送的buffer大小
recv_buffer_size整数通过socket读取的buffer大小

UDP参数列表:

参数类型说明
buffer_size整数系统数据buffer大小
bitrate整数每秒钟发送的码率
localport整数本地端口
localaddr整数本地地址
pkt_size整数最大UDP数据包大小
reuse布尔UDP socket复用
broadcast布尔广播模式开启与关闭
ttl整数多播时配合使用的存活时间
fifo_size整数管道大小
timeout整数设置数据传输的超时时间

使用举例:

# 作为服务器
ffmpeg -listen 1 -f flv -i tcp://127.0.0.1:1234/live/stream -c copy -f flv output.flv
# 作为客户端
ffmpeg -re -i input.mp4 -c copy -f flv tcp://127.0.0.1:1234/live/stream

# 作为客户端
ffmpeg -re -i input.mp4 -c copy -localport 23456 -f flv udp://192.168.100.179:1234/live/stream

几个listen_timeout、timeout、send_buffer_size、recv_buffer_size的例子懒得列了,看一眼参数说明就会用。

推多路流

这节讲的就是如何把一路流同时推到多个地方去。

  • 用管道ffmpeg -i input.mp4 -vodec libx264 -acodec aac -f flv - | ffmpeg f flv -i - -c copy -f flv rtmp://publish.chinaffmpeg.com/live/stream1 -c copy -f flv rtmp://publish.chinaffmpeg.com/live/stream2
  • 用tee封装格式ffmpeg -re -i input.mp4 -vcodec libx264 -acodec aac -map 0 -f tee "[f=flv]rtmp://publish.chinaffmpeg.com/live/stream1 | [f=flv]rtmp://publish.chinaffmpeg.com/live/stream2"
  • 用tee协议ffmpeg -re -i input.mp4 -vcodec libx264 -acodec aac -f flv "tee:rtmp://publish.chinaffmpeg.com/live/stream1|rtmp://publish.chinaffmpeg.com/live/stream2"

HDS流

  • window_size参数控制文件列表大小
    ffmpeg -i input -c copy -f hds -window_size 4 output
  • extra_window_size参数控制文件个数
    ffmpeg -re -i input.mp4 -c copy -f hds -window_size 4 -extra_window_size 1 output

DASH流

  • window_sizeextra_window_size参数ffmpeg -re -i input.mp4 -c:v copy -acodec copy -f dash -window_size 4 -extra_window_size 5 index.mpd
  • single_file参数ffmpeg -re -i input.mp4 -c:v copy -acodec copy -f dash -window_size 4 -extra_window_size 5 -single_file 1 index.mpd

第六章 FFmpeg滤镜使用

FFmpeg的滤镜处理(filter)就是对视频和音频做一些缩放、合并、翻转之类的常规操作,这些操作自己实现也不见得有多困难,但是自己实现的可能没人家高效,定义的接口没有人家设计的好。
FFmpeg的滤镜官方文档

filter的语法

读官方文档,会先让你体会一个使用滤镜的例子:

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

上面的命令描述了如下所示的一个处理流程图:

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

可以看出滤镜大概就是用给定的输入源作为起始节点,对这些起始节点不断应用滤镜可以得到新的节点,最后选取某些节点作为我们想要的输出就可以了。

关于滤镜语法的几点总结:

  • -vffilter_complex不能同时使用。
    使用filter_complex,可用通过""描述一个足够完整和复杂的处理流图。
  • 多个滤镜之间用;相隔;
    位于同一条chain的滤镜可以用,相隔;
  • 滤镜的参数用<filter>=arg1=a:arg2=b这样的key、val对方式提供,不同的key、val对之间用:相隔;
    滤镜的参数也可以不把key写出来,只把val用冒号分开就可以,只是参数的顺序必须要和filter接受的参数保持一致;
    写key和不写key的两种描述参数的方式可以混用,只是只能前面的多个按顺序描述的key、val对可以省略掉参数名,后面的参数必须都把参数名写出来;
  • 每个滤镜都有输入和输出,用[input/output]表示,输入和输出可以有多个,输入写在滤镜名字的前面,输出写在滤镜名字的后面;
  • 滤镜的输入和输出可以不写,上一个无名输出会作为下一个无名输入;
  • 滤镜是基于解码后的画面进行操作的;
    可以在指定完要进行的filter操作之后再指定编码器;

适用于filter的内置变量:

变量说明
t时间戳以秒表示,如果输入的时间戳是未知的,则是NAN
n输入帧的顺序编号,从0开始
pos输入帧的位置,如果未知则是NAN
w输入视频帧的宽度
h输入视频帧的高度

为视频添加水印

  • 文字水印
    ffmpeg -re -i input.mp4 -vf "movie=sub.mp4,scale=480x320[test]; [in][test]overlay[out]" -vcodec libx264 output.flv
    `ffmpeg -re -i input.mp4 -vf “movie=sub.mp4,scale=480×320[test]; [in][test]overlay=x=main_w-480:y=main_h-320[out]” -vcodec libx264 output.flv”
  • 图片水印
    ffmpeg -i input.mp4 -vf "movie=logo.png[wm]; [in][wm]overlay=30:10[out]" output.mp4
    ffmpeg -i input.mp4 -vf "movie=logo.png,colorkey=black:1.0:1.0[wm];[in][wm]overlay=30:10[out]" output.mp4

画中画

  • ffmpeg -re -i input.mp4 -vf "movie=sub.mp4,scale=480x320[test];[in][test]overlay[out]" -vcodec libx264 output.flv
  • ffmpeg -re -i input.mp4 -vf "movie=sub.mp4,scale=480x320[test];[in][test]overlay=x=main_w-480:y=main_h-320[out]" -vcodec libx264 output.flv
  • ffmpeg -re -i input.mp4 -vf "movie=sub.mp4,scale=480x320[test];[in][test]overlay=x='if(gte(t,2), -w+(t-2)*20,NAN)':y=0[out]" -vcodec libx264 output.flv
    这个例子通过内置变量实现了跑马灯式的画中画效果。

多宫格

多宫格和画中画其实没有本质上的区别,都是用overlay这个滤镜,这里列一个官方文档的例子:

ffmpeg -i left.avi -i right.avi -filter_complex "
nullsrc=size=200x100 [background];
[0:v] setpts=PTS-STARTPTS, scale=100x100 [left];
[1:v] setpts=PTS-STARTPTS, scale=100x100 [right];
[background][left]       overlay=shortest=1       [background+left];
[background+left][right] overlay=shortest=1:x=100 [left+right]
"

音频流滤镜操作

  • 双声道合并单声道
    ffmpeg -i input.aac -ac 1 output.aac
  • 双声道提取
    ffmpeg -i input.aac -filter_complex "[0:0]pan=1c|c0=c0[left];[0:0]pan=1c|c0[right]" -map "[left]" left.aac -map "[right]" right.aac
    pan滤镜的介绍
    pan滤镜的参数:l|outdef|outdef|...
  • 双声道转双音频流
    ffmpeg -i input.aac -filter_complex channelsplit=channel_layout=stereo output.mka
    把双声道音频转为了两个单声道的音频流。
  • 单声道转双声道
    ffmpeg -i left.aac -ac 2 output.m4a
  • 两个音频源合并双声道
    两个单声道音频流合并为一个stereo双声道音频流:
    ffmpeg -i left.aac -i right.aac -filter_complex "[0:a][1:a] amerge=inputs=2[aout]" -map "[aout]" output.mka
  • 多音频合并为多声道
    ffmpeg -i front_left.wav -i front_right.wav -i front_center.wav -i lfe.wav -i back_left.wav -i back_right.wav -filter_complex "[0:a][1:a][2:a][3:a][4:a][5:a] amerge=inputs=6[aout]" -map "[aout]" output.wav

音频音量探测

  • 音频音量
    ffmpeg -i output.wav -filter_complex volumedetect -c:v copy -f null /dev/null
  • 绘制音频波形
    ffmpeg -i output.wav -filter_complex "showwavespic=s=640x120:split_channels=1" -frames:v 1 output.png
    ffmpeg -i output.wav -filter_complex "showwavespic=s=640x120" -frames:v 1 output.png

为视频加字幕

  • 通过滤镜添加ASS字幕
    ffmpeg -i input.mp4 -vf ass=t1.ass -f mp4 output.mp4
  • 将ass字幕写入封装容器中
    ffmpeg -i input.mp4 -i t1.ass -acodec copy -vcodec copy -scodec copy output.mkv
    ffmpeg -i input.mp4 -i t1.ass -map 0:0 -map 0:1 -map 1:0 -acodec copy -vcodec copy -scodec copy output.mkv

扣图合并

使用chromakey滤镜可以进行扣图处理,然后通过overlay滤镜就可以把一个纯色背景下的人物融合到另外一个画面中去了。

chromakey参数:

参数类型说明
color颜色设置chromakey颜色值,默认为黑色
similarity浮点设置chromakey相似值
blend浮点设置chromakey融合值
yuv布尔yuv代替rgb,默认为false

颜色代号可以通过ffmpeg -colors命令查询。

ffmpeg -i input.mp4 -i input_green.mp4 -filter_complex "[1:v]chromakey=Green:0.1:0.2[ckout];[0:v][ckout]overlay[out]" -map "[out]" output.mp4

除了chromakey滤镜还可以使用colorkey滤镜,chromakey用于处理YUV数据,colorkey处理纯色数据都可以。

3D视频处理

定时视频截图

  • 获取指定时刻的截图ffmpeg -i input.flv -ss 00:00:7.435 -vframes 1 out.png
  • 用fps滤镜获取图片
    • ffmpeg -i input.flv -vf fps=1 out%d.png
      1秒钟截图一次
    • ffmpeg -i input.flv -vf fps=1/60 img%03d.jpg
      1分钟截图一次
    • ffmpeg -i input.flv -vf fps=1/600 thumb%04d.bmp
      10分钟截图一次
    • ffmpeg -i input.flv -vf "select='eq(pict_type,PICT_TYPE_I)'" -vsync vfr thumb%04d.png
      按照I帧截图

生成测试元数据

  • 生成音频测试流
    可以通过lavfi虚拟音频源的abuffer、aevalsrc、anullsrc、flite、anoisesrc、sine滤镜生成音频流:
    • ffmpeg -re -f lavfi -i abuffer=sample_rate=44100:sample_fmt=s16p:channel_layout=stereo -acodec aac -y output.aac
    • ffmpeg -re -f lavfi "aevalsrc=sin(420*2*PI*t)|cos(430*2*PIT*t):c=FC|BC" -acodec aac output.aac
  • 生成视频测试流
    可以通过lavfi虚拟视频源的allrgb、allyuv、color、haldclutsrc、nullsrc、rgbtestsrc、smptebars、smptehdbars、testsrc、testsrc2、yuvtestsr等滤镜生成视频流:
    • ffmpeg -re -f lavfi -i testsrc=duration=5.3:size=qcif:rate=25 -vcodec libx264 -r:v 25 output.mp4
    • ffmpeg -re -f lavfi -i testsrc2=duration=5.3:size=qcif:rate=25 -vcodec libx264 -r:v 25 output.mp4
    • ffmpeg -re -f lavfi -i color=c=red@0.2:s=qcif:r=25 -vcodec libx264 -r:v 25 output.mp4
    • ffmpeg -re -f lavfi -i "nullsrc=s=256x256, geq=random(1)*255:128:128" -vcodec libx264 -r:v 25 output.mp4

倍速处理

  • 音频倍速处理
    atempo滤镜可以用来处理音频的倍速,其只有一个参数tempo,取值0.5到2.0之间,分别表示速度为原来的一半和2倍。
    • ffmpeg -i input.wav -filter_complex "atempo=tempo=0.5" -acodec aac output.aac
    • ffmpeg -i input.wav -filter_complex "atempo=tempo=2.0" -acodec aac output.aac
  • 视频倍速处理
    seepts滤镜用于处理视频倍速,其只有一个参数expr,用于描述视频的每一帧的时间戳。值说明FRAME_RATE根据帧率设置帧率值,只用于固定频率PTS输入的pts时间戳RTCTIME使用RTC的时间作为时间戳(即将弃用)TB输入的时间戳的时间基(timebase)
    • ffmpeg -re -i input.mp4 -filter_complex "septs=PTS*2" output.mp4
      这个命令把原来的视频调整为了半速播放。
    • ffmpeg -re -i input.mp4 -filter_complex "septs=PTS/2" output.mp4
      这个命令把原来的视频调整为了2倍速播放。

第七章 FFmpeg采集设备

Linux

  • 查看设备列表ffmpeg -devices
  • 从fbdev中采集fbdev是终端里的图像ffmpeg -framerate 30 -f fbdev -i /dev/fb0 output.mp4
  • 从v4l2采集v4l2是摄像头采集到的图像# 查询摄像头支持的格式 ffmpeg -f v4l2 -list_formats all -i /dev/video0 # 从摄像头录像 ffmpeg -s 1920x1080 -i /dev/video0 output.avi
  • 从x11grab采集
    这个是采集的桌面上显示的图像。x11grab支持的参数:参数类型说明draw_mouse整数支持绘制鼠标光标follow_mouse整数跟踪鼠标轨迹数据framerate字符串输入采集的视频帧率show_region整数获得输入桌面的指定区域region_border整数当show_region为1时,设置输入指定区域的边框的粗细程度video_size字符串输入采集视频的分辨率输入设备的命名规则:[主机名]:显示编号id.屏幕编号id[+起始x轴,起始y轴]
  # 桌面录制
  ffmpeg -f x11grab -framerate 25 -video_size 1366x768 -i :0.0 out.mp4
  # 桌面录制指定区域
  ffmpeg -f x11grab -framerate 25 -video_size 352x288 -i :0.0+300,200 out.mp4
  # 桌面录制带鼠标记录的视频
  ffmpeg -f x11grab -video_size 1366x768 -follow_mouse 1 -i :0.0 out.mp4