一、写在前面

  视频点播,是一个曾经很热,现如今依然很热的一项视频服务技术。本人最近致力于研究将各种视频格式应用于点播系统中,现已研究成功FLVF4VMP4TS格式的视频点播解决方案,完全支持以上格式中存放H.264编码视频的情况,并将继续研究其他格式。

  这里有一点需要说明的是,F4V本来指的是Adobe基于ISO/IEC 14496-12标准推出来的视频格式,与MP4格式相同,但因为国内许多的视频网站,均把存放H.264编码视频的FLV文件标注为.f4v格式,而这种文件的点播实现方式和普通的FLV是有所不同的,所以,为了避免更加混淆,我沿用了它们的命名方式,因此,“FLV”将仅指包含H.264/AAC编码的一般FLV视频。

  本文简单介绍如何实现一个简单的基于flv的视频点播系统。

二、FLV格式

  FLV(Flash Video)是Adobe公司推出的视频格式,是一种专门用来在网络上传输的视频存储容器格式。其格式相对简单,不需要很大的媒体头部信息,因此加载速度极快。国内各大视频网站,均有采用FLV格式作为其点播、甚至直播的视频格式。FLV容器格式的主要特点是tag,整个FLV由Video Tag, Audio Tag以及其他Tag组成,没有映射表。

  基本上,可以把FLV格式简要画为如下形式:

  

  其中,FLV Header指的是FLV的头部,只有9个字节,和常规的MP4文件头部相比,这个小太多了。FLV MetaData存放的是一些整个视频文件的媒体信息,包括作者、视频宽高、时长、关键帧列表等等,这些信息对于解析视频文件来说,当然很重要,不过可惜的是,因为FLV的MetaData是可有可无的,所以有不少FLV没有MetaData,而且即便有,其MetaData中的信息也是不正确的,这导致MetaData非常不值得信赖。所以,在解析FLV的时候,应该直接忽略FLV MetaData部分,通过遍历FLV的所有Tag,来获取相应的媒体信息。

三、方案

  点播系统的实现,有几个关键点,最重要的应该是“播放网络流”和“拖动”这两点。其中,关于“拖动”,由于整个系统是基于网络的,客户端在拖动之后,必须重新向服务器端发送请求,服务器根据客户端的拖动请求,寻找最接近的拖动点,返回可以播放的数据流,从而完成点播拖动。

  对于FLV来说,因为其格式简单,头部非常小,而MetaData可以不要,所以只需要寻找到关键帧,然后拼上FLV Header,就可以组成一个可播放的视频文件。如下图所示:

  根据FLV格式的特点,以及拖动后生成新的可播放文件的方法,可以将flv点播系统设计成如下方案:

  1. 服务器端

  首先,解析flv文件,生成flv视频关键帧列表,表明时间和便宜量的对应关系。然后,当接收到客户端发来的数据请求时,根据客户端拖动的时间点的请求,找出时间距离最近的关键帧,根据偏移量,读取flv的文件数据,然后拼接flv的9字节文件头部(还需要再加上4个字节全零的pre tag size,共13字节),返回。

  2. 客户端

  客户端需要特别注意的,除了正确的解析视频流并播放,还需要小心时间轴的行进,因为用户拖动的时间位置并不一定是关键帧,所以,需要根据服务器返回的关键帧的真实时间,重新定位播放进度。

四、实现

  服务器可以实现为一个http server,只需要提供http下载,在响应下载之前,需要完成之前所描述的逻辑。可以完全自己实现,可以直接使用现有的成熟web server,如果对性能要求很高,强烈推荐nginx,借助于nginx强大的处理性能,通过实现自己的nginx module,可以完成你所有的需求。

  客户端播放器,对于不太熟悉播放器开发技术的,可基于libvlc,借助于vlc良好的网络播放能力,基本可以满足需要。

下面是前些日子做的一个演示程序,

------------------------------------------------------------

转载请注明作者和出处,谢谢~

