回 帖 发 新 帖 刷新版面

主题:[原创]FLV文件数据结构以及读取其脚本信息的代码

FLV(Flash Video)是现在非常流行的流媒体格式,文件体积小巧、封装播放简单,目前主流视频网站的标清视频无一例外地使用了FLV格式。
宏观上看,FLV包括文件头(File Header)和文件体(File Body)两部分。文件体由一系列的标签组成,标签又可以分成三类:音频标签、视频标签、脚本标签,且每个标签只能包含一种类型的数据。
FLV文件中最多只能有一个视频流和一个音频流,不能封装两个或以上的同一类型的流数据。
FLV文件使用big-endian字序,也就是我们通常所说的高位在前低位在后。整型数值一般都是UI24类型,使用3字节表示。


一、文件头的结构
FLV的文件头结构很简单,在当前版本中由9个字节组成,见表1。


表1 文件头的结构
-------------------------------------------------------
项目      长度(字节) 说明
-------------------------------------------------------
格式签名   3   文件标识,必须是“FLV”3个大写字母
版本     1   FLV文件的版本
类型标志位  1   包括四部分说明信息
文件体偏移量 4   文件体的起始地点,也是文件头的大小
 ------------------------------------------------------
说明:
1.类型标志位的1个字节,其中高5位和第2位保留,必须=0,第1位表示是否有视频,第3位表示是否有音频。
2.数据偏移量的值在版本1中=9。如果头部中包含了其它信息,这个长度就≠9了。
3.FLV文件中的长度或大小类的数值使用big-endian字序。


二、文件体的结构
文件体是由很多标签组成的,其结构见表2。


表2 文件体的结构
---------------------------------
项目    长度(字节) 说明
---------------------------------
标签0大小  4     恒为0
标签 1
标签1大小  4
标签 2
标签2大小  4
……
标签 N-1
标签N-1大小 4
标签 N
标签N大小  4
----------------------------
说明:
1.注意标签大小是跟在对应的标签后面的,这一点与许多媒体文件的结构是不同的。
2.注意标签大小不包括本身所占用的4字节。
3.标签0的大小≡0,表示没有标签0。


三、标签结构 
标签包括标签头和标签数据区两部分。不同类型的标签,其头结构是相同的,只是标签数据的结构各不相同。标签头的结构见表3。


