H5直播入门(理论篇)

前言

这篇总结实际上是去年公司每周技术分享会轮到个人时候写的。那时候公司正在大刀阔斧地准备直播业务,私觉得主管会委以重任,就翻了很多论坛,作了一次简单的技术分享。后来直播业务让另外一位同事承担了,本身也就没了实践直播的机会,有点惋惜吧。好了,废话很少说,开始咱们的理论篇~html

技术背景

能够看到,直播从 PC 到一直发展到移动端,愈来愈多的直播类 App 上线,同时移动直播进入了史无前例的爆发阶段,可是对于大多数移动直播来讲,仍是要以 Native 客户端实现为主,可是 H5 在移动直播端也承载着不可替代的做用,例如 H5 有着传播快,易发布的优点,同时最为关键的是 H5 一样能够播放直播视频。

2016年是直播元年,一是因为各大宽带提供商顺应民意增宽降价,二是大量资本流进了直播板块,促进了技术的更新迭代。市面上,最经常使用的是 Apple 推出的 HLS 直播协议(原始支持 H5 播放),固然,还有 RTMP、HTTP-FLV、RTP等。前端

视频文件格式和直播协议

视频文件格式

视频文件格式实际上,咱们经常称做为容器格式,也就是,咱们通常生活中最常常谈到的格式,flv,mp4,ogg 格式等。它就能够理解为将比特流按照必定顺序放进特定的盒子里。那选用不一样格式来装视频有什么问题吗?android

答案是,没有任何问题,可是你须要知道如何将该盒子解开,而且可以找到对应的解码器进行解码。那若是按照这样看的话,对于这些 mp4,ogv,webm等等视频格式,只要我有这些对应的解码器以及播放器,那么就没有任何问题。那么将视频比特流放进一个盒子里面,若是其中某一段出现问题,那么最终生成的文件其实是不可用的,由于这个盒子自己就是有问题的。ios

不过,上面有一个误解的地方在于,我只是将视频理解为一个静态的流。试想一下,若是一个视频须要持续不断的播放,例如,直播,现场播报等。这里,咱们就拿 TS/PS 流来进行讲解。nginx

  • PS(Program Stream): 静态文件流web

  • TS(Transport Stream): 动态文件流chrome

针对于上面两种容器格式,其实是对一个视频比特流作了不同的处理。浏览器

  • PS: 将完成视频比特流放到一个盒子里,生成固定的文件
  • TS: 将接受到的视频,分红不一样的盒子里。最终生成带有多个盒子的文件。

那么结果就是,若是一个或多个盒子出现损坏,PS 格式没法观看,而 TS 只是会出现跳帧或者马赛克效应。二者具体的区别就是:对于视频的容错率越高,则会选用 TS,对视频容错率越低,则会选用 PS。服务器

直播协议HLS

HTTP Live Streaming(简称 HLS)是一个基于 HTTP 的视频流协议。这是 Apple 提出的直播流协议。目前,IOS 和 高版本 Android 都支持 HLS。那什么是 HLS 呢?HLS 主要的两块内容是 .m3u8 文件和 .ts 播放文件。架构

HLS 协议基于 HTTP,而一个提供 HLS 的服务器须要作两件事:

编码:以 H.263 格式对图像进行编码,以 MP3 或者 HE-AAC 对声音进行编码,最终打包到 MPEG-2 TS(Transport Stream)容器之中;

分割:把编码好的 TS 文件等长切分红后缀为 ts 的小文件,并生成一个 .m3u8 的纯文本索引文件;

浏览器使用的是 m3u8 文件。m3u8 跟音频列表格式 m3u 很像,能够简单的认为 m3u8 就是包含多个 ts 文件的播放列表。播放器按顺序逐个播放,所有放完再请求一下 m3u8 文件,得到包含最新 ts 文件的播放列表继续播,周而复始。整个直播过程就是依靠一个不断更新的 m3u8 和一堆小的 ts 文件组成,m3u8 必须动态更新,ts 能够走 CDN。

这里,咱们着重介绍一下客户端的过程。首先,直播之因此是直播,在于它的内容是实时更新的。那 HLS 是怎么完成呢?

咱们使用 HLS 直接就用一个 video 进行包括便可:

<video autoplay controls>
    <source src="xxx.m3u8" type="application/vnd.apple.mpegurl" />
    <p class="warning">Your browser doesn't support video</p>
</video>
复制代码

根据上面的描述,它实际上就是去请求一个 .m3u8 的索引文件。该文件包含了对 .ts 文件的相关描述,例如:

不过,这只是一个很是简单,不涉及任何功能的直播流。实际上,HLS 的整个架构,能够分为:
masterplaylist 主要干的事就是根据, 当前用户的带宽,分辨率,解码器等条件决定使用哪个流。因此,master playlist 是为了更好的用户体验而存在的。

当填写了 master playlist URL,那么用户只会下载一次该 master playlist。接着,播放器根据当前的环境决定使用哪个 media playlist(就是 子 m3u8 文件)。若是,在播放当中,用户的播放条件发生变化时,播放器也会切换对应的 media playlist。

固然,HLS 支持的功能,并不仅是分片播放(专门适用于直播),它还包括其余应有的功能。

  • 使用 HTTPS 加密 ts 文件

  • 快/倒放

  • 广告插入

  • 不一样分辨率视频切换

