【视音频处理】FLV文件格式详解

2023-10-13 15:58

本文主要是介绍【视音频处理】FLV文件格式详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

简介

FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧、封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式。另外由于当前浏览器与Flash Player紧密的结合,使得网页播放FLV视频轻而易举,也是FLV流行的原因之一。

FLV是流媒体封装格式,我们可以将其数据看为二进制字节流。总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。

 

FLV格式解析

先来一张图,这是《东风破》——周杰伦(下载)的一个MV视频。我使用的是Binary Viewer的二进制查看工具。

1.png

 

header

头部分由一下几部分组成
Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)

  • signature 占3个字节
    固定FLV三个字符作为标示。一般发现前三个字符为FLV时就认为他是flv文件。
  • Version 占1个字节
    标示FLV的版本号。这里我们看到是1
  • Flags 占1个字节
    内容标示。第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)。截图看到是0x05,也就是00000101,代表既有视频,也有音频。
  • DataOffset 4个字节
    表示FLV的header长度。这里可以看到固定是9

body

FLV的body部分是由一系列的back-pointers + tag构成

  • back-pointers 固定4个字节,表示前一个tag的size。
  • tag 分三种类型,video、audio、scripts。

tag组成

tag type+tag data size+Timestamp+TimestampExtended+stream id+ tag data

  • type 1个字节。8为Audio,9为Video,18为scripts
  • tag data size 3个字节。表示tag data的长度。从streamd id 后算起。
  • Timestreamp 3个字节。时间戳
  • TimestampExtended 1个字节。时间戳扩展字段
  • stream id 3个字节。总是0
  • tag data 数据部分

我们根据实例来分析:
看到第一个TAG
type=0x12=18。这里应该是一个scripts。
size=0x000125=293。长度为293。
timestreamp=0x000000。这里是scripts,所以为0
TimestampExtended =0x00
stream id =0x000000
我们看一下TAG的data部分:

3.png

 

tag的划分

图中红色部分是我标出的两个back-pointers,都是4个字节。而中间就是第一个TAG。那是怎么计算的呢?我们就以这个做个示例。

  • 首先第一个back-pointers是0x00000000,那是因为后面是第一个TAG。所以他为0。
  • 然后根据我们我们前面格式获取到size是0x000125。也就是说从stream id后面再加上293个字节就到了第一个TAG的末尾,我们数一下一下。stream id以前总共有24个字节(9+4+11)。那么到第一个TAG结束,下一个TAG开始的位置是293+24=137=0x13D
  • 接下来我们找到0x13D的地址,从工具上很容易找到,正好就是红色下划线的前面。红色部分是0x00000130=304,这代表的是上一个TAG的大小。
  • 最后我们计算一下,上一个TAG数据部分是293个字节,前面type、stream id等字段占了11个字节。正好是匹配的。

上面我们已经知道了怎么取划分每个TAG。接下来我们就看TAG的具体内容

tag的内容

前面已经提到tag分3种。我们一个个看

script

脚本Tag一般只有一个,是flv的第一个Tag,用于存放flv的信息,比如duration、audiodatarate、creator、width等。
首先介绍下脚本的数据类型。所有数据都是以数据类型+(数据长度)+数据的格式出现的,数据类型占1byte,数据长度看数据类型是否存在,后面才是数据。
一般来说,该Tag Data结构包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用,简单来说,AMF将不同类型的数据用统一的格式来描述。第一个AMF包封装字符串类型数据,用来装入一个“onMetaData”标志,这个标志与Adobe的一些API调用有,在此不细述。第二个AMF包封装一个数组类型,这个数组中包含了音视频信息项的名称和值。具体说明如下,大家可以参照图片上的数据进行理解。

类型说明
0Number type8 Bypte Double
1Boolean type1 Bypte bool
2String type后面2个字节为长度
3Object type 
4MovieClip type 
5Null type 
6Undefined type 
7Reference type 
8ECMA array type数组,类似Map
10Strict array type 
11Date type 
12Long string type后面4个字节为长度

4.png

 

上图为第一个AMF包

  • type=0x02对应String
  • size=0A=10
  • value=onMetaData 正好是10个字节。

     

    5.png

     

    上图为第二个AMF

  • type=0x08 对应ECMA array type。

表示数组,类似Map。后面4个字节为数组的个数。然后是键值对,第一个为键,2个字节为长度。后面跟具体的内容。接着3个字节表示值的类型,然后根据类型判断长度。
上图我们可以判断,总共有13个键值对。
第一个长度为8个字节是duration。值类型是0x004073,第一个字节是00,所以是double,8个字节。
第二个长度5个字节是width。值也是double类型,8个字节。
依次解析下去...

