前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《FFmpeg从入门到精通》读书笔记(二)[通俗易懂]

《FFmpeg从入门到精通》读书笔记(二)[通俗易懂]

作者头像
全栈程序员站长
发布2022-09-13 10:42:47
3K0
发布2022-09-13 10:42:47
举报
文章被收录于专栏:全栈程序员必看

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

写在前面

2019.06.18

第三章 FFmpeg转封装


第三章 FFmpeg转封装

一、MP4格式标准

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

MP4中Box的组成 (书 P61-63)

主要信息:

在这里插入图片描述
在这里插入图片描述

Note:尺寸、类型、版本、标志 这四个字段都有

(1)moov:一级 音视频数据的metadata信息

mdat :一级 media数据容器 moov与mdat的存放位置没有强制要求; 互联网视频点播中,moov在前时,文件可以被快速打开; moov在后时,需要将MP4文件下载完成后才可以进行播放

(2)moov容器

moov容器定义了一个MP4文件中的数据信息,类型是moov,是一个容器Atom,其至少必须包含以下三种Atom中的一种:

mvhd标签,Movie Header Atom,存放未压缩过的影片信息的头容器 cmov标签,Compressed Movie Atom,压缩过的电影信息容器(不常用) rmra标签,Reference Movie Atom, 参考电影信息容器(不常用)

还可以包含其他的标签 (书 P64) mvhd中定义了多媒体文件的time scale、duration以及display characteristics; trak 二级 流的track,定义了多媒体文件中的一个track的信息,track是多媒体文件中可以独立操作的媒体单位,例如一个音频流或一个视频流就是一个track

(3)解析mvhd子容器

参数列表 (书 P66) 解析出视频的基本信息,包括尺寸、类型、时长、速度、音量等

(4)解析trak子容器

trak容器中定义了媒体文件中的一个track的信息,每个trak容器都有与它关联的media容器描述信息。 trak容器的主要使用目的:

包含媒体数据的引用和描述(media track) 包含modifier track 信息 流媒体协议的打包信息(hint track),hint track可以引用或者复制对应的媒体采样数据

hint track和modifier track必须保证完整性,同时要与至少一个media track一起存在。 一个trak容器中要求必须要有一个Track Header Atom(tkhd)、一个Media Atom(mdia),其他Atom可选

(5)解析tkhd容器

解析出track的尺寸、类型、ID、市场、音量等。音频与视频的trak的tkhd的大小相同,里面的内容随着音视频trak类型的不同而有所不同。

(6)解析mdia容器

Media Atom的类型是mdia,其必须包含如下容器:

一个媒体头:Media Header Atom(mdhd) 一个句柄参考:Handler Reference(hdlr) 一个媒体信息:Media Information(minf)和用户数据User Data Atom(udta)

(7)解析mdhd容器

mdhd容器被包含在各个track中,描述Media的Header,包含信息表格 P71:描述尺寸、类型、版本、生成和修订事件等。

Note:音频时长可通过Duration / TimeScale的方式来计算。

(8)解析hdlr容器

hdlr容器中描述了媒体流的播放过程,包含内容有:尺寸、类型、版本、标志、Handle的类型、Handle的子类行、保留、Component name

(9)解析minf容器

minf容器中包含了很多重要的子容器,例如音视频采样等信息相关的容器 minf容器中的信息将作为音视频数据的映射存在,内容具体如下:

视频信息头:Video Media Information Header(vmhd子容器) 音频信息头:Sound Media Information Header(smhd子容器) 数据信息:Data Information(dinf子容器) 采样表: Sample Table(stbl子容器)

(10)解析vmhd容器

图形模式:传输模式,传输模式指定的布尔值 Opcolor:颜色值,RGB颜色值

(11)解析smhd容器

均衡:音频的均衡是用来控制计算机的两个扬声器的声音混合效果,一般是0

(12)解析dinf容器

dinf容器是一个用于描述数据信息的容器,其定义的是音视频数据的信息

(13)解析stbl容器

stbl容器又称为采样参数列表的容器(Sample Table Atom),该容器包含转化媒体时间到实际的sample的信息,也说明了解释sample的信息,例如,视频数据是否需要解压缩、解压缩算法是什么 等信息。

其包含的子容器具体如下:

采样的描述、时间、同步、大小,Chunk采样、偏移等

stbl包含track中media sample的所有时间和数据索引,利用sample信息,就可以定位sample的媒体时间,决定其类型、大小,以及如何在其他容器中找到紧邻的sample

(14)解析edts容器

edts容器定义了创建Movie媒体文件中一个track的一部分媒体,所有的edts数据都在一个表里,包括每一部分的时间偏移量和长度。

一个空的edts数据用来定位到track的起始时间偏移位置。

MP4分析工具:分析MP4封装格式的工具

