HTTP协议更优
目前几乎所有的视频点播网站全部采用HTTP协议传输数据。因为相对于诸如RTMP等协议来说,HTTP协议是无状态的,数据传输完毕就断开连接,这样服务器就可以腾出资源来服务更多的用户。而RTMP则会在用户播放期间一直维护一个连接,这样服务器的负载就非常有限。而且HTTP服务器,CDN等都已经是非常成熟的技术,成本低性能好。另外HTTP的请求可以直接使用浏览器Cookie,容易和网站业务打通。最后,HTTP还能使用浏览器缓存,这算优点也算缺点,优点是请求同样的资源可以直接从缓存中取,缺点是安全性差了点。
HTTP拥有更好的性能,但是没法传输太实时性的东西,否则性能还不如RTMP,比如视频聊天,直播这些。
安全性
有时候我们被访问的视频可能需要做一些限制,比如防盗链,视频收费等等。如果采用HTTP协议的话,传统的鉴权方式就足够,Cookie里带token什么的判断是否有权限访问视频资源,细节我就不说了。唯一的问题是一旦用户有权限访问视频,就有可能把视频下载下来用作他用。
通过分段进一步提升负载能力
为了让HTTP能服务更多的用户,同时维护更少的连接,我们需要传输尽快完毕。但这是我们分段的理由吗?不是,因为无论分段不分段,一个用户加载完全部的视频数据对服务器占用时间是一定的(假设传输速度一定),甚至会多占用很多创建连接和销毁连接的资源。
但是我们看到各大视频网站实际上都是有对视频分段的,这里我就谈谈视频分段的好处。
节约网站流量,也就是节约服务器资源提高负载能力。当用户打开一个视频的时候,很有可能不会把视频看完,只看一部分。如果不对视频做分段,用户一打开网站就把所有视频数据加载完,那么对流量就是极大的浪费。把视频分段后我们可以一段一段加载视频,做到用户看多少我们就加载多少。
更加灵活的seek(拖动),对于一个不做任何分段的视频,比如HTTP服务器上的静态视频文件,我们是无法通过NetStream对象seek方法跳转到未加载的视频部分的。所以为了解决这个问题,apache和nginx都提供了flv模块,支持start参数。当指定start参数的时候,我们可以重新从指定位置加载视频,解决了上述问题。但是带来的问题是流量浪费,可能原本加载过的地方又要重新加载一遍。如果我们采用分段的方式,就可以避免这个问题,具体实现方法后面会详细介绍。
NetStream对象
我们在Flash端如何播放视频很大程度上受NetStream提供的功能所限。所以这里大致介绍下NetStream提供的功能和一些限制,这也是为什么后面程序要这么设计的原因。
NetStream提供两种可以播放HTTP视频的模式,普通模式和数据生成模式。
在普通模式下,往NetStream传入我们要播放的HTTP视频资源地址,NetStream就会开始加载视频并开始播放。我们可以暂停视频播放,但是不能暂停数据的加载,我们可以在已经加载过的数据部分随意seek,但是不能seek到未加载的部分。数据加载完毕之后我们任然可以进行播放,seek等操作,但是如果调用了close方法关闭流,那么如果数据未加载完毕,就会停止加载,并且不能做任何播放,seek等操作,这相当于我们原来加载的数据都白费,不能再使用。所以如果我们要把视频分段后随意在各个视频分段里来回seek,我们必须让一个分段视频对应一个NetStream实例,换句话说有几个分段就需要几个NetStream伺候他们(我们暂且这么认为,后面我们会对这个问题做优化)。
在数据生成模式下,NetStream提供更加灵活的加载方式。NetStream通过appendBytes方法可以添加外部的二进制数据来播放视频,添加数据的顺序就是播放的顺序。这种情况下我们可以通过URLStream对象加载视频文件数据,理论上所有加载过的数据都可以被重复利用。但是注意不要把所有数据往内存里塞,否则内存会被撑爆。具体的缓存策略后续具体讲。
和其他平台的视频播放器不同,Flash不能直接访问本地文件,但是可以通过加载已经加载过的视频让浏览器从缓存中快速取得视频数据。所以如何有效利用缓存是优化的关键。
不要迷信NetStream的NetStatusEvent事件,在不同服务器和浏览器环境下,这个事件发生的时机可能略有差别,所以事件只能做参考,需要另外做一些前提判断。
视频分段需要的服务器支持
静态分段:把视频分为固定的可以独立播放的几段保存到服务器上,播放的时候需要获得一个视频地址列表。每个静态分片都只能从头开始请求不能从切片的中间开始请求。这是最容易做到也是性能做好的方式。
静态分片+start参数:第一个方案的改进,可以支持从分片的中间开始请求到分片的结尾。优酷土豆都是这么做的噢。这样方便seek。也有现成的nginx和apache模块可以支持。
动态分片:同时提供start和end参数,这样可以由播放器来决定如何请求分片,对播放器来说更灵活,对服务器的文件管理来说也更方便。这个解决服务器解决方案nginx和apache应该也有,没有细究过。
以上三种最后请求出来的数据都是一个能完整独立播放的视频文件,服务器会自动帮你加上视频文件头。如果Flash使用的是数据生成模式,那么实际上返回的直接是一个文件数据片段就行了,不需要另外加上文件头。