斗鱼 H5 直播原理解析,它是如何省了 80% 的 CDN 流量?
斗鱼直播相信大家都听说过,打开斗鱼官网就可以直接在浏览器中观看直播。那么斗鱼是如何实现浏览器视频直播的呢?本篇文章就来解析斗鱼是如何实现直播的,以及它是如何节省 80% 的 CDN 流量,要知道视频直播流量费并不便宜,斗鱼每个月光这些流量费都要支付几个亿,节省 CDN 流量就是省钱。
直播技术方案
在实际去斗鱼直播间调试视频直播之前,我就猜它肯定是使用 HTTP-FLV 方案来实现视频直播,因为国内几乎所有直播平台都是使用 HTTP-FLV 方案。
但是去斗鱼直播间并没有找到 .flv 的网络请求,而是找到了 .xs 的网络请求,如下图所示。
不过 .xs 网络请求的响应的 Content-Type 是 video/x-flv,原来只是后缀不同,看来我猜的果真没错,斗鱼就是用的 HTTP-FLV。
HTTP+P2P FLV 拉流
不过为什么后缀是 .xs 而不是 .flv 呢?其实这里是因为斗鱼默认并不完全使用 HTTP 去拉流,而是采用 CDN 和 P2P 两种方式同时去拉流,.xs 并不是一个完整的 FLV 流,而是一个子 FLV 流。
进入斗鱼直播间,斗鱼首先会去请求一个完整的 FLV 流,等 P2P 连接好了再去切换成子流。这是因为 P2P 连接比较慢,如果走来就走 P2P,那么视频起播速度会非常慢。
上图中第二个连接就是一个完整的 FLV 流,等 P2P 连接成功后会断开连接去拉子流。
在 P2P 连接成功后,还可以在网络面板看到一个 WebSocket 连接,如下图所示,它是斗鱼用来推送其他正在观看当前流的用户的,这样播放器就可以直接从推送的用户这里拉流。
斗鱼 P2P 是基于 WebRTC 的 DataChannel,可以打开 chrome 的 WebRTC 的调试页面,可以看到有很多 WebRTC 连接,它可以接收其他用户分享的视频数据,自己也会共享当前下载到的视频数据给其他用户。
斗鱼将一个完整的直播流进行切片,分成一个个小的视频分片并进行编号(这样方便用户之间共享)然后将这些小分片分为多个子流,通过 HTTP 从 CDN 拉一路子流,然后通过 P2P 去其他用户那里拉其他的子流。
但是通过 P2P 从其他用户那里拉流并不是很稳定,例如其他用户可以能退出了直播间,或者网络出了问题,这样就会导致接收它分享的用户直播断流。为了提升直播稳定性,如果在一定时间内没有收到其他用户分享的数据,斗鱼播放器就会立刻从 CDN 去拉对应的子流,并且 WebSocket 也会推荐新的用户给播放器。
可以发现,加上 P2P 拉流,大大增加了直播的复杂度。但是它带来的好处也非常的明显,就是可以省钱,省到就是赚到!因为流量费非常的贵,斗鱼每个月光直播带宽都得花好几个亿。利用 P2P 从其他用户那里拉流可以节省大量流量,例如一个直播流分为两个子流,一个从 CDN 拉,一个从其他用户那里拉,这样理论上就可以节省 50% 的流量,而斗鱼将一个直播流分成 6 个子流,一个从 CDN 拉,其余 5 个全部从其他用户那里拉,理论上可以节省超过 80% 的直播流量!
当然 P2P 拉流也有一些缺点,例如直播延迟较高,不适用于低延迟直播场景,对用户电脑和带宽有一定消耗,因为除了从其他用户那里拉流,当前用户自己还要上传视频数据给其他用户。
如果你想关闭 P2P,也比较简单,可以在网络面板屏蔽下图中的地址即可。
屏蔽之后,斗鱼就只会从 CDN 拉流,不走 P2P,如下图所示,可以发现流的地址变成正常的 .flv 后缀。
无论是只使用 HTTP,还是使用 HTTP + P2P,它们的最终目的是获取 FLV 视频数据。
FLV 格式
FLV 视频格式是由 Adobe 公司开发,在 2003 年发布,用于视频文件在网络上传输。在 Flash 时代几乎所有流媒体平台都在使用 FLV 格式,但是随着 Flash 技术的淘汰,FLV 也跟着没落了,目前国外已经没有流媒体平台在使用 FLV 了,但是在国内 FLV 却广泛用于网络直播场景。
不像 Flash,H5 的 video 元素是无法播放 FLV 视频的,我们需要借助 MSE 来自己控制视频播放,具体原理是将 FLV 转封装成 FMP4 视频格式,然后交给 MSE 播放即可。
MSE 全称是 Media Source Extensions API,它是 Web 流媒体的基础,所有 Web 流媒体平台最终都会用到它,如果对它感兴趣,欢迎查看 流媒体视频基础 MSE 入门 & FFmpeg 制作视频预览缩略图和 fmp4
目前有开源的 flv.js 来帮我们完成这件事,查看斗鱼 dist 后代码,斗鱼也是使用的 flv.js,不过在之上加了很多自定义的代码,例如加上了 h265 编码的支持,flv.js 是不支持 h265 编码的,FLV 官方规范也不支持,但是业务又有这种需求,所以一般将 FLV 视频编码 ID 等于 12 当作 h265 的流。在斗鱼直播中如果发现直播流是 h265 编码并且浏览器不支持 h265,斗鱼会利用 WASM 来软解播放视频。
直播时移
对于赛事直播斗鱼是支持直播时移的,如下图所示。
但是这个播放器的进度条体验不是很好,进度条的高度只有 3px,鼠标非要精准的放上去,才能有 Hover 的效果,这是没那么容易做到的。这里推荐个好用开源的播放器进度条 ppbar,你可以把它集成到任何播放器中去,非常的好用。
斗鱼直播时移是基于 HLS 的,如果点击一下进度条,斗鱼播放器会黑一下,将 FLV 切换成 HLS。
在刚开始进入直播间拉流的时候,斗鱼播放器可以获取到服务器返回的一个时间戳,单位是秒,当用户点击进度条跳转到前 10 分钟时,就直接用当前时间减去 600 秒就得到了前 10 分钟视频的时间戳,然后会用这个时间戳去请求请求一个 getVodStream 接口获取到 HLS 时移流地址,获取到 HLS 过后,就和普通 HLS 直播一样去播放即可。
和 FLV 一样,要在浏览器中播放 HLS 流,同样需要 MSE API 来播放,目前可以借助开源的 hls.js 来在浏览器中播放 HLS 流。查看斗鱼 dist 过后的代码,斗鱼应该没有使用 hls.js,而是自己实现在浏览器中播放 HLS。
总结
这篇文章介绍了斗鱼 H5 直播技术的原理,斗鱼不仅使用国内常用的 HTTP-FLV 方案,还加入了 P2P 拉流,从而节省 CDN 流量。对于赛事直播,斗鱼还支持直播时移,直播时移是使用 HLS 来实现的,用户在 seek 后会通过 seek 到的时间点去服务器换取对应的时移 HLS 流地址,然后走 HLS 拉流即可。
斗鱼 H5 直播原理解析,它是如何省了 80% 的 CDN 流量?的更多相关文章
- 视频技术详解:RTMP H5 直播流技术解析
本文聚焦 RTMP 协议的最精华的内容,接进行实际操作 Buffer 的练习和协议的学习. RTMP 是什么 RTMP 全称即是 Real-Time Messaging Protocol.顾名思义就是 ...
- iOS:app直播---原理篇
[如何快速的开发一个完整的iOS直播app](原理篇) 转载自简书@袁峥Seemygo:http://www.jianshu.com/p/7b2f1df74420 一.个人见解(直播难与易) 直播 ...
- 前端开发:H5直播起航
前言 前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端HTML5直播可行性方案. 发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端 ...
- 视频流协议HLS与RTMP 直播原理 点播原理
小结: 1.HLS原理 视频--->图像.声音分别编码打包切割容器文件ts,建立纯文本索引文件.m3u8--->播放器http下载容器文件.索引文件,播放,下载 基于HLS可以实现直播和点 ...
- 七、H5 直播视频播放
HTML5实现视频直播功能思路详解_html5教程技巧_脚本之家 https://m.jb51.net/html5/587215.html 七.H5 直播视频播放 移动端iOS和 Android 都天 ...
- Flask 上下文(Context)原理解析
:first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...
- android黑科技系列——Apk的加固(加壳)原理解析和实现
一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...
- [原][Docker]特性与原理解析
Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
随机推荐
- 异常分类和异常的产生过程解析和Objects非空判断
java.lang.Throwable类是java语言中所有错误的异常的超类. Exception:编译期异常,进行编译(写代码)java程序出现的问题 RuntimeExeption:运行期异常,j ...
- Excel 逻辑函数(二):AND 和 OR
前言 AND 函数是且:OR 函数是或.AND 函数中的条件必须都满足才返回 TRUE:OR 函数中的条件只要满足一个就返回 TRUE.AND 和 OR 的参数最多允许有 30 个. AND [题目] ...
- python金牌班第七周周末总结
python金牌班第七周周末总结 面向对象前戏 1.我们在学习面相对像之前有一个推导过程如何将我们之前写的东西,从一串代码转向给对象服务. 2.实例 我们首先模拟了两个物种进行战斗的场景,然后我们发现 ...
- 【HTML】学习路径3-段落标签和标题标签
第一章:标题标签 <h1> </h1> <h2> </h2> 等等... 数字越大,字体尺寸越小. <!--标题会加粗.独占一行--> ...
- CF-1675D. Vertical Paths
题意:每次可以选择一条路径,要求这条路径中每个点都是上一个点的子节点,求最少需要几条路径将所有点走完 思路:将每个点有没有子节点判断出来,因为只有没有子节点的点需要新增一条路,所以需要路径的最小数目就 ...
- ansible 002 连接被控端 inventory ansible.cfg ansible-adhoc ansible原理
ssh用普通用户连接被控端 配置主机清单 (/etc/hosts域名解析为前提) [root@workstation ansible]# cat hosts servera serverb [root ...
- Linux配置bond模式 双网卡绑定步骤
什么是bond 网卡bond是通过多张网卡绑定为一个逻辑网卡,实现本地网卡的冗余,带宽扩容和负载均衡,在生产场景中是一种常用的技术.Kernels 2.4.12及以后的版本均供bonding模块,以前 ...
- MYSQL 安装及语法
Ubuntu 16.04 安装MySql 目录 一.安装MySql服务器和客户端 1.登录 2.创建数据库 3.选择数据库 4.查看数据库 5.创建数据表 6.查看数据表 7.更改数据表名字 8.更改 ...
- MySQL 不同隔离级别,都使用了什么锁?
大家好,我是树哥. 在上篇文章,我们聊了「MySQL 啥时候会用表锁,啥时候用行锁」这个问题.在文章中,我们还留了一个问题,即:如果查询或更新时的数据特别多,是否从行锁会升级为表锁?此外,还有朋友留言 ...
- .Net之接口小知识
目的 通过一个简单的项目,在原来的文章基础上完善一下常用的几种WebApi编写方式以及请求方式,一方面是用于给我一个前端朋友用来学习调用接口,另一方面让我测试HttpClient的一些效果. 本文示例 ...