《FFmpeg从入门到精通》读书笔记(五)

2022-09-13 10:47:09 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

写在前面

2019.06.24

第六章 FFmpeg滤镜使用(至 6.5 结束)


FFmpeg滤镜使用

FFmpeg滤镜Filter描述格式
参数排列方式
代码语言:javascript复制
[输入流或标记名] 滤镜参数 [临时标记名]; [输入流或标记名] 滤镜参数 [临时标记名]...

例如:输入两个文件,一个视频文件input1.mp4,一个图片logo.jpg,将图像流缩放为2000×2000分辨率,放置在视频的左上角

代码语言:javascript复制
ffmpeg -i input1.mp4 -i logo.jpg -filter_complex "[0:v] scale=2000:2000[logo]; [logo] overlay=x=0:y=0" -strict -2 output1.mp4

Note:此处需要增加“-strict -2”,否则会报“[aac @ 0xbdb2a0] The encoder ‘aac’ is experimental but experimental codecs are not enabled, add ‘-strict -2’ if you want to use it. ”错误,表示使用FFmpeg自带的aac音频编码。想要了解更多可以参考FFmpeg -strict -2 参数详解。

FFmpeg滤镜Filter时间内置变量

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

FFmpeg为视频加水印
1.文字水印

在视频中增加文字水印,需要有文字字库处理的相关文件,在编译FFmpeg时需要支持FreeType、FontConfig、iconv,系统中需要有相关的字库,在FFmpeg中增加纯字幕水印可以使用drawtext滤镜进行支持。

drawtext滤镜参数 (书 P183-184)

参数

类型

说明

fontfile

String

字体文件

text

String

文字

textfile

String

文字文件

fontcolor

color

字体颜色

box

boolean

字体区域背景框

boxcolor

color

展示字体的区域块的颜色

fontsize

int

显示字体的大小

font

String

字体名称(默认为Sans字体)

x

int

文字显示的x坐标

y

int

文字显示的y坐标

将文字加载视频的左上角

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':x=20:y=20" -strict -2 output2.mp4

再使用fontcolor将文字颜色修改一下

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':x=20:y=20:fontcolor=green" -strict -2 output2.mp4

再使用box和boxcolor给水印加个框

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf "drawtext=fontsize=100:fontfile=FreeSerif.ttf:text='hello world':x=20:y=20:fontcolor=green:box=1:boxcolor=yellow" -strict -2 output2.mp4

以本地时间作为水印

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf "drawtext=fontsize=60:fontfile=FreeSerif.ttf:text='%{localtime:%Y-%m-%d  %H-%M-%S}':x=20:y=20:fontcolor=green:box=1:boxcolor=yellow" -strict -2 output3.mp4

使用drawtext与enable定时显示水印(每三秒显示一次)

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf "drawtext=fontsize=60:fontfile=FreeSerif.ttf:text='test':x=20:y=20:fontcolor=green:box=1:boxcolor=yellow:enable=lt(mod(t,3), 1)" -strict -2 output4.mp4

使用中文字库

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf "drawtext=fontsize=60:fontfile=huawenxingkai.ttf:text='邓啊咿呀子啊咿呀明':x=20:y=20:fontcolor=green" -strict -2 output5.mp4
2.图片水印
moive滤镜参数(书 P187)

参数

类型

说明

filename

String

输入的文件名,可以是文件、协议、设备

format_name,f

String

输入的封装格式

stream_index,si

int

输入的流索引编号

seek_point,sp

float

Seek输入流的事时间位置

stream,s

String

输入的多个流的流信息

loop

int

循环次数

discontinuity

时间差值

支持跳动的时间戳差值

代码语言:javascript复制
知识点:滤镜图,链,和滤镜关系
FFmpeg命令行中,跟在 "-vf"之后的就是一个滤镜图。
滤镜图可以包含多个滤镜链,而每个滤镜链又可以包含多个滤镜。

虽然一个完整的滤镜图描述很复杂,但可以简化以避免歧义。
滤镜链使用";"分隔,滤镜链中滤镜使用","分隔;
并且,滤镜链如果没有指定输入或输出,则默认使用前面的滤镜链的输出为输入,并输出给后面的滤镜链做输入。
 
下面的命令行是相等的:
ffmpeg -i input -vf [in]scale=iw/2:-1[out] output
ffmpeg -i input -vf scale=iw/2:-1 output               # the input and output are implied without ambiguity

