MSE直播方案调优

时隔一个月,项目即将到尾声,现在回过头来看当时记录的问题,甚至想要删掉(现在看当时遇到的问题停蠢的),仔细想想,这都是自己的宝贵经历,还是留下当作纪念

此篇主要介绍博主在开发基于MSE方案的直播项目中,进行的策略优化。

在近期的一个项目中,需要使用MSE进行视频的播放。相关资料本就少,完整参考仅有一份官方的英文文档。因此,笔者踩了很多坑,才将此项目完善。最初遇到的问题,大致分为以下几个:

  1. 偶尔出现回退现象

  2. 进度条显示时间和实际不一致

  3. 视频卡顿,无明显规律

  4. 延时过大(超过1秒)

时间戳

第一个问题主要是由于未打入时间戳引起(fmp4好像有两种封装格式,另一种不需要打入时间戳,但是要保证传输的顺序),导致MSE不能正确识别播放顺序,在打入时间戳后,不再出现这个问题,但是出现了下一个,心累。。。。。。。

frameDuration baseMediaDecodeTime

在花了很久时间搞清楚frameDuration和baseMediaDecodeTime的含义后(楼主对之前对音视频方面是0基础的小白,网上的资料只简单的翻译了一下,都是泪),把这两个参数打入到封装FMP4的接口后,出现了进度条显示时间和实际不一致的问题,具体表现为播放视频10秒,进度条只走了1秒,video.currentTime中表现也如此。最终,把baseMediaDecodeTime的值*10才正常的显示(直到现在也没搞懂原因,捂脸)。

缓存控制

在解决了以上两个问题后,出现了最麻烦的问题,经常性的出现视频的卡顿,并且有时能跳秒追上,大部分时候不能够追上。查阅N篇资料后,一直没有头绪,最后,感谢同项目组的一位大佬,帮助我找出了问题。原因很简单,网上对于MSE的教程中有这么一段代码:

1
2
3
if (this.sourceBuffer.updating){//上一块数据还在添加中
return;
}

当sourceBuffer处于updating的状态时,直接返回了,返回了…..导致了该数据块直接丢失,其中包含N个帧。类似代码在网上各种教程中泛滥,几乎都是这么写,误导了多少小白- - 一言难尽。

解决方案如下:

在此处添加一个buffer,用于存储外部传入的数据块。当sourceBuffer处于updating的状态,先将数据传入buffer中,之后,每次updateend时,从该buffer中取出数据传入SourceBuffer中,若为空,则直接等待外部数据传入(今天写这篇文章时,发现stackoverflow上已经有此方法,之前看到英文不想读)。具体代码如下:

1
待填坑

跳秒解决延时问题

在该项目中,最初播放延时有3秒左右,无奈领导要求必须控制在1秒内,只能想办法解决。

解决延时问题,主要有以下几种方法:

  1. 无缓存

  2. 控制播放速度,缓存较大时增大倍速

  3. 跳秒

第一种,对于MSE好像不能实现,MSE必须要有缓存机制(如果我说错了,欢迎指正),因此,第一个方法直接放弃。

第二种,尝试过,但是,当currentTime和souceBuffer.buffered.end(0)的差值很小时,视频会出现明显的卡顿,需要等待一段时间才能继续播放,因此,使用控制倍速的方式,会出现快放–卡顿–快放–卡顿不断循环的过程。

第三种,
待补坑,明天写。。。。。

Thanks for your Support!