FLV

  • 内部结构
    • 1. FLV Header
      • -- 内部结构图
      • -- 关键栏位
    • 2. FLV file body
  • FLV tag
    • 1. 类型
    • 2. FLV tag header
      • -- 内部结构图
      • -- 关键栏位
    • 3. Audio Tag Body
      • -- 内部结构图
      • -- 关键栏位
      • -- Audio config tag
      • -- Audio raw data tag
    • 4. Video Tag Body
      • -- 内部结构图
      • -- 关键栏位
      • -- Video config tag
      • -- Video raw data tag
      • -- video tag例子
      • -- 关于CompositionTime(cts)
    • 5.Script Tag Body
  • 实际应用遇到的问题

内部结构

FLV(Flash Video)是Adobe公司推出的一种媒体封装格式,适合流媒体传输。优点是封装简单,文件体积小。后缀为.flv。总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。

1. FLV Header

– 内部结构图

– 关键栏位

  • SigNature:开头三个字节,固定为 FLV 的ascii码(0x46 0x4c 0x56)
  • Version:表示FLV的版本号,比如FLV版本1,则该栏位是0x01
  • FlagsAudio:1表示有audio tag,0表示没有
  • FlagsVideo:1表示有video tag,0表示没有
  • DataOffset:表示FLV header的大小,单位为字节。对于FLV版本1,固定是9,也就是header总共9字节,有效字节有5个。

2. FLV file body

  • 由一系列tag和previousTagSize组成(如图: FLV结构图);
  • Tag的大小 = 11(tag header) + n(tag body),其中previousTagSize为4字节。
  • PreviousTagSize0总是0;其它PreviousTagSizeN的值表示TagN的大小,用于逆向读取处理(因为flv没有同步字节)。

FLV tag

  • 由tag header 和 tag body组成,tag header固定为11字节。如下图:

1. 类型

FLV tag分为3种类型:

  • Video Tag:存放视频相关数据
  • Audio Tag:存放音频相关数据
  • Script Tag:存放音视频元数据(metadata),一般会是第一个tag,紧跟着FLV header,有且只有一个。

2. FLV tag header

对于FLV版本1,tag header固定为11字节。

– 内部结构图

– 关键栏位

  • TagType:
    tag类型,1字节

    tag类型 含义
    0x8 该tag为audio tag
    0x9 该tag为video tag
    0x12 该tag为script tag
    其它 保留
  • DataSize:
    tag body的大小,3字节(不包含tag header的11字节),所以整个tag大小 = DataSize + 11。
  • TimeStamp:
    与第一个tag的时间戳差值,单位为毫秒,3字节。对于视频来说,就是DTS,单位为ms。
    第一个audio和video tag的Timestamp分别为0,亦表示解码顺序。
  • TimeStampExtended:
    时间戳的扩展字段,当Timestamp栏位不够用时,会启用这字段,表示最高八位。
  • StreamID:
    总是0。

3. Audio Tag Body

音频tag第一个字节包含音频数据的参数信息(固定的),从第二个字节开始为音频流数据。

– 内部结构图

– 关键栏位

  • SoundFormat:音频格式。

    ID format
    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 logrithmic PCM
    9 reserved
    10 AAC
    11 Speex
    14 MP3 8 kHz
    15 Device-specific sound
  • SoundRate:采样率。
    ID 采样率
    0 5.5 kHz
    1 11 kHz
    2 22 kHz
    3 44 kHz
  • SoundSize:采样位宽。对于压缩过的音频,一般是16位。
    ID 位宽
    0 8 Bits
    1 16 Bits
  • SoundType:声道类型。
    ID 声道数
    0 单声道
    1 双声道
  • SoundData:音频数据,
    对于AAC音频,也就是SoundFormat为10的case。
    从Tag的第二个字节起被称为AACAudioData,定义如下:

    字段 字段类型 字段含义
    AACPacketType UI8 0: AAC sequence header 1: AAC raw data
    Data UI8[n] AACPacketType为0,AudioSpecificConfigAACPacketType为1,AAC帧数据

– Audio config tag

即AACPacketType为0,Tag body第1个字节为简略的参数信息,第2个字节为AAC packet type,从第3个字节开始为audio specific config data。相比于tag body第一个字节中的参数信息,AudioSpecificConfig提供了更加详细的音频信息,它的定义在ISO14496-3中1.6.2.1。
一般的AudioSpecificConfig有2字节定义如下:

|AAC Profile 5bits | 采样率 4bits | 声道数 4bits | 其他 3bits |

对于AAC audio tag,FLV文件中第一个audio tag是audio config tag。
如下图为一个audio config tag的例子:

audio config tag结构图如下:

– Audio raw data tag

即AACPacketType为1的case,Tag body第1个字节为简略的参数信息,第2个字节为AAC packet type,从第3个字节开始为AAC raw data,如下图:

4. Video Tag Body

视频tag body第一个字节包含视频数据的参数信息(固定),从第二个字节开始为视频数据。

– 内部结构图

