作者:施灵凯。 PP云音视频开发高级工程师;6年以上音视频开发经验,目前专注于PP云播放器内核、SDK等领域的开发。SDK及内核产品应用于PP体育、PP视频等数百家行业客户,累计覆盖用户超千万。
从传统的点播,到这几年兴起的直播和短视频,在客户端层面都要用到播放器,那么如何去打造一款播放器来满足点播,直播,短视频三种场景的需求呢?
首先可能来讲讲技术选型,目前笔者所了解到的播放器开源方案有如下几种:vlc,xbmc,ijkplayer,exoplayer,ffplay等,那么哪种开源方案能够满足我们这边的需求或者适合我们做二次开发呢?
答案是都不满足。
因为随着PP云业务的扩展,不同的客户有越来越多合理但很特殊的需求出现,会导致基于现成的开源方案做的播放器功能扩展越来越难,维护的时间成本越来越大。作为云服务商,要能及时响应并能最短时间完成客户的各种合理需求,那就必须要打造一款完全自研的跨平台播放器,也就是播放器的各种技术点都要Full Control。
下面先看一下播放器的框架图:
如上图一般所有的播放器的方案,都会有解封装,数据包队列,解码,帧队列,渲染等几大模块,然后组成一套播放逻辑,大多数的播放器的功能实现也都大同小异。
写到这里,可能会有人认为既然都是大同小异,那写这篇技术分享的文章,有啥价值?虽然播放器的逻辑是一样的,但是不同业务、不同方案的具体做法还是有很大差异。
一、多样化的解封装模块
就比如说解封装技术,一般的做法是直接采用ffmpeg解封装,几乎支持所有的主流媒体解封装协议,虽然ffmpeg是足够厉害,但是有两种情况,是很难做支持的;
一种是基于点播HLS协议,本地硬盘缓存ts数据(不是内存缓存),另一种是基于P2P协议,从P2P内核拿媒体数据包。
基于点播HLS协议,本地硬盘缓存ts数据:PP云实现了PrivateHLSDemuxer模块,就是从服务器请求到的ts文件数据首先下载到本地硬盘,然后从本地硬盘读取ts文件做解封装。
为什么要这样做?
节省内存占用,通过硬盘空间预缓存更多的媒体数据,提高流畅率 。
有些片源用户回拖,replay的频率较高,这种方案正好可以省去回拖,replay的时候,频繁重复向服务器发起ts文件的数据请求,好处是可以降低服务器带宽消耗,同时减少客户端的流量消耗。
基于P2P协议,从P2P内核拿媒体数据包:我们实现了ExternalDemuxer模块,这是一个开放式的模块,可以接入第三方私有的解封装模块,例如基于第三方私有协议的或者基于P2P协议的,在数据源层面增加了播放器的扩展性。
二、自研的跨平台的渲染引擎
这两年短视频开始火起来,各种眼花缭乱的特效滤镜,很吸引人;所以在视频渲染模块,PP云自研了一套渲染引擎GPUImage。
首先声明一下,这不是github开源的基于OC实现的iOS平台的GPUImage;也是不是基于java实现的android平台的GPUImage;这是完全基于C++实现的一套跨平台的GPUImage渲染引擎,目前支持android和iOS。
优势是用C++写一套滤镜,同时支持多平台,省时省力,目前你能够想到的各种滤镜,PP云都有做支持,并且还支持全景VR;具体如何实现?篇幅有限,后续会再写一篇博文细讲,请持续关注PP云微信公众号。
三、不同的直播低延迟追帧策略
这几年火得一塌糊涂的直播,一提直播就会想到低延迟,那么就讲讲在播放器层面,PP云是怎么去优化延迟的?
于rtmp的直播,只要网络有抖动或者卡顿,播放器端的累积延迟会逐步加大,所以网上有一堆技术分享的博文讲直播优化延迟的,例如最直接的:清缓存数据队列。
这个方法确实可以短时间内降低延迟,但是强行跳帧,直播内容强行被跳过,严重影响体验;而且,丢Gop里面的B帧,非参考帧或者序列里面最后几个P帧等;或者丢部分音频数据包,视频帧时间戳同步音频来达到数据的加速消耗等;但是实际测下来,控制延迟的效果甚微;
那么PP云的方案是什么呢?
不丢任何数据,加速消耗音视频数据,其实就是传统的倍数播放,只是这种配速播放策略是实时受控制的;播放端的延迟一般根据数据队列的时长来统计,一般队列时长0-4s,保持1.0倍速播放,4-8s,1.2倍倍速播放,8-16s,1.3倍倍速播放,>16s,1.5倍倍数播放;
通过实际测试,一般因网络抖动带来的累积延迟最多在30s内收敛到4s内,并且微量的倍速播放,用户其实无感知;难点是要控制好音画同步,这样做法的目的是时间戳不变,音频pcm数据通过atempo filter做速率压缩。
四、单路视频流多分辨率码流切换,如何实现无感知的观看体验?
为了提高用户观看的流畅度,PP云提出了要有单路流多分辨率的需求场景,实现播放器层面做到无缝播放。
例如:
当用户的网络状态变差后,如果还是保持原来的码流码率,缓存消耗干净后,马上就会卡顿,所以为了保证流畅,要向服务器请求当前流的低码率低分辨率的数据,因为大多数用户,对卡顿的敏感度远远大于画质。
那么从播放逻辑上来讲,PP云是怎么处理的呢?
首先解封装模块。检测到数据包里面有更新stream info的标志,更新stream info信息放到list里面,在list里面每个streaminfo,打上id标志;并且向音频和视频数据队列里面分别添加一个带有reset decoder标志的数据包。
数据包里面携带streaminfo的id,解码器读到reset decoder数据包,根据携带的id,向解封装模块的streaminfo list里面拿到对应的stream info,然后reset decoder;同时音频要reset resample模块,整个过程在播放观看层面完全是无缝播放的体验,是不是很简单?
以上,是PP云播放器方案相比于开源方案做的一些针对需求场景和功能上的差异点。目前该套方案已成熟运行,并经过行业超过千万级用户量的大规模使用和优化。相关的经验分享会在后续的文章中分享,欢迎大家关注PP视频云公众号。
领取专属 10元无门槛券
私享最新 技术干货