ffmpeg使用说明
介绍
ffmpeg是一个音视频处理软件,很多工具内部都是调用这个
可以剪辑,裁剪,转码音视频,甚至能压缩图片
文档: https://ffmpeg.org/ffmpeg-all.html
安装
官网 http://ffmpeg.org/download.html
本地 游戏开发\软件\辅助软件\ffmpeg
一般下载 release full 版本
用来处理音视频转码,合并,分割等
主要包含2个工具:
- ffprobe
获取音视频信息,比如分辨率、码率等 - ffmpeg
对音视频进行处理,包括裁剪、截取、转码等
ffprobe使用
该工具主要用来获取音视频信息
-
参数说明:
- -v [loglevel] 设置日志等级
ffprobe -v quiet 不想让log影响输出显示,一般设置为 quiet - -of [format] 设置输出打印格式,可选 json xml
ffprobe -of xml - -select_streams [stream_type] 只选择 stream_specifier 指定的流。可选 a v, 该选项只影响那些与流相关的选项(例如:show_streams, show_packets, 等)。
ffprobe -show_streams -select_streams a INPUT 只显示音频流信息
ffprobe -show_streams -select_streams v INPUT 只显示视频流信息 - -show_format 显示输入多媒体流的容器格式信息
- -show_frames 显示输入多媒体流中的每一帧以及字幕的信息
- -show_packets 显示输入多媒体流中每一个包的信息,输出信息和show_frames差不多
- -show_streams 显示输入多媒体流中每一个流的信息
- -show_data 显示有效载荷数据,以十六进制和ASCII转储。与 ‘-show_packets’ 结合使用,它将dump 包数据;与 ‘-show_streams’ 结合使用,它将 dump codec 附加数据。
- -show_programs 显示输入多媒体流中程序以及它们的流的信息
- -count_frames 计算每一个流中的帧数,在相应的段中进行显示
如:ffprobe -show_streams -count_frames -i sample.mp4
n_read_frames会有数据,否则为N/A - -count_packets 计算每一个流中的包数,在相应的段中进行显示
- -show_error 显示探测输入文件时的错误信息
- -v [loglevel] 设置日志等级
-
常用命令:
- 显示视频流信息
ffprobe -show_streams -select_streams v input.mp4 -v quiet - 获得视频宽高的代码:
set inputVideo=%~1 for /f "tokens=1,2 delims==" %%i in ('ffprobe -show_streams -select_streams v -v quiet "%inputVideo%"') do ( if "%%i" == "width" set width=%%j if "%%i" == "height" set height=%%j ) echo video width %width% echo video height %height%
- 显示视频流信息
ffmpeg使用
文档: https://ffmpeg.org/ffmpeg-all.html
该工具主要用来对音视频进行处理,包括裁剪、截取、转码等
音频转换,会自动检测格式,ogg会默认用 -acodec libvorbis
ffmpeg -i aaa.wav -vn aaa.ogg
-
主要参数
- -i 设定输入流
- -f 设定输出格式
- -ss 截取时间 如 -ss 00:00:15
- -t 截取时长 如 -t 00:00:05 ,一定要写在 "-i"前面,否则会有问题
- -to 截止时间,一定要写在"-i"前面!!否则就和"-t"一样
- -c 编码,相当于-acodec和-vcodec,放在输入文件前表示输入编码,放在输出文件前表示输出编码
-c:v 等于 -vcodec , -c:a 等于 -acodec - -y 覆盖已有文件
- map 选择输出流,没有该参数将启用默认流选择行为
默认流选择行为每种类型仅选择 1 个流,比如有3个输入流,则只会选择1个-map 0:0 第一个输入文件的第一个流 -map 0:2? 如果第一个输入文件的第3个流存在就选择 -map 0 -map -0:1 选择第1个视频中的除第2个流外的其它流 -map 0:v:0 第一个输入文件的第一个视频流 -map 1:a:2 第二个输入文件的第三个音频流 -map 1:s:1 第二个输入文件的第二个字幕流
-
视频参数
- -b 设定视频流量(码率),默认为200Kbit/s
- -r 设定帧速率,默认为25
- -s 设定画面的宽与高
- -aspect 设定画面的比例
- -vn 不处理视频
- -vcodec 设定视频编解码器,未设定时则使用与输入流相同的编解码器 ,可以用 -vcodec copy 表示跟输入编码一致
放在输入文件前表示输入编码,放在输出文件前表示输出编码
ffmpeg –encoders 可以查看所有编码,常用有 libx264 - -crf 设置视频输出质量,[0-51] 0表示无损,常用范围18-24,18表示视觉无损,一般建议22,差一点建议24
经测试压缩率为 20:42%;22:31%;24:23.4% - -preset 指定处理速度,速度越慢,压缩率越高,选项有 placebo veryslow slower slow medium fast faster veryfast superfast ultrafast
一般最慢用 veryslow,建议用 slower,placebo以极高的编码时间为代价,只换取了大概1%的视频质量提升。slow 与 medium相比提升了5%~10%;
slower 与 slow相比提升了5%;veryslow 与 slower相比提升了3%。
-
音频参数
- -ar 设定采样率
- -ac 设定声音的Channel数
- -acodec 设定声音编解码器,未设定时则使用与输入流相同的编解码器 ,可以用 -acodec copy 表示跟输入编码一致
放在输入文件前表示输入编码,放在输出文件前表示输出编码 - -an 不处理音频
-
时间格式
- [HH:]MM:SS[.m…]
比如 12:10:11.123 表示 12时10分11.123秒
10 表示10秒
10:11 表示10分11秒 - S+[.m…][s|ms|us]
比如 10.12 表示 10.12秒
10.12ms 表示 10.12毫秒
10.12us 表示 10.12微秒
- [HH:]MM:SS[.m…]
-
过滤器参数
-
vf
视频过滤器参数,针对单个视频应用过滤器,后面可以跟多个过滤器参数,参数之间用,分隔- 语法: [视频流1]过滤器1=过滤器1参数,过滤器2=过滤器2参数[视频流1输出];[视频流2]过滤器3=过滤器3参数[视频流2输出]
也就是不同视频流的处理用分号隔开,同一个视频流中的不同的滤镜用逗号隔开,滤镜的不同参数用冒号隔开,参数名和值用等号隔开,视频流用中括号括起来 - 示例:
-vf “[in]split[split_main][split_delogo];[split_delogo]trim=start=360:end=371,delogo=0:0:640:480[delogoed];[split_main][delogoed]overlay=eof_action=pass[out]”
把输入流拆分成2个流,一个去除水印后再叠加到另一个上面
- 语法: [视频流1]过滤器1=过滤器1参数,过滤器2=过滤器2参数[视频流1输出];[视频流2]过滤器3=过滤器3参数[视频流2输出]
-
filter_complex
复杂过滤器参数,可以针对多个视频应用过滤器,后面跟多个过滤器参数,参数之间用;分隔,参数开始必须指定应用过滤器的视频流,参数结束可以指定过滤后的视频流名称- filter_complex “[0:v]scale=640:400[v0];color=c=black:s=640x400[bg];[v0][bg]xstack=inputs=2:layout=0_0|w0_0[out]”
包含有3个过滤器参数, [0:v]scale=640:400[v0] 处理的视频流为 [0:v] 也就是第1个视频的视频流,scale 为过滤器,[v0] 把处理后的视频流赋值给 [v0] 后续可通过 [v0] 引用该视频流
- filter_complex “[0:v]scale=640:400[v0];color=c=black:s=640x400[bg];[v0][bg]xstack=inputs=2:layout=0_0|w0_0[out]”
-
split
将1个视频流拆分成多个,每个视频流都跟原视频流一样
比如 你可能拆成2个,把1个缩小后叠加到另一个上
[0:v]split=2[ref][out]; 把视频流[0:v] 拆成2个视频流 [ref] 和 [out]
[ref]split[ref1][ref2]; 把视频流 [ref] 拆成2个视频流 [ref1] 和 [ref2] -
trim
剪辑视频流,剪出某个时间段- 语法 : trim=start=0:end=1000
start 开始时间,参考上面的时间格式
end 结束时间,参考上面的时间格式
duration 输出视频的最长时长
- 语法 : trim=start=0:end=1000
-
scale
对视频流缩放- 语法: scale=ow:oh[:force_original_aspect_ratio=decrease/increase]
ow oh 输出视频的大小,填-1时会等比计算高度,填-2时会等比计算高度并保证为偶数
可以使用变量 iw ih dar(输入宽高比)
由于ffmpeg只支持宽/高为偶数,因此如果是等比缩放,要这样写 trunc(ow/2)*2 ,trunc 是取整函数
force_original_aspect_ratio 强制等比缩放,=increase 最终屏幕>=设置的分辨率,=decrease 最终屏幕<=设置的分辨率 - -vf “scale=720:1280” 跟-s 720x1280 效果是一样的,都会对视频进行拉伸
- 语法: scale=ow:oh[:force_original_aspect_ratio=decrease/increase]
-
scaleref
对视频流缩放,以另一个视频流的大小为基准,也就是变量中可以用 main_w main_h 引用另一个视频的宽高
scale=ow:oh[:force_original_aspect_ratio=decrease/increase][ref]
[ref] 表示做为基准的视频流 -
pad
对视频画布进行填充,也就是本来视频跟画布一样大,填充后画布更大,多出来的部分填充黑边
pad=ow[:oh[:ox[:oy[:color]]]]
ow oh 画布宽高
ox oy 黑边起点相对画布左上点坐标为 [-ox,-oy]
black 画布颜色 -
color
生成纯色的视频流,常用于背景
color=c=black:s=640x400[bg] 生成颜色为黑色,大小为640x400的纯色视频流并赋值给 [bg] -
xstack
多路视频流合并,视频之间不会重叠,空间不够会缩小,空间太大不放大,只是摆在左上角
[v0][bg]xstack=inputs=2:layout=0_0|w0_0[out] [v0]和[bg] 视频流合并,总共2路视频,[v0] 摆在 0_0 位置,[bg] 摆在 w0_0 位置 -
hstack
多路视频流合并,视频之间不会重叠,高度必须相同,否则报错
[0:v][1:v]hstack=inputs=2[out] 第1个视频的视频流和第2个视频的视频流合并,赋值给 [out] -
vstack
多路视频流合并,视频之间不会重叠,宽度必须相同,否则报错
[0:v][1:v]hstack=inputs=2[out] 第1个视频的视频流和第2个视频的视频流合并,赋值给 [out] -
overlay
把某个视频流叠加到另一个视频流上- 语法:overlay[=x:y[:rgb={0, 1}]]
x(可选) 从左上角的水平坐标,默认值为 0
y(可选) 从左上角的垂直坐标,默认值为 0
rgb(可选) 值为 0 表示输入颜色空间不改变,默认为 0;值为 1 表示将输入的颜色空间设置为 RGB - 变量说明:如下变量可用在 x 和 y 的表达式中
main_w 或 W 主输入(背景窗口)宽度
main_h 或 H 主输入(背景窗口)高度
overlay_w 或 w overlay 输入(前景窗口)宽度
overlay_h 或 h overlay 输入(前景窗口)高度
- 语法:overlay[=x:y[:rgb={0, 1}]]
-
delogo
去除水印,- 语法:delogo=x:y:w:h[:t[band:[:show]]]
x 水印左上角的水平坐标
y 水印左上角的垂直坐标
w 水印宽度
h 水印高度
show(可选) 1 会显示一个矩形框表示去除范围用于调试,默认是0不显示 - 示例
delogo=x=10:y=10:w=100:h=100:show=1 delogo=10:10:100:100:show=1 按顺序可以省略参数名 ffmpeg -i input.mp4 -vf "delogo=x=50:y=50:w=150:h=50" -c:a copy output.mp4
- 去除多个水印
可以有多个 delogo,用逗号隔开delogo=10:10:100:100:show=1,delogo=100:100:100:100:show=1
- 去除某个时间段内的水印
可以配合enable参数来指定条件,下面只去除10到20秒内的水印
delogo=x=50:y=50:w=150:h=50:enable=‘between(t,10,20)’
- 语法:delogo=x:y:w:h[:t[band:[:show]]]
-
enable
这个不是过滤器,而是可以应用到过滤器的参数,可以指定过滤器触发的条件- 语法:enable=‘条件表达式’
- 条件表达式:
between(参数,起始值,结束值) 在某个时间内
eq(参数,值) 等于某个时间
gt(参数,值) 大于某个时间
gte(参数,值) 大于等于某个时间
lt(参数,值) 小于某个时间 - 逻辑运算符
! 非
|| 或
&& 与
- 条件表达式:
- 示例
ffmpeg -i input.mp4 -vf “delogo=x=50:y=50:w=150:h=50:enable=‘!lt(t,10) || gt(t,90)’” -c:a copy output.mp4
- 语法:enable=‘条件表达式’
-
amerge
把多个音频流合并成1个音频流,但是声道数不变,比如 2个音频流各有2个声道,则最终有4个声道
每个声道的音量被保留
[0:a][1:a]amerge=inputs=2[a] 把视频1和2的音频流合并,并赋值给[a] -
amix
把多个音频流合并成1个音频流,声道数只有一个,比如 2个音频流各有2个声道,则最终有1个声道
每个原始声道的音量在最终声道中各占 1/4
[0:a][1:a]amerge=inputs=2[a] 把视频1和2的音频流合并,并赋值给[a]
-
-
一些参数性能对比
与 veryslow相比,placebo以极高的编码时间为代价,只换取了大概1%的视频质量提升。
这是一种收益递减准则:slow 与 medium相比提升了5%~10%;slower 与 slow相比提升了5%;veryslow 与 slower相比提升了3%。 -
使用 ffmpeg 时可以在命令行中使用函数:
- bitand(ow,65534) 做与运算,该代码使ow变偶数
- trunc(ow) 取整
- ceil 向上取整
-
常用命令
-
有时候网上抓到类似这样的视频地址可以用ffmepg保存
ffmpeg -i “https://vdn.vzuu.com/SD/49c84c7c-c61a-11e8-8bad-0242ac112a0a.mp4?auth_key=1539832492-0-0-c61c22f39c&expiration=1539832492&disable_local_cache=1” ouput.mp4 -
获取视频信息
ffmpeg -i input.mp4 -hide_banner- 获取视频时长(bat中)
::这里获得的是毫秒 for /f "tokens=2-5 delims=:., " %%a in ('ffmpeg -i "%inFile%" 2^>^&1 ^| find "Duration:"') do ( set /a "t=(1%%a%%100*3600+1%%b%%100*60+1%%c%%100)*1000+1%%d0%%1000" ) ::把毫秒转成 hh:mm:ss.ms 格式 set /a "ms=t%%1000,t/=1000" set /a h=t/3600,m=t%%3600/60,s=t%%60,h+=100,m+=100,s+=100,ms+=1000 set "tt=!h:~1!:!m:~1!:!s:~1!.!ms:~1!" echo millsecond=%t% ffmpegTime=%tt%
- 获得视频流/音频流时长
:: 获得视频流时长 :: %1 视频文件 :: %2 接收时长的变量名 :GetVideoDuration set %2= for /f "tokens=1,2 delims==" %%i in ('ffprobe -show_streams -select_streams v -v quiet "%~1"') do ( if "%%i" == "duration" set %2=%%j ) goto :EOF :GetAudioDuration set %2= for /f "tokens=1,2 delims==" %%i in ('ffprobe -show_streams -select_streams a -v quiet "%~1"') do ( if "%%i" == "duration" set %2=%%j ) goto :EOF
-
选择视频中的流
- 仅视频流
ffmpeg -i input.mp4 -map 0:v output.mp4 - 来自不同文件的视频和音频
ffmpeg -i video.mp4 -i audio.m4a -map 0:v -map 1:a output.mp4 - 过滤音频
ffmpeg -i input.mp4 -map 0 -map -0:a output.mp4
- 仅视频流
-
去掉视频中的音频
ffmpeg -i input.mp4 -vcodec copy -an output.mp4
-an: 去掉音频;-vcodec:视频选项,一般后面加copy表示拷贝 -
提取视频中的音频
ffmpeg -i input.mp4 -acodec copy -vn output.mp3
-vn: 去掉视频;-acodec: 音频选项, 一般后面加copy表示拷贝 -
音视频合成
ffmpeg -y –i input.mp4 –i input.mp3 -c copy output.mp4
-y 覆盖输出文件 -
剪切视频,更精确的时间用 0:1:30.100,-c copy等价于 -vcodec copy -acodec copy
ffmpeg -ss 0:1:30 -t 0:0:20 -i input.mp4 -c copy -avoid_negative_ts 1 output.mp4
-ss 开始时间; -t 持续时间; -to 结束时间, -t 和 -to 同时存在则 -t 生效
时间可以用 hh:mm:ss.xxx 格式,也可以直接用多少秒,比如 180.1 等价于 3:00.1- 要注意参数顺序问题
- (推荐)-ss 和 -to 要放在 -i 的前面,从源文件中定位,会搜索到最近的关键帧,默认开启了 -accurate_seek
此时会解码并精准定位到指定时间,但如果使用-c copy,则不会解码,直接从开始点前面最近的关键帧开始 - 如果 -ss 和 -to 都在 -i 后面,则是从解码后的文件中定位,时间精确但速度慢,如果使用-c copy,
则不会在剪裁处插入关键帧,也就是剪裁后的视频前面可能有几秒是不动的,可以加 -copyts - 如果 -ss在-i 前面而 -to在-i 的后面,则-to表示时长,因为定位到-ss后时间戳重置为0
此时可以加 -copyts 参数来达到你要的效果
- (推荐)-ss 和 -to 要放在 -i 的前面,从源文件中定位,会搜索到最近的关键帧,默认开启了 -accurate_seek
- 使用 -c copy 的时侯,如果视频结尾不是关键帧,则视频后面会多出一段空白
此时可以加 -avoid_negative_ts 1 来解决,它会找到下一个关键帧来补全视频
但有一个问题,如果把一个视频分成2半,则这2个视频会有点交集
想要彻底解决该问题,就不能用 -c copy,而是要 -c:v libx264 -c:a aac 重新编码
- 要注意参数顺序问题
-
剪裁视频,剪裁区域为 [x,y,x+ow,y+oh]
ow默认为iw;oh默认为ih;x 默认为 (iw-ow)/2; y默认为 (ih-oh)/2;
ow oh 可以使用变量 iw ih dar(输入视频宽高比)
ffmpeg -i input.mp4 -vf crop=ow[:oh[:x[:y[:keep_aspect]]]] output.mp4
ffmpeg -i input.mp4 -vf crop=iw/3:ih/2 output.mp4 -
视频截图
ffmpeg –i test.mp4 –f image2 -t 0.001 -s 320x240 image-%3d.jpg
-s 设置分辨率; -f 强迫采用格式fmt; -
视频分解为图片
ffmpeg –i test.mp4 –r 1 –f image2 image-%3d.jpg
-r 指定截屏频率 -
将图片合成视频
ffmpeg -f image2 -i image%d.jpg output.mp4 -
视频拼接,多个视频文件按照时间顺序连接在一起
把视频文件列在 filelist.txt 中,每行一个文件
如果视频帧率,屏幕大小不同,则会自动先转成相同再合并
ffmpeg -f concat -i filelist.txt -c copy output.mp4 -
视频合并,多个视频流的内容叠加在一起
-
使用 xstack 进行合并
保证拼接的视频不重叠,如果空间不够,则视频会缩小,如果空间太大,则视频不放大,只是摆在左上角-
简单拼接
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -i video5.mp4 -filter_complex “[0:v][1:v][2:v][3:v][4:v]xstack=inputs=5:layout=0_0|w0_0|0_h0|w0_h0|w0+w1_h0[v];[0:a][1:a][2:a][3:a][4:a]amix=inputs=5[a]” -map [v] -map [a] output.mp4- filter_complex 指定拼接参数
- [0:v] [1:v] 指定要拼接的视频流,[0,v] 指第1个视频中的视频流
- xstack滤镜用于将输入的视频流进行拼接
- inputs=5表示有五个输入视频
- layout用于指定拼接的布局
- 0_0|w0_0|0_h0|w0_h0|w0+w1_h0表示五个视频的位置
- 最终视频是矩形,没内容的会填充绿色背景,如果想填充黑色背景,可用 color=c=black:s=640x400[bg] 生成黑色视频流,然后使用 overlay 叠加
- [v] 将拼接后的视频流赋值给 [v] ,后面要用到
- [0:a][1:a][2:a][3:a][4:a] 指定音频流
- amix=inputs=5将输入音频流混合
- [a] 将混合后的音频流赋值给 [a],后面要用到
-map [v] -map [a] 指定输出的视频流,音频流,使用filter_complex后,默认选择器没有选择任何视频流和音频流
- filter_complex 指定拼接参数
-
每个视频自定义缩放
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -i video5.mp4 -filter_complex “[0:v]scale=640:400[v0];[1:v]scale=640:400[v1];[2:v]scale=640:400[v2];[3:v]scale=640:400[v3];[4:v]scale=640:400[v4];color=c=black:s=640x400[bg];[v0][v1][v2][v3][v4][bg]xstack=inputs=6:layout=0_0|w0_0|w0+w1_0|0_h1|w0_h1|w0+w1_h1[out]” -map “[out]” -c:v libx264 output.mp4- filter_complex 指定拼接参数
- [0:v]scale=640:400[v0] 把第1个视频中的视频流缩放后赋值给 [v0]
- color=c=black:s=640x400[bg] 使用黑色填充一个640x400 的视频流并赋值给[bg]
- [v0][v1][v2][v3][v4][bg]xstack=inputs=6:layout=0_0|w0_0|w0+w1_0|0_h1|w0_h1|w0+w1_h1[out] 使用前面缩放后的视频流按一定布局拼接后赋值给 [out]
-map “[out]” 指定[out]做为输出的视频流
- filter_complex 指定拼接参数
-
-
使用 vstack 进行合并
视频垂直排列,保证视频不重叠,视频必须具有相同的宽度,否则报错
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -filter_complex “[0:v][1:v][2:v][3:v]vstack=inputs=4[v];[0:a][1:a][2:a][3:a]amix=inputs=4[a]” -map [v] -map [a] output.mp4 -
使用 hstack 进行合并
视频水平排列,保证视频不重叠,视频必须具有相同的高度,否则报错
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -filter_complex “[0:v][1:v][2:v][3:v]hstack=inputs=4[v];[0:a][1:a][2:a][3:a]amix=inputs=4[a]” -map [v] -map [a] output.mp4 -
使用 overlay 合并
把第2个视频叠加到第1个视频中,视频是重叠在一起的,可以实现画中画功能
ffmpeg -i video1.mp4 -i video2.mp4 -i video3.mp4 -i video4.mp4 -filter_complex"[0:v]pad=iw2:ih2[a];[a][1:v]overlay=w[b];[b][2:v]overlay=0:h[c];[c][3:v]overlay=w:h" output.mp4- filter_complex 指定拼接参数
- [0:v]pad=iw2:ih2[a] 表示把第1个视频中的视频流画布宽度和高度都乘以2,注意视频大小并没有乘以2,并赋值给 [a]
- [a][1:v]overlay=w[b] 把第2个视频中的视频流跟 [a] 拼接,坐标为 w:0(小w是叠加视频的宽度,大W是主视频的宽度),并赋值给 [b]
- … 后续不断拼接新视频即可
ffmpeg -i input.mp4 -i logo.jpg -filter_complex [0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map 0:a -codec:a copy output.mp4
视频添加水印 main_w-overlay_w-10 视频的宽度-水印的宽度-水印边距; - filter_complex 指定拼接参数
-
-
将视频转为gif
ffmpeg -i input.mp4 -ss 0:0:30 -t 10 -s 320x240 -pix_fmt rgb24 output.gif
-pix_fmt 指定编码 -
将视频前30帧转为gif
ffmpeg -i input.mp4 -vframes 30 -f gif output.gif -
旋转视频
ffmpeg -i input.mp4 -vf rotate=PI/2 output.mp4 -
缩放视频,oh不能省略,填-1时会等比计算高度,填-2时会等比计算高度并保证为偶数,可以使用变量 iw ih dar(输入宽高比)
force_original_aspect_ratio 强制等比缩放,=increase 最终屏幕>=设置的分辨率,=decrease 最终屏幕<=设置的分辨率
由于ffmpeg只支持宽/高为偶数,因此如果是等比缩放,要这样写 trunc(ow/2)*2 trunc 是取整函数
-s 720x1280 跟 -vf “scale=720:1280” 效果是一样的,都会对视频进行拉伸
ffmpeg -i input.mp4 -vf scale=ow:oh[:force_original_aspect_ratio=decrease/increase] output.mp4 -
iw 是输入的宽度,ow是输出宽度, iw/2就是一半;-1 为保持宽高比,如果高度必须是2的整数倍则填-2
ffmpeg -i input.mp4 -vf scale=iw/2:-1 output.mp4 -
等比缩放视频,如果输入是 496x368,则输出为 720x534,如果改成increase,则输出为 1725x1280(由于1725是奇数会报错,可用下面填黑边方法处理)
ffmpeg -i input.mp4 -vf “scale=720:1280:force_original_aspect_ratio=decrease” output.mp4 -
等比缩放视频,不足部分填充黑边,在上面的基础上填充黑边到分辨率为720x1280
ffmpeg -i input.mp4 -vf “scale=720:1280:force_original_aspect_ratio=decrease,pad=720:1280:(ow-iw)/2:(oh-ih)/2” output.mp4 -
视频变速
ffmpeg -i input.mp4 -filter:v setpts=0.5*PTS output.mp4 -
音频变速
ffmpeg -i input.mp3 -filter:a atempo=2.0 output.mp3 -
音视频同时变速,但是音视频为互倒关系
ffmpeg -i input.mp4 -filter_complex “[0:v]setpts=0.5*PTS[v];[0:a]atempo=2.0[a]” -map “[v]” -map “[a]” output.mp4 -
视频压缩为h264
ffmpeg -i D:\src.mov -c:v libx264 -preset veryslow -crf 20 -c:a copy D:\dest1.mp4 -
下载m3u8文件,也就是一系列ts文件
ffmpeg -i https://v6.438vip.com/2018/10/17/3JAHPTdvPhQb9LrE/playlist.m3u8 -c copy OUTPUT.mp4 -
获取音频响度
for /f tokens^=1^,2^,3^,4^ delims^=^" %%a in ('ffmpeg -hide_banner -i "%~1" -af "loudnorm=I=-16:TP=-1:LRA=11:print_format=json" -f null NUL 2^>^&1 ^| findstr "input_i input_tp input_lra input_thresh target_offset"') do ( echo %%a %%b %%c %%d if "%%b" == "input_i" set _i=%%d if "%%b" == "input_tp" set _tp=%%d if "%%b" == "input_lra" set _lra=%%d if "%%b" == "input_thresh" set _thresh=%%d if "%%b" == "target_offset" set _offset=%%d )
-
调整音频响度
先了解下 音频基础知识
ffmpeg响度调整
ffmpeg音频过滤器-
(推荐)方法一: 直接使用别人写的python插件 ffmpeg-normalize
本质上也是是使用下面提到的loudnorm过滤器-
安装 ffmpeg 5.x+ , python 3.8+
-
把 ffmpeg.exe 添加到环境变量 Path
可以设置环境变量 FFMPEG_PATH 为 ffmpeg 路径,不设也可以但不能设置错误 -
python 安装插件: pip install ffmpeg-normalize
帮助文档: https://github.com/slhck/ffmpeg-normalize -
调整声音
ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k
调整到EBU R128响度标准中广播常用的 -23
默认是使用 wav 格式,如果是mp4一般是aac格式,要加 -c:a aac,如果是mp3要加 -c:a libmp3lame
-b:a 192k 指定比特率,默认128K,192k算比较好的,一般音乐用192k,视频用128kffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k -t -16 -lrt 11 -tp -1
调整到流行音乐的 I=-16:LRA=11:tp=-1,一般响度范围用 11 就够了,大多数在 6-9
只有 -t 指定的响度是要匹配的, -tp 和 -lrt 指定的都是最大值,实际值可能差挺多ffmpeg-normalize input.mp4 -o output.mp4 -c:a aac -b:a 192k -t -16 --keep-loudness-range-target -tp -1
调整到流行音乐的 I=-16:tp=-1,但保持原有的响度范围 -
查看帮助
ffmpeg-normalize -h
-
-
方法二: 直接使用ffmpeg提供的高级过滤器
-
loudnorm
响度平均标准化,最常用的标准化算法,广泛应用在有线电视/广播- 原理
先计算出整体声音的平均音量,再根据平均音量到期望音量的差值,做为调整的依据,最后使的平均音量达到期望音量的大小,峰值声音调整后有可能被削除波峰
会先尝试使用线性调整,也就是方法三的直接加音量,如果音量峰值超出设置的峰值就会改用动态调整,也就是类似 dynaudnorm 滤镜
会把音量小的部分放大倍数大,音量大的部分放大倍数小,各部分音量调整后变得均衡 - 应用场景
适合有很多歌曲声音大小不同,通过该过滤器调整成同样的标准 - 使用:
需要执行2遍:- 第一遍测量、分析音频文件,得到响度标准化所需要的参数
这里设置标准化为流行音乐的参数 I=-16:LRA=11:tp=-1
第一遍输出的 normalization_type 一定是 dynamic
得到参数如下ffmpeg -hide_banner -i demux.aac -c:a:0 pcm_s24le -af "loudnorm=I=-16:TP=-1:LRA=11:print_format=json" -f null NUL
{ "input_i" : "-23.53", "input_tp" : "-13.68", "input_lra" : "3.10", "input_thresh" : "-33.53", "output_i" : "-16.45", "output_tp" : "-6.32", "output_lra" : "2.30", "output_thresh" : "-26.45", "normalization_type" : "dynamic", "target_offset" : "0.45" }
- 第二遍把得到的参数,填入 loudnorm 的滤镜设置中,对音频做标准化处理
如果调整后峰值不超出 -tp 设定值,lra不小于原有lra,则采用 linear 处理
否则使用 dynamic 处理,dynamic 会把 lra 调整到7以下ffmpeg -hide_banner -y -i input.aac -af "loudnorm=I=-16:TP=-1:LRA=11:measured_I=-23.53:measured_tp=-13.68:measured_LRA=3.10:measured_thresh=-33.53:offset=0.45:print_format=summary" output.aac
- 第一遍测量、分析音频文件,得到响度标准化所需要的参数
- 原理
-
dynaudnorm
动态音频归一化器,使声音整体音量变得均衡- 原理
对输入音频施加一定的增益,以使其峰值幅度达到目标电平,会动态调整增益使安静的部分增益变大,响亮部分增益变小,
各自增益后都不会超出目标电平且保留各自的动态范围,但是整体的动态范围可能会变 - 效果
声音音量小的部分放大倍数大,音量大的部分放大倍数小,各部分音量调整后变得均衡
- 原理
-
speechnorm
-
volume
直接增益所有电平- 通过 volumedetect 获取音量值
ffmpeg -i 01.mp3 -af “volumedetect” -vn -sn -dn -f null NUL - 根据获取的音量值确定调整的幅度,再使用 volume 调整音量,
比如 获取到最大音量 -14dB,我们想要调整到 -9dB
就要 +5dB
ffmpeg -i 01.mp4 -af “volume=5dB” -c:v copy -c:a aac -cutoff 20000 output.mp4 - 如果增益到峰值还不是达到需要的响度,可先调整动态范围
调整动态范围可考虑以下方法-
compand
压缩动态范围并调整增益电平
按电平范围进行压缩,比如 -30到-20区间怎么压缩,-20到-10区间怎么压缩
跟 acompressor 区别是 compand 是
acompressor 是 -
acompressor
压缩器,压缩动态范围
设定阈值,超出的电平超出部分按多少比例进行压缩 -
alimiter
限制器,电平大于设定的值会进行压缩
-
- 通过 volumedetect 获取音量值
-
-
-
常见问题
-
Too many packets buffered for output stream 0:1.
有些视频数据有问题,导致视频处理过快,容器封装时队列溢出,常见的是转换rmvb时出现,导致不能转换
在输出文件前加参数 -max_muxing_queue_size 1000 -
Non-monotonous DTS in output stream 0:1;
多在合并多个视频文件时出现,这是由于音频码率不同,会导致声音错位或视频快进
增加音频转换时固定码率,在输出文件前加参数 -ac 1 -ar 48000 表示单声道,采样率为 48000