表3 标签头的数据结构
---------------------------------------
项目        长度(字节) 说明
---------------------------------------
标签类型  1     目前只有3类
数据区大小 3     标签数据区的大小
时间戳   3
扩展时间戳 1
流ID    3     ≡0
---------------------------------------
说明:
1.标签类型目前只有3类:8表示音频标签,9表示视频标签,18表示脚本标签。其它值被保留。
2.时间戳表示该标签从什么时间开始播放,这是一个UI24类型((该类型为3字节的整型数据,VB中没有对应的数据类型)的值。时间戳的单位为ms。标签1的时间戳=0,脚本标签的时间戳也=0(实际上脚本标签一般就是标签1)。 
3.扩展时间戳是当时间戳的3字节24位不够用时,该字节作为最高位(注意是最高位)将时间戳扩展为32位值。 
4.数据区大小不包括标签头的11字节,也不包括表2中的标签大小项目本身占用的4字节,标签头之后紧接着就是标签数据区。
5.标签大小=数据区大小+标签头长度。


四、音频标签数据区的结构 
音频标签数据区的第1个字节包含了音频数据的参数信息,从第2个字节开始为音频流数据。 
第1个字节的的含义,见表4、表5、表6、表7,数据位从左至右。


表4 前4位表示音频数据的格式
--------------------------
值  含义
--------------------------
0  未压缩 
1  ADPCM 
2  MP3 
5  Nellymoser 8kHz momo 
6  Nellymoser 
--------------------------
说明:
1.Nellymoser 8kHz 是一个特殊的类型,8kHz采样率在其它格式中不被支持。当音频格式是Nellymoser 8kHz mono的时候,采样精度(见表6)和音频类型(见表7)被忽略了。
2.对于其它的 Nellymoser,采样率,采样精度、音频类型照常。


表5 第5-6位的数值表示采样率
---------------
值  含义
---------------
0  5.5kHz
1  11kHz
2  22kHz
3  44kHz
---------------


表6 第7位表示采样精度
--------------
值  含义
--------------
0  8位
1  16位
--------------


表7 第8位表示音频类型
--------------
值  含义
--------------
0  单声道
1  立体声 
--------------

回复列表 (共8个回复)

沙发

五、视频标签数据区的结构
  视频标签数据区的第1个字节包含了视频数据的参数信息,从第2个字节开始为视频流数据。
  第1个字节的含义见表8、表9,数据位从左至右。

表8 前4位的数值表示帧类型
-------------------------------------------------------------
值  含义
-------------------------------------------------------------
1  关键帧(keyframe)
2  中间帧(inner frame)
3  可任意使用的中间帧(disposable inner frame (H.263 only))
-------------------------------------------------------------
说明:
  1.关键帧存储的是整个画面完整的数据,可以提取它来生成图片。
  2.中间帧是关键帧之间的状态,不完整的画面数据,需要依靠前面帧的数据生成。

表9 后4位的数值表示视频编码ID
-------------------------------------------------
值  含义
-------------------------------------------------
1  JPEG(现已不用)
2  Seronson H.263(mencoder转换所使用的视频编码)
3  Screen video
4  On2 VP6
5  On2 VP6 without channel
6  Screen video version 2
-------------------------------------------------


六、脚本标签数据区的结构
  脚本标签通常又被称为元数据标签(Metadata Tag),包含一些关于FLV视频和音频的参数信息,如持续时间(duration)、视频宽度和高度等。通常脚本标签紧跟在文件头后面作为第一个标签出现,并且一般只有一个。
  一般来说,脚本标签数据区的结构就包含两个AMF包。AMF(Action Message Format)是Adobe设计的一种通用数据封装格式,在Adobe的很多产品中应用。简单来说,AMF将不同类型的数据用统一的格式来描述。
  第一个AMF包封装字符串类型数据,用来装入一个"onMetaData"标志,这个标志与Adobe的一些API调用有关,在此不详述。
  第二个AMF包封装一个数组类型,这个数组中包含了一些媒体信息:例如视频的高、宽和编码ID、帧率;音频的信息如采样率、编码ID、样本大小、是否立体声,还有整个文件的大小等等。
  具体说明见表10。

表10 脚本标签数据区的结构
------------------------------------------
字节序 项目及意义
------------------------------------------
  ***第一个AMF包***
1    AMF包类型,一般总是02,表示字符串
2—3  包内容长度,一般总是00 0A
4—13  包内容,一般总是"onMetaData"

  ***第二个AMF包***
14   AMF包类型,一般总是08,表示ECMA数组
15—18 ECMA数组元素个数
19—  数组元素1
    数组元素2
    ……
    数组元素N
最后3字节为数组结束标志,≡00 00 09
-------------------------------------------
说明:
  1.AMF包的类型见表13。
  2.从第19字节起,后面即为各数组元素。
  3.这里的数组与我们在VB编程中的数组大不一样,别弄混了。ECMA数组元素的结构,见表11。

表11 ECMA数组元素的结构
------------------------------------------
字节序  项目及含义
------------------------------------------
1—2   数组元素名称的长度,假设为L
3—L+2  数组元素名称(字符串)
L+3    元素值类型
L+4—   元素值
*L+4—L+5 元素值长度(如果元素值是字符串)
*L+6—  元素值(字符串)
------------------------------------------
说明
  1.元素值占用字节数取决于值的类型。
  2.如果元素值类型为字符串,那么在元素值类型之后就还有2字节的长度(表11中星号所表示的项
目)。如果为长字符串,那么在元素值类型之后就有4字节的长度,相应地,元素值的字节序要后推4字
节。
  3.常用的数组元素名称见表12。
  4.元素值类型见表13。

板凳

表12 常用数组元素名称
-----------------------------------------------------
名称          中译义       数据类型
-----------------------------------------------------
audiocodecid      音频编码ID      双精度
audiodatarate     音频位率(千字节/秒) 双精度
audiodelay       音频延迟       双精度
audiosamplerate    音频采样率      双精度
audiosamplesize    音频采样大小     双精度
audiosize       音频大小       双精度
canSeekToEnd      能否查找到结束    布尔
creator        创作者        字符串
cuePoints       提示点        ECMA数组
datasize        数据大小       双精度
duration        持续时间(秒)    双精度
encoder        编码器        字符串
filepositions     文件位置       精确数组
filesize        文件大小       双精度
framerate       帧速率(帧/秒)    双精度
hasAudio        是否有音频      布尔
hasKeyframes      是否有关键帧     布尔
hasMetadata      是否有元数据     布尔
hasVideo        是否有视频      布尔
height         视频高度       双精度
keyframes       关键帧        对象
lastkeyframelocation  最后一个关键帧位置  双精度
lastkeyframetimestamp 最后一个关键帧时间戳 双精度
lasttimestamp     最后一个时间戳    双精度
metadatacreator    元数据创建者     字符串
stereo         是否立体声      布尔
times         概述(次数)     精确数组
width         视频宽度       双精度
videocodecid      视频编码ID      双精度
videodatarate     视频位率(千位/秒)   双精度
videosize       视频大小       双精度
-----------------------------------------------------
说明:
  1.数组元素名称一般是小写字母。
  2.canSeekToEnd的意思是:如果FLV文件是用最后一帧(它允许定位到渐进式下载影片剪辑的末尾)上的关键帧编码的,则该值为1,如果FLV文件不是用最后一帧上的关键帧编码的,则该值为0。
  3.只有duration(持续时间)这个元素是必须的,其它的元素都是可选的。
  4.据笔者观察,lasttimestamp(最后一个时间戳)=duration(持续时间)。

表13 AMF包及数组元素的常用类型
-----------------------------------
值  类型     说明  占用字节
-----------------------------------
0  Number    双精度  8
1  Boolean    布尔   1
2  String    字串   不定
3  Object    对象   2
4  MovieClip   视频剪辑
5  Null
6  Undefined   未定义
7  Reference   参考
8  ECMA array  ECMA数组
A  Strict array 精确数组
B  Date     日期
C  Long string  长字串  不定
-----------------------------------
说明:
  1.笔者经过多次实验,发现FLV文件的双精度值虽然也占用8个字节,但字节的排列顺序与VB的双精度值完全相反,如果用VB的双精度变量去读硬盘上的FLV文件的双精度值,你只会得到一个莫名其妙的数值,所以必须用CopyMemory这个API函数把8个字节复制到Double变量里面,具体做法见下面的代码。
  2.由双精度值的字节排列顺序,以及文件体中的所谓“标签0大小”这个项目,笔者推测,FLV解码时可能是从后向前的,这样双精度值的字节排列顺序就正好符合要求,而“标签0大小”的4个为0的字节可能是文件体的结束标志。


七、FLV视频合并的注意事项
  从网上下载的FLV视频,有许多是零碎的小片断,可以自己编个程序,将它们合并成一个文件。合并的注意事项最重要的有三点:
  1.只有第一个FLV文件才需要保留脚本标签,删除后面的FLV文件的脚本标签。
  2.更改第一个FLV文件脚本标签中的持续时间值,把后面的FLV文件的持续时间都加上去。这里要注意的是:FLV文件与VB的双精度值的字节顺序是相反的。
  3.后面的FLV文件中,所有视频标签和音频标签中的时间戳,要加上第一个FLV文件中的“持续时间”这个元素值,再加上56(视频标签时间戳)或26(音频标签时间戳,加26是因为FLV的音频类型基本上都是mp3,而mp3每帧的时长都是26ms)。


八、读取脚本标签信息的代码
  下面的代码你复制到记事本后,另存为“Form6.frm”,然后用添加现存窗体的方法,把它添加到你自己的工程中。
  本代码只读取了脚本标签中的9个元素,你可以参考表12增加自己需要的元素。

3 楼

遗憾,代码传不上,总说有错误。
需要代码的请在跟贴中写上你的邮箱地址,我直接发到你邮箱去。

4 楼

我邮箱wedown@163.com
谢谢大神 了!

5 楼

这几天总进不了这个栏目,总说发生错误(不知大家进这个栏目是否这个情况?我用的是360极速浏览器),刚才碰巧又能进了。
代码已经发到孙瑞的邮箱。

6 楼

[quote]这几天总进不了这个栏目,总说发生错误(不知大家进这个栏目是否这个情况?我用的是360极速浏览器),刚才碰巧又能进了。
代码已经发到孙瑞的邮箱。[/quote]
终于现在论坛恢复了。我找个时间整理下。

7 楼

很长一段时间论坛进不来。楼主还在开发么?可以发我么?1583336933@QQ.com

8 楼

可到163邮箱下载。

帐号:vb62013

密码:vb620132013

我来回复

您尚未登录,请登录后再回复。点此登录或注册