flv的流式拖动

首先说一下什么是流式拖动:

所谓流式拖动是指flash根据用户的拖动请求向服务器发送请求,传递拖动起始位置,服务器根据用户请求实时构建flv文件流,然后将流推送给flash的方案。

目前youku做的还不错,youku不仅对文件进行了物理分段(一个大的flv文件切分成了几个小的flv文件),而且对每个段还支持start = n秒 参数的流式传输。

通常进行物理分段的时候,会有专门的软件处理flv文件,文件中的一些关键帧会进行处理,尤其是时间戳还有flv的header部分,所以切割后的每个分段文件还能正常播放,而且都有自己独立于之前全局大文件的时间戳,即每一段的时间戳都是从0开始。

但是进行流式拖动的时候,通常只会找到start时间对应的关键帧,然后从这里截断,带上flv头部构成一个新的flv流,这个时候流中的关键帧都是没有进过调整的。就是说假如传入的参数是start = 100 , 那么服务器会找到离100s最近的关键帧,然后从这一帧开始传送数据。
那么这样会有什么问题呢?
当然会有问题,主要是播放时间和seek时间的问题。

flash播放器接收到flv流的时候从帧中读取播放时间,本来用户认为推送过来的start = 100的流的起始时间应该是0s,但是由于收到的流的第一帧对应的时间戳是100s,所以播放时间直接从100s开始,当然把这个流保存成文件进行播放也是一样的。

在进行seek拖动的时候,如果对start = 100的flv流进行拖动操作seek(20),那么会出现异常(不报错),因为flv中找不到20s对应的关键帧,所以会存在很大的误差,实际上返回的flv流支持的seek区间应该是从100s开始的,就是说对返回的流执行seek(100)的操作,实际上是从第一帧开始播放的。

附:看到网上不少人说flv是不是不能拖动到任意时间,我的回答是:不能拖动到任意时间。flv的文件头中有一个canSeekToEnd的属性,里头明确表示文件是否可以拖动到文件最末尾。上面说过了flv进行拖动是寻找离拖动时间最近的关键帧,然后定位到那里,如果寻找该帧出现什么问题,当然就返回InvalidateTime的错误了。

头文件:

HTTP/1.1 200 OK Date: Tue, 30 Dec 2008 10:11:12 GMT Content-Type: video/flv Connection: keep-alive Content-Length: 2000000000 Expires: Mon, 26 Jul 1997 05:00:00 GMT Server: TSS/0.11 Last-Modified: Tue, 30 Dec 2008 10:11:11 GMT Pragma: no-cache Cache-Control: no-store, must-revalidate, post-check=0, pre-check=0, false

点赞