FFmpeg、Elecard StreamEye、mp4box、mp4info等

Elecard StreamEye

视频信息查看工具,能查看帧的排列信息,将I P B帧以不同颜色的柱状展示出来,柱的长度根据帧的大小显示;还可以分析MP4的封装内容,包括流的信息、宏块的信息、文件头信息、图像信息以及文件的信息等;还可以逐帧查看每一帧的详细信息和状态

mp4box

GPAC项目中的一个组件;针对媒体文件进行合成、拆解等操作

mp4info

可视化分析工具,将MP4文件的各Box解析出来并展示数据

MP4在FFmpeg中的Demuxer
代码语言:javascript
复制
ffmpeg -h demuxer=mp4

默认开启:

seek_streams_individually 根据单独的流进行seek

默认不开启:

user_absolute_path 可以通过绝对路径加载外部的track,可能有安全因素影响 ignore_editlist 忽略EditList Atom信息 ignore_chapters 忽略Chapters信息 enable_drefs 外部track支持

MP4在FFmpeg中的Muxer (参数 书P80)
1.faststart参数

正常情况下ffmpeg生成moov是在mdat写完成之后再写入,可以通过faststart将moov容器移动值mdat的前面(如前文所说,moov在前面,视频可以边下边播)

代码语言:javascript
复制
ffmpeg -i input.flv -c copy -f mp4 -movflags faststart output.mp4
2.dash参数
代码语言:javascript
复制
知识点:DASH介绍
DASH是一种服务端、客户端的流媒体解决方案
服务端: 
将视频内容分割为一个个分片,每个分片可以存在不同的编码形式(不同的codec、profile、分辨率、码率等); 
播放器端: 
就可以根据自由选择需要播放的媒体分片;可以实现adaptive bitrate streaming技术。不同画质内容无缝切换,提供更好的播放体验。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

DASH简介及使用方法(FFmpeg, MP4Box)

代码语言:javascript
复制
ffmpeg -i input.flv -c copy -f mp4 -moveflags dash output.mp4
3.isml参数

ISMV为微软发布的一个流媒体格式,通过参数isml可以发布ISML直播流,将ISMV推流至IIS服务器

代码语言:javascript
复制
ffmpeg -i input.mp4 -c copy -moveflags isml+frag_keyframe -f ismv Stream

二、FLV格式标准

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

1.FLV文件头格式解析(字段 书P84)

签名字段用了三个字节,组成“FLV”;然后是版本、音频标记类型、视频标记类型、数据偏移

2.FLV文件内容格式解析

内容格式为上一个Tag大小+FLAGTAG,FLAGTAG分为两部分:TAGHeader部分和TAGBody部分

3.FLVTAG格式解析

头部:保留字段、滤镜位、TAG类型、数据大小占用、时间戳及扩展时间戳、流ID; 之后是Tag的data。

存储的数据分为视频数据、音频数据及脚本数据

4.VideoTag数据解析

header中读取到的Tag类型为0x09

帧类型、编码标识(CodecID)、H264的包类型(AVCPackerType)、CTS、视频数据

代码语言:javascript
复制
知识点:
PTS:Presentation Time Stamp。PTS主要用于度量解码后的视频帧什么时候被显示出来
DTS:Decode Time Stamp。DTS主要是标识读入内存中的bit流在什么时候开始送入解码器中进行解码。
在没有B帧存在的情况下DTS的顺序和PTS的顺序应该是一样的。

I,P,B帧和PTS,DTS的关系

5.AudioTag数据格式解析

header中读取到的Tag类型为0x08

声音格式(AAC、MP3、Speex等)、音频采样率(Hz)、采样大小(8或16位)、音频类型(Mono/Stereo sound)、音频包类型、音频数据

6.ScriptData格式解析

header中读取到的Tag类型为0x12 ScriptData常见的展现方式是FLV的Metadata,里面存储的数据格式一般为AMF数据 类型、数据

代码语言:javascript
复制
知识点:
AMF是Action Message Format协议的简称,AMF协议是Adobe公司自己的协议,主要用于数据交互和远程过程调用,
在功能上相当于WebService,但是AMF与 WebService中的XML不同的是AMF是二进制数据,而XML是文本数据,
AMF的传输效率比XML高。
AMF使用HTTP方式传输,目前主要是 用于ActionScript中,即实现Flex和Server之间的通信。
FFmpeg转FLV (书 P89)

封装FLV时,内部的音频或者视频不符合标准时,无法封装进FLV,如音频格式为AC3,需要先将其转换为AAC,再封装进FLV

代码语言:javascript
复制
ffmpeg -i input_ac3.mp4 -vcodec copy -acodec aac -f flv output.flv

生成带索引的FLV:将FLV文件中的关键帧建议一个索引,并将索引写入Metadata头中

