【视音频处理】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 Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

K8S(Kubernetes)开源的容器编排平台安装步骤详解

K8S(Kubernetes)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。以下是K8S容器编排平台的安装步骤、使用方式及特点的概述: 安装步骤: 安装Docker:K8S需要基于Docker来运行容器化应用程序。首先要在所有节点上安装Docker引擎。 安装Kubernetes Master:在集群中选择一台主机作为Master节点,安装K8S的控制平面组件,如AP

嵌入式Openharmony系统构建与启动详解

大家好,今天主要给大家分享一下,如何构建Openharmony子系统以及系统的启动过程分解。 第一:OpenHarmony系统构建      首先熟悉一下,构建系统是一种自动化处理工具的集合,通过将源代码文件进行一系列处理,最终生成和用户可以使用的目标文件。这里的目标文件包括静态链接库文件、动态链接库文件、可执行文件、脚本文件、配置文件等。      我们在编写hellowor

LabVIEW FIFO详解

在LabVIEW的FPGA开发中,FIFO(先入先出队列)是常用的数据传输机制。通过配置FIFO的属性,工程师可以在FPGA和主机之间,或不同FPGA VIs之间进行高效的数据传输。根据具体需求,FIFO有多种类型与实现方式,包括目标范围内FIFO(Target-Scoped)、DMA FIFO以及点对点流(Peer-to-Peer)。 FIFO类型 **目标范围FIFO(Target-Sc

019、JOptionPane类的常用静态方法详解

目录 JOptionPane类的常用静态方法详解 1. showInputDialog()方法 1.1基本用法 1.2带有默认值的输入框 1.3带有选项的输入对话框 1.4自定义图标的输入对话框 2. showConfirmDialog()方法 2.1基本用法 2.2自定义按钮和图标 2.3带有自定义组件的确认对话框 3. showMessageDialog()方法 3.1

Thymeleaf:生成静态文件及异常处理java.lang.NoClassDefFoundError: ognl/PropertyAccessor

我们需要引入包: <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework</groupId><artifactId>sp