找回密码
 立即注册
LiveVideoStack 首页 资讯 查看内容
  • QQ空间
  • 回复
  • 收藏

熊猫TV直播H5播放器架构探索(2)

2018-6-28 08:00

接上文



上图是6000kbps的高清的直播,可以清晰看到主播面部的细节。对熊猫来说,高清直播是一座里程碑,也是我们产品的一个卖点。我们不可能用3000kbps的冒充蓝光线路,所以在这种大型活动熊猫基本上都维持在一个6000到8000kbps推流码率下的高清直播。



而对于普通主播而言高码率采集同样重要。上图是根据某天下午几个FPS主播们的直播房间统计出来的结果,可以看到很多主播都将码率采样推到6000以上,对此主播们也是乐此不疲,这是为什么?



这是我自己喜欢的几位主播平时的推流规律。其中有一个最高需要推到一万四的码率,这样一个高码率对熊猫来讲可以说是非常普遍的。我们需要保证页面不崩溃的同时维持这样一个高码率的推流,可以说难度不小。



这是FPS游戏《绝地求生》的直播画面。可以看到游戏中对手距离非常远,有的时候在画面中就是一个小黑点。像这样的FPS游戏一旦推至很高的码率便会大大降低用户体验。因为会带来明显的卡顿,包括主播也对这一点心知肚明。一般情况下如果出现卡顿的问题主播会给出“换线路板”、“调清晰度”等提示语。但无论如何我们需要支持主播的高码率直播需求,那么如何解决?


2) 解决方案



如果你打开熊猫HTML5播放器并右键点击打开监控,会看到显示“正在清洗能量槽”,很多人问我什么是正在清洗能量槽?其实是正在清理缓存的意思。这个功能的实现其实只需要几行代码,但背后会遇到了什么问题呢?


a.什么时候清洗

做前端的同学应该知道这个Setinterval。当Setinterval或新的GOP准备好时会触发清洗能量槽的功能。


b.一次清洗多少

先说Setinterval和新GOP。 Setinterval解决方式有优点与缺点,其问题在于此定时器在页面挂起的状态下并非按照设置的时间运行,而只是把这一段代码推至站并等待运行;此时如果超过时间而又在休眠状态便失去作用。而新GOP会过于频繁, 干扰系统正常运行,因此最后我们选择Setinterval解决方式。那么关于清理多少,我们暂时是确定10秒以前的全部清洗。


c.容易洗出什么问题

BufferUpdating是MSE的Buffer的一个状态。在新的GOP准备好时这是一个写操作,此时一定会存在这样一个无法清理的状态,这也是我们没有用新GOP的原因。


3) 改进效果



下面来看一下我们内存控制的效果,这是我们新版内核与老版内核的对比,请注意内存的变化。



在同样的测试环境下,上面的标签页是我们使用老版内核得出的占用内存值为285736k,下面的标签页是我们使用新版内核得出的占用内存值为75632k,大概是老板内核内存占用的1/4。


2.3 累计延时问题



CDN的同事应该知道累计延时也是一个困扰大家很久的问题。上图是我自己直播间的一个界面,左半图右侧是老版内核的,左侧是新版内核,右半图是我在新版内核网站刷新出的的一个状态,最左边的和最右边我都是已经放置了一段比较长的时间。先对比来看时间戳,老版内核页面与刚刷新完的页面相比存在大概4分钟的延迟,这4分钟的延迟可以说为观影体验带来的影响是毁灭性的。


1) 问题定位



延迟问题与码率有关。当下行网速小于平均码率时便会出现这种视频卡顿的现象。浏览器的Video标签是针对点播设计的,出现卡顿后一定是从卡顿点开始继续播放,这种小规模无法被轻易感知的卡顿累计多了便会造成明显的延迟,那我们该如何处理呢?


2) 解决方案



这一部分是我们写的一个重新拉流,处理方法为网络抖动。如果使用网络抖动而后面网络又平滑了该怎么办?此时需要看最后一帧是否满足需求,如果不满足就重新拉流并重新计算起始时间;然后将始终时间和当天时间作差,得出实际播出的时间以及实际消耗的时间,便是累计延时的时长。若大于一定阈值便会触发重新拉流的操作,当然这个阀值可根据应用环境进行修改,这里我设定的是15秒。


3) 改进效果



以上是在弱网环境下的测试结果。大家可以看到如果在放置比较久的情况下会产生一定的累计延迟,大概为3秒。但这种体验已经比之前好很多了,可以基本保证同步。


3. 熊猫HTML5播放器内核架构



3.1 明确问题


在整个开发过程中我们遇到了以下的一些问题使得我们将内核进行重新架构。



1) 不同业务

不同业务对播放器内核的需求是不一样的。虽然这是个外层问题,但当我们再去剖析时会发现,其实针对不同需求的不同业务下所需要的内核也不太一样。这个时候该怎么办呢?当然不可能将所有的业务都写在内核里,一个业务对应一个内核会带来庞大的开发体量。


2) 新技术接入

大家可以看到熊猫之前有十个多月处于Bata阶段。为什么我们一直没有发布正式版?因为我们想在播放器当中接入一些新技术。而每次新技术的接入就需要改变包中代码,可想而知其有多么不稳定。


3) 团队新人加入

我们团队会遇到的一个很正常的问题就是当有新人加入该怎么办?新人一开始不熟悉开发过程,在开发过程中有时对内核造成不必要的影响。


3.2 构架特征



我们对于新版内核的要求就是——“高度解耦”、“模块化”、“易扩展”,也就是下面我们重构的架构。



1) Modules层

大家可以看到在Modules层是由Loader模块、Demuxer模块、Remuxer模块与Build Packages模块组成,每个模块都有一些自己的插件。讲到这里,大家可能会想到一些以前的库,包括HLSJS、FLAVJS等都大概有这样的一个架构,那么我们在Mccree Core层做了哪些工作?


2) Mccree Core层

首先我们设置了一个消息通道Message Channal,其作用是当有模块要完成某些任务时会通知给下一个模块,然后会把数据给到缓冲区。

这个消息通道采用广播模式,任何一个模块在得到对应的消息时会触发对应功能。


3) 底层

底层的数据结构分为Loader Buffer、Tracks与Remuxed Buffer,分别用来放置原始的流数据、Demuxer后的数据与Demuxer前的数据,并提供给MICE。其中MICE是一个插件,其他的几个部分是我们的核心模块。可能大家刚开始看到这个构架有些复杂,接下来我会向大家介绍这些模块是如何工作的。


3.3 模块、插件与封装


&

来自: LiveVideoStack
文章点评
相关文章