对于下面: 
ffmpeg -i input -vf [in]yadif=0:0:0[middle];[middle]scale=iw/2:-1[out] output  # 两个链的方式,每个链一个滤镜,链间使用[middle]填充
ffmpeg -i input -vf [in]yadif=0:0:0,scale=iw/2:-1[out] output                           # 一个链的方式,链包含两个滤镜,使用默认链接
ffmpeg -i input -vf yadif=0:0:0,scale=iw/2:-1  output                                      # 输入输出也使用默认链接

FFmpeg中加入图片水印有两种方式:通过movie指定水印文件路径和通过filter读取输入文件的流并指定水印

代码语言:javascript复制
ffmpeg -i input1.mp4 -vf  "movie=logo.jpg[dzm];[in][dzm]overlay=30:10[out]" -strict -2 output6.mp4

使用movie和colorkey滤镜将图片设置为半透明

代码语言:javascript复制
// 颜色值、相似度、混合度
ffmpeg -i input1.mp4 -vf  "movie=logo.jpg,colorkey=black:1.0:1.0[dzm];[in][dzm]overlay=30:10[out]" -strict -2 output6.mp4
FFmpeg生成画中画

通过overlay将多个视频流、多个媒体采集设备、多个视频文件合并到一个界面

overlay参数(书 P189)

参数

类型

说明

x

String

x坐标

y

String

y坐标

eof_action

int

标志,默认为0 repeat(0)、endall(1,停止所有的流)、pass(2,保留主视图)

shortest

boolean

终止最短的视频时全部终止(默认关闭)

format

int

设置output的像素格式,默认为yuv420; yuv420(0)、yuv422(1)、yuv444(2)、rgb(3)

例如:

代码语言:javascript复制
ffmpeg -re -i input2.mp4 -vf "movie=input1.mp4,scale=480*320[dzm]; [in][dzm] overlay [out]" -strict -2 output7.mp4

指定子视频的位置

代码语言:javascript复制
ffmpeg -re -i input2.mp4 -vf "movie=input1.mp4,scale=480*320[dzm]; [in][dzm] overlay=x=main_w-480:y=main_h-320 [out]" -strict -2 output8.mp4

配合正则表达式进行跑马灯式画中画处理,动态改变x和y

代码语言:javascript复制
ffmpeg -re -i input2.mp4 -vf "movie=input1.mp4,scale=480*320[dzm];[in][dzm]overlay=x='if(gte(t,1),-w (t-2)*20,NAN)':y=0[out]" -strict -2 output8.mp4

Note:各位同学在写的时候,符号一定要小写!一定要是英文字符!我因为单引号打了个中文字符一直报错,卡了半天,很难受。。。我在搜索问题的时候也查了一些资料,推荐一篇博文FFmpeg命令行语法之-filter_complex (Android环境)。

代码语言:javascript复制
知识点:表达式gte(x,y)。
如果x大于等于y则表达式的值为1,反之为0。
所以if(gte(t,2),10,NAN)的意思就是,当时间大于等于2秒时,水印x位置为10,反之不显示水印。
(或者你也可以用lte来判断“小于或等于”)
FFmpeg视频多宫格处理
代码语言:javascript复制
ffmpeg -re -i input1.mp4 -re -i input2.mp4 -re -i output7.mp4 -re -i output8.mp4 -filter_complex "nullsrc=size=640*480 [base]; [0:v] setpts=PTS-STARTPTS, scale=320*240[topleft]; [1:v] setpts=PTS-STARTPTS, scale=320*240[topright];  [2:v] setpts=PTS-STARTPTS, scale=320*240[downleft]; [3:v] setpts=PTS-STARTPTS, scale=320*240[downright]; [base][topleft] overlay=shortest=1[tmp1]; [tmp1][topright] overlay=shortest=1:x=320[tmp2]; [tmp2][downleft] overlay=shortest=1:y=240[tmp3]; [tmp3][downright] overlay=shortest=1:x=320:y=240" -c:v libx264 -strict -2 output10.mp4

执行语句很长,其实逻辑很简单:

1.四个输入视频为1,2,3,4,首先设定base大小为640×480,则每个视频大小为320×240; 2.四个视频分别位于左上、右上、左下、右下; 3.每个视频与base合并后,生成新的名称[tmp%d],最后得到四宫格

