FLV视频封装格式详解
目录(?)[-]
- Overview
- File Structure
- The FLV header
- The FLV File Body
- FLV Tag Definition
- FLVTAG
- Audio Tags
- Video Tags
- SCRIPTDATA
- onMetaData
- keyframes
File Structure
从整个文件上开看,FLV是由The FLV header 和 The FLV File Body 组成.
1.The FLV header
| Field | Type | Comment |
| Signature | UI8 | Signature byte always 'F' (0x46) |
| Signature | UI8 | Signature byte always 'L' (0x4C) |
| Signature | UI8 | Signature byte always 'V' (0x56) |
| Version | UI8 | File version (for example, 0x01 for FLV version 1) |
| TypeFlagsReserved | UB [5] | Shall be 0 |
| TypeFlagsAudio | UB [1] | 1 = Audio tags are present |
| TypeFlagsReserved | UB [1] | Shall be 0 |
| TypeFlagsVideo | UB [1] | 1 = Video tags are present |
| DataOffset | UI32 | The length of this header in bytes |
Signature: FLV 文件的前3个字节为固定的‘F’‘L’‘V’,用来标识这个文件是flv格式的.在做格式探测的时候,
如果发现前3个字节为“FLV”,就认为它是flv文件.
Version: 第4个字节表示flv版本号.
Flags: 第5个字节中的第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)
DataOffset : 最后4个字节表示FLV header 长度.
2.The FLV File Body
| Field | Type | Comment |
| PreviousTagSize0 | UI32 | Always 0 |
| Tag1 | FLVTAG | First tag |
| PreviousTagSize1 | UI32 | Size of previous tag, including its header, in bytes. For FLV version1, this value is 11 plus the DataSize of the previous tag. |
| Tag2 | FLVTAG | Second tag |
| ... | ... | ... |
| PreviousTagSizeN-1 | UI32 | Size of second-to-last tag, including its header, in bytes. |
| TagN | FLVTAG | Last tag |
| PreviousTagSizeN | UI32 | Size of last tag, including its header, in bytes |
FLV header之后,就是 FLV File Body.
FLV File Body是由一连串的back-pointers + tags构成.back-pointers就是4个字节数据,表示前一个tag的size.
FLV Tag Definition
FLV文件中的数据都是由一个个TAG组成,TAG里面的数据可能是video、audio、scripts.
下表是TAG的结构:
1.FLVTAG
| Field | Type | Comment |
| Reserved | UB [2] | Reserved for FMS, should be 0 |
| Filter | UB [1] | Indicates if packets are filtered. 0 = No pre-processing required. 1 = Pre-processing (such as decryption) of the packet is required before it can be rendered. Shall be 0 in unencrypted files, and 1 for encrypted tags. See Annex F. FLV Encryption for the use of filters. |
| TagType | UB [5] | Type of contents in this tag. The following types are |
| DataSize | UI24 | Length of the message. Number of bytes after StreamID to end of tag (Equal to length of the tag – 11) |
| Timestamp | UI24 | Time in milliseconds at which the data in this tag applies. This value is relative to the first tag in the FLV file, which always has a timestamp of 0. |
| TimestampExtended | UI8 | Extension of the Timestamp field to form a SI32 value. This field represents the upper 8 bits, while the previous Timestamp field represents the lower 24 bits of the time in milliseconds. |
| StreamID | UI24 | Always 0. |
| AudioTagHeader | IF TagType == 8 AudioTagHeader | |
| VideoTagHeader | IF TagType == 9 VideoTagHeader | |
| EncryptionHeader | IF Filter == 1 EncryptionTagHeader | |
| FilterParams | IF Filter == 1 FilterParams | |
| Data | IF TagType == 8 AUDIODATA IF TagType == 9 VIDEODATA IF TagType == 18 SCRIPTDATA | Data specific for each media type. |
TagType: TAG中第1个字节中的前5位表示这个TAG中包含数据的类型,8 = audio,9 = video,18 = script data.
DataSize:StreamID之后的数据长度.
Timestamp和TimestampExtended组成了这个TAG 包数据的PTS信息,记得刚开始做FVL demux的时候,并没有考虑TimestampExtended的值,直接就把Timestamp默认为是PTS,后来发生的现 象就是画面有跳帧的现象,后来才仔细看了一下文档发现真正数据的PTS是PTS= Timestamp | TimestampExtended<<24.
StreamID之后的数据就是每种格式的情况不一样了,接下格式进行详细的介绍.
Audio Tags
如果TAG包中的TagType==8时,就表示这个TAG是audio。
StreamID之后的数据就表示是AudioTagHeader,AudioTagHeader结构如下:
| Field | Type | Comment |
| SoundFormat | UB [4] | Format of SoundData. The following values are defined: 0 = Linear PCM, platform endian 1 = ADPCM 2 = MP3 3 = Linear PCM, little endian 4 = Nellymoser 16 kHz mono 5 = Nellymoser 8 kHz mono 6 = Nellymoser 7 = G.711 A-law logarithmic PCM 8 = G.711 mu-law logarithmic PCM 9 = reserved 10 = AAC 11 = Speex 14 = MP3 8 kHz 15 = Device-specific sound Formats 7, 8, 14, and 15 are reserved. AAC is supported in Flash Player 9,0,115,0 and higher. Speex is supported in Flash Player 10 and higher. |
| SoundRate | UB [2] | Sampling rate. The following values are defined: 0 = 5.5 kHz 1 = 11 kHz 2 = 22 kHz 3 = 44 kHz |
| SoundSize | UB [1] | Size of each audio sample. This parameter only pertains to |
| SoundType | UB [1] | Mono or stereo sound 0 = Mono sound 1 = Stereo sound |
| AACPacketType | IF SoundFormat == 10 UI8 | The following values are defined: 0 = AAC sequence header 1 = AAC raw |
AudioTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着音频类型、采样率等的基本信息.表里列的十分清楚.
AudioTagHeader之后跟着的就是AUDIODATA数据了,也就是audio payload 但是这里有个特例,如果音频格式(SoundFormat)是10 = AAC,AudioTagHeader中会多出1个字节的数据AACPacketType,这个字段来表示AACAUDIODATA的类型:0 = AAC sequence header,1 = AAC raw。
| Field | Type | Comment |
| Data | IF AACPacketType ==0 AudioSpecificConfig | The AudioSpecificConfig is defined in ISO14496-3. Note that this is not the same as the contents of the esds box from an MP4/F4V file. |
| ELSE IF AACPacketType == 1 Raw AAC frame data in UI8 [ ] | audio payload |
AAC sequence header也就是包含了AudioSpecificConfig,AudioSpecificConfig包含着一些更加详细音频的信息,AudioSpecificConfig的定义在ISO14496-3中1.6.2.1 AudioSpecificConfig,这里就不详细贴了。而且在ffmpeg中有对AudioSpecificConfig解析的函数,ff_mpeg4audio_get_config(),可以对比的看一下,理解更深刻。
AAC raw 这种包含的就是音频ES流了,也就是audio payload.
在FLV的文件中,一般情况下 AAC sequence header 这种包只出现1次,而且是第一个audio tag,为什么要提到这种tag,因为当时在做FLVdemux的时候,如果是AAC的音频,需要在每帧AAC ES流前边添加7个字节ADST头,ADST在音频的格式中会详细解读,这是解码器通用的格式,就是AAC的纯ES流要打包成ADST格式的AAC文件,解码器才能正常播放.就是在打包ADST的时候,需要samplingFrequencyIndex这个信息,samplingFrequencyIndex最准确的信息是在AudioSpecificConfig中,所以就对AudioSpecificConfig进行解析并得到了samplingFrequencyIndex。
到这步你就完全可以把FLV 文件中的音频信息及数据提取出来,送给音频解码器正常播放了。
Video Tags
如果TAG包中的TagType==9时,就表示这个TAG是video.
StreamID之后的数据就表示是VideoTagHeader,VideoTagHeader结构如下:
| Field | Type | Comment |
| Frame Type | UB [4] | Type of video frame. The following values are defined: 1 = key frame (for AVC, a seekable frame) 2 = inter frame (for AVC, a non-seekable frame) 3 = disposable inter frame (H.263 only) 4 = generated key frame (reserved for server use only) 5 = video info/command frame |
| CodecID | UB [4] | Codec Identifier. The following values are defined: 2 = Sorenson H.263 3 = Screen video 4 = On2 VP6 5 = On2 VP6 with alpha channel 6 = Screen video version 2 7 = AVC |
| AVCPacketType | IF CodecID == 7 UI8 | The following values are defined: |
| CompositionTime | IF CodecID == 7 SI24 | IF AVCPacketType == 1 Composition time offset ELSE 0 See ISO 14496-12, 8.15.3 for an explanation of composition times. The offset in an FLV file is always in milliseconds. |
VideoTagHeader的头1个字节,也就是接跟着StreamID的1个字节包含着视频帧类型及视频CodecID最基本信息.表里列的十分清楚.
VideoTagHeader之后跟着的就是VIDEODATA数据了,也就是video payload.当然就像音频AAC一样,这里也有特例就是如果视频的格式是AVC(H.264)的话,VideoTagHeader会多出4个字节的信息.
AVCPacketType 和 CompositionTime。AVCPacketType 表示接下来 VIDEODATA (AVCVIDEOPACKET)的内容:
IF AVCPacketType == 0 AVCDecoderConfigurationRecord(AVC sequence header)
IF AVCPacketType == 1 One or more NALUs (Full frames are required)
AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的sps和pps信息,再给AVC解码器送数据 流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都 需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个 video tag.
AVCDecoderConfigurationRecord的定义在ISO 14496-15, 5.2.4.1中,这里不在详细贴,
SCRIPTDATA
如果TAG包中的TagType==18时,就表示这个TAG是SCRIPT.
SCRIPTDATA 结构十分复杂,定义了很多格式类型,每个类型对应一种结构.
| Field | Type | Comment |
| Type | UI8 | Type of the ScriptDataValue. The following types are defined: 0 = Number 1 = Boolean 2 = String 3 = Object 4 = MovieClip (reserved, not supported) 5 = Null 6 = Undefined 7 = Reference 8 = ECMA array 9 = Object end marker 10 = Strict array 11 = Date 12 = Long string |
| ScriptDataValue | IF Type == 0 DOUBLE IF Type == 1 UI8 IF Type == 2 SCRIPTDATASTRING IF Type == 3 SCRIPTDATAOBJECT IF Type == 7 UI16 IF Type == 8 SCRIPTDATAECMAARRAY IF Type == 10 SCRIPTDATASTRICTARRAY IF Type == 11 SCRIPTDATADATE IF Type == 12 SCRIPTDATALONGSTRING | Script data value. The Boolean value is (ScriptDataValue ≠ 0). |
类型在FLV的官方文档中都有详细介绍.
onMetaData
onMetaData 是SCRIPTDATA中对我们来说十分重要的信息,结构如下表:
| Property Name | Type | Comment |
| audiocodecid | Number | Audio codec ID used in the file (see E.4.2.1 for available SoundFormat values) |
| audiodatarate | Number | Audio bit rate in kilobits per second |
| audiodelay | Number | Delay introduced by the audio codec in seconds |
| audiosamplerate | Number | Frequency at which the audio stream is replayed |
| audiosamplesize | Number | Resolution of a single audio sample |
| canSeekToEnd | Boolean | Indicating the last video frame is a key frame |
| creationdate | String | Creation date and time |
| duration | Number | Total duration of the file in seconds |
| filesize | Number | Total size of the file in bytes |
| framerate | Number | Number of frames per second |
| height | Number | Height of the video in pixels |
| stereo | Boolean | Indicating stereo audio |
| videocodecid | Number | Video codec ID used in the file (see E.4.3.1 for available CodecID values) |
| videodatarate | Number | Video bit rate in kilobits per second |
| width | Number | Width of the video in pixels |
这里面的duration、filesize、视频的width、height等这些信息对我们来说很有用.
keyframes
当时在做flv demux的时候,发现官方的文档中并没有对keyframes index做描述,但是flv的这种结构每个tag又不像TS有同步头,如果没有keyframes index 的话,seek及快进快退的效果会非常差,因为需要一个tag一个tag的顺序读取。后来通过网络查一些资料,发现了一个keyframes的信息藏在SCRIPTDATA中。
keyframes几乎是一个非官方的标准,也就是民间标准.在网上已经很 难看到flv文件格式,但是metadata里面不包含 keyframes项目的视频 . 两个常用的操作metadata的工具是flvtool2和FLVMDI,都是把keyframes作为一个默认的元信息项目.在FLVMDI的主页 (http://www.buraks.com/flvmdi/)上有描述:
keyframes: (Object) This object is added only if you specify the /k switch. 'keyframes' is known to FLVMDI and if /k switch is not specified, 'keyframes' object will be deleted.
'keyframes' object has 2 arrays: 'filepositions' and 'times'. Both arrays have the same number of elements, which is equal to the number of key frames in the FLV. Values in times array are in 'seconds'. Each correspond to the timestamp of the n'th key frame. Values in filepositions array are in 'bytes'. Each correspond to the fileposition of the nth key frame video tag (which starts with byte tag type 9).
也就是说keyframes中包含着2个内容 'filepositions' and 'times'分别指的是关键帧的文件位置和关键帧的PTS.通过keyframes可以建立起自己的Index,然后再seek和快进快退的操作中,快速有效的跳转到你想要找的关键帧的位置进行处理。
相关文章:
FLV视频封装格式详解
目录(?)[-] OverviewFile Structure The FLV headerThe FLV File BodyFLV Tag Definition FLVTAGAudio TagsVideo TagsSCRIPTDATA onMetaDatakeyframes Overview Flash Video(简称FLV),是一种流行的网络格式。目前国内外大部分视频分享网站都是采用的这种格式. File Structure…...
搭建vue3+vant项目架构
git代码仓库,直接下载压缩包使用 1、首先要安装node.js(18.3 或更高版本) 2、创建vue3项目 npm create vuelatest然后按照自己的需要进行选择就行 到此vue3项目创建完成,接下来是搭建项目架构 3、配置Vant (移动端ui) vue3项目引入vant,…...
【Linux】进程间通信 -> 匿名管道命名管道
进程间通信的目的 数据传输:一个进程许需要将它的数据发送给另外一个进程。资源共享:多个进程之间共享同样的资源。通知事件:一个进程需要向另一个或一组进程发送消息,通知它们发生了某种事件(如进程终止时要通知父进程…...
大数据开发学习路线
编程语言: Python:数据分析、数据预处理 Java:Hadoop和许多大数据工具的基础 Scala:用于Apache Spark数据库知识: SQL和NoSQL数据库的基本概念 数据库系统如MySQL、MongoDB等操作系统: Linux基础命令和脚本…...
华为云计算HCIE笔记05
第七章:其它模式 灾备组网 高可用性组网,单核心场景下,直接在两个站点中设置一个第三方仲裁站点,两个站点同时连接到仲裁,并且连接到对方。一旦出现问题,则由仲裁站点进行判断,进行业务切换 双核…...
wordpress网站用token登入开发过程
生成跳转token 示例: function generate_login_token($user_id, $secret_key) {$payload [user_id > $user_id,timestamp > time(),];$payload_json json_encode($payload);$signature hash_hmac(sha256, $payload_json, $secret_key);return base64_en…...
Python基础知识回顾
数据类型 Python可以区分整数(integers、下文简写为int)、浮点数(float)、字符串(string)和布尔值(Boolean)等数据类型。 1)int是可正可负的整数 2)float包…...
C++--------效率和表示
C 效率和表示 效率 时间效率:在 C 中,不同的数据结构和算法有着各异的时间复杂度。例如,访问数组元素的时间复杂度是 O ( 1 ) O(1) O(1),而遍历链表查找元素的时间复杂度最坏情况下是 O ( n ) O(n) O(n)。选择合适的算法与数据…...
在 Ubuntu 服务器上添加和删除用户
在 Ubuntu 服务器上添加和删除用户通常使用命令行工具,如 adduser、useradd、deluser 等。以下是详细的步骤和说明: 添加用户 使用 adduser 命令 adduser 是一个更为友好的脚本,用于创建新用户并设置相关信息。 添加新用户 sudo adduser 用…...
安卓 SystemServer 启动流程
目录 引言 Android系统服务启动顺序 zygote fork SystemServer 进程 SystemServer启动流程 1、SystemServer.main() 2、SystemServer.run() 3、初始化系统上下文 4、创建系统服务管理 5、启动系统各种服务 总结 引言 开机启动时 PowerManagerService 调用 AudioSer…...
深度分析 es multi_match 中most_fields、best_fields、cross_fields区别
文章目录 1. multi_match 查询的类型1.1 best_fields(默认)1.2 most_fields1.3 cross_fields 2. 不同类型的示例查询示例数据: 3. 示例 1: 使用 best_fields查询:说明: 4. 示例 2: 使用 most_fields查询:说…...
中职计算机网络技术理实一体化实训室建设方案
构建理实一体化教学模式对于改善中等职业学校计算机网络技术课程的教学现状、提升教学质量和效率具有重要意义。在中职教育不断深化改革的背景下,积极推进理实一体化教学模式的发展,不仅能够提高计算机网络技术课程的教学水平,满足教育改革的…...
Java技术专家视角解读:SQL优化与批处理在大数据处理中的应用及原理
引言 在大厂架构中,提升系统性能和稳定性是技术团队的首要任务。SQL优化与批处理作为两大关键技术手段,对于处理大规模数据和高并发请求具有重要意义。本文将从Java技术专家的视角出发,深入探讨SQL优化与批处理在大数据处理中的应用及原理&a…...
数据结构(Java版)第六期:LinkedList与链表(一)
目录 一、链表 1.1. 链表的概念及结构 1.2. 链表的实现 专栏:数据结构(Java版) 个人主页:手握风云 一、链表 1.1. 链表的概念及结构 链表是⼀种物理存储结构上⾮连续存储结构,数据元素的逻辑顺序是通过链表中的引⽤链接次序实现的。与火车…...
云边端一体化架构
云边端一体化架构是一种将云计算、边缘计算和终端设备相结合的分布式计算模型。该架构旨在通过优化资源分配和数据处理流程,提供更高效、更低延迟的服务体验。 下面是对这个架构的简要说明: 01云计算(Cloud Computing) — 作为中心…...
人工智能之基于阿里云进行人脸特征检测部署
人工智能之基于阿里云进行人脸特征检测部署 需求描述 基于阿里云搭建真人人脸68个关键点检测模型,模型名称:Damo_XR_Lab/cv_human_68-facial-landmark-detection使用上述模型进行人脸关键点识别,模型地址 业务实现 阿里云配置 阿里云配置…...
基于高云GW5AT-15 FPGA的SLVS-EC桥MIPI设计方案分享
作者:Hello,Panda 一、设计需求 设计一个4Lanes SLVS-EC桥接到2组4lanes MIPI DPHY接口的电路模块: (1)CMOS芯片:IMX537-AAMJ-C,输出4lanes SLVS-EC 4.752Gbps Lane速率; (2&…...
MPLS小实验:利用LDP动态建立LSP
正文共:1234 字 19 图,预估阅读时间:2 分钟 通过上个实验(MPLS小实验:静态建立LSP),我们了解到静态LSP不依靠标签分发协议,而是在报文经过的每一跳设备上(包括Ingress、T…...
C++ 面向对象编程
面向对象编程(Object-Oriented Programming, OOP)是C语言的一个重要特性,它允许开发者以更直观和模块化的方式来设计和构建程序。OOP的四个主要原则是:封装(Encapsulation)、继承(Inheritance&a…...
我的Serverless实战——引领云计算的下一个十年,附答案
(Serverless模式下,按照实际消耗资源及使用存储进行计费) 4.更少的代码,更快的交付速度。 (Serverless提供成熟的代码构建发布、版本切换等特性,交付速度更快) Serverless由开发者实现的服务端逻…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
【2025年】解决Burpsuite抓不到https包的问题
环境:windows11 burpsuite:2025.5 在抓取https网站时,burpsuite抓取不到https数据包,只显示: 解决该问题只需如下三个步骤: 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.
ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #:…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...
React、Git、计网、发展趋势等内容——前端面试宝典(字节、小红书和美团)
React React Hook实现架构、.Hook不能在循环嵌套语句中使用 , 为什么,Fiber架构,面试向面试官介绍,详细解释 用户: React Hook实现架构、.Hook不能在循环嵌套语句中使用 , 为什么,Fiber架构,面试向面试官介绍&#x…...
【见合八方平面波导外腔激光器专题系列】用于干涉光纤传感的低噪声平面波导外腔激光器2
----翻译自Mazin Alalus等人的文章 摘要 1550 nm DWDM 平面波导外腔激光器具有低相位/频率噪声、窄线宽和低 RIN 等特点。该腔体包括一个半导体增益芯片和一个带布拉格光栅的平面光波电路波导,采用 14 引脚蝶形封装。这种平面波导外腔激光器设计用于在振动和恶劣的…...
MySQL 数据库深度剖析:事务、SQL 优化、索引与 Buffer Pool
在当今数据驱动的时代,数据库作为数据存储与管理的核心,其性能与可靠性至关重要。MySQL 作为一款广泛使用的开源数据库,在众多应用场景中发挥着关键作用。在这篇博客中,我将围绕 MySQL 数据库的核心知识展开,涵盖事务及…...
