深入浅出看流媒体前世今生,分分钟二逼变牛逼

【流媒体网】消息:CDN这几年爆炸式增长,带宽提速是根源,而HTTP始终还是那个屌样,因此目前CDN大多是资本性行业,不用多少知识就能干了;直到流媒体粗现,直播咋这么难搞呢?因为它是流媒体,让我带你深入浅出看流媒体前世今生,分分钟二逼变牛逼。

 

  流媒体分为点播和直播,点播已经堕落为HTTP文件了,直播永远不可能只用HTTP就OK,这是他们的业务差异导致的。流媒体本质上是:现实的图像,经过编码器压缩,持久化为点播文件或者直播流,经过传输,在终端解码和展示。

  点播为何属于HTTP而不是流媒体呢?点播,譬如电影或者录制的影像,传输给观看的终端时是不变的,一万个人看一个电影无论什么时候看都是一样的媒体数据,因此传输上直接使用HTTP就可以了。点播的流媒体特征还是有的:

  点播的重新编码,譬如为不同终端输出不同码率和尺寸的点播文件,需要媒体知识了。这部分因为使用太广泛,所以开源届早就支持得很成熟,ffmpeg对文件重新编码已经做得很好了。

  点播P2P,这个实际上分为客户端的P2P和web P2P,这个和媒体没有什么关系,但属于点播需要做的范围,没有现成的方案。(插播广告:观止创想已经支持了点播HLS的P2P,现有系统不用修改就可以加上web P2P)

  其他的什么分片,DRM,弹幕,分享,多终端转封装,文件调度,HTTP API调度,热点,mp4/flv-range请求,存储等等。大多都有了成熟的方案,和HTTP文件一样的技术,要么就是播放器支持,这些和流媒体一毛钱关系都没有。

  这就是为何CDN支持点播支持得很得心应手,几乎所有的CDN都能直接支持点播分发,甚至一些新兴的行业公司,譬如在线教育,对于点播都能自己搞。点播就是HTTP而已,不属于流媒体范畴。

  直播呢,从古老的RTSP到RTMP,HTTP渐进式下载,到HTTP流,到HLS和HDS,到DASH,到私有的websocket。这些不过是直播分发的表象,譬如HTTP直播流就是HTTP点播吗?不是。HTTP点播本质上是文件分发,而HTTP流是流媒体服务器在内存中将直播的包,打包成RTSP、RTMP、HTTP后发送给每个客户端。

  当然总有例外的,有一个公司尝试过直播进行点播化,就是时移直播,将直播流录制成点播文件,然后客户端请求时总是请求点播。这种私有协议迟早是要死掉的,只有自己的播放器能播,而且得在CDN上部署自己的流媒体;现在这个公司也放弃了自己的“高大上”的私有协议——互联网的基本精神就是开放标准。可惜中国人很难认同这个理念,牛逼的总喜欢搞私有协议,譬如使用websocket的公司,大多属于这种类型,牛逼的人太多就是这种结果,一般这种公司也很有钱,譬如某上市的做在线秀场的公司。

  目前直播分发有几个特点:

  偏好flv,少用ts:flv标准11页,ts标准174页。标准文档十倍差异,代码实现起来十倍都不止。因此一般的公司都喜欢flv,pc时代都是flv的天下,什么flv流,flv切片;因为自己写代码支持ts比较麻烦,用ffmpeg的代码又太庞大。直到移动端粗现,现在直播只支持pc的少之又少了,使用flv作为基础结构的产品要么艰难转型,要么就掩耳盗铃说FLV很优雅,HLS太垃圾。

  rtmp和hls并存:rtmp一般用于pc-flash播放直播,而hls用于移动端播放。flash能播放hls吗?前年jwplayer就支持了,可惜是商业版不开源;去年有很多开源的as播放器支持hls。而直播系统,特别是cdn的直播,不会更新这么快,pc端还是rtmp系为主。这个特点是由于平台客户端支持的流决定的,并非最佳方案,也不是用户愿意这么干。

  实时流大多使用rtmp:实时流,延迟要求在5秒之内的流,大多使用rtmp协议。pc上可以直接播放,移动端就需要使用ffmpeg解码播放。有没有更好的分发方案?实际上http-flv比rtmp更合适,延迟一样,要求服务器支持,pc能直接播,移动端需要使用ffmpeg,还有个好处是能穿墙。为何cdn大多不支持http-flv直播?因为一般的web服务器支持不了,这是个流媒体问题。

  rtsp永远死不了:这是监控行业的协议,我们都有门户之见,“RTMP这个烂货怎么还在互联网上用呢?RTSP多么优美!”因此有监控行业背景的公司做互联网业务,都带着门户之见不得已将RTSP转RTMP,而且还要愤愤的说——只不过是不用装个插件而已。

  直播的本质特点,就是需要专门的服务器分发,至少需要直播源站切片HLS后分发。也就是直播需要专门的流媒体服务器,目前开源的流媒体,最古老的是RED5,后面是CRTMPD,风生水起的是NGINX-RTMP,目前最新出的是SRS。

  为何RED5不能一统天下?RED5和FMS一样古老,先行者如果不能放掉自己的光环,迟迟不肯变革,就会被后来者超越。RED5性能是很差,但并非是因为使用了java的原因,这个看看wowza就知道了,商业服务器wowza虽然是个内存杀手,但是支持的并发一点都不含糊。RED5没有广泛商用的原因可能一直是一个先行者,祖先的角色。软件只有快速变化适应需求才能发展,和年纪没有关系。

  那么CRTMPD怎样?牛逼!使用单进程单线程异步socket,这是和nginx同时代的产物。CRTMFPD是有不少铁杆粉丝的,以那个时代开始做直播业务的为主。CRTMDP生不逢时,遇到NGINX了,不少NGINX的粉丝是技术牛逼的人物,不然怎么能看懂void*****呢?除了社区的差异之外,CRTMPD没有支持HLS,倒是支持了RTSP,这就是典型的倒行逆施,互联网上支持RTSP,大约只有CRTMPD能想到了。

  NGINX-RTMP风生水起有几个很重要的因素。首先2012年开始CDN业务开始快速增长,随之直播业务也需求暴涨,没有特别满意的流媒体服务器;其次,NGINX在HTTP领域绝对是霸主,大家对于NGINX系的熟悉程度很高,便于维护;再次,直播点播使用一套服务器,很有诱惑力,这可以算是“万金油”效应,很多套服务器搞得焦头烂额,肯定一套服务器能解决问题;最后,CDN是运维比技术牛逼的行业,运维的信心都是运行出来的,NGINX运行那么良好,那么NGINX-RTMP也肯定不错。

  SRS粗来了,并非石头缝里蹦粗来个SRS,SRS其实诞生的历史是:第一个版本实际上是参考NGINX,基本上和NGINX-RTMP同时间点做出来;第二版本是改用ST作为基础结构,支持RTMP直播点播;第三版本是从CDN出来后重写的,只支持直播。为何SRS不使用NGINX那种基础结构,这个和google为何开发golang的原因一样。SRS和NGINX-RTMP最重要的区别有两点:其一,使用类似golang的服务器架构;其二,流媒体业务驱动的产品管理,如果可以装装逼,SRS是以流媒体业务为主的服务器,而不是以分发协议为主的服务器。

  什么是以流媒体为主?流媒体系统的层次包括:网络层(socket或st)负责传输,协议层(rtmp或http)负责网络打包,封装层(flv、ts、hls、hds、adts、annexb)负责编解码数据的封装,编码层(h.264和aac)负责图像压缩。流媒体服务器的重点在于封装层,譬如flv、ts、hls、hds、adts和annexb的解析和打包都是自己实现的代码,参考标准规范,支持完善的封装转换和解析。而网络层因为使用st简化,使得协议层更简单,错误的概率更低,这个和流媒体的关系就不大了。

  什么是以业务为主?“跑起来”和“商用”是两回事情,商用需要对于流媒体的业务有很好的支持:譬如vhost,这个是计费才有的概念,基于app的也能计费,结果就是要求用户不能app重复,新增app需要联系运维,凡是添加app需要联系运维的cdn,肯定是NGINX-RTMP;譬如日志,出现问题能将流媒体的整个链条的日志都能找出来,从边缘到回源链接,到上层节点的日志,一直追溯到推流连接的日志,每个日志都是基于连接的;譬如rtmp+http-flv+hls,国内主要的直播业务都能支持,还有hds可以供那些想装逼的客户用;更多牛逼的业务功能就不啰嗦了。

  对于流媒体服务器,除非能忘记HTTP服务器,才能看清楚到底为何流媒体和HTTP没有一毛钱关系,而流媒体在于团队对于流媒体和服务器的理解,而并非找到一个万金油服务器能涂抹掉客户问题。

  直播这么多协议,这多么服务器,当前直播重心在哪里?该如何选择合适的协议?只要问自己三个问题就可以了:

  延迟要求,是否要求低于5秒的延迟?如果是硬指标,就只能选择RTMP或HTTP-FLV流。移动端需要自己编译FFMPEG支持,无法直接播放。

  终端适配,是否要求支持PC和移动端(IOS和Android)?如果需要广泛支持移动端,HLS是最好的选择。

  节约带宽,是否要求支持WebP2P?如果需要支持FlashP2P,或者移动端P2P,选择HLS。

  当初有个跨国老牌的流媒体公司,劝说不要使用RTMP了,因为半年时间RTMP就会死掉,DASH会替代所有的流媒体协议。现在2年过去了,RTMP和HLS除了更加爆炸性应用之外,我看死掉的是那些过于技术至上的公司。

  如果用一句话说流媒体直播:实时性要求高的用RTMP或HTTP-FLV,其他都用HLS。