– 关键栏位

  • FrameType:帧类型

    ID 帧类型
    1 Keyframe;对于H264,IDR帧
    2 Inter frame;对于H264,普通I帧
    3 Disposable inter frame(H.263 only)
    4 generated keyframe
    5 video info (如sps、pps);
    command frame,普通的帧
  • Codec ID: 编解码器类型
    ID 编解码器类型
    1 JPEG
    2 Sorenson H.263
    3 Screen video
    4 On2 VP6
    5 On2 VP6 with alpha channel6
    7 AVC
  • VideoData:视频数据
    CodecID VideoDataType
    2 H263VideoPacket
    3 ScreenVideoPacket
    4 VP6FlvVideoPacket
    5 VP6FlvAlphaVideoPacket
    6 ScreenV2VideoPacket
    7 AVCVideoPacket

    其中,AVCVideoPacket的定义如下:

    字段 字段类型 字段含义
    AVCPacketType UI8 0:AVC sequence header,也就是sps和pps
    1:AVC NALU
    2:AVC end of sequence
    CompositionTime SI24 AVCPacketType == 1,该栏位有效,表示pts与dts的差值,单位ms;
    否则,为0
    Data UI8[n] AVCPacketType:
    0–> AVCDecoderConfigurationRecord
    1–> NALU(一个或多个)
    2–> 空

– Video config tag

即AVCPacketType为0的case,Tag body第一个字节固定为0x17(key frame,AVC),packet data里面是该视频的SPS和PPS。
下图为实例:

– Video raw data tag

即AVCPacketType为1的case,Packet data里面是NALU。
下图是实例:

– video tag例子

– 关于CompositionTime(cts)

CompositionTime表示pts相对于该帧dts的差值,CompositionTime= (pts – dts) ms
当B帧存在时,视频帧的pts和dts可能不同,dts在flv中是指tag header中的timestamp。
所以视频帧的pts = CompositionTime + timestamp。
如果B帧不存在,则CTS固定为0,也就是CompositionTime这个栏位0,
即pts = timestamp。

5.Script Tag Body

  • Script Tag通常用来存放跟FLV中音视频相关的元数据信息(onMetaData),比如时长、分辨率等。
    采用AMF(Action Message Format)封装了一系列数据类型,如字符串,数值,数值等。
  • AMF格式的有一系列Object和SCRIPTDATAOBJECTEND(0x9,表示script data结束),示意图如下:
  • 在Script tag中一般包含2个AMF包。
    1> 第一个AMF包,内容固定,分别为:▪ 第1个字节:固定为0x02,表示字符串类型▪ 第2-3个字节:UI16类型,固定为0x000A,表示字符串的长度为10(onMetaData的长度);▪ 第4-13个字节:字符串onMetaData对应的16进制数字(0x6F 0x6E 0x4D 0x65 0x74 0x61 0x44 0x61 0x74 0x61);(这个包与Adobe的一些API调用有关)2> 第二个AMF包:▪ 第1个字节:固定为0x08,表示数组类型;▪ 第2-5个字节:UI32类型,表示数组的长度,onMetaData中具体包含哪些属性是不固定的。▪ 第6个字节+:比如该AMF包表示duration,则:○ 第6-9个字节:0x0008,表示长度为8个字节;○ 第10-17个字节:0x64 75 72 61 74 69 6F 6E,表示 duration 这个字符串;○ 第18个字节:固定为0x00,表示为数值类型;○ 第19-26个字节:0x...,表示具体的时长;
    

    解析出来的script tag为:

    那说明总共有26组元数据信息,比如duration为391.495s,分辨率为1280X720


实际应用遇到的问题

  1. 如何probe一个数据流为FLV类型?
    满足以下三个条件:

    i. "FLV"。数据流开头前3个字节是'F', 'L', 'V' --> FLV Header前3个字节固定是'F', 'L', 'V'
    ii. 保留位。数据流第5个字节 & 0xf2的值为0  --> FLV Header前5个字节的高5位和第7位为保留位,固定为0
    iii. 大小。数据流第6个字节到第9个字节固定为 0x 00 00 00 09  --> FLV Header的长度固定为9个字节,记录与FLV Header最后4个字节。
    
  2. 如何获得FLV文件的duration?
    首先,从Script tag中的duration metadata中获取duration。
    然后,拿到第一个video tag的timestamp 和 最后一个video tag的timestamp,两者的差值就是duration(单位ms)

  3. 如何识别一个tag,并且一个一个tag的读取数据?
    识别方法是:先找到一个字节为0x08、0x09或者0x12,如果是tag的话,那么后面三个字节为datasize,在往后跳(datasize + 11 + 4)bytes,如果第一个字节还是0x08、0x09或者0x12,再往后跳(datasize + 11 + 4)bytes,如此循环判断五次,每次都找到0x08、0x09和0x12的话,那说明第一个找到的字节为一个tag的开始。如果有一个找不到的话,那就寻找下一个字节为0x08、0x09或者0x12,按照上述方式再进行判断。

  4. 如何seek?
    ▪ FLV官方标准对seek的支持不好,每次seek都必须从当前位置加载tag数据,直到目标位置,从而导致缓冲时间长,效果极差。
    ▪ 而较为常用但非官方的做法是在Script Tag中加入keyframe字段,用来建立关键帧时间点和文件位置的映射表。
    ▪ keyframe字段包含file positions和times两个数组,times为关键帧时间点数组,filepositions数组为关键帧在文件中偏移量数组。两个数组的长度相同,类型为double类型,且fileposition和time一一对应。借助keyframe字段,seek过程是:

    i. 根据用户想要seek的时间点,在times数组中比对最接近值,拿到该值对应数组索引,记为KeyframeIndex
    ii. 根据keyframeIndex,在fileposition数组中取得对应的偏移量,记为keyframeOffset
    iii. 从该偏移量开始读取数据即可完成seek播放。
    