如何实现一个c/s模式的flv视频点播系统相关推荐

  1. 面试官让我手写一个生产者消费者模式?

    不知道你是否遇到过面试官让你手写生产者消费者代码.别说,前段时间有小伙伴还真的遇到了这种情况,当时是一脸懵逼. 但是,俗话说,从哪里跌倒就要从哪里爬起来.既然这次被问到了,那就回去好好研究一下,争取下 ...

  2. JDK源码解析 Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法

    JDK源码解析 Runnable是一个典型命令模式, Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法 /命令接口(抽象命令角色) public interfa ...

  3. 发布一个基于 Reactor 模式的 C++ 网络库

    发布一个基于 Reactor 模式的 C++ 网络库 陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice 2010 Aug 30 本文主要介绍 muduo 网 ...

  4. Nginx搭建flv视频点播服务器

    Nginx搭建flv视频点播服务器 前一段时间使用Nginx搭建的多媒体服务器只能在缓冲过的时间区域内拖放, 而不能拖放到未缓冲的地方. 这就带来了一个问题: 如果视频限速的速率很小, 那么客户端观看 ...

  5. 如何使用Openfiler为VMware ESX设置一个免费的iSCSI或NAS储存系统

    如何使用Openfiler为VMware ESX设置一个免费的iSCSI或NAS储存系统 By admin ⋅ 2008/09/19 ⋅ 3,135 views ⋅ Post a comment 所有 ...

  6. 设计模式 日志系统设计_模式:我们设计系统的故事

    设计模式 日志系统设计 Design Patterns are some of the most over-used concepts in design today. And we all know ...

  7. 设计模式之策略模式在地铁票价系统中的应用

    引言 设计模式是面向对象编程的一个非常精彩的部分.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性,它能帮助我们将应用组织成容易了解,容易维护,具有弹性的架构.本文通过一个简单的案 ...

  8. linux 格式化u盘_【Ventoy】一个U盘,启动多个系统

    经常用电脑,难免会遇到重装系统的情况.现在安装系统大部分的情况都是通过U盘来安装的,这个时候最重要的就是需要一个可启动U盘.空空之前用过什么老毛桃.U启动之类的WinPE来安装系统,但是多少都会有些瑕 ...

  9. bs模式Java web,基于BS模式的即时通讯系统的设计与实现(MyEclipse)

    基于BS模式的即时通讯系统的设计与实现(MyEclipse)(包含选题审批表,任务书,开题报告,中期检查表,毕业论文13000字,答辩记录,成绩评定册,源程序) 摘  要:即时通讯(Instant M ...

最新文章

  1. 15瓶饮料4个空瓶换一瓶_2021江苏公务员考试行测技巧:你会用“空瓶”换水吗?...
  2. ionic3 java,ionic3-环境搭建问题
  3. CentOS/用FTP客户端软件连接到服务器
  4. Ubuntu利用Samba映射磁盘到Windows(转)
  5. 如何学习Flex Framework
  6. 心电信号去噪(part2)--中值滤波器
  7. mac使用eclipse创建java_【Java】Mac上使用Eclipse创建Java项目的一般步骤
  8. c#.net常用函数列表
  9. Spring JDBC 【继承JdbcDaoSupport】
  10. 民间股神:上海殷保华的股票操盘手奇人绝技
  11. 计算机实验云平台,浅析基于云平台的计算机实验教学中心建设
  12. 图书馆管理系统mysql的创建_简单的图书馆管理系统数据库设计
  13. 微信小程序的版本更新机制是什么?
  14. 24微信小程序开发2
  15. 大学电路题目怎么搜_电路,中国大学MOOC(慕课)答案公众号搜题
  16. win10控制面板快捷键_在win10打开注册表编辑器的七种方法,你知道几种
  17. [nrf52][SDK17] 如何修改BLE_MAC地址?
  18. 用C#识别图像中的文字_MODI OCR
  19. 足迹推荐位,淘宝足迹推荐位,旺旺打标足迹显示问题,详情页足迹推荐,淘宝详情页的下拉出现足迹,v兔电商
  20. CH340T制作STC51单片机下载器

热门文章

  1. 设计模式的七大设计原则:其一:单一职责原则
  2. Strus2_Action中访问Web资源
  3. jenkins pipeline之语法篇
  4. python基础之类的属性方法、魔术方法普通方法
  5. php 开发桌面应用,使用NW将开发的网站打包成桌面应用
  6. java 解析docx_java解析xlsx和docx 文件 | 学步园
  7. 前端工程师:现在是最糟糕的时代,也是最好的时代
  8. i7 3960x支持服务器内存吗,酷睿i7 3960X支持多大内存
  9. C语言学习笔记---数据拷贝函数memcpy()和memmove()函数
  10. C语言学习笔记---C库排序函数qsort()