时间: 2024-10-03 19:45:32

深入浅出看流媒体前世今生,分分钟二逼变牛逼的相关文章

深入浅出看懂AlphaGo Zero - PaperWeekly 第51期

AlphaGo Zero = 启发式搜索 + 强化学习 + 深度神经网络,你中有我,我中有你,互相对抗,不断自我进化.使用深度神经网络的训练作为策略改善,蒙特卡洛搜索树作为策略评价的强化学习算法. 1. 论文正文内容详细解析 先上干货论文:Mastering the Game of Go without Human Knowledge [1],之后会主要以翻译论文为主,在语言上尽量易懂,避免翻译腔. AlphaGo Zero,从本质上来说完全不同于打败樊麾和李世石的版本. 算法上,自对弈强化学习

深入浅出Java回调机制-(二)

前几天看了一下Spring的部分源码,发现回调机制被大量使用,觉得有必要把Java回调机制的理解归纳总结一下,以方便在研究类似于Spring源码这样的代码时能更加得心应手. 注:本文不想扯很多拗口的话来充场面,我的目的是希望以最简明扼要的语言将Java回调的大概机制说清楚.好了,言归正传. 一句话,回调是一种双向调用模式,什么意思呢,就是说,被调用方在被调用时也会调用对方,这就叫回调."If you call me, i will call back". 不理解?没关系,先看看这个可以