封装格式 -- FLV相关推荐

  1. FLV 封装格式解析

    本文为作者原创,转载请注明出处:https://www.cnblogs.com/leisure_chn/p/10662941.html FLV (Flash Video) 是由 Adobe 公司推出的 ...

  2. 将h.264视频流封装成flv格式文件(一.flv格式)

    原帖地址:http://blog.csdn.net/yeyumin89/article/details/7932368 原帖虽然贵为好贴,看感觉看起来有点乱,没有层次感,贴过来,修改下格式,阅读起来方 ...

  3. 视音频编解码学习工程:FLV封装格式分析器

    ===================================================== 视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习 ...

  4. LiveVideoStack线上分享第三季(十四):FLV封装格式介绍及解析

    随着流媒体的高速发展,FLV成为了最主流的视频流传输封装格式,但是作为占市场较大份额的Web端的实际应用中,各大浏览器却没有对FLV解码做完善的支持.8月17日 20:00,LiveVideoStac ...

  5. FLV封装格式分析器

    ===================================================== 视音频编解码学习工程系列文章列表: 视音频编解码学习工程:H.264分析器 视音频编解码学习 ...

  6. FLV封装格式介绍及解析

    FLV(Flash Video)是Adobe公司推出的一种流媒体格式,由于其封装后的音视频文件体积小.封装简单等特点,非常适合于互联网上使用.目前主流的视频网站基本都支持FLV.采用FLV格式封装的文 ...

  7. FLV封装格式的分析

    FLV封装格式的分析,各种详细的参数比较多没有详细解释,这是总体的格式分布.详细的参数说明可以参照文档. 以flv格式内封装的音频流是aac.视频流是h264分析: flv文件tag部分截图:可以看到 ...

  8. java封装264成flv,将H.264封装为FLV格式-Go语言中文社区

    本文将介绍如何将H.264封装成flv格式. 在看本文之间,建议先看一看下面两篇文章: 首先说一说构建一个FLV文件需要什么? FLV Header + FLv script tag + FLV Vi ...

  9. 我的开源项目:FLV封装格式分析器

    本文介绍一个自己的开源小项目:FLV封装格式分析器.FLV全称是Flash Video,是互联网上使用极为广泛的视频封装格式.像Youtube,优酷这类视频网站,都使用FLV封装视频.我这个项目规模不 ...

最新文章

  1. 泪目!兰大硕导的《致谢》火了:我从来不曾优秀过,也从来不曾放弃过!
  2. 漫画 | 如何用 Kubernetes 实现 CI/CD 发布流程?
  3. UiPickerView基本使用方法
  4. C# Replace字符替换函数
  5. thymeleaf 获取yml中的值_Thymeleaf模板引擎学习
  6. Ajax的JSP示例以及相关知识介绍,适合于入门者
  7. Linux中 Vi的使用
  8. Notepad2 巧妙替换回车换行符
  9. CodeGym—Java自学神器
  10. [ZT]IBM骨灰心得:在你决定购买IBM某个系列前你认真思考过这些吗?
  11. 用Python合并多个txt文件
  12. html怎么控制文字的行数,CSS3属性 line-clamp控制文本行数的使用
  13. android 签到自定义,Android日历签到,超级简单的实现方式
  14. GoLang之图解panic recover
  15. html 页面长度单位,css绝对长度单位有哪些?
  16. 如何通过织云Lite愉快地玩转TSW
  17. 家里网络连不上outlook_家里OUTLOOK上不了如何处理--
  18. MSB30M-ASEMI贴片整流桥MSB30M
  19. AE(Aeternity)项目分析
  20. Solaris 11 安装桌面

热门文章

  1. Expected the Promise rejection reason to be an Error
  2. JQuery-jq属性操作、jq文本属性值、jq元素(创建、添加、移除)操作、jq尺寸、位置操作
  3. ChatGPT启示录: 智能、推理的本质是什么?神经网络既是推理机,也是知识规则库?
  4. Qt快速读取Excel文件
  5. SPI FLASH 二线/四线模式
  6. 我的世界java萌新须知_我的世界萌新游戏指南 萌新第一天都应该做什么?
  7. myeclipse启动异常——tomcat启动失败
  8. 儿童写作业的台灯怎么选择?2023给孩子买台灯最新推荐一下
  9. ESD监控系统、防静电闸机的应用案例
  10. 程序员必须学会释放压力——对程序员的3条另类忠告