FFmpeg音频流滤镜操作

FFmpeg可以对音频进行操作,如拆分声道、合并多声道为单声道、调整声道布局、调整音频采样率等

1.双声道合并单声道

layouts参数可以查看音频的声道布局

代码语言:javascript复制
ffmpeg -i input4.aac -ac 1 -strict -2 output.aac

input4.aac是stereo布局方式,即FL与FR两个声道;转换为mono布局,单声道

2.双声道提取
代码语言:javascript复制
// 使用map_channel
ffmpeg -i output.aac -strict -2 -map_channel 0.0.0  left.aac -strict -2 -map_channel  0.0.1 right.aac
// 使用pan滤镜
ffmpeg -i output.aac -filter_complex "[0:0] pan=1c|c0=c0 [left]; [0:0] pan=1c|c0=c1 [right]"  -strict -2 -map "[left]" left.aac -strict -2 -map "[right]" right.aac 
3.双声道转双音频流

将双声道提取出来转为一个音频文件的两个音频流

代码语言:javascript复制
ffmpeg -i output.aac -filter_complex channelsplit=channel_layout=stereo -strict -2 output.mka
4.单声道转双声道

只有中央声道或mono布局时,才可以通过FFmpeg转换为stereo布局

代码语言:javascript复制
// 使用ac参数
ffmpeg -i output.aac -ac 2 -strict -2 output2.m4a
// 使用amerge滤镜
 ffmpeg -i output.aac -filter_complex "[0:a][0:a] amerge=inputs=2[aout]" -strict -2 -map "[aout]" output.m4a
5.两个音频源合并双声道
代码语言:javascript复制
ffmpeg -i output.aac -i output1.aac -filter_complex "[0:a][1:a] amerge=inputs=2[aout]" -strict -2 -map "[aout]" output3.mka
6.多个音频合并为多声道
代码语言:javascript复制
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]" -strict -2 -map "[aout]" output.wav

附录

代码语言:javascript复制
知识点:FFmpeg选项
a) 通用选项
-L license
-h 帮助
-fromats 显示可用的格式,编解码的,协议的。。。
-f fmt 强迫采用格式fmt
-I filename 输入文件
-y 覆盖输出文件
-t duration 设置纪录时间 hh:mm:ss[.xxx]格式的记录时间也支持
-ss position 搜索到指定的时间 [-]hh:mm:ss[.xxx]的格式也支持
-title string 设置标题
-author string 设置作者
-copyright string 设置版权
-comment string 设置评论
-target type 设置目标文件类型(vcd,svcd,dvd) 所有的格式选项(比特率,编解码以及缓冲区大小)自动设置,只需要输入如下的就可以了:
ffmpeg -i myfile.avi -target vcd /tmp/vcd.mpg
-hq 激活高质量设置
-itsoffset offset 设置以秒为基准的时间偏移,该选项影响所有后面的输入文件。该偏移被加到输入文件的时戳,定义一个正偏移意味着相应的流被延迟了 offset秒。 [-]hh:mm:ss[.xxx]的格式也支持

b) 视频选项
-b bitrate 设置比特率,缺省200kb/s
-r fps 设置帧频 缺省25
-s size 设置帧大小 格式为WXH 缺省160X128.下面的简写也可以直接使用:
Sqcif 128X96 qcif 176X144 cif 252X288 4cif 704X576
-aspect aspect 设置横纵比 4:3 16:9 或 1.3333 1.7777
-croptop size 设置顶部切除带大小 像素单位
-cropbottom size –cropleft size –cropright size
-padtop size 设置顶部补齐的大小 像素单位
-padbottom size –padleft size –padright size –padcolor color 设置补齐条颜色(hex,6个16进制的数,红:绿:兰排列,比如 000000代表黑色)
-vn 不做视频记录
-bt tolerance 设置视频码率容忍度kbit/s
-maxrate bitrate设置最大视频码率容忍度
-minrate bitreate 设置最小视频码率容忍度
-bufsize size 设置码率控制缓冲区大小
-vcodec codec 强制使用codec编解码方式。如果用copy表示原始编解码数据必须被拷贝。
-sameq 使用同样视频质量作为源(VBR)
-pass n 选择处理遍数(1或者2)。两遍编码非常有用。第一遍生成统计信息,第二遍生成精确的请求的码率
-passlogfile file 选择两遍的纪录文件名为file