到处,我们已经知道了如何解析FLV中Tag为script的数据。

video

 

6.png


type=0x09=9。这里应该是一个video。
size=0x000030=48。长度为48。
timestreamp=0x000000
TimestampExtended =0x00
stream id =0x000000
我们看到数据部分:
视频信息+数据

 

视频信息,1个字节。

前4位为帧类型Frame Type

类型
1keyframe (for AVC, a seekable frame) 关键帧
2inter frame (for AVC, a non-seekable frame)
3disposable inter frame (H.263 only)
4generated keyframe (reserved for server use only)
5video info/command frame

后4位为编码ID (CodecID)

类型
1JPEG (currently unused)
2Sorenson H.263
3Screen video
4On2 VP6
5On2 VP6 with alpha channel
6Screen video version 2
7AVC

特殊情况

视频的格式(CodecID)是AVC(H.264)的话,VideoTagHeader会多出4个字节的信息,AVCPacketType 和CompositionTime。

  • AVCPacketType 占1个字节
类型
0AVCDecoderConfigurationRecord(AVC sequence header)
1AVC NALU
2AVC end of sequence (lower level NALU sequence ender is not required or supported)

AVCDecoderConfigurationRecord.包含着是H.264解码相关比较重要的spspps信息,再给AVC解码器送数据流之前一定要把sps和pps信息送出,否则的话解码器不能正常解码。而且在解码器stop之后再次start之前,如seek、快进快退状态切换等,都需要重新送一遍sps和pps的信息.AVCDecoderConfigurationRecord在FLV文件中一般情况也是出现1次,也就是第一个video tag.

  • CompositionTime 占3个字节
条件
AVCPacketType ==1Composition time offset
AVCPacketType !=10

我们看第一个video tag,也就是前面那张图。我们看到AVCPacketType =0。而后面三个字节也是0。说明这个tag记录的是AVCDecoderConfigurationRecord。包含sps和pps数据。
再看到第二个video tag

 

8.png


我们看到 AVCPacketType =1,而后面三个字节为000043。这是一个视频帧数据。

 

解析到的数据完全符合上面的理论。

sps pps

前面我们提到第一个video 一般存放的是sps和pps。这里我们具体解析下sps和pps内容。先看下存储的格式(图6):
0x01+sps[1]+sps[2]+sps[3]+0xFF+0xE1+sps size+sps+01+pps size+pps
我们看到图 。
sps[1]=0x64
sps[2]=00
sps[3]=0D
sps size=0x001B=27
跳过27个字节后,是0x01
pps size=0x0005=5
跳过5个字节,就到了back-pointers。

视频帧数据

解析出sps和pps tag后,后面的video tag就是真正的视频数据内容了

9.png


这是第二个video tag其实和图8一样,只是我圈出来关键信息。先看下格式
frametype=0x17=00010111
AVCPacketType =1
Composition Time=0x000043
后面就是NALU DATA

 

Audio

与视频格式类似
前4位为音频格式

类型
0Linear PCM, platform endian
1ADPCM
2MP3
3Linear PCM, little endian
4Nellymoser 16-kHz mono
5Nellymoser 8-kHz mono
6Nellymoser
7G.711 A-law logarithmic PCM
8G.711 mu-law logarithmic PCM
9reserved
10AAC
11Speex
14MP3 8-Khz
15Device-specific sound

接着2位为采样率

类型
05.5-kHz
111-kHz
222-kHz
344-kHz

对于AAC总是3

接着1位为采样的长度

类型
0snd8Bit
1snd16Bit

压缩过的音频都是16bit

接着1位为音频类型

类型
0sndMono
1sndStereo

对于AAC总是1

我们看到第三个TAG

7.png

 

这个留给大家自己来解析吧。


 

这篇关于【视音频处理】FLV文件格式详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/204317

相关文章

Spring Boot中的路径变量示例详解

《SpringBoot中的路径变量示例详解》SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及... 目录一. 基本用法与参数映射1.路径定义2.参数绑定&nhttp://www.chinasem.cnbs

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

Redis中Stream详解及应用小结

《Redis中Stream详解及应用小结》RedisStreams是Redis5.0引入的新功能,提供了一种类似于传统消息队列的机制,但具有更高的灵活性和可扩展性,本文给大家介绍Redis中Strea... 目录1. Redis Stream 概述2. Redis Stream 的基本操作2.1. XADD

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用