本文我们将第三模块所讲的知识做一次梳理,让你在整体上了解“万人直播”到底是怎样实现的。我们将从万人直播的整体架构、主播客户端架构、观众客户端架构和流量统计这四个方面向你讲述万人直播的构建。

通过这几个方面的介绍,我想你就知道了一个真正的“万人直播”是如何构建起来的。

万人直播架构

下面这张万人直播架构图与《31 | 一对多直播系统 RTMP/HLS,你该选哪个?》一文中介绍的直播架构图很类似,它们之间最大的不同在于真正的万人直播系统中并不会只使用一家 CDN 网络,而是接入多家 CDN 网络。在使用它们时,你可以按照一定的比例将“节目”分配到不同的 CDN 网络上。

万人直播架构图

多家 CDN 网络的管理一般是由信令服务器控制的。当要接入某家 CDN 网络时,你可以通过信令服务器的注册界面进行注册。在注册界面中,一般要求填入 CDN 厂商的名字、分配比例、CDN API 操作地址等信息。

比如,当某个主播要分享一个节目时,信令服务器首先根据分配比例决定使用哪个 CDN 网络,然后获得该 CDN 网络的 API 操作地址。获取到 CDN 网络的 API 操作地址后,它就可以调用该 CDN 网络提供的 HTTP/HTTPS API 进行操作了,创建域名、生成直播地址、生成拉流地址等等。有了这些地址后,就可以将音视频流推送到 CDN 网络,观众端获取到观看地址后就可以“观看”节目了。

除了接入多家 CDN 网络之外,其他功能与我们之前文章中介绍的是一样的,这里我就不再赘述了。

主播客户端架构

了解了万人直播架构后,接下来我们再看一下主播端的架构。之前我们介绍过,如果在 PC 端进行直播的话,直接使用 OBS 工具就可以了,这个工具是一个非常专业的 PC 端推流工具,功能非常强大,很多主播都使用该工具进行推流。

但如果是移动端的话,就需要我们自己来实现了。主播端的架构如下图所示,按层级分为三层,即传输层、编码与展示层采集层

推流客户端架构图

下面我们对各层级的模块分别做下说明。

传输层,包括了信令处理和 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 厂商结算费用时会非常有用。

观众端架构

介绍完主播端的功能后,接下来我们再来看看观众端(如下图)。观众端与主播端是很类似的,但实际上我们自己并不会将每个模块都亲手实现,因为对于观众端来说,大部分模块都属于播放器的功能。因此,我们在实现观众端的时候,只需要实现信令处理模块、数据统计模块,并将播放器集成进来就可以了。

观众端架构图

对于移动端,我们一般都使用 Ijkplayer 作为观众端播放器。Ijkplayer 是由 bilibili 公司开源的项目,地址为: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 厂商,如蓝汛、网宿等,它们的质量具体如何还需要你多进行测试。从我个人经验来讲,阿里无论价格还是质量都还不错。

思考时间

今天留给你的思考题:如何判断用户在播放音视频流时是否出现过卡顿?

欢迎在留言区与我分享你的想法,也欢迎你在留言区记录你的思考过程。感谢阅读,如果你觉得这篇文章对你有帮助的话,也欢迎把它分享给更多的朋友。