Android 流媒体系列(二)

import java.io.IOException; import android.app.Activity; import android.content.ContentResolver; import android.database.Cursor; import android.media.ExifInterface; import android.os.Bundle; import android.provider.MediaStore; public class MainActivi

微信加关注链接 一键关注公众号 解决用手机看网页无法扫二维码的烦恼

现在很多网页都会设置wap手机版,移动端的流量逐渐显现.问题来了,如果你用手机浏览网页,你又很想微信加关注,上面正好有个二维码,苦于手机分身无术,又不想打一长串的微信号,还是舍弃吧.站长们可要在这方面提高用户体验了.那么有没专用的微信加关注链接一键关注公众号呢?幸好微信团队早就发明了微信文字链接,也即是微信一键关注代码,只是我们平时没有发现而已. 我们平时的文字链接或其他链接(A标签)一般都是<a href="http://开头的,这种链接在微信中也是通用的,具体可以查看微信添加文字链接一

想搭建一款流媒体服务器

问题描述 想搭建一款流媒体服务器 需求如下, ① 把摄像头采集的视频数据,通过流媒体服务器如VLC或OBS流媒体服务器框架 把采集的视频数据转换为流. ② 基于哪种协议( http或者rtsp或者其他)可以把流放到网络上看,或者生成二维码,手机扫一下即可观看 问题:① 选择哪一款流媒体框架? ② 如何把流放到网络上?

机器学习系列|从白富美相亲看特征预处理与选择

上篇 1. 引言 再过一个月就是春节,相信有很多码农就要准备欢天喜地地回家过(xiang)年(qin)了.我们今天也打算讲一个相亲的故事. 讲机器学习为什么要讲相亲?被讨论群里的小伙伴催着相亲,哦不,催着讲特征工程紧啊.只是我们不太敢讲这么复杂高深的东西,毕竟工程实践的经验太复杂了,没有统一的好解释的理论,一般的教材讲这方面的内容不多.我们就打算以一个相亲的故事为例,串一些特征工程的内容. 2. 故事背景 事先声明:本故事纯属虚构,如有雷同,纯属巧合! 海归白富美韩梅梅刚回国,还没适应工作,母亲

J2EE设计模式:CMP到BMP模式(二)

j2ee|设计 特定厂商的weblogic-ejb-jar.xml 我们首先在weblogic-ejb-jar.xml中定义厂商特定的信息.在这里我们告诉服务器在哪儿存放本地存根(stub)和哪儿去查找CMP映射. 持久映射信息: <persistence-type><type-identifier>WebLogic_CMP_RDBMS</type-identifier><type-version>6.0</type-version><ty

教你怎么看内存条频率

我们知道内存性能由内存容量以及内存频率共同决定,在相同容量的内存中,内存频率越高,其性能就越好.目前内存频率主要有: DDR2内存频率主要有:333MHz和400MHz的DDR内存,667MHz.800MHz和1066MHz DDR3内存频率主要有:1066MHz.1333MHz.1600MHz 其中DDR2内存如今已经淘汰,很多早两三年购买或者更早购买的电脑均为DDR2内存,内存频率普遍较低,最高也不过只有1066Mhz,如今主流的内存频率是1333MHz和1600MHz频率内存,并且随着In

java-关于Java二位数组行列互换问题

问题描述 关于Java二位数组行列互换问题 刚开始学Java,不太懂,这个为什么报错呢? 解决方案 行列下标搞错了,结果数组越界,仔细检查下就能看出来. 解决方案二: 笔误了吧 swap中i<arr[i].length改成j<arr[i].length