CategoryResourceRepost/极客时间专栏/从0打造音视频直播系统/支持上万人同时在线的直播系统/38 | 实战推演:带你实现一个支持万人同时在线的直播系统.md
louzefeng d3828a7aee mod
2024-07-11 05:50:32 +00:00

96 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<audio id="audio" title="38 | 实战推演:带你实现一个支持万人同时在线的直播系统" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/55/5e/5587c617bc93dd7c6d54ce5744fc3b5e.mp3"></audio>
本文我们将第三模块所讲的知识做一次梳理,让你在整体上了解“万人直播”到底是怎样实现的。我们将从万人直播的整体架构、主播客户端架构、观众客户端架构和流量统计这四个方面向你讲述万人直播的构建。
通过这几个方面的介绍,我想你就知道了一个真正的“万人直播”是如何构建起来的。
## 万人直播架构
下面这张万人直播架构图与[《31 | 一对多直播系统RTMP/HLS你该选哪个》](https://time.geekbang.org/column/article/140181)一文中介绍的直播架构图很类似,它们之间最大的不同在于真正的万人直播系统中并不会只使用一家 CDN网络而是接入多家 CDN网络。在使用它们时你可以按照一定的比例将“节目”分配到不同的CDN网络上。
<img src="https://static001.geekbang.org/resource/image/4e/bf/4e52d2ea1567a9821e1188f7bc6befbf.png" alt="">
多家 CDN 网络的管理一般是由信令服务器控制的。当要接入某家CDN网络时你可以通过信令服务器的注册界面进行注册。在注册界面中一般要求填入CDN厂商的名字、分配比例、CDN API操作地址等信息。
比如当某个主播要分享一个节目时信令服务器首先根据分配比例决定使用哪个CDN网络然后获得该CDN网络的API操作地址。获取到 CDN 网络的API操作地址后它就可以调用该CDN网络提供的 HTTP/HTTPS API 进行操作了创建域名、生成直播地址、生成拉流地址等等。有了这些地址后就可以将音视频流推送到CDN网络观众端获取到观看地址后就可以“观看”节目了。
除了接入多家 CDN 网络之外,其他功能与我们之前文章中介绍的是一样的,这里我就不再赘述了。
## 主播客户端架构
了解了万人直播架构后,接下来我们再看一下主播端的架构。之前我们介绍过,如果在 PC 端进行直播的话直接使用OBS工具就可以了这个工具是一个非常专业的 PC 端推流工具,功能非常强大,很多主播都使用该工具进行推流。
但如果是移动端的话,就需要我们自己来实现了。主播端的架构如下图所示,按层级分为三层,即**传输层、编码与展示层**和**采集层**。
<img src="https://static001.geekbang.org/resource/image/5e/b6/5e0f7b59e401a1939ce3a618082e55b6.png" alt="">
下面我们对各层级的模块分别做下说明。
**传输层**包括了信令处理和RTMP数据传输。信令处理与业务逻辑关系紧密比如创建房间、获得推流地址、聊天、送礼物等都属于信令处理的范畴。RTMP 数据传输就更简单了,当从信令模块获取到推流地址后,就可以将编码后的音视频数据通过 RTMP 协议推送给 CDN 网络了。
**编码与展示层**,该层包括的功能比较多,包括音频检测、音频编码、视频编码、视频预览以及视频美颜。接下来,我们再对这每个功能模块做一下说明。
- 音频检测,主要用于在直播开始前检测音频设备是否可用。
- 音频编码用于将音频采集模块采集的PCM数据进行压缩编码。常见的音频编码有 AAC、MP3、Opus等。一般情况下使用 AAC 编码方式。另外,编码也分为两种,一种是软编,一种是硬编。所谓软编,就是指通过 CPU 执行压缩算法进行编码会对CPU造成很大损耗硬编是指通过 GPU 或固定的集成电路进行数据的压缩它可以将CPU资源节省出来。
- 视频编码用于将视频采集模块采集的YUV数据进行压缩编码。常见的视频编码有 H264/H265、VP8/VP9等。大多数情况下我们都使用 H264 对视频进行编码。视频编码同样分为软编和硬编。在移动端一般我建议使用硬件编码这样可以大大节省CPU资源。
- 视频预览,将采集的视频展示出来,以便让主播看到从移动端采集到的视频数据的效果。由于视频帧每秒要刷新很多次,并且视频的数据都比较大,所以在处理视频渲染时如果没有处理好,会引起性能问题,如手机反应迟顿、发烫等问题。一般情况下,我们都会使用 OpenGL ES/ Metal 对视频渲染进行加速,从而解决反应迟顿、发烫等问题。
- 视频美颜,美颜目前可以说是娱乐直播的必备功能,尤其是对于美女主播就显得更为重要。如美白、瘦脸、长腿等这些功能是美女主播最喜欢用的功能。这种特效通常也是通过 OpenGL/Metal 来实现的。当然随着技术的发展现在一些AR技术也逐渐应用于各种视频效果中如雨滴、飘雪等等。
**采集层**,包括音频采集和视频采集。这两个功能模块非常简单,一个用于采集音频数据,另一个用于采集视频数据。它们都是与硬件打交道。
除了上面这些内容外在主播端还会有数据统计模块。比如什么时候创建房间、什么时候开始推流、推流时音视频的码率是多少等等这些信息都是由数据统计模块记录的。有了这个模块之后一是便于我们分析问题二是便于我们进行计费核算在与各CDN厂商结算费用时会非常有用。
## 观众端架构
介绍完主播端的功能后,接下来我们再来看看观众端(如下图)。观众端与主播端是很类似的,但实际上我们自己并不会将每个模块都亲手实现,因为对于观众端来说,大部分模块都属于播放器的功能。因此,我们在实现观众端的时候,只需要实现信令处理模块、数据统计模块,并将播放器集成进来就可以了。
<img src="https://static001.geekbang.org/resource/image/9e/f8/9eb7c783f2ef7ae9158148d34819e1f8.png" alt="">
对于移动端我们一般都使用Ijkplayer作为观众端播放器。 Ijkplayer是由bilibili公司开源的项目地址为[https://github.com/bilibili/ijkplayer.git](https://github.com/bilibili/ijkplayer.git) 。它既可以用于 Android 端又可以用于 iOS端使用起来非常方便。
实际上Ijkplayer就是 FFmpeg 中 FFplay 的变种它们的基本逻辑是一致的只不过Ijkplayer 更容易移植到移动端上。另外作为 iOS 端,它自带的 player 非常成熟,你也可以直接使用它自己的 player 来实现观众端。
在 PC 端你可以集成 VLC它与Ijkplayer一样也是非常优秀的一款播放器。该播放器的集成也非常简单你在网上可以找到非常多的资料所以这里我就不对它做更多的介绍了。
当然Web端也是必不可少的你可以使用我们前面文章中介绍的 flv.js 或 video.js 作为Web 端的播放器就可以了。
## 流量统计
下面我们再简要介绍一下流量统计。当在我们的直播系统中接入 CDN 网络时一个非常重要的工作就是费用结算。一般情况下都是按流量进行结算的。也就是说CDN厂商会根据我们或我们的用户使用了多少CDN流量进行费用的结算所以我们一定要知道自己用了多少流量。
另一方面,除了流量,我们还要监控我们的服务质量,比如是否出现了卡顿?每小时卡顿了多少次?引起卡顿的原因是什么?是否发生过分辨率切换?缓冲区还有多少数据没有播放出来?这些都与服务质量有着密切的关系。
那么接下来我们就来讲讲该如何采集数据,以达到监控服务质量和费用结算的目的。根据我的实际经验,以下信息是你在每个用户使用 CDN 网络时必须要记录下来的信息:
- 视频分辨率、帧率、码率相关信息
- 开启播放时间
- 关闭播放时间
- 暂停播放时间
- 恢复播放时间
- 缓冲区为0的时间
- 拖放时间以及拖放到的时间
- 分辨率切换的时间
- ……
通过以上这些信息你就可以将用户使用的流量精确地计算出来了这样再与CDN厂商核对数据时你心里就有谱了。
举个例子,当我们想统计一个用户使用了多少流量时,最简单的公式是(关闭播放时间-开启播放时间)* 码率,通过这个公式,你就可以计算出结果了;如果中间有暂停,则计算公式就变成了((暂停播放时间-开启播放时间)+ (关闭播放时间-恢复播放时间)* 码率;如果是多次暂停和恢复,那公式就更加复杂了,你需要按照上面的方法一步一步去推导就可以了。
另外,由于统计数据是一个特别精细的活儿,把这件事儿做好不容易,而且又涉及到费用问题,所以在后端统计时一定要细致,否则当一个节目观看人数众多时,就很容易出现比较大的偏差。
通过上面的介绍,我想在你脑海中一定有了一个统计流量的雏形了,你可以在这个雏形的基础上不断完善你的算法,就可以实现商用的统计系统了。
## 小结
本文我们从四个方面向你全面介绍了传统直播系统是如何实现的。首先讲解了传统直播系统的架构该架构与我们前面介绍的架构是类似的最重要的差别是可以接入多个CDN网络。在真正商用的系统中这个CDN网络都是按一定比例分配资源当有某个CDN网络出现问题时还可以进行CDN网络的切换。然后我们又详细阐述了主播客户端与观众客户端是如何实现的。最后还讲述了流量统计模块因为它关系到统计计费与服务质量所以是直播系统中必不可少的一个模块。
目前国内的CDN厂商特别多如阿里、腾讯、金山等当然也还有很多老牌的CDN厂商如蓝汛、网宿等它们的质量具体如何还需要你多进行测试。从我个人经验来讲阿里无论价格还是质量都还不错。
## 思考时间
今天留给你的思考题:如何判断用户在播放音视频流时是否出现过卡顿?
欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友。