文章目录
第3章 FFmpeg工具使用基础
3.1 ffmpeg常用命令
ffmpeg --help
ffmpeg -h
ffmpeg -h long 查看高级参数部分
ffmpeg -h full 产科全部参数部分
ffmpeg -h type=name
其中 type为 decoder/encoder/demuxer/muxer/filter/bsf/protocol 的一种
name为对应的组件的名字
ffmpeg -L 查看ffmpeg目前支持的license协议
ffmpeg -version 查看ffmpeg版本,以及子模块的详细版本信息
ffmpeg -formats 查看当前ffmpeg支持的容器文件格式,返回值如下:
File formats:
D. = Demuxing supported
.E = Muxing supported
--
D 3dostr 3DO STR
E 3g2 3GP2 (3GPP2 file format)
E 3gp 3GP (3GPP file format)
...
共三列,
第一列 D表示 Demuxing, E表示 Muxing
第二列 容器格式在FFmpeg中使用的简短名字
第三列 容器文件格式的补充说明
ffmpeg -codecs 查看编解码格式的所有信息,如:
Codecs:
D..... = Decoding supported
.E.... = Encoding supported
..V... = Video codec
..A... = Audio codec
..S... = Subtitle codec
..D... = Data codec
..T... = Attachment codec
...I.. = Intra frame-only codec
....L. = Lossy compression
.....S = Lossless compression
-------
D.VI.S 012v Uncompressed 4:2:2 10-bit
D.V.L. 4xm 4X Movie
...
共三列,
第一列 D表示支持解码,E表示支持编码,以及编码的音频/视频/字幕/数据/附件类型,或者只有I帧的编码压缩格式,以及有损和无损压缩类型
第二列 Codec在FFmpeg中使用的简短名字
第三列 Codec格式的详细说明,如果一个Codec有多个对应实现,也会在小括号中显示出来
ffmpeg -encoders / ffmpeg -decoders
ffmpeg -h muxer=flv
ffmpeg -h demuxer=flv
ffmpeg -h encoder=h264
ffmpeg -h filter=colorkey
3.1.1
ffmpeg 中 AVFormatContext 的主要参数
参数 | 说明 |
---|---|
avioflags | 缓冲设置, 默认为0 direct: 无缓冲 |
probesize | probing size |
等等
ffmpeg 中 AVCodecContext 的主要参数
参数 | 说明 |
---|---|
b | 设置文件码流 |
ab | 设置音频码率(不同音频encoder有不同的默认值), |
g | 设置max gop size |
ar | 设置音频sample_rate, |
ac | 设置音频channel_count, |
bf | 设置连续编码B帧的个数,设置为0是无B帧 |
profile | 设置音视频的profle |
level | 设置音视频的level |
level | 设置音视频的level |
color_primaries | 设置视频的primaries (from 1 to 10) (default unspecified) |
color_trc | 设置视频的color transfer characteristics (from 1 to 18) (default unspecified) |
colorspace | 设置视频的colorspace,如 bt709, rgb 等 |
color_range | 设置视频的range mpeg: MPEG (219*2^(n-8)) jpeg: JPEG (2^n-1) |
更多信息查看ffmpeg -h full 的返回值 |
3.1.3 转码流程
ffmpeg -i input1.rmvb -vcodec mpeg4 -b:v 200k -r 15 -an output.mp4
3.2 ffprobe 常用命令
3.2.1 ffprobe常用参数
ffprobe -v 指定log级别, quiet/panic -> debug/ trace
ffprobe -show_format
ffprobe -show_streams 查看文件的流信息, 如视频codec, 帧率,位深,nal_length_size, profile/level, has_b_frames等
ffprobe -show_chpters
ffprobe -v trace -show_format -show_streams -show_chapters -of json video.mp4
3.2.2 ffprobe 使用示例
ffprobe -show_packets input.flv 查看多媒体数据包信息
ffprobe -show_data -show_packets input.flv 查看每一包信息以及包中的具体数据
ffprobe -show_format output.mp4 查看文件format信息
ffprobe -show_frames input.flv 查看视频的每一帧信息
ffprobe -of xml -show_streams input.flv 查看每一路stream的信息,xml的格式输出
此外,of还可以跟 ini/ json/ csv / flat 等信息
ffprobe -show_frames -select_streams v -of xml input.mp4 只查看视频信息
select_streams 后面可以跟 v a s,分别表示 视频/音频/字幕
如果不需要输出所有字段的信息,可以结合 show_entries来使用,如:
ffprobe -select_streams v -show_packets -show_entries packet=codec_type,pts_time,pos input.mp4
表示只输出 packet中的 codec_type/pst_time/pos等字段信息
ffprobe -v trace input.mp4 2>&1| findstr “parent:‘root’” 查看文件中box的位置信息
3.3 ffplay常用命令
3.3.1 ffplay常用参数
ffplay --help
与ffplay 相关的命令
x, y 设置显示窗口的宽高
s 设置视频显示宽高,主要用于播放yuv/rgb裸流, 有的版本没有这个信息
fs 强制全屏播放
an/vn/sn 屏蔽音频/视频/字幕
ss/t 设置seek开始的秒数/设置播放的时间长度
bytes: seek by byes, 0:off, 1:on, -1 auto
nodisp: 关闭显示窗口
f 强制使用某格式,主要用于rawvideo播放裸流
window_title 设置显示窗口的标题
af/vf 设置音频/视频滤镜
codec 强制使用某个codec, 主要针对存在多个视频codec的情况
autorotate 自动旋转视频
ffplay -ss 0 -t 10 input.mp4
ffplay -window_title “Hello, World” output.mp4
ffplay -window_title “播放测试” rtmp://up.v.test.com/live/stream //实际播放不了
3.3.2 ffplay高级参数
ast/vst/sst 设置将要播放音频/视频/字幕流
stats 输出多媒体播放状态 //没发现有啥作用
autoexit 播放完成后自动退出ffplay, 默认不自动退出
exitonkeydown/exitonmousedown 有按键事件/鼠标按键事件后退出ffplay
loop 设置播放循环次数
framedrop cpu占用过高时,自动丢帧
infbuf 设置无极限的播放器buffer,主要用于流媒体播放场景
vf 设置视频滤镜
acodec/vcodec/scodec 强制使用某个codec
time xxx // window上无法使用time统计耗时信息
ffplay -vcodec h264 output.mp4 强制使用h264解码器解码非h264码流会报错
ffmpeg -vst 4 -ast 5 test.ts 针对ts流中有多路节目时,选择对应的音频流和视频流
ffplay -window_title “Test Movie” -vf “subtitles=input.srt” output.mp4
播放视频时,带上 input.srt的字幕文件
input.srt内容可以为
1
00:00:00.000 --> 00:00::30.000
Test first 30 second
2
00:00:00.301 --> 00:00::60.000
Test second 30 second
3
00:01:01.000 --> 00:01::10.000
Test end
3.3.3 ffplay的数据可视化分析应用
ffplay -showmode 1 output.mp3 //音频的波形以振幅的形式显示出来
ffplay -debug vis_mb_type -window_title “show vis_mb_type” -ss 20 -t 10 -autoexit output.mp4
注: 较新的版本上的 AVCodecContext 帮助中,其-debug没有 vis_mb_type, 只有 qp/mb_type 等信息,不是打印在视频的宏块上,而是直接打印在log里面,如下图,打印的是720x960(每帧45x60个宏块)视频的qp信息,
下面时某一帧每个宏块的qp值
ffplay -vismv pf output.mp4 // 没有 vismv 这个命令
ffplay -flags2 +export_mvs video.mp4 -vf codecview=mv=pf+bf+bb // 这个可以将mv信息显示在画面上,如果没有 flags参数,单纯使用 codecview filter,还是无效果
3.3.4 ffplay快捷键
ffplay播放过程中的一些快捷键
快捷键 | 功能 |
---|---|
f | 全屏/非全屏切换 |
f | 全屏/非全屏切换 |
s | 逐帧显示图像,(暂停的状态时) |
w | 显示图像和声音波形之间切换 |
← / → | 后退10s/前进10s |
↑ / ↓ | 前进60s/后台60s |
鼠标右键单击 | seek至指定位置 |
鼠标左键双击 | 切换全屏/非全屏 |
m | 静音切换 |
功能键区(非小键盘)的 9和0 | 增大和减小音量 |
小键盘区的 / 和 * | 增大和减小音量 |
p | 暂停/恢复播放 |
q和 ESC | 退出播放 |
第4章 封装与解封装
4.1 视频文件转MP4
4.1.4 MP4在FFmpeg中的Demuxer
ffmpeg -h demuxer=mp4
个人觉得有用的信息
ignore_editlist 忽略EditList box信息,默认不开启,
如果同一个视频,ffplay播放音视频不同步,其他播放器正常,可能是mp4的 editlist box里面的参数缘故,设置这个参数再尝试一下
ffmpeg -h muxer=mp4
个人觉得有用的信息
movflags
faststart 设置将moov box置于文件的开头,
dash 将MP4封装为fragment mp4,以便兼容DASH
ffmpeg -i input.flv -c copy -f mp4 output.mp4
ffmpeg -i input.flv -c copy -f mp4 -movflags faststart output.mp4
ffmpeg -i input.flv -c copy -f mp4 -movflags dash output.mp4
ffmpeg -re -i input.mp4 -c copy -movflags isml+frag_keyframe -f ismv Stream //与普通mp4的差异就是,Stream里面的 compatible_brands为 ismlpiff, 这里的 -re 表示 每秒只读取1s的input.mp4数据来处理,所以视频有多长,转码时间就会有多长,为了加快速度,可以取消到 -re 这个命令
ffmpeg -i input.mp4 -c:v libx265 -c:a aac -crf 25 -tag:v hvc1 outputh265.mp4
与不加 -tag:v hvc1生成的普通Mp4相比,
普通MP4视频生成 hev1 box, 这里生成 hvc1 box
4.2 视频文件转FLV
ffmpeg -h muxer=flv 查看 flv muxer的使用信息
ffmpeg -i input_ac3.mp4 -c copy -f flv output.flv
ffmpeg -i input_ac3.mp4 -vcodec copy -acodec aac -f flv output.flv
ffmpeg -i input.mp4 -c copy -f flv -flvflags add_keyframe_index output.flv
相比默认 不加 flvflags的命令,生成的flv文件,多了存放关键帧信息的metadata
ffprobe -v trace -i output.flv // 查看flv信息
4.3 视频文件转MPEG-TS
TS/PS 分为三层
- ES层: 单独的音频流视频流组成的Elementary Stream, ES
- PES层: 将ES按一定的规则进行封装,如H.264的AU作为拆分单元,打上时间戳,组成分组的基本数据流 Packetized Elementary Stream, PES,
- TS/PS 层: 将PES包进行切分再封装成固定大小(一般为188 Byte)的传输流 Transport Stream, TS
ffmpeg -h muxer=mpegts 查看mpegts muxer的帮助信息
4.4 视频文件转HLS
ffmpeg -h muxer=hls 查看hls muxer的help信息
ffmpeg -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb output.m3u8
实操发现是否加 -bsf:v h264_mp4toannexb, 效果一样,ffmpeg内部会自动把MP4中nal的长度头更换为起始码的头
- start_number参数
ffmpeg -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -start_number 300 output.m3u8 // 设置m3u8中的切片从 300开始
ffmpeg -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb -hls_time 10 output.m3u8
每一个切片,几乎都是10s
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:11
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:11.066667,
output0.ts
#EXTINF:10.166667,
output1.ts
#EXTINF:10.000000,
output2.ts
#EXTINF:6.166667,
output3.ts
#EXT-X-ENDLIST
ffmpeg -i input.mp4 -c copy -f hls -hls_list_size 3 output.m3u8
只保留了最多3片的切片
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:13
#EXTINF:2.266667,
output13.ts
#EXTINF:2.300000,
output14.ts
#EXTINF:1.600000,
output15.ts
#EXT-X-ENDLIST
hls_wrap 参数已经废弃
ffmpeg -i input.mp4 -c copy -f hls -hls_base_url http://192.168.0.1/lives/ output1.m3u8
从生成的m3u8来看,每个分片都加了 http://192.168.0.1/lives/ 的前缀
D:\_Video>type output1.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:1.800000,
http://192.168.0.1/lives/output111.ts
#EXTINF:1.833333,
http://192.168.0.1/lives/output112.ts
#EXTINF:2.266667,
http://192.168.0.1/lives/output113.ts
#EXTINF:2.300000,
http://192.168.0.1/lives/output114.ts
#EXTINF:1.600000,
http://192.168.0.1/lives/output115.ts
#EXT-X-ENDLIST
ffmpeg -i input.mp4 -c copy -vframes 1000 -f hls -hls_segment_filename test_output-%d.ts output.m3u8
可以看出,切片名字不再是默认的 output1.ts, output2.ts 这些ts
而是指定的 test_output-%d.ts
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:9
#EXTINF:3.066667,
test_output-9.ts
#EXTINF:3.300000,
test_output-10.ts
#EXTINF:1.800000,
test_output-11.ts
#EXTINF:1.833333,
test_output-12.ts
#EXTINF:2.100000,
test_output-13.ts
#EXT-X-ENDLIST
ffmpeg -f lavfi -i testsrc2=s=176x144:r=15 -vcodec libx264 -g 30 -r:v 15 -f hls -hls_time 2 -hls_list_size 4 -hls_flags delete_segments -t 30 output-test.m3u8
D:\_Video>type output-test.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:2.000000,
output-test11.ts
#EXTINF:2.000000,
output-test12.ts
#EXTINF:2.000000,
output-test13.ts
#EXTINF:2.000000,
output-test14.ts
#EXT-X-ENDLIST
-t 30 指定要生成30s的视频,hls_time 为2,指定切片duration为2s, 故一共有15个切片
从 output-test0 - output-test14
而这是了 delete_segment, 且 hls_list_size 4, 故前11个切片都删了,只保留最后4个
ffmpeg -i input.mp4 -c copy -f hls -hls_flags round_durations output.m3u8
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:2
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:2,
output11.ts
#EXTINF:2,
output12.ts
#EXTINF:2,
output13.ts
#EXTINF:2,
output14.ts
#EXTINF:2,
output15.ts
#EXT-X-ENDLIST
每一片的切片时长变为了整数,而不是浮点数了
ffmpeg -i input.mp4 -c copy -f hls -hls_flags discont_start -bsf:v h264_mp4toannexb output.m3u8
生成的m3u8文件中,实际并没有 discontinuity 标签, why?
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:1.800000,
output11.ts
#EXTINF:1.833333,
output12.ts
#EXTINF:2.266667,
output13.ts
#EXTINF:2.300000,
output14.ts
#EXTINF:1.600000,
output15.ts
#EXT-X-ENDLIST
ffmpeg -i input.mp4 -c copy -vframes 2000 -f hls -hls_flags omit_endlist -bsf:v h264_mp4toannexb output.m3u8
生成的 m3u8文件中,没有 endlist 标签
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:1.800000,
output11.ts
#EXTINF:1.833333,
output12.ts
#EXTINF:2.266667,
output13.ts
#EXTINF:2.300000,
output14.ts
#EXTINF:1.600000,
output15.ts
ffmpeg -i input.mp4 -c copy -f hls -hls_time 2 -hls_flags split_by_time output.m3u8
hls_time设置的切片duration已经生效,几乎都是2s,
由于不是根据关键帧分隔的,所有播放某些片段是,会先花屏或者报错,直至遇到I帧
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:14
#EXTINF:2.033333,
output14.ts
#EXTINF:1.966667,
output15.ts
#EXTINF:2.000000,
output16.ts
#EXTINF:2.133333,
output17.ts
#EXTINF:1.400000,
output18.ts
#EXT-X-ENDLIST
ffmpeg -re -i input.mp4 -c copy -vframes 2000 -f hls -strftime 1 -bsf:v h264_mp4toannexb output.m3u8
strftime参数用于设置HLS切片文件名,以生成TS切片文件时的系统时间作为文件名。
注意必须要加 -re参数,要不文件1s内生成完毕,所有的文件名都是同一个
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:1.800000,
output-20250125232835.ts
#EXTINF:1.833333,
output-20250125232837.ts
#EXTINF:2.266667,
output-20250125232838.ts
#EXTINF:2.300000,
output-20250125232841.ts
#EXTINF:1.600000,
output-20250125232843.ts
#EXT-X-ENDLIST
ffmpeg -i input.mp4 -c copy -f hls -hls_time 3 -hls_list_size 0 -method PUT -t 30 http://127.0.0.1/test/output_test.m3u8
没有搭建推流服务器,等搭建了Nginx后再试(todo)
ffmpeg -i input.mp4 =b:a:0 32k -b:a:1 64k -b:v:0 1000k -map 0:a -map 0:a -map 0:v -f hls -var_stream_map "a:0,agroup:aud_ow,default:yes,language:ENG a:1,agroup:aud_high,language:CHN v:0,agroup:aud_low" -master_pl_name master.m3u8 -t 30 output%v.m3u8
此命令一共生成4个m3u8文件, master.m3u8和 output0.m3u8, output1.m3u8, output2.m3u8,
其中 output0.m3u8和 output1.m3u8中关联的都是音频,output2.m3u8中关联的是视频,
直接播放master.m3u8时,播放的是无声视频,尚不清楚如何播放出相关的音频
内容分别为:
D:\_Video>type master.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud_ow",NAME="audio_0",DEFAULT=YES,LANGUAGE="ENG",URI="output0.m3u8"
#EXT-X-MEDIA:TYPE=AUDIO,GROUP-ID="group_aud_high",NAME="audio_1",DEFAULT=NO,LANGUAGE="CHN",URI="output1.m3u8"
#EXT-X-STREAM-INF:BANDWIDTH=1100000,RESOLUTION=720x960,CODECS="avc1.64001f"
output2.m3u8
D:\_Video>type output0.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:1.996911,
output011.ts
#EXTINF:1.996922,
output012.ts
#EXTINF:1.996911,
output013.ts
#EXTINF:1.996922,
output014.ts
#EXTINF:0.023222,
output015.ts
#EXT-X-ENDLIST
D:\_Video>type output1.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:11
#EXTINF:1.996911,
output111.ts
#EXTINF:1.996922,
output112.ts
#EXTINF:1.996911,
output113.ts
#EXTINF:1.996922,
output114.ts
#EXTINF:0.023222,
output115.ts
#EXT-X-ENDLIST
D:\_Video>type output2.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:3
#EXT-X-MEDIA-SEQUENCE:10
#EXTINF:1.033333,
output210.ts
#EXTINF:2.033333,
output211.ts
#EXTINF:3.333333,
output212.ts
#EXTINF:0.900000,
output213.ts
#EXTINF:1.466667,
output214.ts
#EXT-X-ENDLIST
4.5 视频文件切片
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 test_output-%d.mp4
此命令生成一堆切片好的mp4文件
如下命令查看第一个切片文件的最后三个pts_time,
ffprobe -v quiet -show_packets -select_streams v test_output-0.mp4 | findstr pts_time > 0.txt
type 0.txt | find /c /v "" > tmp.txt && set /p line=<tmp.txt && set /a last=%line%-10
more +%last% 0.txt
为
pts_time=2.632682
pts_time=2.766016
pts_time=2.699349
pts_time=2.666016
pts_time=2.732682
pts_time=2.932682
pts_time=2.832682
pts_time=2.799349
pts_time=2.866016
pts_time=2.899349
···
ffprobe -v quiet -show_packets -select_streams v test_output-1.mp4 | findstr pts_time > 1.txt
for /l %l in (1,1,10) do @for /f “tokens=1,2* delims=:” %a in (‘findstr /n /r “^” 1.txt ^| findstr /r “^%l:”’) do @echo %b
···
为
pts_time=2.966016
pts_time=3.099349
pts_time=3.032682
pts_time=2.999349
pts_time=3.066016
pts_time=3.232682
pts_time=3.166016
pts_time=3.132682
pts_time=3.199349
pts_time=3.366016
可以看出 test_output-0.mp4的最后一帧时间戳为 2.932682
test_output-1.mp4的第一帧时间戳为 2.966016
是相邻的
- 生成 ffconcat格式的索引文件
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type ffconcat -segment_list output.lst test_output-%d.mp4
生成的 output.lst 内容如下:
D:\_Video>type output.lst
ffconcat version 1.0
file test_output-0.mp4
file test_output-1.mp4
file test_output-2.mp4
file test_output-3.mp4
file test_output-4.mp4
file test_output-5.mp4
file test_output-6.mp4
file test_output-7.mp4
file test_output-8.mp4
file test_output-9.mp4
file test_output-10.mp4
file test_output-11.mp4
file test_output-12.mp4
file test_output-13.mp4
file test_output-14.mp4
file test_output-15.mp4
- 生成FLAT格式索引文件
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type flat -segment_list filelist.txt test_output-%d.mp4
生成的 filelist.txt的内容如下:
D:\_Video>type filelist.txt
test_output-0.mp4
test_output-1.mp4
test_output-2.mp4
test_output-3.mp4
test_output-4.mp4
test_output-5.mp4
test_output-6.mp4
test_output-7.mp4
test_output-8.mp4
test_output-9.mp4
test_output-10.mp4
test_output-11.mp4
test_output-12.mp4
test_output-13.mp4
test_output-14.mp4
test_output-15.mp4
- 生成 csv格式索引文件
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type csv -segment_list filelist.csv test_output-%d.mp4
生成的 filelist.txt的内容如下:
D:\_Video>type filelist.csv
test_output-0.mp4,0.000000,2.966667
test_output-1.mp4,2.966667,4.833333
test_output-2.mp4,4.833333,6.866667
test_output-3.mp4,6.866667,8.833333
test_output-4.mp4,8.833333,11.133333
test_output-5.mp4,11.133333,14.466667
test_output-6.mp4,14.466667,17.133333
test_output-7.mp4,17.133333,19.566667
test_output-8.mp4,19.566667,21.300000
test_output-9.mp4,21.300000,24.366667
test_output-10.mp4,24.366667,27.666667
test_output-11.mp4,27.666667,29.466667
test_output-12.mp4,29.466667,31.300000
test_output-13.mp4,31.300000,33.566667
test_output-14.mp4,33.566667,35.866667
test_output-15.mp4,35.866667,37.466667
- 生成 M3U8索引文件
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type m3u8 -segment_list output.m3u8 test_output-%d.mp4
生成的 output.m3u8 的内容如下:
D:\_Video>type output.m3u8
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-ALLOW-CACHE:YES
#EXT-X-TARGETDURATION:4
#EXTINF:2.966667,
test_output-0.mp4
...
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -reset_timestamps 1 test_output-%d.mp4
ffprobe -v quiet -show_packets -select_streams v test_output-1.mp4 | findstr pts_time > 1.txt
发现test_output_1.mp4的其实时间戳已经变为了0
pts_time=0.000000
pts_time=0.133333
pts_time=0.066667
pts_time=0.033333
pts_time=0.100000
ffmpeg -i input.mp4 -c copy -f segment -segment_format mp4 -segment_times 3,9,12 test_output-%d.mp4
所有查看切片视频文件,前三片的duration几乎为 3s/6s/3s
4.5.3 使用ss与t参数切片
- 使用ss指定剪切开头
ffmpeg -ss 8 -i input.mp4 -c copy output.ts
从第8s位置开始切片,随后查看原始视频和切片后视频,duration相差几乎8s
D:\_Video>ffprobe -v quiet -show_format input.mp4 | findstr duration
duration=37.400000
D:\_Video>ffprobe -v quiet -show_format output.ts | findstr duration
duration=30.690433
- 使用 t 指定视频总长度
ffmpeg -i input.mp4 -c copy -t 10 -copyts output.ts
查看转码前后文件信息,转码后文件duration几乎为10s
D:\_Video>ffprobe -v quiet -show_format input.mp4 | findstr "start_time duration"
start_time=0.000000
duration=37.400000
D:\_Video>ffprobe -v quiet -show_format output.ts | findstr "start_time duration"
start_time=1.465667
duration=10.134333
- 使用 output_ts_offset 指定输出 start_time
ffmpeg -i input.mp4 -c copy -t 10 -output_ts_offset 120 output.ts
可以看出转码后的文件的其实时间戳几乎为 120s
D:\_Video>ffprobe -v quiet -show_format input.mp4 | findstr "start_time duration"
start_time=0.000000
duration=37.400000
D:\_Video>ffprobe -v quiet -show_format output.ts | findstr "start_time duration"
start_time=121.399000
duration=10.134333
4.6 视频文件的音视频流提取
4.6.1 提前AAC音频流
ffmpeg -i input.mp4 -vn -acodec copy output.aac
4.6.2 提取H.264视频流
ffmpeg -i input.mp4 -vcodec copy -an output.h264
注意:input.mp4里面的视频流必须是H.264格式才能这样做
4.6.3 提取H.265视频流
ffmpeg -i input.mp4 -vcodec copy -an -bsf hevc_mp4toannexb -f hevc output.hevc
注意:input.mp4里面的视频流必须是H.265格式才能这样做, 另,最新ffmpeg中,不需要加 -bsf hevc_mp4toannexb 参数,内部会自动处理,将长度头转换成起始码头
4.7 系统资源使用情况
注意:
ffmpeg -re -i input.mp4 -c copy -f mpegts output.ts 不涉及转码,只涉及转封装
比命令
ffmpeg -re -i input.mp4 -vcodec libx264 -acodec copy -f mpegts output.ts 既转码又转封装
的负载要轻,后条命令需要大量的转码计算。
第5章 编码与转码
5.1 软编码 H.264
ffmpeg -h encoder=libx264 查看libx264编码的使用说明
附:
x264 window bin 下载地址
x265 window bin 下载地址
5.1.2 H.264编码举例
1. 编码器预设参数设置
x264 --fullhelp 查看preset参数包含的集中预设参数
- ultrafast 最开的编码方式
- superfast 超级快的编码方式
- veryfast 非常快的编码方式
- faster
- fast
- medium
- slow
- slower
- veryslow
- placebo
查看help中关于preset的参数
- ultrafast:
--no-8x8dct --aq-mode 0 --b-adapt 0
--bframes 0 --no-cabac --no-deblock
--no-mbtree --me dia --no-mixed-refs
--partitions none --rc-lookahead 0 --ref 1
--scenecut 0 --subme 0 --trellis 0
--no-weightb --weightp 0
- superfast:
--no-mbtree --me dia --no-mixed-refs
--partitions i8x8,i4x4 --rc-lookahead 0
--ref 1 --subme 1 --trellis 0 --weightp 1
- veryfast:
--no-mixed-refs --rc-lookahead 10
--ref 1 --subme 2 --trellis 0 --weightp 1
- faster:
--no-mixed-refs --rc-lookahead 20
--ref 2 --subme 4 --weightp 1
- fast:
--rc-lookahead 30 --ref 2 --subme 6
--weightp 1
- medium:
Default settings apply.
- slow:
--direct auto --rc-lookahead 50 --ref 5
--subme 8 --trellis 2
- slower:
--b-adapt 2 --direct auto --me umh
--partitions all --rc-lookahead 60
--ref 8 --subme 9 --trellis 2
- veryslow:
--b-adapt 2 --bframes 8 --direct auto
--me umh --merange 24 --partitions all
--ref 16 --subme 10 --trellis 2
--rc-lookahead 60
- placebo:
--bframes 16 --b-adapt 2 --direct auto
--slow-firstpass --no-fast-pskip
--me tesa --merange 24 --partitions all
--rc-lookahead 60 --ref 16 --subme 11
--trellis 2
随后分别测试 ultrafast和medium级别的转码速度
ffmpeg -i input.mp4 -c:v libx264 -preset ultrafast -b:v 2000k output_ultrafast.mp4
转码速度约为10.1倍速
frame= 1122 fps=304 q=-1.0 Lsize= 10989kB time=00:00:37.36 bitrate=2409.1kbits/s speed=10.1x
video:10369kB audio:587kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.294363%
[libx264 @ 0000028a77241340] frame I:5 Avg QP:19.80 size: 33589
[libx264 @ 0000028a77241340] frame P:1117 Avg QP:21.62 size: 9355
[libx264 @ 0000028a77241340] mb I I16..4: 100.0% 0.0% 0.0%
[libx264 @ 0000028a77241340] mb P I16..4: 4.5% 0.0% 0.0% P16..4: 22.2% 0.0% 0.0% 0.0% 0.0% skip:73.4%
[libx264 @ 0000028a77241340] final ratefactor: 25.50
[libx264 @ 0000028a77241340] coded y,uvDC,uvAC intra: 46.1% 26.5% 5.1% inter: 12.1% 4.1% 0.1%
[libx264 @ 0000028a77241340] i16 v,h,dc,p: 47% 26% 11% 16%
[libx264 @ 0000028a77241340] i8c dc,h,v,p: 56% 20% 18% 5%
[libx264 @ 0000028a77241340] kb/s:2271.13
[aac @ 0000028a771003c0] Qavg: 1228.998
再测试 medium基本的转码,转码速度约为2.43倍速
ffmpeg -i input.mp4 -c:v libx264 -preset medium -b:v 2000k output_medium.mp4
frame= 1122 fps= 73 q=-1.0 Lsize= 11075kB time=00:00:37.30 bitrate=2432.4kbits/s speed=2.43x
video:10447kB audio:587kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.368136%
[libx264 @ 0000021dc16a1740] frame I:36 Avg QP: 4.22 size: 43106
[libx264 @ 0000021dc16a1740] frame P:343 Avg QP: 6.77 size: 17844
[libx264 @ 0000021dc16a1740] frame B:743 Avg QP:10.07 size: 4071
[libx264 @ 0000021dc16a1740] consecutive B-frames: 5.1% 15.7% 12.6% 66.7%
[libx264 @ 0000021dc16a1740] mb I I16..4: 62.8% 18.4% 18.8%
[libx264 @ 0000021dc16a1740] mb P I16..4: 2.0% 5.4% 3.6% P16..4: 13.4% 8.2% 6.0% 0.0% 0.0% skip:61.5%
[libx264 @ 0000021dc16a1740] mb B I16..4: 0.1% 0.5% 0.5% B16..8: 12.4% 3.9% 1.5% direct: 1.3% skip:79.8% L0:49.7% L1:37.7% BI:12.5%
[libx264 @ 0000021dc16a1740] final ratefactor: 12.31
[libx264 @ 0000021dc16a1740] 8x8 transform intra:35.5% inter:49.4%
[libx264 @ 0000021dc16a1740] coded y,uvDC,uvAC intra: 58.3% 38.9% 24.9% inter: 8.1% 3.3% 1.1%
[libx264 @ 0000021dc16a1740] i16 v,h,dc,p: 81% 10% 4% 5%
[libx264 @ 0000021dc16a1740] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 39% 19% 11% 4% 4% 6% 5% 7% 6%
[libx264 @ 0000021dc16a1740] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 32% 24% 10% 5% 6% 6% 6% 6% 5%
[libx264 @ 0000021dc16a1740] i8c dc,h,v,p: 68% 16% 14% 3%
[libx264 @ 0000021dc16a1740] Weighted P-Frames: Y:2.9% UV:1.5%
[libx264 @ 0000021dc16a1740] ref P L0: 65.9% 9.7% 15.8% 8.5% 0.1%
[libx264 @ 0000021dc16a1740] ref B L0: 84.2% 13.1% 2.7%
[libx264 @ 0000021dc16a1740] ref B L1: 98.2% 1.8%
[libx264 @ 0000021dc16a1740] kb/s:2288.19
[aac @ 0000021dbf7ab280] Qavg: 1228.998
对比生成的转码文件,medium比ultrafast的画质会稍微好点
由于原始视频画质太差,好的不太明显
2. H.264编码优化
除了preset参数,还有 tune 参数,即
film 用于高质量的电脑内容,使用低强度的deblocking
animation 用于动画片,使用高强度的deblocking和更多的参考帧
grain 保留老的,有颗粒的电影素材中的颗粒结构
stillimage 适用于类似幻灯片这种变换较慢的内容
psnr
ssim
fastdecode 允许通过禁止某些过滤器、CABAC等来加速解码
zerolatency 适用于快速编码和低延时流媒体。
- film (psy tuning):
--deblock -1:-1 --psy-rd <unset>:0.15
- animation (psy tuning):
--bframes {+2} --deblock 1:1
--psy-rd 0.4:<unset> --aq-strength 0.6
--ref {Double if >1 else 1}
- grain (psy tuning):
--aq-strength 0.5 --no-dct-decimate
--deadzone-inter 6 --deadzone-intra 6
--deblock -2:-2 --ipratio 1.1
--pbratio 1.1 --psy-rd <unset>:0.25
--qcomp 0.8
- stillimage (psy tuning):
--aq-strength 1.2 --deblock -3:-3
--psy-rd 2.0:0.7
- psnr (psy tuning):
--aq-mode 0 --no-psy
- ssim (psy tuning):
--aq-mode 2 --no-psy
- fastdecode:
--no-cabac --no-deblock --no-weightb
--weightp 0
- zerolatency:
--bframes 0 --force-cfr --no-mbtree
--sync-lookahead 0 --sliced-threads
--rc-lookahead 0
3. H.264的profile和level设置
profile涉及的编码参数为
- baseline:
--no-8x8dct --bframes 0 --no-cabac
--cqm flat --weightp 0
No interlaced.
No lossless.
- main:
--no-8x8dct --cqm flat
No lossless.
- high:
No lossless.
- high10:
No lossless.
Support for bit depth 8-10.
- high422:
No lossless.
Support for bit depth 8-10.
Support for 4:2:0/4:2:2 chroma subsampling.
- high444:
Support for bit depth 8-10.
Support for 4:2:0/4:2:2/4:4:4 chroma subsampling.
ffmpeg -i input.mp4 -c:v libx264 -profile:v baseline -level 3.1 output_baseline.ts
ffmpeg -i input.mp4 -c:v libx264 -profile:v high -level 3.1 output_high.ts
查看两次生成的码流的B帧情况
统计码流B帧数量
D:\_Video>ffprobe -v quiet -show_frames -select_streams v output_baseline.ts | findstr "pict_type=B" | find /c /v ""
0
D:\_Video>ffprobe -v quiet -show_frames -select_streams v output_high.ts | findstr "pict_type=B" | find /c /v ""
743
4. 控制场景切换时关键帧的插入
ffmpeg -i input.mp4 -c:v libx264 -g 50 -t 60 output.mp4
ffmpeg -i input.mp4 -c:v libx264 -g 50 -sc_threshold 0 -t 60 -y output2.mp4
查看I帧间隔信息
D:\_Video>ffprobe -v quiet -select_streams v -show_packets -i output.mp4 | findstr /N "K__"
12:flags=K__
272:flags=K__
610:flags=K__
1143:flags=K__
1351:flags=K_
...
D:\_Video>ffprobe -v quiet -select_streams v -show_packets -i output2.mp4 | findstr /N "K__"
12:flags=K__
662:flags=K__
1312:flags=K__
1962:flags=K__
2612:flags=K__
3262:flags=K__
可以看出,后者生成的码流的I帧间隔更均匀,每隔 650/13=50帧出现一个I帧
因为前者遇到场景切换时会自动插入IDR帧,后者的 sc_threshold 0 关闭了场景切换判定
13的来由,每个PACKET的信息占13行
[PACKET]
codec_type=video
stream_index=0
pts=0
pts_time=0.000000
dts=-1024
dts_time=-0.066667
duration=512
duration_time=0.033333
size=8368
pos=48
flags=K__
[/PACKET]
[PACKET]
codec_type=video
stream_index=0
pts=512
pts_time=0.033333
dts=-512
dts_time=-0.033333
duration=512
duration_time=0.033333
size=268
pos=8416
flags=___
[/PACKET]
5. 设置x264内部参数
ffmpeg -i input.mp4 -vframes 500 -c:v libx264 -x264-params “bframes=0” -g 50 -sc_threshold 0 output_nb.mp4
转码过程中,可以看到没有生成B帧
[libx264 @ 00000244b9931740] frame I:10 Avg QP:14.86 size: 11698
[libx264 @ 00000244b9931740] frame P:490 Avg QP:21.12 size: 2144
[libx264 @ 00000244b9931740] mb I I16..4: 62.9% 28.4% 8.7%
[libx264 @ 00000244b9931740] mb P I16..4: 2.0% 3.6% 0.6% P16..4: 11.3% 1.9% 0.6% 0.0% 0.0% skip:79.9%
[libx264 @ 00000244b9931740] 8x8 transform intra:50.5% inter:81.2%
ffmpeg -i input.mp4 -vframes 500 -c:v libx264 -x264-params “bframes=3:b-adapt=0” -g 20 -sc_threshold 0 output_b.mp4
6. CBR设置
ffmpeg -i input.mp4 -an -c:v libx264 -x264opts “nal-hrd=cbr:force-cfr=1” -b:v 5M -maxrate 5M -minrate 5M -bufsize 5M -muxrate 5.5M output-cbr.ts
转码过程的log信息如下:
frame= 1122 fps= 60 q=-1.0 Lsize= 25092kB time=00:00:37.30 bitrate=5510.9kbits/s speed= 2x
video:22785kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 10.129636%
[libx264 @ 00000225840d03c0] frame I:36 Avg QP: 1.25 size: 69722
[libx264 @ 00000225840d03c0] frame P:343 Avg QP: 3.03 size: 34462
[libx264 @ 00000225840d03c0] frame B:743 Avg QP: 5.29 size: 12114
[libx264 @ 00000225840d03c0] consecutive B-frames: 5.1% 15.7% 12.6% 66.7%
[libx264 @ 00000225840d03c0] mb I I16..4: 64.4% 11.4% 24.1%
[libx264 @ 00000225840d03c0] mb P I16..4: 2.2% 4.2% 5.3% P16..4: 14.3% 7.7% 6.6% 0.0% 0.0% skip:59.7%
[libx264 @ 00000225840d03c0] mb B I16..4: 0.1% 0.5% 0.7% B16..8: 11.9% 4.1% 2.1% direct: 2.7% skip:78.0% L0:49.7% L1:37.5% BI:12.8%
[libx264 @ 00000225840d03c0] 8x8 transform intra:25.9% inter:35.0%
[libx264 @ 00000225840d03c0] coded y,uvDC,uvAC intra: 63.0% 42.9% 33.9% inter: 12.2% 5.2% 3.4%
[libx264 @ 00000225840d03c0] i16 v,h,dc,p: 82% 10% 5% 3%
[libx264 @ 00000225840d03c0] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 40% 18% 11% 4% 4% 6% 5% 7% 6%
[libx264 @ 00000225840d03c0] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 35% 24% 9% 5% 6% 6% 5% 6% 5%
[libx264 @ 00000225840d03c0] i8c dc,h,v,p: 67% 16% 14% 3%
[libx264 @ 00000225840d03c0] Weighted P-Frames: Y:2.9% UV:1.5%
[libx264 @ 00000225840d03c0] ref P L0: 66.3% 8.9% 15.6% 9.1% 0.1%
[libx264 @ 00000225840d03c0] ref B L0: 82.9% 14.1% 3.0%
[libx264 @ 00000225840d03c0] ref B L1: 98.1% 1.9%
[libx264 @ 00000225840d03c0] kb/s:4990.66
使用MediaInfo查看信息如下:
5.2 硬件加速
ffmpeg -hwaccels 查询的结果如下:
Hardware acceleration methods:
cuda
dxva2
qsv
d3d11va
opencl
vulkan
5.2.1 基于OS的硬件加速方案简介
- Windows: Direct3D 及 DirectShow系列
AMD AMF:
ffmpeg -hwaccel dxva2 -hwaccel_output_format dxva_vld -i input.mp4 -c:v h264_amf -b:v 2M -y out_dxva2.mp4
ffmpeg -hwaccel d3d11va -hwaccel_output_format d3d11 -i input.mp4 -c:v h264_amf -b:v 2M -y out_d3d11va.mp4
Intel QSV:
ffmpeg -hwaccel dxva2 -hwaccel_output_format dxva2_vld -i input.mp4 -c:v h264_qsv -vf hwmap=derive_device=qsv,format=qsv -b:v 2M -y out.mp4
ffmpeg -hwaccel d3d11va -hwaccel_output_format d3d11 -i input.mp4 -c:v h264_qsv -vf hwmap=derive_device=qsv,format=qsv -b:v 2M -y out.mp4
分别有如下报错:
[h264 @ 000001e916abb1c0] Failed setup for format dxva2_vld: hwaccel initialisation returned error.
[AVHWFramesContext @ 000001e916b222c0] The hardware pixel format 'qsv' is not supported by the device type 'DXVA2'
[h264 @ 000001e8134176c0] Failed setup for format d3d11: hwaccel initialisation returned error.
[AVHWFramesContext @ 000001e818334980] The hardware pixel format 'qsv' is not supported by the device type 'D3D11VA'
NVIDIA NVENC:
ffmpeg -hwaccel d3d11va -hwaccel_output_format d3d11 -i input.mp4 -c:v h264_nvenc -b:v 2M -y out.mp4
有如下报错:
[h264 @ 00000279f93ec780] Failed setup for format d3d11: hwaccel initialisation returned error.
[h264_nvenc @ 00000279f942e740] Driver does not support the required nvenc API version. Required: 12.0 Found: 11.1
[h264_nvenc @ 00000279f942e740] The minimum required Nvidia driver for nvenc is 522.25 or newer
升级最新的NVDIA驱动后,
[h264 @ 000001e68184ca80] Failed setup for format d3d11: hwaccel initialisation returned error.
[h264_nvenc @ 000001e68188e740] OpenEncodeSessionEx failed: no encode device (1): (no details)
调整input.mp4的profile为baseline也是类似的报错
2. Linux: VDPAU/VAAPI/V4L2 及 M2M
VDPAU: Video Decode and Presentation API for Unix
VAAPI: Video Acceleration API (Intel)
M2M: Memory to Memory
3. macOS/iOS: VideoToolbox
ffmpeg -hwaccel videotoolbox -i input.mp4 -f null - // 待验证
4. Android MediaCodec
Android API 16, 支持 Java MediaCodec
Android API 21, 支持 Native MediaCodec
FFmpeg 3.1, 增加 Android MediaCodec的硬件解码支持,实现了FFmpeg的 HWaccel接口,但至今未支持MediaCodec的硬件编码。
5.2.2 NVIDIA GPU 硬编解码
ffmpeg -h encoder=h264_nvenc
ffmpeg -h decoder=h264_cuvid
ffmpeg -hwaccel cuvid -vcodec h264_cuvid -i input.mp4 -vf scale=1920:1080 -vcodec h264_nvenc -acodec copy -f mp4 -y output.mp4
本人PC版本为windows 10, GPU显卡为 NVIDIA GeForce 940MX
查看NVIDIA官网,可知此款GPU支持NVENC和NVDEC
但是使用了如上命令,还是会报错,不支持 h264_cuvid
[h264_cuvid @ 000001e4a3488480] Codec h264_cuvid is not supported.
尚不知如何使能?
5.2.3 Intel QSV硬编解码
ffmpeg -hide_banner -codecs | findstr h264
ffmpeg -h encoder=h264_qsv
ffmpeg -h decoder=h264_qsv
ffmpeg -i input.mp4 -pix_fmt nv12 -vcodec h264_qsv -an -y output.mp4
有报错:
[h264_qsv @ 000001aa26b3e840] Error creating a MFX session: -9.
[vost#0:0/h264_qsv @ 000001aa26b3e540] Error initializing output stream: Error while opening encoder for output stream #0:0 - maybe incorrect parameters such as bit_rate, rate, width or height
Conversion failed!
ffmpeg -hide_banner -y -hwaccel qsv -i input.mp4 -an -c:v hevc_qsv -load_plugin hevc_hw -b:v 5M -maxrate 1M out.mp4
有报错:
[AVHWDeviceContext @ 0000018dac1cf100] Error creating a MFX session: -9.
Device creation failed: -1313558101.
No device available for decoder: device type qsv needed for codec h264_qsv.
Stream mapping:
Stream #0:0 -> #0:0 (h264 (h264_qsv) -> hevc (hevc_qsv))
Device setup failed for decoder on input stream #0:0 : Unknown error occurred
5.2.4 Raspberry Pi 硬编解码
ffmpeg -h encoder=h264_omx
ffmpeg -i input.mp4 -vcodec h264_omx -b:v 500k -acodec copy -y output.mp4
以上命令未验证
5.2.5 macOS系统硬编解码
ffmpeg -h encoder=h264_videotoolbox
ffmpeg -hwaccel videotoolbox -hwaccel_output_format videotoolbox_vld -i input.mp4 -b:v 2000k -vcodec hevc_videotoolbox -vtag hvc1 -acodec copy output.mp4
5.3 输出MP3
ffmpeg -h encoder=libmp3lame
ffmpeg -i input.mp4 -acodec libmp3lame output.mp3
ffmpeg -i input.mp4 -acodec libmp3lame -q:a 8 output_q8.mp3
ffmpeg -i input.mp4 -acodec libmp3lame -b:a 64k output_64k.mp3
ffmpeg -i input.mp4 -acodec libmp3lame -b:a 64k -abr 1 output_64k_abr.mp3
5.4 输出AAC
新版本的libfaac已经被删除
5.4.1 AAC编码器操作
ffmpeg -i input.mp4 -c:a aac -b:a 160k output.aac
ffmpeg -i input.mp4 -vn -c:a aac -q:a 2 output.m4a
5.4.2 FDK-AAC
- CBR模式
ffmpeg -i input.mp4 -c:a libfdk_aac -b:a 128k output_128k.m4a
ffmpeg -i input.mp4 -c:v copy -c:a libfdk_aac -b:a 384k output_384k.m4a - VBR模式
ffmpeg -i input.mp4 -c:a libfdk_aac -vbr 3 output.m4a
5.4.3 高质量AAC设置
ffmpeg -i input.wav -c:a libfdk_aac -profile:a aac_he -b:a 64k output_he_64k.m4a
ffmpeg -i input.wav -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k output_he_v2_32k.m4a
5.5 系统资源使用情况
ffmpeg -re -i input.mp4 -vcodec libx264 -an output.mp4
第6章 流媒体技术
6.1 录制与发布RTMP流
RTMP直播流的URL格式:
rtmp://[username:password@]server[:port][/app][/instance][/playpath]
如: rtmp://127.0.0.1/telvue-rtmp/fmle
rtmp:// 代表 协议
127.0.0.1 代表RTMP的源地址
telvue-rtmp 代表应用名称
fmle 代表流名称
-
rtmp_app参数
ffmpeg -rtmp_app live -i rtmp://publish.chinaffmpeg.com -c copy -f flv output.flv
此chinaffmpeg的源站不可用
可用的RTMP源站有
伊拉克 Al Sharqiya 电视台(20250203)——rtmp://ns8.indexforce.com/home/mystream
使用如下命令拉流并转换(加不加 -rtmp_app home 效果一样)
ffmpeg -rtmp_app home -i rtmp://ns8.indexforce.com/home/mystream -c copy -f flv output.flv
ffmpeg -re -i input.mp4 -c copy -f flv -rtmp_app live rtmp://publish.chinaffmpeg.com
有报错,找不到对应的rtmp server
ffmpeg -re -i input.mp4 -c copy -f flv -rtmp_app home rtmp://ns8.indexforce.com/home/mystream
有报错,
-
rtmp_playpath参数
ffmpeg -re -i input.mp4 -c copy -f flv -rtmp_app home -rtmp_playpath class rtmp://ns8.indexforce.com/home/mystream
ffmpeg -rtmp_app home -rtmp_playpath class -i rtmp://ns8.indexforce.com/home/mystream -c copy -f flv output.flv
3.rtmp_pageurl、rtmp_swfurl、rtmp_tcurl 参数
ffmpeg -rtmp_pageurl “http://www.chinaffmpeg.org” -i rtmp://publish.chinaffmpeg.com/live/class
6.2 录制与发布RTSP流
ffmpeg -h demuxer=rtsp
测试之前,可以搭建一个简单的RTSP服务器,
- 登陆RTSP网址
- 找到并点击 Start for free
- 点击后输入邮箱,会接收到一个URL,点击后有若干可以测试的RTSP流
ffmpeg -rtsp_transport tcp -i rtsp://rtspstream:zkv9G_GWKPOucjzi_8VkI@zephyr.rtsp.stream/movie -c copy -f mp4 output.mp4
使用TCP方式代替UDP方式来拉流
ffmpeg -user_agent “FFmpeg-Test” -i rtsp://rtspstream:zkv9G_GWKPOucjzi_8VkI@zephyr.rtsp.stream/movie -c copy -f mp4 output2.mp4
拉流时设置User-Agent 参数
ffplay -max_delay 500000 -rtsp_transport udp -i rtsp://rtspstream:zkv9G_GWKPOucjzi_8VkI@zephyr.rtsp.stream/movie
设置最大延迟时间
ffmpeg -rtsp_flags listen -i rtsp://rtspstream:zkv9G_GWKPOucjzi_8VkI@zephyr.rtsp.stream/movie test.flv
设置被动接受RTSP流时,有如下报错:
[rtsp @ 0000024ecdf98ac0] Unable to open RTSP for listening
rtsp://rtspstream:zkv9G_GWKPOucjzi_8VkI@zephyr.rtsp.stream/movie: Error number -10049 occurred
6.3 录制HTTP流
ffmpeg -h protocol=http 查看帮助
参考此篇文章 搭建 Nginx 流媒体服务器
- seekable参数举例
ffmpeg -ss 10 -seekable 0 -i http://localhost:8080/input.mp4 -c copy -y output_noseek.mp4
ffmpeg -ss 10 -seekable 1 -i http://localhost:8080/input.mp4 -c copy -y output_seek.mp4
实操发现,不论seekable 设置为0还是1,都不会阻塞 - headers参数举例
ffmpeg -headers “refer: http://localhost:8080/” -i http://localhost:8080/input.mp4 -c copy -f flv output.flv - user_agent参数设置
ffmpeg -user_agent “Demo player” -i http://localhost:8080/input.mp4 - HTTP拉流录制
ffmpeg -i http://localhost:8080/input.mp4 -c copy -f flv output.flv 类似本地码流转码过程
6.4 录制和发布 UDP/TCP流
ffmpeg -h protocol=udp
ffmpeg -h protocol=tcp
没有搭建tcp/udp服务器,以下命令没有经过检验
ffmpeg -listen 1 -f flv -i tcp://127.0.0.1:1234/live/stream -c coy -f flv output.flv
ffmpeg -re -i input.mp4 -c copy -f flv tcp://127.0.0.1:1234/liv/stream
time ffmpeg -listen_timeout 5000 -listen 1 -f flv -i tcp://127.0.0.1:1234/live/stream -c copy -f flv output.flv
time ffmpeg -timeout 20000000 -i tcp://127.0.0.1:1234/live/stream -c copy -f flv output.flv
ffmpeg -re -i input.mp4 -c copy -send_buffer_size 256 -f flv tcp://192.168.100.179:1234/live/stream
ffmpeg -re -i input.mp4 -c copy -localport 23456 -f flv udp://192.168.100.179:1234/live/stream
6.5 多路流输出
6.5.1 管道方式输出多路流
ffmpeg -i input.mp4 -acodec aac -vcodec libx264 -f flv - | ffmpeg -f flv -i - -c copy output1.flv -c copy output2.flv -c copy output3.flv
其中 - 代表标准输出,通过管道传递给了下一条ffmpeg的命令,另一条对codec的copy可以实现一次编码,多路输出
一般用于推流至不同的url,如
ffmpeg -i input.mp4 -acodec aac -vcodec libx264 -f flv - | ffmpeg -f flv -i - -c copy -f flv rtmp://xxx/live/stream1 -c copy -f flv rtmp://xxx/live/stream2 -c copy -f flv rtmp://xxx/live/stream2
6.5.2 tee封装格式输出
ffmpeg -i input.mp4 -acodec aac -vcodec libx264 -map 0 -f tee “[f=flv]output1.flv | [f=flv]output2.flv”
注意 [f=flv] 与 output.flv之间不能有空格
6.5.3 tee协议输出多路流
ffmpeg -i input.mp4 -vcodec copy -acodec aac -f flv “tee:output3.flv|output4.flv”
一般用于多路推流,将output.flv更改为 rtmp的推流url
6.6 DASH流输出
ffmpeg -h muxer=dash
ffmpeg -i input.mp4 -c copy -f dash -window_size 4 -extra_window_size 5 index.mpd
文件列表长度为4个切片,切片之外保留5个切片,DASH直播格式中,音视频是分开的,也就是说,音视频各有9个切片
但是生成的切片,视频6个,音频8个,生成的文件如下:
chunk-stream0-00001.m4s
chunk-stream0-00002.m4s
chunk-stream0-00003.m4s
chunk-stream0-00004.m4s
chunk-stream0-00005.m4s
chunk-stream0-00006.m4s
chunk-stream1-00001.m4s
chunk-stream1-00002.m4s
chunk-stream1-00003.m4s
chunk-stream1-00004.m4s
chunk-stream1-00005.m4s
chunk-stream1-00006.m4s
chunk-stream1-00007.m4s
chunk-stream1-00008.m4s
init-stream0.m4s
init-stream1.m4s
index.mpd
也可以将切片列表中的文件写入到一个文件中,使用single_file参数,如下:
ffmpeg -i input.mp4 -c copy -f dash -window_size 4 -extra_window_size 5 -single_file 1 index2.mpd
生成的文件如下:
index2-stream0.mp4
index2-stream1.mp4
index2.mpd
6.7 HDS流输出
HDS: HTTP Dynamic Streaming
ffmpeg -h muxer=hds
ffmpeg -i input.mp4 -c copy -f hds -window_size 4 output
生成文件列表如下:
其中, index.f4m 索引文件
stream0.abst 文件流相关描述信息
stream0Seg1-Frag1 文件切片,内部均为mdat数据
ffmpeg -i input.mp4 -c copy -f hds output
ffmpeg -i input.mp4 -c copy -f hds -window_size 4 -extra_window_size 1 output4_1
ffmpeg -i input.mp4 -c copy -f hds -window_size 4 -extra_window_size 5 output4_5
实测发现 window_size 与 extra_window_size 设置与否,区别不大
第7章 bitstream 过滤器
几个概念
libavcodec中的parser: 接受一串输入数据并将其分割成完整的压缩帧,不丢弃任何数据或增加任何数据,其作用为解析码流,确定数据包边界;
libavcodec中的bitstream: 允许修改数据,但是不涉及压缩的数据,可以和 -c copy 一起使用
libavfilter中的 filter: 主要用于处理 YUV/PCM数据,不允许和 -c copy 一起使用
7.1 aac_adtstoasc 过滤器
ADTS: Audio Data Transport Stream 一般用于直播流,定于在ISO-13318-7的MPEG2中,每一帧前面都包含了ADTS头信息,可以从任意一帧开始解码,一般用于裸ADTS封装中;
ASC: Audio Special Config 通常存储于MP4格式中,全局头部有一个配置,比ADTS更省空间,一般使用 LATM (Low-overhead Audio TransportMultiplex 低开销音频传输服用通路)格式的封装,其核心是 MPEG-4 Audio Specific Config(ASC), ASC结构定义在 ISO-14496-3 Audio 中,一般存储在封装容器的独立模块中,作为AAC全局元数据。如FLV的第一个音频Tag中包含ASC, MP4的 ESDS(Element Stream Descriptors) box也包含 ASC。
ASC与ADTS之间的转换,主要靠 aac_adtstoasc 来晚餐
7.2 mp4toannexb 过滤器
AAV/HEVC/VVC的编码数据存储方式有二:
- 标准协议Annex B的存储格式,即起始码加数据的格式
此格式主要用于实时传输流,如 MPEG-TS - MP4方式的存储格式,即 AVCConfiguration格式
此格式主要用于点播MP4/AVCC中
h264_mp4toannexb/hevc_mp4toannexb用于两种格式之间的转换。
旧版本的ffmpeg转换时需要手动调用这些bsf;
新版本的ffmpeg将mp4toannexb相关的bsf集成到将视频数据写入文件的过程中;
ffmpeg -i input.mp4 -c copy -bsf:v h264_mp4toannexb -v verbose output.h264
转码过程输出信息如下:
EOF in input file 0 q=-1.0 size= 0kB time=-00:00:00.06 bitrate= -0.0kbits/s speed=N/A
No more output streams to write to, finishing.
[out#0/h264 @ 000002518acc7600] All streams finished
Terminating demuxer thread 0
[out#0/h264 @ 000002518acc7600] Terminating muxer thread
[AVIOContext @ 000002518cbbe440] Statistics: 3614162 bytes written, 0 seeks, 14 writeouts
frame= 1122 fps=0.0 q=-1.0 Lsize= 3529kB time=00:00:37.30 bitrate= 775.2kbits/s speed= 733x
video:3529kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.000000%
Input file #0 (input.mp4):
Input stream #0:0 (video): 1122 packets read (3613522 bytes);
Input stream #0:1 (audio): 1 packets read (364 bytes);
Total: 1123 packets (3613886 bytes) demuxed
Output file #0 (output.h264):
Output stream #0:0 (video): 1122 packets muxed (3614162 bytes);
Total: 1122 packets (3614162 bytes) muxed
[AVIOContext @ 000002518aca4940] Statistics: 4240002 bytes read, 0 seeks
ffmpeg -i input.mp4 -c copy -v verbose output.h264
转码过程输出信息如下:
Press [q] to stop, [?] for help
Automatically inserted bitstream filter 'h264_mp4toannexb'; args=''e= -0.0kbits/s speed=N/A
EOF in input file 0
Terminating demuxer thread 0
No more output streams to write to, finishing.
[out#0/h264 @ 000001b64c24ff00] All streams finished
[out#0/h264 @ 000001b64c24ff00] Terminating muxer thread
[AVIOContext @ 000001b64c9feb00] Statistics: 3614162 bytes written, 0 seeks, 14 writeouts
frame= 1122 fps=0.0 q=-1.0 Lsize= 3529kB time=00:00:37.30 bitrate= 775.2kbits/s speed= 939x
video:3529kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.017711%
Input file #0 (input.mp4):
Input stream #0:0 (video): 1122 packets read (3613522 bytes);
Input stream #0:1 (audio): 1 packets read (364 bytes);
Total: 1123 packets (3613886 bytes) demuxed
Output file #0 (output.h264):
Output stream #0:0 (video): 1122 packets muxed (3613522 bytes);
Total: 1122 packets (3613522 bytes) muxed
[AVIOContext @ 000001b64c244880] Statistics: 4240002 bytes read, 0 seeks
后者(不加 -bsf:v h264_mp4toannexb)相比前者,增加了 一条信息:
Automatically inserted bitstream filter ‘h264_mp4toannexb’; args=’
7.3 h264_metadata 过滤器
此bsf会在H.264视频流中嵌入metadata信息,如增加SEI信息,插入或删除AUD标签,处理显示方向等。
ffmpeg -h bsf=h264_metadata
- aud参数
ffmpeg -i input.h264 -vcodec libx264 -r:v 5 -t 1 -bsf:v h264_metadata=aud=1 output_insert.h264
ffmpeg -i input.h264 -vcodec libx264 -r:v 5 -t 1 -bsf:v h264_metadata=aud=2 output_remove.h264
对比二者生成结果, 左侧新增了 AUD NAL
- sample_aspect_ratio 采样宽高比参数
ffmpeg -i input.h264 -vcodec libx264 -r:v 5 -t 1 -bsf:v h264_metadata=sample_aspect_ratio=16/9 output.h264
转换前后对比
- video_format 视频制式参数
参考H.264标准附录表E-2,可知video_format的值与含义如下
ffmpeg -i input.h264 -vcodec libx264 -t 1 -bsf:v h264_metadata=video_format=2 output_format_2.h264
- colour_primaries 参数
ffmpeg -i input.mp4 -c copy -bsf:v h264_metadata=colour_primaries=4 output_primaries_4.mp4
使用ffprobe查看输出文件,可知生效
- sei_user_data SEI 数据参数
sei_user_data 可以设置用户自定义的SEI数据,使用方法比较简单,通过UUID加字符串的方式即可。
ffmpeg -i input.mp4 -c copy -bsf:v h264_metadata=sei_user_data=31DA5C95-1F94-4DC2-89C2-AB65EDDE21BE+FFmpeg output_sei.h264
对比二进制流,添加成功
- crop_left, crop_right, crop_top和crop_bottom 剪切参数
ffmpeg -i input.h264 -c copy -bsf:v h264_metadata=crop_left=200 output_crop.h264
裁剪效果对比
7.3.3 其他Codec的metadata过滤器
ffmpeg -h bsf=hevc_metadata
ffmpeg -h bsf=av1_metadata
7.4 其他常用的bitstream过滤器
7.4.1 dump_extra
ffmpeg -f lavfi -i testsrc2=1280x720 -map 0 -flags:v +global_header -c:v libx264 -bf 0 -t 5 -y out_raw.h264
ffmpeg -f lavfi -i testsrc2=1280x720 -map 0 -flags:v +global_header -c:v libx264 -bsf:v dump_extra=freq=e -bf 0 -t 5 -y out.h264
对比两次生成结果,可知 dump_extra=freq=e 是将每个NAL前面都插入了XPS
dump_extra=freq=k 或 dump_extra=freq=keyframe 是在每个关键帧前面插入XPS
7.4.2 trace_headers (非常推荐)
dump每一个NAL的头信息,
ffmpeg -i input.mp4 -c copy -bsf:v trace_headers -y output.mp4 2> dump_trace_headers.txt
目前支持的格式如下:
7.4.3 filter_units
此bsf用于透传或者删除一些NALU信息
仅移除AUD NAL的命令
ffmpeg -i output_insert.h264 -c copy -bsf:v filter_units=remove_types=9 -y output_remove_9.h264
如下可以看出, 移除操作生效
移除NAL UNIT TYPE 为 1,2,3,9的NAL, 注意,此处必须用双引号括起来,单引号或者不加引号都不行
ffmpeg -i output_insert.h264 -c copy -bsf:v “filter_units=remove_types=1|2|3|9” -y output_remove_1239.h264
如下可以看出,移除生效。
-bsf:v “filter_units=remove_types=1|2|3|9” 也可以写成 -bsf:v “filter_units=remove_types=1-3|9”, 效果一样
ffmpeg -i output_insert.h264 -c copy -bsf:v “filter_units=remove_types=1-3|9” -y output_remove_1-39.h264
第8章 滤镜使用
8.1 滤镜表达式使用
FFmpeg通过 libavutil/eval.h实现了对算数表达式的支持,具备了初步的可编程能力,视为一个简单的领域特定语言(domain-specific language). 滤镜表达式中包含了常量,一元,二元和函数表达式,相关功能如下:
常量: PI 圆周率, E 自然对数底数,欧拉数, PHI 黄金分割率, 1.618
一元表达式: + 正号运算符 - 符号运算符
二元表达式: + - * / ^
关系表达式函数:
函数 | 功能说明(伪代码) |
---|---|
between(x, min, max) | min <= x <= max ? 1 : 0 |
eq(x, y) | x == y ? 1 : 0 |
gt(x, y) | x > y ? 1 : 0 |
gte(x, y) | x >= y ? 1 : 0 |
lt(x, y) | x < y ? 1 : 0 |
lte(x, y) | x <= y ? 1 : 0 |
max(x, y) | 返回x、y中较大的值 |
min(x, y) | 返回x、y中较小的值 |
数学表达式函数:
函数 | 功能说明(伪代码) |
---|---|
abs(x) | |
sin(x) | |
cos(x) | |
acos(x) | |
asin(x) | |
tan(x) | |
atan(x) | |
tanh(x) | 计算x的双曲线正切 |
sinh(x) | 计算x的双曲线正弦 |
cosh(x) | 计算x的双曲线余弦 |
atan2(x, y) | 计算坐标(x, y)的四象限反正切 |
bitand(x, y) | 计算(x, y)按位与的值 |
bitor(x, y) | 计算(x, y)按位或的值 |
exp(x) | 计算x的指数值,底为e |
gauss(x) | 计算x的高斯函数值 |
gcd(x, y) | 求x,y的最大公约数。如果x、y均为0或x、y中任意一个负数,则结果未定义 |
hypot(x, y) | 求x,y的平方和的平方根,即sqrt(xx, yy)。如点(x, y)到原点的距离 |
st(var, expr) | 保存expr的值到以var为索引的内部变量中,var取值范围为0~9 |
ld(var) | 返回使用st函数保存的索引为var的内部变量的值 |
root(expr, max) | 循环去ld(0)的值为参数计算expr的值,在0到max区间上返回表达式expr结果为0时ld(0)的值。 其中ld(0)的值在循环过程中通过给定的表达式变化,表达式expr必须是一个连续函数,否则结果不可预期 |
taylor(expr, x, id) | 以 ld(id) 为表达式expr在id处的导数y,计算表达式expr在x处的泰勒级数。 其中 id默认为0,如果非0则相当于 taylor(expr, x - y),如果级数不收敛,则结果不可预期 |
lerp(x, y, z) | 以z为单位,返回x和y之间的线性插值 |
log(x) | |
mod(x, y) | |
pow(x, y) | 计算x的y次幂 |
random(x) | 返回一个0.0到1.0之间的伪随机数,随机数种子/状态是以x为索引的内部变量 |
sgn(x) | 计算x的阶跃函数值 |
sqrt(expr) | 计算表达式expr结果的平方根 |
squish(x) | 计算表达式1/(1 + exp(4*x)) 的值 |
条件表达式函数:
函数 | 功能说明(伪代码) |
---|---|
while(cond, expr) | 当cond的值不为0时,循环计算expr的值,并返回最后一次expr的值。若cond的值一直为false,则返回NAN |
not(expr) | 表达式expr == 0 ? 1.0 : 0.0 |
if (x, y) | 表达式x的结果 != 0 ? y : 0 |
if (x, y, z) | 表达式x的结果 != 0 ? y : z |
ifnot (x, y) | 表达式x的结果 == 0 ? y : 0 |
ifnot (x, y, z) | 表达式x的结果 == 0 ? y : z 注意:书中此处有误,此处参考了ffmpeg的官方文档,此处我的解释是正确的 |
isinf (x) | 表达式x的结果为正/负无穷 ? 1.0 : 0.0 |
isnan (x) | 表达式x的结果不为数值 ? 1.0 : 0.0 |
eval表达式的官方链接
其他表达式函数:
函数 | 功能说明(伪代码) |
---|---|
ceil(expr) | 对表达式expr的结果向上取整 |
floor(expr) | 对表达式expr的结果向下取整 |
round(expr) | 对表达式expr的结果四舍五入取整 |
trunc(expr) | 对表达式expr的结果舍尾取整 |
clip(x, min, max) | x < min ? min : (x > max ? max : x) |
print(t) | 以日志形式打印t的值 |
FFmpeg的表达式可以由多个表达式通过分号组合成一个新的表达式:“exprt; expr2”, 新的表达式将会分别对 expr1, expr2 求值,并将 expr2 的结果作为新表达式的结果返回。
ffmpeg -f lavfi -i testsrc=s=1280x720:d=10 -vcodec libx264 -f mp4 -y input.mp4 生成一段10s 720P的测试码流
ffmpeg -i input.mp4 -filter_complex “color=c=black:s=1920x1080:d=5[v0];[0:v]format=rgba,colorchannelmixer=aa=0.5:enable=‘between(t,1,2)’, [v0]overlay=x=‘(main_w-overlay_w)/2’:y=‘(main_h-overlay_h)/2’[v1]” -map [v1] -t 5 -c:v libx264 -an between.mp4 将输入码流叠加到一张黑色的1920x1080的底板上,并且调节第1-2s时刻的颜色, input.mp4与处理后的between.mp4对比如下
ffmpeg -i input.mp4 -f image2 -vframes 1 -vf “select=(isnan(prev_selected_t)+gte(t-prev_selected_t,2)),tile=1x2” select.jpg
从第0帧开始,每隔2s选择一帧,由于tile filter的参数是1x2,故一共会选择两张,即0s, 2s位置的图片,实际效果如下
如果参数为 tile=1x3, 则选择0/2/4 位置的图
扩展,生成电影或电视剧的缩略图
ffmpeg -i SanGuo.mp4 -f image2 -vframes 1 -vf “select=(isnan(prev_selected_t)+gte(t-prev_selected_t,5)),tile=4x4,scale=1920:1080” Thumbnail.jpg
每隔5s取一帧图像,共取16帧,存放到一张图片中,Thumbnail的效果
(注意:如果视频较长,间隔时间较大,提取时间会比较慢,因为要一帧一帧解码过去)
8.2 滤镜描述格式
8.2.1 滤镜基本排列方式
[输入流或标记名]滤镜参数[临时标记名];[输入流或标记名]滤镜参数[临时标记名];…
ffmpeg -i input.mp4 -i logo.png -filter_complex “[1:v]scale=176:144[logo];[0:v][logo]overlay=x=0:y=0” output.mp4
8.2.2 时间内置变量
ffmpeg -h filter=xxx 查看xxx filter的使用说明时,如果尾部有如下描述,
This filter has support for timeline through the 'enable' option.
如 ffmpeg -h filter=colorchannelmixer
说明此FIlter可以使用时间相关的内置变量, 基本内置变量如下:
变量 | 说明 |
---|---|
t | 时间戳,以秒表示,如果输入时间戳是未知的,则为NAN |
n | 输入帧的顺序编号,从0开始 |
pos | 输入帧的位置,如果未知就是NAN,从0开始 |
w | 输入帧的宽度 |
h | 输入帧的高度 |
8.3 视频水印操作
ffmpeg -i input.mp4 -vf “drawtext=fontsize=100:fontfile=arial.ttf:text=‘hello world’:x=20:y=20” output.mp4
视频左上角添加文字水印,注意 字体文件必须位于当前目录下
ffmpeg -i input.mp4 -vf “drawtext=fontsize=100:fontfile=arial.ttf:text=‘hello world’:fontcolor=green” output_green.mp4
ffmpeg -i input.mp4 -vf “drawtext=fontsize=100:fontfile=arial.ttf:text=‘hello world’:fontcolor=green:box=1:boxcolor=yellow” output_green_yellow.mp4
以本地时间作为文字水印, windows上如下命令生效,(与书上命令不一致, 要对引号内部的冒号转义)
ffmpeg -i input.mp4 -vf "drawtext=fontsize=60:fontfile=arial.ttf:text='%{localtime\:%Y-%m-%d%H-%M-%S}':fontcolor=green:box=1:boxcolor=yellow" output_time.mp4
每3秒的前1s显示文字水印(与书上命令不一致,要对引号中的逗号转义)
ffmpeg -i input.mp4 -vf “drawtext=fontsize=60:fontfile=arial.ttf:text=‘test’:fontcolor=green:box=1:boxcolor=yellow:enable=lt(mod(t,3),1)” output_time_enable.mp4
显示汉字文字水印, 必须下载支持汉字的字符库,否则会是乱码
ffmpeg -i input.mp4 -vf “drawtext=fontsize=50:fontfile=msyh.ttc:text=‘文字水印测试’:fontcolor=green:box=1:boxcolor=yellow” output_word.mp4
也可以选择指定目录中的字体库,注意必须要对冒号和反斜杠做转义
ffplay -i input.mp4 -vf "drawtext=fontsize=50:fontfile='C\:\\Windows\\Fonts\\msyh.ttc':text='文字水印测试':fontcolor=green:box=1:boxcolor=yellow"
8.3.2 图片水印示例
ffmpeg -h filter=movie
logo.png 为透明logo
ffmpeg -i input.mp4 -vf “movie=logo.png[wm];[in][wm]overlay=30:10[out]” output.mp4
logo3.png 为不透明logo
ffmpeg -i input.mp4 -vf “movie=logo3.png[wm];[in][wm]overlay=30:10[out]” output3.mp4
ffmpeg -i input.mp4 -vf “movie=logo3.png,colorkey=black:0.5:1.0[wm];[in][wm]overlay=30:10[out]” output3_color.mp4
实际效果对比,实测如果colorkey的参数设置为1.0和1.0时,logo完全看不到
8.4 画中画效果
ffmpeg -i input.mp4 -vf “movie=input2.mp4,scale=480x320[test];[in][test]overlay[out]” -vcodec libx264 -f mp4 output_overlay.mp4
画中画位于右下角
ffmpeg -i input.mp4 -vf “movie=input2.mp4,scale=480x320[test];[in][test]overlay=x=main_w-480:y=main_h-320[out]” -vcodec libx264 -f mp4 output_overlay2.mp4
2s后画中画从左上角逐渐向右缓缓出现
ffmpeg -i input.mp4 -vf “movie=input2.mp4,scale=480x320[test];[in][test]overlay=x=‘if(gte(t,2),-w+(t-2)*20,NAN)’:y=0[out]” -vcodec libx264 -f mp4 output_overlay3.mp4
8.5 视频多宫格处理
ffmpeg -i input.mp4 -i input2.mp4 -i input2.mp4 -i input.mp4 -filter_complex "nullsrc=size=640x480[base];[0:v]setpts=PTS-STARTPTS,scale=320x240[upperleft];[1:v]setpts=PTS-STARTPTS,scale=320x240[upperright];[2:v]setpts=PTS-STARTPTS,scale=320x240[lowerleft];[3:v]setpts=PTS-STARTPTS,scale=320x240[lowerright];[base][upperleft]overlay=shortest=1[tmp1];[tmp1][upperright]overlay=shortest=1:x=320[tmp2];[tmp2][lowerleft]overlay=shortest=1:y=240[tmp3];[tmp3][lowerright]overlay=shortest=1:x=320:y=240" -c:v libx264 output_overlay_4.mp4
最终效果如下:
8.6 视频字幕操作
将字幕编码到图像中
ffmpeg -i input.mp4 -vf ass=t1.ass -f mp4 output_ass.mp4
将字幕内嵌到视频中,不改变编码结构
ffmpeg -i input.mp4 -i t1.ass -vcodec copy -acodec copy -scodec copy output_ass.mkv
使用input.mp4的音频流和视频流以及 t1.ass的字幕流,封装到文件中
ffmpeg -i input.mp4 -i t1.ass -map 0:0 -map 0:1 -map 1:0 -acodec copy -vcodec copy -scodec copy output.mkv
8.7 视频3D化处理
ffmpeg -h filter=stereo3d
并排显示视频
ffplay -vf “split=2[v1][v2],[v1][v2]hstack” input.mp4
生成并排的视频
ffmpeg -i input.mp4 -vf “split=2[v1][v2],[v1][v2]hstack” -vcodec libx264 -f mp4 output_3d.mp4
并排的视频(左右排列效果)合并为黄蓝并排列效果,注意sbs后面跟的字母是L,不是一
ffplay -vf “stereo3d=sbsl:aybd” output_3d.mp4
并排的视频(左右排列效果)合并为红蓝并排列效果
ffplay -vf “stereo3d=sbsl:arbg” output_3d.mp4
8.8 视频截图操作
8.8.1 vframes参数截取一张图片
ffmpeg -i SampleVideo_1280x720_10mb.mp4 -ss 00:00:7.435 -vframes 1 out.png
8.8.2 fps滤镜定时获取图片
每秒截取1张图
ffmpeg -i input.mp4 -vf fps=1 out%d.png
每秒截取1/60张图,即1分钟截取一张图
ffmpeg -i SanGuo.mp4 -vf fps=1/60 img%03d.jpg
每10min截取一张图
ffmpeg -i SanGuo.mp4 -vf fps=1/600 thumb%04d.bmp
按照关键帧截图
ffmpeg -i SanGuo.mp4 -vf “select=‘eq(pict_type,PICT_TYPE_I)’” -vsync vfr thumb%04d.png
8.9 音频流滤镜操作
8.9.1 双声道合并单声道
ffmpeg -i input.aac -ac 1 output.aac
8.9.2 双声道提取
普通提取,0.0.0 表示 file-0的 stream-0的 左声道,
ffmpeg -i input.aac -map_channel 0.0.0 left.aac -map_channel 0.0.1 right.aac
具体用法参见 ffmpeg -h full
的 帮助信息
-map_channel file.stream.channel[:syncfile.syncstream] map an audio channel from one stream to another
使用pan filter提取,具体可参考pan filter的用法
ffmpeg -i input.aac -filter_complex “[0:0]pan=1c|c0=c0[left];[0:0]pan=1c|c0=c1[right]” -map “[left]” left2.aac -map “[right]” right2.aac
8.9.3 双声道转双音频流
ffmpeg -i input.aac -filter_complex channelsplit=channel_layout=stereo output.mka
8.9.4 单声道转双声道
ffmpeg -i left.aac -ac 2 output.m4a
还可以用amerge filter来处理
ffmpeg -i left.aac -filter_complex “[0:a][0:a]amerge=inputs=2[aout]” -map “[aout]” output2.m4a
8.9.5 两个音频源合并双声道
ffmpeg -i left.aac -i right.aac -filter_complex “[0:a][1:a]amerge=inputs=2[aout]” -map “[aout]” output2.mka
8.9.6 多个音频合并为多声道
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
8.10 音频音量探测
8.10.1 获取音频音量
ffmpeg -i input.aac -filter_complex volumedetect -c:v copy -f null null
因为 volumedetect 是 audio filter, 所以此条命令也可以改写为
ffmpeg -i input.aac -af volumedetect -c:v copy -f null null
8.10.2 绘制音频波形
ffmpeg -i input.aac -filter_complex “showwavespic=s=640x120” -frames:v 1 output_wav.png
由于 showwavespic 是 audio -> video 转换的filter,既不属于audio filter, 也不属于 video filter
所以这里的 -filter_complex 不能更换为 -af 或者 -vf
查看每个声道的音频波形图
ffmpeg -i input.aac -filter_complex “showwavespic=s=640x240:split_channels=1” -frames:v 1 output_wav2.png
8.11 生成测试元数据
8.11.1 生成音频测试流
可以通过 lavfi虚拟音频源的 abuffer、aevalsrc、anullsrc、flite、anoisesrc、sine等滤镜生成音频流
通过anullsrc生成音频流, 注意第一个参数是cL, 不是c一
ffmpeg -f lavfi -i “anullsrc=cl=stereo:r=44100:d=5” -acodec aac -y output.aac
通过aevalsrc生成音频流
ffmpeg -f lavfi -i “aevalsrc=sin(4202PIt)|cos(4302PIt):c=FL|FR” -acodec aac output2.aac
注意:此处与书上有差异, windows上双声道的音频,layout排布不能是FC和BC,只能先 FL和FR
如果不加duration, 按q停止生成
8.11.2 生成视频测试流
使用 testsrc 和 testsrc2 生成 测试序列
ffmpeg -f lavfi -i testsrc=duration=5.3:size=qcif:rate=25 -vcodec libx264 -r:v 25 output_testsrc.mp4
ffmpeg -f lavfi -i testsrc2=duration=5.3:size=qcif:rate=25 -vcodec libx264 -r:v 25 output_testsrc.mp4
使用 color和 nullsrc 生成测试序列
ffmpeg -f lavfi -i color=c=red@0.2:s=qcif:r=25 -vcodec libx264 -r:v 25 output_color.mp4
ffmpeg -f lavfi -i “nullsrc=s=256x256,geq=random(1)*255:128:128” -vcodec libx264 -r:v 25 output_nullsrc.mp4
也可以使用ffplay来直接播放测试序列,如
ffplay -f lavfi -i testsrc=duration=5.3:size=qcif:rate=25
fflay -f lavfi -i testsrc2=duration=5.3:size=qcif:rate=25
ffplay -f lavfi -i color=c=red@0.2:s=qcif:r=25
ffplay -f lavfi -i “nullsrc=s=256x256,geq=random(1)*255:128:128”
注意,ffmpeg的命令,大部分可以直接用在ffplay上,但是涉及多个输入码流时,ffmpeg需要使用 -filter_complex 命令
此时ffplay命令不支持
8.12 音视频倍速处理
音频0.5倍速和2倍速处理
ffmpeg -i input.aac -filter_complex “atempo=tempo=0.5” -acodec aac output_atempo_0.5.aac
ffmpeg -i input.aac -filter_complex “atempo=tempo=2.0” -acodec aac output_atempo_2.0.aac
视频0.5倍速和2倍速处理
ffmpeg -i input.mp4 -filter_complex “setpts=PTS*2” output_PTS_0.5.mp4
ffmpeg -i input.mp4 -filter_complex “setpts=PTS/2” output_PTS_2.0.mp4
8.13 云剪辑常用技术
MSE (Media Source Extensions):
Media Source Extensions (MSE) are a set of APIs in most modern desktop browsers which allow player developers to play back audio and video content to a viewer.
8.13.1 定格帧
ffmpeg -i input.mp4 -vf “select=if(isnan(prev_selected_pts),1,lte(t,10)),reverse” -an -frames 1 output.png
使用trim + select 来定个 2820s位置的视频帧
ffmpeg -i SanGuo.mp4 -vf “trim=2819:2821,select=if(isnan(prev_selected_pts),1,lte(t,2820)),reverse” -an -frames 1 output2.png
建议使用 -ss/-t 的方式来截取片段, 因为 trim filter需要解码每一帧,非常耗时
ffmpeg -ss 2819 -t 2 -i SanGuo.mp4 -vf “select=if(isnan(prev_selected_pts),1,lte(t,2820)),reverse” -an -frames 1 output3.png
8.14.1 透明视频兼容处理
手动生成透明视频
ffmpeg -filter_complex “color=0x000000@0x00:s=1280x720:d=10,format=rgba,drawtext=fontcolor=white:fontsize=100:x=w/2:y=h/2:text=‘FFmpeg’:fontcolor=green:fontfile=arial.ttf” -c:v png alpha.mov
获取素材的透明信息
ffmpeg -i alpha.mov -vf “format=rgba,geq=r=‘alpha(X,Y)’:g=‘alpha(X,Y)’:b=‘alpha(X,Y)’” -c:v libx264 -an mask_simple.mp4
ffmpeg -i alpha.mov -filter_complex “[0:v]format=rgba,split=3[v0][v1][v2];[v0]drawbox=c=black@1:replace=1:t=fill[bg];[bg][v1]overlay[v3];[v2]geq=r=‘alpha(X,Y)’:g=‘alpha(X,Y)’:b=‘alpha(X,Y)’,[v3]vstack[vo]” -map [vo] -c:v libx264 -an mask_complex.mp4
生成视频效果如下:
8.13.3 隔行交错视频兼容处理
使用idet filter 检测视频扫描方式,
ffmpeg -i input.mp4 -vf idet -frames:v 10 -an -f null -
返回结果可知, input.mp4为非交错视频
使用 showinfo filter 检测视频扫描方式
ffmpeg -i input.mp4 -vf showinfo -frames:v 10 -an -f null -
使用yadif filter处理反交错视频,因为没有交错视频,
ffmpeg -i bg.jpg -i interlace.mp4 -filter_complex “[1:v]yadif,scale=1280x720,[0:v]overlay[vo]” -map [vo] -c:v libx264 progressive.mp4
8.13.4 HDR视频兼容处理
检测 hdr视频
ffprobe -show_streams -v error hdr.mp4 |findstr “color_transfer color_space color_primaries”
返回结果如下
color_space=bt2020nc
color_transfer=smpte2084
color_primaries=bt2020
使用zscale和tonemap滤镜把HDR视频转换为SDR视频,其中 tonemap 用于色调映射处理,zscale 对HDR视频做线性处理并设置SDR显示相关的meta信息。
ffmpeg -i bg.jpg -i hdr.mp4 -filter_complex “[1:v]zscale=transfer=linear,tonemap=hable,zscale=transfer=709:p=709:m=709,format=yuv420p[v1];[v1][0:v]overlay[vo]” -map [vo] -c:v h264 -c:a copy sdr.mp4
另外,FFmpeg还支持GPU显卡的色调映射滤镜 tonemap_opencl 和 tonemap_vaapi, 可根据具体应用场景选择使用。
8.13.5 雪碧图和WebVTT
生成雪碧图
ffmpeg -i SanGuo.mp4 -f image2 -vframes 1 -vf “select=(isnan(prev_selected_t)+gte(t-prev_selected_t,5)),scale=180:101,crop=180:100,tile=10x13,format=pix_fmts=rgb24” sprite.jpg
实际效果如下:
如果雪碧图内容过多,可以通过 扩展的 WebVTT 来把视频的雪碧图拆分为多个雪碧图,具体可以搜索相关资料。
8.13.6 缩略图
ffmpeg可以通过 thumbnail filter, 可以从给定的连续序列帧中按指定量分组做直方图统计平均分析,选取其中最具有代表性的一帧作为缩略图,避免截取某一帧产生黑帧的情况。
ffmpeg -i hdr.mp4 -vf thumbnail,scale=300:200 -frames:v 1 output_thumbnail.png
8.13.7 复杂项目渲染
针对类似如下的,非常长的渲染命令,容易超出系统的命令行长度限制,导致渲染失败
ffmpeg -i input2.mp4 -ss 1 -i input.mp4 -filter_complex "color=c=black:s=1080x1920:d=20.400[v0];[0:v]fifo,format=rgba,colorchannelmixer=aa=0.000,[v0]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':enable='between(t,0.000,20.400)'[v1];[1:v]fifo,[v1]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':enable='between(t,0.000,20.400)'[v2]" -map [v2] -pix_fmt yuv420p -r 30 -crf 18 -movflags faststart -use_editlist 1 -metadata comment=[tid=1234567890][type=tran] output_complex.mp4
可以使用 filter_complex_script 参数和movies 滤镜, movies 滤镜指定输入素材,filter_complex_script 指定存放 滤镜脚本的文本文件,如将如下滤镜写到complex.flt文件中
color=c=black:s=1080x1920:d=20.400[v0];movie=input2.mp4,fifo,format=rgba,colorchannelmixer=aa=0.000,[v0]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':enable='between(t,0.000,20.400)'[v1];movie=input.mp4,fifo,[v1]overlay=x='(main_w-overlay_w)/2':y='(main_h-overlay_h)/2':enable='between(t,0.000,20.400)'[v2]
然后使用如下命令直接引用这个脚本
ffmpeg -filter_complex_script complex.flt -map [v2] -pix_fmt yuv420p -r 30 -crf 18 -movflags faststart -use_editlist 1 -metadata comment=[tid=1234567890][type=tran] output_complex2.mp4
8.13.8 色度抠图
涉及两个filter,用于处理YUV数据的 chromakey 和 处理 RGB 数据的 colorkey.
ffmpeg -stream_loop 1 -i input.jpg -filter_complex “color=c=black:s=1920x1080[v0];[0:v]chromakey=color=white:similarity=0.2:blend=0.2[v1];[v0][v1]overlay[vo]” -map [vo] -frames:v 1 chromakey.jpg
ffmpeg -stream_loop 1 -i input.jpg -filter_complex “color=c=black:s=1920x1080[v0];[0:v]colorkey=color=white:similarity=0.2:blend=0.2[v1];[v0][v1]overlay[vo]” -map [vo] -frames:v 1 colorkey.jpg
最终效果,上中下分别为原图,chromakey.jpg 和 colorkey.jpg,相关素材可以在这里下载
8.13.9 蒙版抠图
没有蒙版素材,如下命
ffmpeg -i input.mov -vf alphaextract -c:v h264 -an mask.mp4
ffmpeg -i input.mp4 -i mask.mp4 -filter_complex “color=0x000000@0x00:s=1920x1080:d=10[bg];[0:v][1:v]alphamerge[v1];[bg][v1]overlay[vo]” -map [vo] -c:v png -an output.mov
ffmpeg -i output.mov -i 4k.jpg -filter_complex “[1:v][0:v]overlay=x=‘(main_w-overlay_w)/2’:y=(main_h-overlay_h)[vo]” -map [vo] -c:v h264 -an mask_overlay.mp4
8.13.10 调色
ffmpeg -i input.jpg -filter_complex “[0:v]split=2[v1][v2];[v1]hue=h=60:b=0.5:s=0.7:s=2,[v2]hstack[vo]” -map [vo] output.jpg
调色前后效果对比
8.13.11 透明度调整
涉及的filter有 colorchannelmixer, geq, fade
colorchannelmixer 适应于静态调整某个固定画面的透明值,
fade 【比较有用】适合从 0 (完全透明)~ 1(完全不透明)或 1~0 变化过程
geq 比较灵活,适用于任意的透明度调整区间
ffmpeg -i input.mp4 -filter_complex “color=c=black:s=1920x1080:d=5[v0];[0:v]format=rgba,colorchannelmixer=aa=0.5,[v0]overlay[vo]” -map [vo] -c:v libx264 -t 5 -an color_mix.mp4
淡入效果,前3s完全透明,随后正常显示
ffmpeg -i input.mp4 -vf fade=st=5:d=10 -t 15 -c:v libx264 -an fade.mp4
ffmpeg -i input.mp4 -filter_complex “color=c=black:s=1920x1080:d=15[v0];[0:v]format=rgba,geq=r=‘p(X,Y)’:g=‘p(X,Y)’:b=‘p(X,Y)’:a=‘(0.5*(T-5)/7+0.2)*p(X,Y)’:enable=‘between(t,5,12)’,[v0]overlay[vo]” -map [vo] -c:v h264 -t 5 -an geq.mp4
8.13.12 动态缩放
不是太理解使用场景
ffmpeg -i input.mp4 -vf “zoompan=z=‘min(max(zoom,pzoom)+0.04,1.5)’:x=‘iw/2-(iw/zoom/2)’:y=‘ih/2-(ih/zoom/2)’:d=1:s=1920x1080” -c:v libx264 -pix_fmt yuv420p output_zoompan.mp4
可以通过一下命令,实时查看原视频和动态缩放视频的变换关系
ffplay -i input.mp4 -vf “split[v0][v1];[v1]zoompan=z=‘min(max(zoom,pzoom)+0.04,1.5)’:x=‘iw/2-(iw/zoom/2)’:y=‘ih/2-(ih/zoom/2)’:d=1:s=1920x1080[v2];[v0][v2]vstack” -x 1280 -y 720
8.13.13 画质检测
主要filter有 psnr, ssim, libvmaf等
psnr: 通过计算两个视频每一帧的均方差MSE(Mean Squared Error),进一步计算每一帧的峰值信噪比PSNR,最后计算出整个序列的平均PSNR; (Mean Squared Error = (1/n) * Σ(Yi - Ŷi)^2)
ssim: 计算两个视频的每一帧的结构相似性指标SSIM(structural similarity index measure),计算出整个序列的SSIM;
libvmaf: 计算两个视频的每一帧的视频多方法评估融合 VMAF(video multi-method assessment fusion),计算出整个序列的VMAF;
-
计算PSNR指标
ffmpeg -i input.mp4 -i output.mp4 -filter_complex psnr=“stats_file=psnr.log” -f null -
最终输出结果:[Parsed_psnr_0 @ 000002295e057fc0] PSNR y:42.999352 u:47.378736 v:48.734656 average:44.817456 min:43.884056 max:46.873746
psnr.log 的内容
-
计算SSIM指标
ffmpeg -i input.mp4 -i output.mp4 -filter_complex ssim=stats_file=ssim.log -f null -
最终输出结果:[Parsed_ssim_0 @ 0000019cfd697fc0] SSIM Y:0.982084 (17.467615) U:0.987382 (18.990079) V:0.989278 (19.697078) All:0.985207 (18.299420)
ssim.log 的内容
-
计算VMAF指标
ffmpeg -i input.mp4 -i output.mp4 -filter_complex libvmaf=mode1=‘path=vmaf/mode1/vmaf)v0.6.1.json’:log_path=vmaf.log -f null -
以上3种画质指标对比:
PSRN是最普遍,最广泛的评价画质的客观测量法,取值范围一般是20~50db, 数值越大质量越好
SSIM 是一种偏主观的客观评价方式,从亮度、对比度、结构3方面计算图像相似性,与PSNR相比可以较好地反映人眼的主观质量感受,取值范围是0~1,数值越大质量越好。
VMAF 是Netflix 发明的一套将人类视觉建模与机器学习相结合的视频质量评价体系,更符合人眼视觉的质量评分,取值范围是0~100,数值越多质量越好。VMAF 解决了传统指标不能反映多种场景、多种特征的视频的情况,并且实现了用自动化代替通常需要人类观看和评价视频的主观质量测试工作,是目前互联网视频最主流的客观视频评价指标。
注:如果碰到编码后的图像和参考图像在时间上没有对齐(有B帧以及编码结构发生变化),导致计算出的结果不可信,可以使用解码后的YUV文件来对其或者调整start time和PTS来强行对齐。
8.13.14 滤镜动态调整
普通FFmpeg filter 命令行启动退出前,路径的配置不会发生变化,但是在视频会议、导播等一些直播场景中,需要有一些动态调整滤镜的需求,FFmpeg的 zmq和 azmq filter支持使用zmq协议来实现动态调整其他滤镜的配置。
首先, FFmpeg执行命令的同时会启动一个zmq协议的TCP服务器端,
然后,通过FFmpeg自带的 zmq客户端 zmqsend 发送修改滤镜请求
FFmpeg收到调整请求后根据指定的滤镜实例更新滤镜配置。
FFmpeg为视频添加文件并启动zmq服务的命令如下:
ffmpeg -y -v verbose -re -i input.mp4 -filter_complex "zmq=bind_address=tcp\\\://*\\\:5556,drawtext=text='FFmpeg':fontcolor=red:fontsize=200:x=200:y=20:fontfile=arial.ttf" -t 10 zmq.mp4
通过zmqsend客服端发送请求,修改文字内容为ZeroMQ, 颜色为蓝色
(由于windows本机没有搭建编译 zmqsend 客户端,所以一下命令不work)
echo Parsed_drawtext_1 reinit ‘text=ZeroMQ:fontcolor=blue’| zmqsend -b “tcp://127.0.0.1:5556”
注:需要ffmpeg编译时, 通过 --enable-libzmq 指定使能libzmq,且执行 make tools/zmqsend命令生成了对应的zmq客户端;
且实现了 process_command 接口的滤镜才支持。
8.13.15 深度学习
涉及 dnn_processing filter, 此filter支持所有基于深度学习模型的图像处理算法的通用路径,目前已支持 超分(SR), 去雨(DeRain), 去雾(DeHaze) 等深度学习模型算法;
运行环境方面,目前已支持 Native, TensorFlow 和 OpenVINO 三种后端运行环境,
基于CPU的Native为FFmpeg默认方式,但性能较差
推荐使用 基于 NVIDIA显卡的 TensorFlow 或者 Intel显卡的 OpenVINO 后端。
准备编译过程略。
相关使用命令如下(没有环境,没有实际运行)
ffmpeg -i srcnn_in.mp4 -vf format=yuv420p,scale=iw2:h=ih2,dnn_processing=dnnbackend=tensorflow:mode1=./dnn_processing/models/srcnn.pb:input=x:output=y srcnn_out.mp4
ffmpeg -i espcn_in.mp4 -vf format=yuv420p,dnn_processing=dnnbackend=tensorflow:mode1=./dnn_processing/models/espcn.pb:input=x:output=y espcn_out.mp4
第9章 采集设备操作
9.1 Linux设备操作
16.04版本的unbutu
9.1.1 查看设备列表
ffmpeg -devices -hide_banner
Devices:
D. = Demuxing supported
.E = Muxing supported
--
DE alsa ALSA audio output
DE fbdev Linux framebuffer
D lavfi Libavfilter virtual input device
DE oss OSS (Open Sound System) playback
E sdl,sdl2 SDL2 output device
DE sndio sndio audio playback
DE video4linux2,v4l2 Video4Linux2 output device
D x11grab X11 screen capture, using XCB
E xv XV (XVideo) output device
9.1.2 采集设备fbdev参数说明和使用
ffmpeg -h demuxer=fbdev
录制终端中的图像,需要sudo权限
sudo ffmpeg -f fbdev -framerate 30 -i /dev/fb0 output_fbdev.mp4
9.1.3 采集设备v4l2参数说明和使用
ffmpeg -h demuxer=v4l2
查看当前机器上摄像头所支持的色彩格式及分辨率
ffmpeg -hide_banner -f v4l2 -list_formats all -i /dev/video0
[video4linux2,v4l2 @ 0x3df5140] Raw : yuyv422 : YUYV 4:2:2 : 640x480 160x120 176x144 320x240 352x288
ffmpeg -hide_banner -s 640x480 -i /dev/video0 output_video0.mp4
录制的视频如下(摄像头未开)
9.1.4 采集设备x11grab参数说明和使用
ffmpeg -h demuxer=x11grab
FFmpeg通过x11grab录制屏幕时,输入设备的设备名规则如下:
[主机名]:显示编号id.屏幕编号id[+起始x轴,起始y轴]
- 桌面录制
ffmpeg -f x11grab -framerate 25 -video_size 1366x768 -i :0.0 output_x11grab.mp4
录制整个屏幕的左上角的1366x768的尺寸
- 桌面录制指定起始位置
ffmpeg -f x11grab -framerate 25 -video_size 1366x768 -i :0.0+300,200 output_x11grab_xy.mp4
从桌面的(300, 200) 的坐标位置开始录制
9.1.5 其他设备alsa/oss/sndio
ALSA: Advanced Linux Sound Architecture
ffmpeg -h demuxer=alsa
aplay -l //查看可以设卡设备id
ffmpeg -f alsa -sample_rate 44100 -channels 2 -i hw:0 alasout.wav
OSS: Open Sound System
ffmpeg -h demuxer=oss
oss的设备一般为 /dev/dsp
ffmpeg -f oss -sample_rate 44100 -channels 2 -i /dev/dsp ossout.wav
sndio设备
sndio的设备一般为 /dev/audio0
ffmpeg -f sndio -sample_rate 44100 -channels 2 -i /dev/audio0 sndio_out.wav
9.2 macOS设备操作
无设备,skip
9.3 Windows设备采集
主要设备有 dshow, vfwcap, gdigrab, 其中
dshow 可以用来采集摄像头、采集卡、麦克风等设备
vfwcap 主要用来采集摄像头类设备
gdigrab 用来抓取Windows窗口程序
9.3.1 使用dshow
ffmpeg -f dshow -list_devices true -i dummy
返回信息如下:
打开摄像头
ffplay -f dshow -video_size 640x480 -i video=“USB2.0 VGA UVC WebCam”
注意给video_size设置的采集图像的宽高参数一定要与硬件Camera的匹配,否则会有如下错误:
录制音视频并保存为文件
ffmpeg -f dshow -video_size 640x480 -i video="USB2.0 VGA UVC WebCam" -f dshow -i audio="麦克风 (Realtek High Definition Audio)" output_dshow.mp4
9.3.2 使用vfmcap采集视频设备
查看vfwcap支持的采集设备
ffmpeg -f vfwcap -i list
尝试录制视频(未成功,尚未解决)
ffmpeg -f vfwcap -i 0 -r 25 -vcodec libx264 output_vfwcap.mp4
产生如下弹窗:
点击 确认 或 应用后,有如下报错:
9.3.3 使用 gdigrab采集窗口
gdigrab支持桌面级或窗口级采集视频数据
-
录制整个桌面
ffmpeg -i gdigrab -framerate 6 -i desktop out_desktop.mp4
录制的视频内容 -
录制某个窗口
ffmpeg -f gdigrab -framerate 6 -i title=ffmpeg output_title.mp4
录制前使用ffmpeg命令(ffplay -loop -1 input.mp4 -window_title ffmpeg)在播放一个视频,随后使用此录制命令会自动抓取播放窗口的内容,尽管播放窗口的图层不在最顶层。
最终原始播放窗口和录屏回放如下:
尽 -
录制带偏移量的窗口
ffmpeg -f gdigrab -framerate 6 -offset_x 50 -offset_y 50 -video_size 400x400 -i title=ffmpeg output_title_offset.mp4
实际的录制效果
(命令行学习完)