视频点播(目前主要指MP4和FLV视频点播),是一个曾经很热,现如今依然很热的一项视频服务技术,MP4点播目前已经通过nginx+lua+mp4模块+slice模块实现,因此本节主要以FLV点播实现为主。
FLV在H.264的视频规格或是AAC的音源规格都达到功能极限,为了克服这个格式上的限制,F4V于是诞生,F4V是基于ISO base media file format制定出来的容器格式(Container format),与MP4格式相同,至少于Flash Player 12.0 update 3以上版本才能播放,F4V支持的视频类型为H.264、GIF、PNG以及JPEG,音频类型为AAC以及MP3。在国内许多的视频网站,均把存放H.264编码视频的FLV文件标注为.f4v格式,而这种文件的点播实现方式和普通的FLV是有所不同的,所以,为了避免更加混淆,继续沿用了它们的命名方式,因此,“FLV”将仅指不包含H.264/AAC编码的一般FLV视频。
FLV视频拖拉的主要工作原理是:根据用户传入的offset,找到关键帧最接近的offset,并修改metadata,最后将组装的metadata和视频数据发送给用户,需要注意的是如果是H.264格式,需要将第一个video tag和audio tag加到metadata之后一起传送给用户。
FLV(Flash Video)是Adobe公司推出的视频格式,是一种专门用来在网络上传输的视频存储容器格式,其格式相对简单,不需要很大的媒体头部信息,因此加载速度极快,国内各大视频网站,均有采用FLV格式作为其点播、甚至直播的视频格式。
FLV容器格式的主要特点是tag,整个FLV由Video Tag、Audio Tag以及其他Tag组成,没有映射表,基本上可以把FLV格式简要画为如下形式:
第5个字节的第8个bit视频类型标志(TypeFlagsVideo),表示是否有视频;
FLV tag主要有3种类型:音频、视频和脚本流(也称metadata)。tag头一般由15个字节组成=prev_tag_size(4字节)+tag header。
(1)1-4:主要标记上个tag的总体大小(11字节+tag data);
(2)5:标记该tag的类型;
(3)6-8:tag数据大小;
(4)9-11:时间戳,以ms为单位;
(5)12:扩展的时间戳;
(6)13-15:stream ID,一般为0;
备注:计算时间戳,需要重新组装这4个字节:
FLV文件中的元信息,是一些描述flv文件各类属性的信息如作者、视频宽高、时长、关键帧列表等,这些信息以AMF格式保存在文件的起始部分,这些信息虽然很重要,但是因为FLV的MetaData是可有可无的且准确性不够,这导致MetaData非常不值得信赖,因此在解析FLV的时候,应该直接忽略FLV MetaData部分,通过遍历FLV的所有Tag,来获取相应的媒体信息。(FLV视频拖拉却强依赖于metadata,否则无法实现拖拽)
在FLV tag中,该类型tag属于script tag(控制帧),会放一些关于FLV视频和音频的元数据信息如duration、width、heigh等,通常该类型tag会跟在FLV header后面作为第一个tag出现,而且有且只有一个。
AMF主要有以下类型组成:
普通FLV文件头信息中不带关键帧信息,在网页播放器中播放时,拖拉速度很慢,为了加快FLV视频的拖拉速度,需要在FLV头信息中写入关键帧信息。
主要方法为在写头信息时预留一定的位置用来写关键帧信息,在写包时包关键帧信息先保存起来,等到写文件结束时,根据需要把保存的关键帧信息写到预留的头信息中。
keyframes格式一般由times和filepositions组成,这也是FLV视频可以拖拉的关键点:
备注:video数据的第一个字节前4位标记该帧是否为关键帧,5-8位标记编码格式,如果是AVC(H.264)编码则需要在支持FLV拖拉的时候,将第一个video tag同步加上(配置信息在该tag中),否则无法正常播放。
备注:audio数据的第一个字节前4位标记编码格式,如果是AAC(H.264)编码则需要在支持FLV拖拉的时候,将第一个video tag同步加上(配置信息在该tag中),否则无法正常播放。
#wget http://jaist.dl.sourceforge.net/project/yamdi/yamdi/1.9/yamdi-1.9.tar.gz
#cd yamdi-1.9
#make &&make install
#yamdi -i test.flv -o test-with-frame.flv
#yamdi -i test.flv -x -
工作原理:yadmi的作用是为FLV文件添加关键帧,以便实现拖动播放扫描整个文件,记录关键帧的时间戳和offset,然后在metadata添加关键帧信息。
#./configure --enable-debug --extra-cflags="-g -O0" --extra-ldflags="-g -O0" --disable-yasm
#make
#make install
备注:编译成可调试版本。
#ffmpeg -i test.flv
备注:H264文件缺乏special
tag即第一个video/audio tag。
[flv @ 0x383d240] Invalid keyframes object, skipping.
备注:关键帧信息和FLV视频文件不匹配。
[flv @ 0x383d240] subtitle stream discovered after head already parsed
备注:由于视频拖拉后,第一个tag的时间戳不为0,因此导致该warning,因此该错误忽略。
[aac @ 0x383ea40] element type mismatch 1 != 0
备注:该错误暂时不知道。
备注:详见https://github.com/cjhust/tools/tree/master/jwplayer,用来播放flv视频。
备注:详见https://github.com/cjhust/tools/tree/master/flowplayer,用来实现FLV拖拉逻辑。
flv格式和点播实现逻辑:
http://www.cnblogs.com/haibindev/archive/2011/09/21/2181989.html
flv格式:
http://blog.csdn.net/bsplover/article/details/7426511
http://nkwavelet.blog.163.com/blog/static/2277560382013101321517473/