c)高级视频选项
-g gop_size 设置图像组大小
-intra 仅适用帧内编码
-qscale q 使用固定的视频量化标度(VBR)
-qmin q 最小视频量化标度(VBR)
-qmax q 最大视频量化标度(VBR)
-qdiff q 量化标度间最大偏差 (VBR)
-qblur blur 视频量化标度柔化(VBR)
-qcomp compression 视频量化标度压缩(VBR)
-rc_init_cplx complexity 一遍编码的初始复杂度
-b_qfactor factor 在p和b帧间的qp因子
-i_qfactor factor 在p和i帧间的qp因子
-b_qoffset offset 在p和b帧间的qp偏差
-i_qoffset offset 在p和i帧间的qp偏差
-rc_eq equation 设置码率控制方程 默认tex^qComp
-rc_override override 特定间隔下的速率控制重载
-me method 设置运动估计的方法 可用方法有 zero phods log x1 epzs(缺省) full
-dct_algo algo 设置dct的算法 可用的有 0 FF_DCT_AUTO 缺省的DCT 1 FF_DCT_FASTINT 2 FF_DCT_INT 3 FF_DCT_MMX 4 FF_DCT_MLIB 5 FF_DCT_ALTIVEC
-idct_algo algo 设置idct算法。可用的有 0 FF_IDCT_AUTO 缺省的IDCT 1 FF_IDCT_INT 2 FF_IDCT_SIMPLE 3 FF_IDCT_SIMPLEMMX 4 FF_IDCT_LIBMPEG2MMX 5 FF_IDCT_PS2 6 FF_IDCT_MLIB 7 FF_IDCT_ARM 8 FF_IDCT_ALTIVEC 9 FF_IDCT_SH4 10 FF_IDCT_SIMPLEARM
-er n 设置错误残留为n 1 FF_ER_CAREFULL 缺省 2 FF_ER_COMPLIANT 3 FF_ER_AGGRESSIVE 4 FF_ER_VERY_AGGRESSIVE
-ec bit_mask 设置错误掩蔽为bit_mask,该值为如下值的位掩码 1 FF_EC_GUESS_MVS (default=enabled) 2 FF_EC_DEBLOCK (default=enabled)
-bf frames 使用frames B 帧,支持mpeg1,mpeg2,mpeg4
-mbd mode 宏块决策 0 FF_MB_DECISION_SIMPLE 使用mb_cmp 1 FF_MB_DECISION_BITS 2 FF_MB_DECISION_RD
-4mv 使用4个运动矢量 仅用于mpeg4
-part 使用数据划分 仅用于mpeg4
-bug param 绕过没有被自动监测到编码器的问题
-strict strictness 跟标准的严格性
-aic 使能高级帧内编码 h263 
-umv 使能无限运动矢量 h263 
-deinterlace 不采用交织方法
-interlace 强迫交织法编码仅对mpeg2和mpeg4有效。当你的输入是交织的并且你想要保持交织以最小图像损失的时候采用该选项。可选的方法是不交织,但是损失更大
-psnr 计算压缩帧的psnr
-vstats 输出视频编码统计到vstats_hhmmss.log
-vhook module 插入视频处理模块 module 包括了模块名和参数,用空格分开

D)音频选项
-ab bitrate 设置音频码率
-ar freq 设置音频采样率
-ac channels 设置通道 缺省为1
-an 不使用音频纪录
-acodec codec 使用codec编解码

E)音频/视频捕获选项
-vd device 设置视频捕获设备。比如/dev/video0
-vc channel 设置视频捕获通道 DV1394专用
-tvstd standard 设置电视标准 NTSC PAL(SECAM)
-dv1394 设置DV1394捕获
-av device 设置音频设备 比如/dev/dsp

F)高级选项
-map file:stream 设置输入流映射
-debug 打印特定调试信息
-benchmark 为基准测试加入时间
-hex 倾倒每一个输入包
-bitexact 仅使用位精确算法 用于编解码测试
-ps size 设置包大小,以bits为单位
-re 以本地帧频读数据,主要用于模拟捕获设备
-loop 循环输入流。只工作于图像流,用于ffserver测试

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/153365.html原文链接:https://javaforall.cn

0 人点赞