能够看到 HLS 协议本质仍是一个个的 HTTP 请求 / 响应,因此适应性很好,不会受到防火墙影响。但它也有一个致命的弱点:延迟现象很是明显。若是每一个 ts 按照 5 秒来切分,一个 m3u8 放 6 个 ts 索引,那么至少就会带来 30 秒的延迟。若是减小每一个 ts 的长度,减小 m3u8 中的索引数,延时确实会减小,但会带来更频繁的缓冲,对服务端的请求压力也会成倍增长。因此只能根据实际状况找到一个折中的点。

注意:HLS 在 PC 端仅支持safari浏览器,相似chrome浏览器使用HTML5 video标签没法播放 m3u8 格式,可直接采用网上一些比较成熟的方案,如:sewise-player、MediaElement、videojs-contrib-hls、jwplayer。

直播协议RTMP

Real Time Messaging Protocol(简称 RTMP)是 Macromedia 开发的一套视频直播协议,如今属于 Adobe。和 HLS 同样均可以应用于视频直播,区别是 RTMP 基于 flash 没法在 iOS 的浏览器里播放,可是实时性比 HLS 要好。因此通常使用这种协议来上传视频流,也就是视频流推送到服务器。

下面是 HLS 和 RTMP 的对比:

直播协议HTTP-FLV

HTTP-FLV 和 RTMP 相似,都是针对于 FLV 视频格式作的直播分发流。但,二者有着很大的区别。

  • 直接发起长链接,下载对应的 FLV 文件
  • 头部信息简单

如今市面上,比较经常使用的就是 HTTP-FLV 进行播放。但,因为手机端上不支持,因此,H5 的 HTTP-FLV 也是一个痛点。不过,如今 flv.js 能够帮助高版本的浏览器,经过 mediaSource 来进行解析。HTTP-FLV 的使用方式也很简单。和 HLS 同样,只须要添加一个链接便可:

<object type="application/x-shockwave-flash" src="xxx.flv"></object>
复制代码

直播基本架构

目前较为成熟的直播产品,大体都是以 Server 端和 H5 和 Native(android,ios)搭配实现直播,基本是下图这个套路:

完整的直播能够分为如下几块:

  • 视频录制端:通常是电脑上的音视频输入设备或者手机端的摄像头或者麦克风,目前以移动端的手机视频为主。

  • 视频播放端:能够是电脑上的播放器,手机端的 Native 播放器,还有就是 H5 的 video 标签等,目前仍是已手机端的 Native 播放器为主。

  • 视频服务器端:通常是一台 nginx 服务器,用来接受视频录制端提供的视频源,同时提供给视频播放端流服务。

而现行H5相似直播页面,实现技术难点不大,其能够经过实现方式分为:① 底部视频背景使用video视频标签实现播放 ② 关注、评论模块利用 WebScoket 来实时发送和接收新的消息经过DOM 和 CSS3 实现 ③ 点赞利用 CSS3 动画

对于弹幕来讲,要稍微复杂一些,可能须要关注如下几点:

  • 弹幕实时性,能够利用 webscoket 来实时发送和接收新的弹幕并渲染出来。

  • 对于不支持 webscoket 的浏览器来讲,只能降级为长轮询或者前端定时器发送请求来获取实时弹幕。

  • 弹幕渲染时的动画和碰撞检测(即弹幕不重叠)等等

H5直播方案

使用flv.js作直播

  • 简介

flv.js是来自Bilibli的开源项目。它解析FLV文件喂给原生HTML5 Video标签播放音视频数据,使浏览器在不借助Flash的状况下播放FLV成为可能。

  • 优点

因为浏览器对原生Video标签采用了硬件加速,性能很好,支持高清。同时支持录播和直播。去掉对Flash的依赖。

  • 浏览器依赖

flv.js依赖的浏览器特性兼容列表

一、HTML5 Video

二、Media Source Extensions

三、WebSocket

四、HTTP FLV: fetch 或 stream

  • 原理

flv.js只作了一件事,在获取到FLV格式的音视频数据后经过原生的JS去解码FLV数据,再经过Media Source Extensions API 喂给原生HTML5 Video标签。(HTML5 原生仅支持播放 mp4/webm 格式,不支持 FLV)

flv.js 为何要绕一圈,从服务器获取FLV再解码转换后再喂给Video标签呢?缘由以下:

一、兼容目前的直播方案:目前大多数直播方案的音视频服务都是采用FLV容器格式传输音视频数据。

二、FLV容器格式相比于MP4格式更加简单,解析起来更快更方便。

  • 兼容方案

PC端

一、优先使用 HTTP-FLV,由于它延迟小,性能也不差1080P都很流畅。

二、不支持 flv.js 就使用 Flash播放器播 RTMP 流。Flash兼容性很好,可是性能差默认被不少浏览器禁用。

三、不想用Flash兼容也能够用HLS,可是PC端只有Safari支持HLS

移动端

一、优先使用 HTTP-FLV,由于它延迟小,支持HTTP-FLV的设备性能运行 flv.js 足够了。

二、不支持 flv.js 就使用 HLS,可是 HLS延迟很是大。

三、HLS 也不支持就无法直播了,由于移动端都不支持Flash。

好了,毕竟是入门理论篇,后续若是有业务实践我会更新的,感受阅读至此,比心~

相关文章
相关标签/搜索