当前位置: 首页 > article >正文

【深入理解FFMPEG】命令行阅读笔记

这里写自定义目录标题

  • 第三章 FFmpeg工具使用基础
    • 3.1 ffmpeg常用命令
      • 3.1.1
      • 3.1.3 转码流程
    • 3.2 ffprobe 常用命令
      • 3.2.1 ffprobe常用参数
      • 3.2.2 ffprobe 使用示例
    • 3.3 ffplay常用命令
      • 3.3.1 ffplay常用参数
      • 3.3.2 ffplay高级参数
      • 3.3.4 ffplay快捷键
  • 第4章 封装与解封装
    • 4.1 视频文件转MP4
      • 4.1.4 MP4在FFmpeg中的Demuxer
    • 4.2 视频文件转FLV
    • 4.3 视频文件转MPEG-TS
    • 4.4 视频文件转HLS
    • 4.5 视频文件切片
      • 4.5.3 使用ss与t参数切片
    • 4.6 视频文件的音视频流提取
      • 4.6.1 提前AAC音频流
      • 4.6.2 提取H.264视频流
      • 4.6.3 提取H.265视频流
    • 4.7 系统资源使用情况
  • 第5章 编码与转码
    • 5.1 软编码 H.264
      • 5.1.2 H.264编码举例
        • 1. 编码器预设参数设置
        • 2. H.264编码优化
        • 3. H.264的profile和level设置
        • 4. 控制场景切换时关键帧的插入
        • 5. 设置x264内部参数
        • 6. CBR设置

第三章 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: 无缓冲
probesizeprobing 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 分为三层

  1. ES层: 单独的音频流视频流组成的Elementary Stream, ES
  2. PES层: 将ES按一定的规则进行封装,如H.264的AU作为拆分单元,打上时间戳,组成分组的基本数据流 Packetized Elementary Stream, PES,
  3. 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的长度头更换为起始码的头

  1. 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
是相邻的

  1. 生成 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
  1. 生成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
  1. 生成 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
  1. 生成 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参数切片

  1. 使用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
  1. 使用 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
  1. 使用 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参数包含的集中预设参数

  1. ultrafast 最开的编码方式
  2. superfast 超级快的编码方式
  3. veryfast 非常快的编码方式
  4. faster
  5. fast
  6. medium
  7. slow
  8. slower
  9. veryslow
  10. 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设置

P152 TODO


http://www.kler.cn/a/521145.html

相关文章:

  • 【Spring】Spring启示录
  • 论文阅读笔记:VMamba: Visual State Space Model
  • 【深度学习入门_机器学习理论】K近邻法(KNN)
  • DeepSeek API 的获取与对话示例
  • Three.js实战项目02:vue3+three.js实现汽车展厅项目
  • Go语言开发项目文件规范
  • 基于微信小程序的外卖点餐系统设计与实现ssm+论文源码调试讲解
  • DeepSeek R1:AI领域的新突破与挑战
  • 【集合】ArrayList扩容机制的源码剖析
  • 航空开放系统架构OSA 与集成 IMA 概念解析
  • 安装 docker 详解
  • CSS all 属性
  • 单片机基础模块学习——DS1302时钟芯片
  • Linux 入门 常用指令 详细版
  • 第四节 提升专业和业务能力
  • mysql查询中常见函数
  • Day46:访问元组元素
  • Linux 系统错误处理简介
  • 基于语义-拓扑-度量表征引导的大语言模型推理的空中视觉语言导航
  • 好看的测试用例模板
  • 探索JavaScript前端开发:开启交互之门的神奇钥匙(二)
  • std::function的简易实现
  • 算法日记9:SC61滑动窗口(单调队列)
  • c++学习第十二天
  • 神经网络|(五)概率论基础知识-条件概率
  • 开源AI模型发布策略:平衡开放与质量的艺术