如何实现一个c/s模式的flv视频点播系统
一、写在前面
视频点播,是一个曾经很热,现如今依然很热的一项视频服务技术。本人最近致力于研究将各种视频格式应用于点播系统中,现已研究成功FLV, F4V, MP4, TS格式的视频点播解决方案,完全支持以上格式中存放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视频点播系统的更多相关文章
- 公布一个基于 Reactor 模式的 C++ 网络库
公布一个基于 Reactor 模式的 C++ 网络库 陈硕 (giantchen_AT_gmail) Blog.csdn.net/Solstice 2010 Aug 30 本文主要介绍 muduo 网 ...
- CREATE SCHEMA - 定义一个新的模式
SYNOPSIS CREATE SCHEMA schemaname [ AUTHORIZATION username ] [ schema_element [ ... ] ] CREATE SCHEM ...
- 自己实现一个 DFA 串模式识别器
自己实现一个 DFA 串模式识别器 前言 这是我编译原理课程的实验.希望读完这篇文章的人即便不知道 NFA,DFA 和正规表达式是什么,也能够对它们有一个简单的理解,并能自己去实现一个能够识别特定模式 ...
- UEFI+GPT模式下的Windows系统中分区结构和默认分区大小及硬盘整数分区研究
内容摘要:本文主要讨论和分析在UEFI+GPT模式下的Windows系统(主要是最新的Win10X64)中默认的分区结构和默认的分区大小,硬盘整数分区.4K对齐.起始扇区.恢复分区.ESP分区.MSR ...
- 【翻译】DotNetMQ: 一个.NET版完整的消息队列系统
在一个大型的分布式系统中,消息队列是不可缺少的中间件,能很好的解决异步消息.应用解耦.均衡并发等问题.在.net中,偶然发现一个效率不错.安全可靠.功能齐全的消息组件,忍不住翻译过来,供大家快速预览. ...
- Nginx搭建flv视频点播服务器
Nginx搭建flv视频点播服务器 前一段时间使用Nginx搭建的多媒体服务器只能在缓冲过的时间区域内拖放, 而不能拖放到未缓冲的地方. 这就带来了一个问题: 如果视频限速的速率很小, 那么客户端观看 ...
- 打造一个全命令行的Android构建系统
IDE都是给小白程序员的,大牛级别的程序员一定是命令行控,终端控,你看大牛都是使用vim,emacs 就一切搞定” 这话说的虽然有些绝对,但是也不无道理,做开发这行要想效率高,自动化还真是缺少不了命令 ...
- 用ES6创建一个简单工厂模式
1 什么是工厂模式? 工厂模式是用来创建对象的一种最常用的设计模式.我们不暴露创建对象的具体逻辑,而是将将逻辑封装在一个函数中,那么这个函数就可以被视为一个工厂.工厂模式根据抽象程度的不同可以分为:简 ...
- 自己实现一个 DFA 串模式识别器(二)
正规表达式的实现原理 上文讨论了串的模式的表达,即正规表达式.那么这一小节将讨论我们实现一个正规表达式的方法和原理.因为我们知道,一个正规表达式对应着一个串模式,而一个串模式又对应着一些列符合该模 ...
随机推荐
- javascript对象事件绑定方法
javascript对象事件绑定方法 今天在做对象事件绑定的过程中出现了一点异外情况,由于事件方法是由参数传过来的,需要将当前对象call过去,方便方法体里直接调用this 错误写法 obj.oncl ...
- BITED-Windows8应用开发学习札记之四:如何在Win8 应用中实现语义缩放
语意缩放的意义在于:创新的语意缩放外观,让你的应用随时展现信息可视化的力量.如图表般的Tile,随着数据的不同而变化,让你的页面更富节奏.而所谓的语意缩放就是通过上下文的跳转,帮助我们实现一种更快更便 ...
- 基于Heritrix的特定主题的网络爬虫配置与实现
建议在了解了一定网络爬虫的基本原理和Heritrix的架构知识后进行配置和扩展.相关博文:http://www.cnblogs.com/hustfly/p/3441747.html 摘要 随着网络时代 ...
- iOS开发-你真的会用SDWebImage?(转发)
原文地址: http://www.jianshu.com/p/dabc0c6d083e SDWebImage作为目前最受欢迎的图片下载第三方框架,使用率很高.但是你真的会用吗?本文接下来将通过例子分析 ...
- Linux操作系统时间与BIOS硬件时间
注:以Ubuntu为例说明 在Linux计算机上,有两个时间,一个是硬件时间(BIOS中记录的时间,称为hwclock),另一个是操作系统时间(osclock).硬件时钟由BIOS电池供电, 当计算机 ...
- jquery 回车切换 tab功能
挺有趣的,Jquery 回车切换tab功能的实现哦 <html> <head><!--jquery库.js--></head> <body> ...
- Codeforces 627 A. XOR Equation (数学)
题目链接:http://codeforces.com/problemset/problem/627/A 题意: 告诉你s 和 x,a + b = s a xor b = x a, b > ...
- CCF 201312-1 出现次数最多的数 (水题)
问题描述 给定n个正整数,找出它们中出现次数最多的数.如果这样的数有多个,请输出其中最小的一个. 输入格式 输入的第一行只有一个正整数n(1 ≤ n ≤ 1000),表示数字的个数. 输入的第二行有n ...
- URAL 2068 Game of Nuts (博弈)
题意:给定 n 堆石子,每次一个人把它们分成三堆都是奇数的,谁先不能分,谁输. 析:因为每堆都是奇数,那么最后肯定都是要分成1的,那么就把不是1的全加和,然后判断奇偶就OK了. 代码如下: #prag ...
- 通过set和waitOne来控制子线程的运行和停止
public partial class Form1 : Form { //自动重置事件类 //主要用到其两个方法 WaitOne() 和 Set() , 前者阻塞当前线程,后者通知阻塞线程继续往下执 ...