斗鱼直播相信大家都听说过,打开斗鱼官网就可以直接在浏览器中观看直播。那么斗鱼是如何实现浏览器视频直播的呢?本篇文章就来解析斗鱼是如何实现直播的,以及它是如何节省 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 流量?的更多相关文章

  1. 视频技术详解:RTMP H5 直播流技术解析

    本文聚焦 RTMP 协议的最精华的内容,接进行实际操作 Buffer 的练习和协议的学习. RTMP 是什么 RTMP 全称即是 Real-Time Messaging Protocol.顾名思义就是 ...

  2. iOS:app直播---原理篇

    [如何快速的开发一个完整的iOS直播app](原理篇) 转载自简书@袁峥Seemygo:http://www.jianshu.com/p/7b2f1df74420   一.个人见解(直播难与易) 直播 ...

  3. 前端开发:H5直播起航

    前言 前不久抽空对目前比较火的视频直播,做了下研究与探索,了解其整体实现流程,以及探讨移动端HTML5直播可行性方案. 发现目前 WEB 上主流的视频直播方案有 HLS 和 RTMP,移动 WEB 端 ...

  4. 视频流协议HLS与RTMP 直播原理 点播原理

    小结: 1.HLS原理 视频--->图像.声音分别编码打包切割容器文件ts,建立纯文本索引文件.m3u8--->播放器http下载容器文件.索引文件,播放,下载 基于HLS可以实现直播和点 ...

  5. 七、H5 直播视频播放

    HTML5实现视频直播功能思路详解_html5教程技巧_脚本之家 https://m.jb51.net/html5/587215.html 七.H5 直播视频播放 移动端iOS和 Android 都天 ...

  6. Flask 上下文(Context)原理解析

    :first-child { margin-top: 0; } blockquote > :last-child { margin-bottom: 0; } img { border: 0; m ...

  7. android黑科技系列——Apk的加固(加壳)原理解析和实现

    一.前言 今天又到周末了,憋了好久又要出博客了,今天来介绍一下Android中的如何对Apk进行加固的原理.现阶段.我们知道Android中的反编译工作越来越让人操作熟练,我们辛苦的开发出一个apk, ...

  8. [原][Docker]特性与原理解析

    Docker特性与原理解析 文章假设你已经熟悉了Docker的基本命令和基本知识 首先看看Docker提供了哪些特性: 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上, ...

  9. 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现

    本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...

随机推荐

  1. 《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(9)-Fiddler如何设置捕获Https会话

    1.简介 由于近几年来各大网站越来越注重安全性都改成了https协议,不像前十几年前直接是http协议直接裸奔在互联网.还有的小伙伴或者童鞋们按照上一篇宏哥的配置都配置好了,想大展身手抓一下百度的包, ...

  2. Vue 引出声明周期 && 组件的基本使用

    1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 & ...

  3. Luogu2783 有机化学之神偶尔会做作弊 (树链剖分,缩点)

    当联通块size<=2时不管 #include <iostream> #include <cstdio> #include <cstring> #includ ...

  4. LuoguP3047 [USACO12FEB]附近的牛Nearby Cows(树形DP,容斥)

    \[f[u][step] = \begin{cases} C[u] & step = 0 \\ (\sum{f[v][step - 1]}) - f[u][step - 2] \cdot (d ...

  5. java学习第四天高级数组.day13

    正则表达式 冒泡排序 二分法查找 线性查找:从头找到尾,性能比较低. 二分法查找(折半查找):前提数组元素是有序的,性能非常优异. Arrays

  6. jsp获取单选按钮组件的值

    jsp获取单选按钮组件的值 1.首先,写一个带有单选按钮组件的前台页 1 <%@ page language="java" contentType="text/ht ...

  7. Live2d Widget

    写在最前 最早的时候看别人的博客很多都有一个可爱的看板娘,然后就找了教程给自己也整了一个.因为找到的教程都是稂莠不齐的,原作者自己说的也略显含糊(其实是我自己看不懂).总之秉承着一如既往的小白风格.把 ...

  8. 自定义注解,利用AOP实现日志保存(数据库),代码全贴,复制就能用

    前言 1,在一些特定的场景我们往往需要看一下接口的入参,特别是跨系统的接口调用(下发,推送),这个时候的接口入参就很重要,我们保存入参入库,如果出问题就可以马上定位是上游还是下游的问题(方便扯皮) 2 ...

  9. linux之间上传下载--SCP

    1.远程拷贝文件 [root@rhel8-client01 yum.repos.d]# scp root@192.168.72.149:/etc/yum.repos.d/* . (.表示拷贝到当前文件 ...

  10. SpringMVC完整版详解

    1.回顾MVC 1.1什么是MVC MVC是模型(Model).视图(View).控制器(Controller)的简写,是一种软件设计规范. 是将业务逻辑.数据.显示分离的方法来组织代码. MVC主要 ...