分享内容:html
互联网内容载体变迁历程,文字——图片/声音——视频——VR/AR——…….。从直播1.0秀场时代(YY),2.0游戏直播(斗鱼、虎牙、熊猫)到现在全民直播3.0泛生活娱乐时代(映客、花椒),国外直播app(Meerkat 、Periscope),随着VA/AR/MR提出的沉浸式视听体验,直播4.0时代很快就能到来。前端
在这个全民娱乐的时代,直播已经火得不要不要的,各大公司都有本身的直播产品。本文主要从直播的一些基本知识,一步步打造直播app。直播那么火的背后有什么样的技术支撑呢?android
先将这些APP按照视频网站按照视频网站、弹幕视频、直播平台、在线秀场、移动短视频、移动直播来划分类别。再按照内容和社交这个维度来进行区分,能够明显看出视频网站、弹幕网站和直播平台更偏内容,他们对内容的需求更加高,用户在上面进行社交沉淀相对比较浅。ios
然后面三者更加偏向社交,他们强调人而不强调内容。因此短时间内不会有大的竞争关系,只是前三类、后三者之间的竞争会出现。nginx
大致框架
基本是下图这个套路:git
录制->编码->网络传输->解码->播放github
以上为直播的总体流程,根据该流程分为如下技术点:web
怎样录制直播视频api
怎样实时上传直播视频浏览器
怎样播放直播视频
直播间的用户是如何交互
PC直播(固定场所)——>移动端(形式自由)。
随着愈来愈多的直播类 App 上线,移动直播进入了史无前例的爆发阶段,目前大多数移动直播以 Native 客户端为主。可是H5端的直播在移动直播端也承载着不可替代的做用,例如 H5 有着传播快,易发布的优点。
完整的直播包括:
视频录制端
电脑上的音视频输入设备或者手机端的摄像头或者麦克风,目前以移动端的手机视频为主。
视频播放端
能够是电脑上的播放器,手机端的 Native 播放器,还有 H5 的 video 标签等。
流媒体服务器端
用来接受视频录制端提供的视频源,同时提供给视频播放端流服务。目前开源的流媒体有RED5,CRTMPD,NGINX-RTMP,SRS。
如何生产视频数据
封装格式的主要做用是把视频码流和音频码流按照必定的格式存储在一个文件中。
为何要分封装格式和视频编码格式呢?
这个其实跟网络分七层模型一个原理。解耦和,下降依赖,底层给上层提供基础功能,底层和上层都均可以单独扩展,能够以多种方案组合编码与封装,好比MP4与H26四、MP4与MPEG、TS与H264等等。好比这里面的这边文章的编码就只负责将最原始的音频和视频数据就行压缩,而压缩完的数据要怎么组织就拜托给上层的封装,封装接到视频音频数据负责给数据编号,指定同步协议,加入字幕等操做。通过封装后,获得的就是能够播放的上面提到的视频文件MP4或者MKV等等。把这个过程反过来就是上图描述的视频播放的过程。
PC端的摄像头、屏幕
对于PC端的流媒体源,可使用Open Broadcaster Software串流(支持多种直播平台)。
移动端iOS、Android的摄像头和麦克风。
iOS、Android主要是系统提供的API实现。
webRTC (Web Real-Time Communication)
webRTC是一个支持网页浏览器进行实时语音对话或视频对话的技术,能够在网页浏览器中进行采集、传输、播放,缺点是只在 PC 的 Chrome 上支持较好,移动端支持不太理想。
使用 webRTC 录制视频基本流程是:
调用window.navigator.webkitGetUserMedia()
获取用户的PC摄像头视频数据。
将获取到视频流数据转换成 window.webkitRTCPeerConnection
(一种视频流数据格式)。
利用webscoket
将视频流数据传输到服务端
因为许多方法都要加上浏览器前缀,因此不少移动端的浏览器还不支持 webRTC,因此真正的视频录制仍是要靠客户端(iOS,Android)来实现,效果会好一些。
推荐Andorid4.3(API18)或以上使用硬编,如下版本使用软编;iOS使用全硬编方案。
软编码:
libffmpeg
硬编码:
MediaCodec(sdk level 16+, Android 4.1, 4.1.1, the JELLY_BEAN)
FLV(Flash Video)是Adobe公司设计开发的一种流行的流媒体格式,FLV可使用Flash Player进行播放,FLV封装格式的文件后缀一般为“.flv”。整体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag组成。
特色:视频文件体积轻巧、封装简单
每一个Tag前面还包含了Previous Tag Size字段,表示前面一个Tag的大小。Tag的类型能够是视频、音频和Script,每一个Tag只能包含以上三种类型的数据中的一种。图2展现了FLV文件的详细结构。
Tag Data
Audio Tag
Video Tag
Script Tag(控制帧)或叫meta data tag
该类型Tag又一般被称为Metadata Tag,会放一些关于FLV视频和音频的元数据信息如:duration、width、height等。一般该类型Tag会跟在File Header后面做为第一个Tag出现,并且只有一个。
如图以Android为例的推流的流程图:
如何推
往哪里推
国内常见公开的直播协议有几个:RTMP、HDL(HTTP-FLV)、HLS、RTP。
Real Time Messaging Protocol是 Macromedia 开发的一套视频直播协议,如今属于 Adobe。
使用RTMP技术的流媒体系统有一个很是明显的特色:使用 Flash Player 做为播放器客户端,而Flash Player 如今已经安装在了全世界将近99%的PC上,所以通常状况下收看RTMP流媒体系统的视音频是不须要安装插件的。用户只须要打开网页,就能够直接收看流媒体。
和 HLS 同样均可以应用于视频直播,区别是 RTMP 基于 flash 没法在 iOS 的浏览器里播放,可是实时性比 HLS 要好。因此通常使用这种协议来上传视频流,也就是视频流推送到服务器。
rtmp如今大部分国外的CDN已不支持,在国内流行度很高。缘由有几个方面:
开源软件和开源库的支持稳定完整。如斗鱼主播经常使用的OBS软件,开源的librtmp库,服务端有nginx-rtmp插件。
播放端安装率高。只要浏览器支持FlashPlayer就能播放RTMP的直播。相对其余协议而言,RTMP协议初次创建链接的时候握手过程过于复杂(RTMP协议自己的交互是基于TCP),视不一样的网络情况会带来给首开带来100ms以上的延迟。基于RTMP延迟在2~5秒。
即便用HTTP协议流式的传输媒体内容,直接向后台上传编码后的流媒体数据。相对于RTMP,HTTP更简单和广为人知,并且不担忧被Adobe的专利绑架。内容延迟一样能够作到2~5秒,打开速度更快,由于HTTP自己没有复杂的状态交互。因此从延迟角度来看,HTTP-FLV要优于RTMP。
SRS2.0支持该协议:GitHub
即Http Live Streaming,是由苹果提出基于HTTP的流媒体传输协议。HLS有一个很是大的优势:HTML5能够直接打开播放;这个意味着能够把一个直播连接经过微信等转发分享,不须要安装任何独立的APP,有浏览器便可,因此流行度很高。社交直播APP,HLS能够说是刚需 。
Issue:SRS3.0提出了一种加强型HLS+
Real-time Transport Protocol,用于Internet上针对多媒体数据流的一种传输层协议。
实际应用场景下常常须要RTCP(RTP Control Protocol)配合来使用,能够简单理解为RTCP传输交互控制的信令,RTP传输实际的媒体数据。
RTP在视频监控、视频会议、IP电话上有普遍的应用,由于视频会议、IP电话的一个重要的使用体验:内容实时性强。
对比与上述3种或实际是2种协议,RTP和它们有一个重要的区别就是默认是使用UDP协议来传输数据,而RTMP和HTTP-FLV是基于TCP协议传输。
UDP:单个数据报,不用创建链接,简单,不可靠,会丢包,会乱序;
TCP:流式,须要创建链接,复杂,可靠 ,有序。
实时音视频流的场景不须要可靠保障,所以也不须要有重传的机制,实时的看到图像声音,网络抖动时丢了一些内容,画面模糊和花屏,彻底不重要。TCP为了重传会形成延迟与不一样步,如某一截内容由于重传,致使1秒之后才到,那么整个对话就延迟了1秒,随着网络抖动,延迟还会增长成2秒、3秒,若是客户端播放是不加以处理将严重影响直播的体验。
是否有除了HLS外更低延迟的方案?
HLS的优势点是显而易见的:移动端无需安装APP使用兼容HTML5的浏览器打开便可观看,全部主流的移动端浏览器基本都支持HTML5,在直播的传播和体验上有巨大的优点。
下面是 HTTP-FLV、HLS 、 RTMP 的对比:
所谓推流,就是将咱们已经编码好的音视频数据发往视频流服务器中,经常使用的第三方库 librtmp-iOS 进行推流,librtmp 封装了一些核心的 API 供使用者调用。例如推流 API 等等,配置服务器地址,便可将转码后的视频流推往服务器。通常的推流服务器都配置了服务器端信息。
百度云推流SDK: 官方文档
七牛推流SDK: Github上的官方源码及说明
网易云推流SDK:官方文档
腾讯云推流SDK:官方文档
其余推流SDK:
https://github.com/daniulive/SmarterStreaming
https://github.com/leixiaohua1020/simplest_ffmpeg_mobile
https://github.com/begeekmyfriend/yasea
https://github.com/simple-rtmp-server/srs-sea
注:点击底部“阅读原文”便可查看文中连接。
那么如何搭建一个推流服务器呢?
简单的推流服务器搭建,服务器支持 RTMP ,大概须要如下几个步骤:
安装一台 nginx 服务器。
安装 nginx 的 RTMP 扩展,目前使用比较多的是 https://github.com/arut/nginx-rtmp-module
配置 nginx 的 conf 文件
重启 nginx,将 RTMP 的推流地址写为 rtmp://ip:1935/hls/mystream, 其中 hls_path 表示生成的 .m3u8 和 ts 文件所存放的地址,hls_fragment 表示切片时长,mysteam 表示一个实例,即未来要生成的文件名能够先本身随便设置一个。
更多配置能够参考:https://github.com/arut/nginx-rtmp-module/wiki/
下面是 nginx 的配置文件
[后台SDK]主要是调用腾讯云API。
[服务器API]提供了直播控制台api概览:
建立直播频道 CreateLVBChannel
查询直播频道列表 DescribeLVBChannelList
查询直播频道详情 DescribeLVBChannel
修改直播频道 ModifyLVBChannel
批量启用直播频道 StartLVBChannel
批量中止直播频道 StopLVBChannel
查询直播频道当前并发收看数 DescribeLVBOnlineUsers
删除直播频道 DeleteLVBChannel
建立录制任务 CreateRecord
终止录制任务 StopRecord
查询已录制分片列表 DescribeRecord
建立截图任务 CreateLVBShot
终止截图任务 StopLVBShot
查看队列消息 DescribeQueueLog
腾讯云直播方案总体流程
方案根据腾讯云的快速对接,最终造成闭环逻辑。
APP
视频源推流
向后台发起建立直播频道请求
向后台发起中止直播请求
后台
向腾讯云发起建立、删除(删除前先关闭)直播频道请求
直播频道缓存队列,处理僵尸频道
向APP客户端推送直播URL
Web
PC端的流视频播放器
移动客户端的流视频播放器
Step1:建立频道
客户端发起直播请求,后台调用CreateLVBChannel,由返回的channel_id调用DescribeLVBChannel查看频道信息。
后台向客户端返回推流url和Web直播地址(非flv流视频地址)。
Step2:SDK推流
推流SDK
Step3:删除频道
APP端推流结束,向后台发送请求删除频道,只有关闭的频道是能够删除的,因此后台删除一个频道以前,要先经过中止直播频道接口StopLVBChannel,先将频道状态置为中止,以后在调用删除直播频道接口DeleteLVBChannel对频道进行删除。
如何看
下载直播视频有如下方式:
HLS
rtmp
flv
好看的指标参数
码率:影响体积,与体积成正比:码率越大,体积越大;码率越小,体积越小。
帧率:影响画面流畅度,与画面流畅度成正比:帧率越大,画面越流畅;帧率越小,画面越有跳动感。若是码率为变量,则帧率也会影响体积,帧率越高,每秒钟通过的画面越多,须要的码率也越高,体积也越大。
分辨率:影响图像大小,与图像大小成正比:分辨率越高,图像越大;分辨率越低,图像越小。
对于H5视频播放,可使用 HLS(HTTP Live Streaming)协议播放直播流,iOS和 Android 都自然支持这种协议,配置简单,直接使用 video 标签便可。
使用 video在移动客户端上播放直播视频:
<video controls autoplay> <source src="xxx.m3u8" type="application/vnd.apple.mpegurl"/></video>
HLS是一个由苹果公司提出的基于HTTP的流媒体网络传输协议。
HLS直播最大的不一样在于,直播客户端获取到的,并非一个完整的数据流。
HLS协议在服务器端将直播数据流存储为连续的、很短时长的媒体文件(MPEG-TS格式),而客户端则不断的下载并播放这些小文件,由于服务器端老是会将最新的直播数据生成新的小文件,这样客户端只要不停的按顺序播放从服务器获取到的文件,就实现了直播。
因而可知,基本上能够认为,HLS是以点播的技术方式来实现直播。因为数据经过HTTP协议传输,因此不用考虑防火墙或者代理的问题,并且分段文件的时长很短,客户端能够很快的选择和切换码率,以适应不一样带宽条件下的播放。不过HLS的这种技术特色决定了延迟通常老是会高于普通的流媒体直播协议。
每个 .m3u8 文件,分别对应若干个 ts 文件,这些 ts 文件才是真正存放视频的数据,m3u8 文件只是存放了一些 ts 文件的配置信息和相关路径,当视频播放时,.m3u8 是动态改变的,video 标签会解析这个文件,并找到对应的 ts 文件来播放,因此通常为了加快速度,.m3u8 放在 Web 服务器上,ts 文件放在 CDN 上。
支持的视频流编码为H.264,音频流编码为AAC。
简单讲就是把整个流分红一个个小的,基于 HTTP 的文件来下载,每次只下载一些,前面提到了用于 H5 播放直播视频时引入的一个 .m3u8 的文件,这个文件就是基于 HLS 协议,存放视频流元数据的文件。
HLS的分段策略,基本上推荐是10秒一个分片,固然,具体时间还要根据分好后的分片的实际时长作标注
为了缓存等方面的缘由,在索引文件中会保留最新的三个分片地址,以“滑动窗口”的形式进行刷新。
.m3u8 文件,其实就是以 UTF-8 编码的 m3u 文件,这个文件自己不能播放,只是存放了播放信息的文本文件。
打开以后就是这个样子:
#EXTM3U m3u文件头,必须放在第一行 #EXT-X-MEDIA-SEQUENCE 第一个TS分片的序列号 #EXT-X-TARGETDURATION 每一个分片TS的最大的时长 #EXT-X-ALLOW-CACHE 是否容许cache #EXT-X-ENDLIST m3u8文件结束符 #EXTINF extra info,分片TS的信息,如时长,带宽等
#EXTM3U
#EXT-X-TARGETDURATION:11#EXT-X-VERSION:3#EXT-X-MEDIA-SEQUENCE:0#EXT-X-PLAYLIST-TYPE:VOD #EXTINF:10.133333, fileSequence0.ts #EXTINF:10.000666, fileSequence1.ts #EXTINF:10.667334, fileSequence2.ts #EXTINF:9.686001, fileSequence3.ts #EXTINF:9.768665, fileSequence4.ts #EXTINF:10.000000, fileSequence5.ts #EXT-X-ENDLIST
ts 文件,就是存放视频的文件:
HLS只请求基本的HTTP报文,与实时传输协议(RTP)不一样,HLS能够穿过任何容许HTTP数据经过的防火墙或者代理服务器。它也很容易使用内容分发网络来传输媒体流。
HTTP 请求 m3u8 的 url。
服务端返回一个 m3u8 的播放列表,这个播放列表是实时更新的,通常一次给出5段数据的 url。
客户端解析 m3u8 的播放列表,再按序请求每一段的 url,获取 ts 数据流。
咱们知道 hls 协议是将直播流分红一段一段的小段视频去下载播放的,因此假设列表里面的包含5个 ts 文件,每一个 TS 文件包含5秒的视频内容,那么总体的延迟就是25秒。由于当你看到这些视频时,主播已经将视频录制好上传上去了,因此时这样产生的延迟。固然能够缩短列表的长度和单个 ts 文件的大小来下降延迟,极致来讲能够缩减列表长度为1,而且 ts 的时长为1s,可是这样会形成请求次数增长,增大服务器压力,当网速慢时回形成更多的缓冲,因此苹果官方推荐的 ts 时长时10s,因此这样就会大改有30s的延迟。因此服务器接收流,转码,保存,切块,再分发给客户端,这里就延时的根本缘由。
更多关于延迟的问题能够参考苹果官方地址:
https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/StreamingMediaGuide/FrequentlyAskedQuestions/FrequentlyAskedQuestions.html
可是 H5 直播视频却有一些不可替代的优点:
传播性好,利于分享等操做。
能够动态发布,有利于实时迭代产品需求并迅速上线。
不用安装 App,直接打开浏览器便可。
RTMP协议是应用层协议,是要靠底层可靠的传输层协议(一般是TCP)来保证信息传输的可靠性的。在基于传输层协议的连接创建完成后,RTMP协议也要客户端和服务器经过“握手”来创建基于传输层连接之上的NetConnection连接,在Connection连接上会传输一些控制信息,如SetChunkSize,SetACKWindowSize。其中CreateStream命令会建立一个NetStream连接,用于传输具体的音视频数据和控制这些信息传输的命令信息。他们的关系如图所示:
RTMP协议传输时会对数据作本身的格式化,这种格式的消息咱们称之为RTMP Message,而实际传输的时候为了更好地实现多路复用、分包和信息的公平性,发送端会把Message划分为带有Message ID的Chunk,每一个Chunk多是一个单独的Message,也多是Message的一部分,在接受端会根据chunk中包含的data的长度,message id和message的长度把chunk还原成完整的Message,从而实现信息的收发。
Basic Header(基本的头信息)
chunk stream ID(流通道Id)和chunk type(chunk的类型,2位fmt),chunk stream id通常被简写为CSID,用来惟一标识一个特定的流通道,chunk type决定了后面Message Header的格式。长度有一、2或3个字节
Message Header(消息的头信息)
Message Header的格式和长度取决于Basic Header的chunk type,共有4种不一样的格式,由上面所提到的Basic Header中的fmt字段控制。包含timestamp,timestamp delta,message length,message type id,msg stream id,和0(表示与上一个相同)。
timestamp(时间戳):占用3个字节,所以它最多能表示到16777215=0xFFFFFF=2
24-1, 当它的值超过这个最大值时,这三个字节都置为1,这样实际的timestamp会转存到Extended Timestamp字段中,接受端在判断timestamp字段24个位都为1时就会去Extended timestamp中解析实际的时间戳。
message length(消息数据的长度):占用3个字节,表示实际发送的消息的数据如音频帧、视频帧等数据的长度,单位是字节。注意这里是Message的长度,也就是chunk属于的Message的总数据长度,而不是chunk自己Data的数据的长度。
message type id(消息的类型id):占用1个字节,表示实际发送的数据的类型,如8表明音频数据、9表明视频数据。
msg stream id(消息的流id):占用4个字节,表示该chunk所在的流的ID,和Basic Header的CSID同样,它采用小端存储的方式,
Extended Timestamp(扩展时间戳)
4个字节,当扩展时间戳启用时,timestamp字段或者timestamp delta要全置为1,表示应该去扩展时间戳字段来提取真正的时间戳或者时间戳差。注意扩展时间戳存储的是完整值,而不是减去时间戳或者时间戳差的值。
Chunk Data(块数据)
用户层面上真正想要发送的与协议无关的数据,长度在(0,chunkSize]之间。
RTMP在收发数据的时候并非以Message为单位的,而是把Message拆分红Chunk发送,并且必须在一个Chunk发送完成以后才能开始发送下一个Chunk。每一个Chunk中带有MessageID表明属于哪一个Message,接受端也会按照这个id来将chunk组装成Message。
举个例子
chunk表示例1
首先包含第一个Message的chunk的Chunk Type为0,由于它没有前面可参考的chunk,timestamp为1000。type为0的header占用11个字节,假定CSID为3<127,所以Basic Header占用1个字节,再加上Data的32个字节,所以第一个chunk共44=11+1+32个字节。
第二个chunk和第一个chunk的CSID,TypeId,Data的长度都相同,所以采用Chunk Type=2,timestamp delta=1020-1000=20,所以第二个chunk占用36=3+1+32个字节。
第三个chunk和第二个chunk的CSID,TypeId,Data的长度和时间戳差都相同,所以采用Chunk Type=3省去所有Message Header的信息,占用33=1+32个字节。
第四个chunk和第三个chunk状况相同,也占用33=1+32个字节。
最后实际发送的chunk以下:
chunk表示例2
注意到Data的Length=307>128,所以这个Message要切分红几个chunk发送,第一个chunk的Type=0,Timestamp=1000,承担128个字节的Data,所以共占用140=11+1+128个字节。
第二个chunk也要发送128个字节,其余字段也同第一个chunk,所以采用Chunk Type=3,此时时间戳也为1000,共占用129=1+128个字节。
第三个chunk要发送的Data的长度为307-128-128=51个字节,仍是采用Type=3,共占用1+51=52个字节。
最后实际发送的chunk以下:
Q:为何RTMP要将Message拆分红不一样的Chunk呢?
A:经过拆分,数据量较大的Message能够被拆分红较小的“Message”,这样就能够避免优先级低的消息持续发送阻塞优先级高的数据,好比在视频的传输过程当中,会包括视频帧,音频帧和RTMP控制信息,若是持续发送音频数据或者控制数据的话可能就会形成视频帧的阻塞,而后就会形成看视频时最烦人的卡顿现象。同时对于数据量较小的Message,能够经过对Chunk Header的字段来压缩信息,从而减小信息的传输量。
阻塞 vs. CPU
Chunk的默认大小是128字节,在传输过程当中,经过一个叫作Set Chunk Size的控制信息能够设置Chunk数据量的最大值,在发送端和接受端会各自维护一个Chunk Size,能够分别设置这个值来改变本身这一方发送的Chunk的最大大小。大一点的Chunk减小了计算每一个chunk的时间从而减小了CPU的占用率,可是它会占用更多的时间在发送上,尤为是在低带宽的网络状况下,极可能会阻塞后面更重要信息的传输。小一点的Chunk能够减小这种阻塞问题,但小的Chunk会引入过多额外的信息(Chunk中的Header),少许屡次的传输也可能会形成发送的间断致使不能充分利用高带宽的优点,所以并不适合在高比特率的流中传输。在实际发送时应对要发送的数据用不一样的Chunk Size去尝试,经过抓包分析等手段得出合适的Chunk大小,而且在传输过程当中能够根据当前的带宽信息和实际信息的大小动态调整Chunk的大小,从而尽可能提升CPU的利用率并减小信息的阻塞机率。
来源于《带你吃透RTMP》
播放一个RTMP协议的流媒体须要通过如下几个步骤:握手,创建链接,创建流,播放。RTMP链接都是以握手做为开始的。创建链接阶段用于创建客户端与服务器之间的“网络链接”;创建流阶段用于创建客户端与服务器之间的“网络流”;播放阶段用于传输视音频数据。
一个RTMP链接以握手开始,双方分别发送大小固定的三个数据块
握手开始于客户端发送C0、C1块。服务器收到C0或C1后发送S0和S1。
当客户端收齐S0和S1后,开始发送C2。当服务器收齐C0和C1后,开始发送S2。
当客户端和服务器分别收到S2和C2后,握手完成。
理论上来说只要知足以上条件,如何安排6个Message的顺序都是能够的,但实际实现中为了在保证握手的身份验证功能的基础上尽可能减小通讯的次数,通常的发送顺序是这样的:
Client发送C0+C1到Sever
Server发送S0+S1+S2到Client
Client发送C2到Server,握手完成
客户端发送命令消息中的“链接”(connect)到服务器,请求与一个服务应用实例创建链接。
服务器接收到链接命令消息后,发送确认窗口大小(Window Acknowledgement Size)协议消息到客户端,同时链接到链接命令中提到的应用程序。
服务器发送设置带宽(Set Peer Bandwitdh)协议消息到客户端。
客户端处理设置带宽协议消息后,发送确认窗口大小(Window Acknowledgement Size)协议消息到服务器端。
服务器发送用户控制消息中的“流开始”(Stream Begin)消息到客户端。
服务器发送命令消息中的“结果”(_result),通知客户端链接的状态。
客户端在收到服务器发来的消息后,返回确认窗口大小,此时网络链接建立完成。
服务器在收到客户端发送的链接请求后发送以下信息:
主要是告诉客户端确认窗口大小,设置节点带宽,而后服务器把“链接”链接到指定的应用并返回结果,“网络链接成功”。而且返回流开始的的消息(Stream Begin 0)。
客户端发送命令消息中的“建立流”(createStream)命令到服务器端。
服务器端接收到“建立流”命令后,发送命令消息中的“结果”(_result),通知客户端流的状态。
客户端发送publish推流指令。
服务器发送用户控制消息中的“流开始”(Stream Begin)消息到客户端。
客户端发送元数据(分辨率、帧率、音频采样率、音频码率等等)。
客户端发送音频数据。
客户端发送服务器发送设置块大小(ChunkSize)协议消息。
服务器发送命令消息中的“结果”(_result),通知客户端推送的状态。
客户端收到后,发送视频数据直到结束。
客户端发送命令消息中的“播放”(play)命令到服务器。
接收到播放命令后,服务器发送设置块大小(ChunkSize)协议消息。
服务器发送用户控制消息中的“streambegin”,告知客户端流ID。
播放命令成功的话,服务器发送命令消息中的“响应状态” NetStream.Play.Start & NetStream.Play.reset,告知客户端“播放”命令执行成功。
在此以后服务器发送客户端要播放的音频和视频数据。
对于直播中的用户交互大体能够分为:
送礼物
发表评论或者弹幕
对于送礼物,在 H5 端能够利用 DOM 和 CSS3 实现送礼物逻辑和一些特殊的礼物动画,实现技术难点不大。
对于弹幕来讲,要稍微复杂一些,可能须要关注如下几点:
弹幕实时性,能够利用 webscoket 来实时发送和接收新的弹幕并渲染出来。
对于不支持 webscoket 的浏览器来讲,只能降级为长轮询或者前端定时器发送请求来获取实时弹幕。
弹幕渲染时的动画和碰撞检测(即弹幕不重叠)等等
该组件主要适用于基于Html5的web 大群互动直播场景。具有以下特色:
1)支持匿名身份入群,粉丝与主播进行亲密互动
2)支持多人聊天,主播同一个账号多标签页收发消息,粉丝再多也不用愁
3)支持多种聊天方式,文本,表情,红包,点赞,想怎么互动就怎么互动
4)支持不一样优先级消息的频率控制,一键在手,权利尽在掌握中
5)对互动直播场景进行了专门的优化,参与人数多,消息量再大也能从容应对
秒开
时延
流畅
清晰度
目前较为成熟的直播产品,大体都是以 Server 端、 H5直播前端 和 Native(Android,iOS)搭配实现直播。
主要从android客户端出发,从最初的录制视频到客户端观看直播的整个流程,给出了各个技术点的概要和解决方案,从0到1完成了简单的直播实现。从0到1易,从1到100还有更多的技术细节有待研究。
参考文章:HTML 5 视频直播一站式扫盲