38 | 实战推演:带你实现一个支持万人同时在线的直播系统

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

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

万人直播架构

下面这张万人直播架构图与《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厂商,如蓝汛、网宿等,它们的质量具体如何还需要你多进行测试。从我个人经验来讲,阿里无论价格还是质量都还不错。

思考时间

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

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

精选留言

  • bigeast

    2020-03-21 21:59:23

    看接收端两帧之间的渲染间隔,大于某个阈值就记为一次卡顿。视频间隔可以比音频大一些。
    作者回复

    对的。大大的赞!

    2020-03-24 16:11:21

  • 神经旷野舞者

    2019-12-18 20:45:00

    卡顿应该是帧延迟了,可以检测没秒传了几个,和服务器对一下,不过这样感觉计算量太大
    作者回复

    目前处理卡顿的方法就是在一开始多缓冲一些数据哈!

    2019-12-22 23:05:24

  • John

    2019-11-16 03:16:18

    请问老师 如果我要在APP里用webrtc做一个非视频的百人群聊功能 只使用p2p的连接 能实现么
    作者回复

    一路 640*420 的视频咱们估算是 500kbps, 那么 100 人同时与一个人通信就需要 100*500kbps, 也就是说需要 50M的带宽。而这 100 人的 NAT 类型千奇百怪。你想想这样做靠谱吗?

    2019-11-23 17:35:29

  • Mickey

    2020-09-28 09:12:43

    最近一年在从事在线直播相关的前端开发,很长一段时间,对音视频完全不了解,有问题,只能两手一摊,我咩都唔知啊~~,现在学习完老师的课堂,对音视频有了小小的了解了,也算是一只脚指头踏进门!!加油ヾ(◍°∇°◍)ノ゙
  • Jason

    2019-10-10 09:55:26

    我猜测,视频卡顿是因为帧数不足导致,所以可以通过统计用户播放的总帧数来统计。
    作者回复

    卡顿并不会丢帧。因为 TCP 连接,不会丢数据的。除非断连了。

    2019-10-12 02:36:00

  • piboye

    2020-12-31 18:26:48

    客户端直接推到多个cdn不合适吧?应该是服务端负责推送到多个cdn吧?
    作者回复

    两种方案都比较常用

    2021-03-30 11:06:05

  • 王兵

    2020-04-21 11:25:53

    老师,您好!请教一下,目前做 线上网课,老师与学生交互的,您认为是 RTMP好 还是 WebRTC好?您认为 钉钉上课之类的,是 WebRTC吗?您是如何看待 腾讯视频 采用 webrtc 播放的,这是腾讯 对 flash被禁止 而采用的措施吗?谢谢您
    作者回复

    目前做实时互动的基本上都是用的 WebRTC。腾讯云直播使用webrtc是因为 webrtc是大势所驱,不支持 webrtc的最终都会被淘汰

    2020-04-27 18:31:07

  • 酸橙

    2020-01-18 15:47:04

    老师,请教下,如果是obs推流端网络抖动或闪断导致了卡顿,有什么好的解决方案吗?是否需要建立自己的媒体中心来保障输出连续的流,通过转码中心预留的缓存自动无缝拼接,跳过中间的空挡
    作者回复

    对于推流端最好的解决办法是购买好的带宽,你只要肯花钱,运营商就可以给你提供很好的带宽。这个花费比你自己去建媒体中心花费的少的多的多

    2020-02-23 12:02:00

  • 阳仔

    2019-11-03 15:05:05

    这套支持万人的直播系统,没有使用 webRTC ? 可以通过 webRTC 实现么?成本会不会较大?
    作者回复

    可以将WebRTC 与 万人直播融合到一起。这样就实现在即可以进行实时通信,又可以进行万人直播的效果。

    2019-11-08 13:46:42

  • 2019-10-10 18:02:28

    老师,请教下,安卓是否可以做到边下载,边转码,边播放。达到类似直播的效果。原因是我们这边反馈服务端处理可能时间很长,想把细节处理的工作放到安卓端
    作者回复

    没有这样做的。如果说服务端认为处理时间很长,那么客户端做这个事儿就更麻烦了。

    2019-10-12 02:29:09

  • 刘丹

    2019-10-10 10:31:08

    请问老师在实际使用中,OBS等工具能否把同一个直播流同时推送到多个CDN?常见的开源观众客户端是否支持自动切换CDN,还是我们要改播放端的代码手工切换呢?
    作者回复

    每个 OBS客户端只能向一个 CDN 推流,主播可以开多个客户端。不过最好的方式是你在后台自己进行多个 CDN 的中转。

    另外,开源客户端不支持自动切换。你要自己实现。这些都是上层逻辑,不是播放器要考虑的事儿。

    2019-10-12 02:33:00

  • ifelse

    2025-08-12 12:14:39

    学习打卡
  • 付俊

    2022-09-10 00:07:50

    请问老师一个高并发的直播和会议系统,如何规划服务器的配置?
  • Geek_6d49f5

    2021-10-14 14:30:06

    老师,SEI信息 和音视频播放出来的对不上,有优化方法吗
  • Jocelyn

    2021-03-30 09:56:45

    老师您好 请教两个问题:1. 请问这个部分除了您在文章中罗列的 还有哪些需要记录呀?“每个用户使用 CDN 网络时必须要记录下来的信息”;2. 请问如何记录卡顿和卡顿原因呢?
    作者回复

    当缓冲区里的数据为0时就是卡断,卡顿原因都是网络问题

    2021-04-02 16:36:52

  • Geek_d51f97

    2021-03-13 21:53:10

    cdn 流量使用多大时需要统计呢? cdn也有日志,直接拿到 cdn 厂商的日志是否可信?
    作者回复

    你可以信任云厂商,但我不信,作为一个企业花出去的每一分钱都要确认

    2021-03-30 10:32:27

  • 白马

    2020-09-22 19:08:00

    李老师,腾讯课堂是在一对多的直播系统基础上改进的吗?
    作者回复

    应该是

    2020-11-10 18:36:51

  • 平凡

    2020-07-04 01:58:54

    请问基于OBS定制化开发一个推流工具,类似直播姬、斗鱼伴侣这种需要哪些技术
    作者回复

    OBS本身已经很成熟悉了,你需要的是熟悉它的API

    2020-07-29 19:57:26

  • 天空之城

    2020-06-18 20:59:49

    老师,问一下webrtc获取的流如何推流到rtmp服务器进行直播
    作者回复

    你要自己实现一个推流工具,将采集到的流转成 rtmp 再发给RTMP服务器。不过现在有一个更好的方案,在 SRS4.0中可以直接推 webrtc流,然后拉 RTMP流。不过 SRS4.0目前还处理开发阶段

    2020-06-23 09:55:07

  • QD账号

    2020-04-21 11:56:28

    老师,请问这块有没有一些监控手段或者开源监控系统可以起到监控作用?
    作者回复

    对于万人直播,一般都使用云直播(阿里云,腾讯云),云直播都有监控信息。你可以自己去了解一下

    2020-04-27 18:29:23