代码语言:javascript
复制
ffmpeg -i input.mp4 -c copy -f flv -flvflags add_keyframe_index output.flv
FLV文件格式分析工具

flvparse、FlvAnalyzer、ffprobe

代码语言:javascript
复制
ffprobe -v trace -i output.flv
在这里插入图片描述
在这里插入图片描述
三、M3U8格式标准介绍

M3U8是一种常见的流媒体格式,主要以文件列表的形式存在,既支持直播也支持点播 标签:

  • EXTM3U:M3U8文件必须包含的标签,且必须在文件的第一行
  • EXT-X-VERSION:M3U8文件的版本
  • EXT-X-TARGETDURATION:每一个分片都会有一个分片自己的duration,这个标签是最大的那个分片的浮点数四舍五入后的整数值
  • EXT-X-MEDIA-SEQUENCE:M3U8直播时的直播切片序列,当播放打开M3U8时,以这个标签的值为参考,播放对应序列号的切片

客户端播放M3U8的标准还有更多规则:

分片必须是动态改变的,序列不能相同,且序列必须是增序的 当M3U8列表中没有出现EXT-X-ENDLIST标签时,无论M3U8列表中有多少片分片,都从倒数第三片开始播放;不满三片不应该播放 前一片与后一片有不连续时播放可能会出错,需要使用EXT-X-DISCONTINUITY标签来解决 以播放当前分片的duration时间刷新M3U8列表,然后做对应的加载动作 如果播放列表在刷新之后与之前的列表相同,那么在播放当前分片duration一半的时间再刷新一次

  • EXTINF:M3U8列表中每一个分片的duration,还包含其他信息,主要为标注切片信息
  • EXT-X-STREAM-INF:主要出现在多级M3U8文件中,例如不同清晰度
FFmpeg转HLS参数

FFmpeg自带HLS的封装参数,使用HLS格式即可进行HLS的封装,参数表格 P96 常规的文件转HLS直播:ffmpeg -re -i input.mp4 -c copy -f hls -bsf:v h264_mp4toannexb output.m3u8 ” -bsf:v h264_mp4toannexb”将MP4中的H.264转换为H.264 AnnexB标准的编码,AnnexB标准的编码常见与实时传输流中。如果源文件为FLV、TS等可作为直播传输流的视频,则不需要这个参数

参数解析
1.start_number参数

设置M3U8列表中第一片的序列号,例如:

代码语言:javascript
复制
ffmpeg -re -i input.flv -c copy -f hls -start_number 300 output.m3u8
2.hls_time参数

设置M3U8列表中切片的duration;该切片规则是从关键帧开始切片,时间不均匀;如果先转码再切片,则会比较规律

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_time 10 output.m3u8
3.hls_list_size参数

设置M3U8列表中TS切片的个数

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_list_size 3 output.m3u8
4.hls_wrap参数

为M3U8列表中TS设置刷新回滚参数

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_wrap 3 output.m3u8
5.hls_base_url参数

为M3U8列表中的文件路径设置前置基本路径参数

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_base_url http://xxx.xxx.x.x/live/ output.m3u8
6.hls_segment_filename参数

设置切片文件名的规则

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_segment_filename test_output-%d.ts output.m3u8
7.hls_flags参数

该参数包含了一些子参数

  • 7.1 delete_segments

删除已经不在M3U8列表中的旧文件。 注意:FFmpeg删除切片时会将hls_list_size大小的2倍作为删除的依据

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_flags delete_segments -hls_list_size 4 output.m3u8
在这里插入图片描述
在这里插入图片描述
  • 7.2 round_duration

实现切片信息duration为整型

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_flags round_durations output.m3u8
  • 7.3 discont_start

在生成M3U8时,在切片信息的前边插入discontinuity标签

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_flags discont_start output.m3u8
在这里插入图片描述
在这里插入图片描述
  • 7.4 omit_endlist

在生成M3U8结束的时候,若不在文件末尾,则不追加endlist标签:因为在常规的生成M3U8的操作中,FFmpeg会默认写入endlist标签

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_flags omit_endlist output.m3u8
  • 7.5 split_by_time

生成M3U8时根据hls_time参数设定的数值作为秒数参考对TS进行切片,并不一定要遇到关键帧

代码语言:javascript
复制
ffmpeg -re -i input.flv -f hls -hls_time 2 -hls_flags split_by_time output.m3u8 
8.use_localtime

以本地系统时间为切片文件名

代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f hls -use_localtime 1 -bsf:v h264_mp4toannexb output.m3u8
9.method

设置HLS将M3U8及TS文件上传至Http服务器; Http服务器要支持上传相关方法,如POST、PUT等

代码语言:javascript
复制
ffmpeg -i input.mp4 -c copy -f hls -hls_time 3 -hls_list_size 0 -method POST -t 6 http://www.baidu.com
在这里插入图片描述
在这里插入图片描述
上述命令中两个FFmpeg参数的含义

-bsf 比特流过滤器设置 首先使用ffmpeg -bsfs来查看所有的比特流过滤器,使用下面的命令 ffmpeg -i h264.mp4 -c:v copy -bsf:v h264_mp4toannexb -an out.h264 来匹配要复制的视频流,也是就是说,是有条件复制视频流,必须匹配上才复制

-c -codec的缩写 ffmpeg -i INPUT -map 0 -c:v libx264 -c:a copy OUTPUT 意思是encodes all video streams with libx264 and copies all audio streams.


视频文件切片

视频文件切片与HLS基本类似,但HLS切片在标准中只支持TS格式的切片,且是直播与点播切片。视频切片可以使用segment方式,也可以使用ss加上t参数

FFmpeg切片segment参数 (参数表格 P105)参数中一些与HLS用法相同,下面分析一些用法不同的

在这里插入图片描述
在这里插入图片描述
FFmpeg使用segment方式进行切片
1.segment_format

指定切片文件的格式。HLS切片的格式主要为MPEGTS文件格式; 在segment中,可以根据segment_format来指定切片文件的格式,既可以为MPEGTS格式,也可以为MP4切片、FLV切片等

代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 test_output%d.mp4
在这里插入图片描述
在这里插入图片描述
2.segment_list与segment_list_type指定切片索引列表

使用segment切割文件时,不仅可以切割MP4,同样可以切割TS或FLV等文件,生成的文件索引列表名称也可以指定名称

1)生成ffconcat格式索引文件

代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type ffconcat -segment_list output.lst test_output-%d.mp4
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

该命令生成ffconcat格式的索引文件output.lst,内包含MP4切片的文件列表

2)生成FLAT格式索引文件

代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type flat -segment_list flielist.txt test_output-%d.mp4
在这里插入图片描述
在这里插入图片描述

3)生成CSV格式索引文件

代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type csv -segment_list flielist.csv test_output-%d.mp4
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4)生成M3U8格式索引文件

代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_list_type m3u8 -segment_list flielist.m3u8 test_output-%d.mp4
在这里插入图片描述
在这里插入图片描述
3.reset_timestamps 使切片时间戳归零
代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -reset_timestamps 1 test_output-%d.mp4
4.segment_times 按照事件点剪切
代码语言:javascript
复制
ffmpeg -re -i input.mp4 -c copy -f segment -segment_format mp4 -segment_times 3,9,12 test_output-%d.mp4

根据命令参数,切片的时间点分别为3,9,12秒,在这三个时间点进行切片

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

使用ss可以进行视频文件的seek定位,ss所传递的参数为时间值,t所传递的参数也为时间值

1.使用ss指定剪切开头部分

代码语言:javascript
复制
例如:从视频的第10秒开始截取
ffmpeg -ss 10 -i input.mp4 -c copy output.ts

2.使用t指定视频总长度

代码语言:javascript
复制
例如:截取前10秒的数据
ffmpeg -i input.mp4 -c copy -t 10 -copyts output.mp4

3.使用output_ts_offset指定输出start_time 使用ss与t可以达到切割视频的某一段的效果,但不能指定输出文件的start_time

代码语言:javascript
复制
ffmpeg -i input.mp4 -c copy -t 10 -output_ts_offset 120 output.mp4
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
FFmpeg抽取音视频文件中的AAC音频流
代码语言:javascript
复制
ffmpeg -i input.mp4 -vn -acodec copy output.aac
在这里插入图片描述
在这里插入图片描述

(由于我的input.mp4是录屏文件,没有音轨,所以没有获取到)

FFmpeg抽取音视频文件中的H.264视频流
代码语言:javascript
复制
ffmpeg -i input.mp4 -an -vcodec copy output.h264
在这里插入图片描述
在这里插入图片描述
FFmpeg抽取音视频文件中的H.265视频流
代码语言:javascript
复制
ffmpeg -i input.mp4 -an -vcodec copy -bsf hevc_mp4toannexb -f hevc output.hevc

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 写在前面
  • 第三章 FFmpeg转封装
    • 一、MP4格式标准
      • MP4分析工具:分析MP4封装格式的工具
      • MP4在FFmpeg中的Demuxer
      • MP4在FFmpeg中的Muxer (参数 书P80)
    • 二、FLV格式标准
      • FFmpeg转FLV (书 P89)
      • FLV文件格式分析工具
    • 三、M3U8格式标准介绍
      • FFmpeg转HLS参数
      • 参数解析
    • 视频文件切片
      • FFmpeg使用segment方式进行切片
      • FFmpeg使用ss与t参数进行切片
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档