您当前的位置:网站首页>破阵,美拍直播首屏耗时削减50%以上的优化实践,秋天的成语

破阵,美拍直播首屏耗时削减50%以上的优化实践,秋天的成语

2019-04-05 11:14:51 投稿作者:admin 围观人数:138 评论人数:0次

跟着移动直播的火爆,许多的事务都有直播需求,这就使直播成了一种根本的装备。在观看直播过程中,首屏时刻是最重要的体会之一,它的快慢直接影响了用户对该直播APP的体会。为了进步用户体会性,美拍对DNS解析优化、TCP衔接耗时、HTTP呼应耗时、音视频流的勘探耗时、buffer缓冲的耗时等方面进行了优化,使得首屏时刻从2017年头仍是秒等级以上的耗时,到现黄凯芹老婆在是秒等级内,耗时减少50%以上,而且大破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语部分恳求落在0~500ms 和 500~1000ms 的区间规模,然后使得大部分抢手视频到达瞬开的作用。后边咱们将依据 ijkplayer 和 ffpmeg 的源码进行剖析。

为什么挑选ijkplayer播映器来剖析

ijkplayer 播映器是一款开源的依据 ffmpeg 的移动版的播映器,现在现已被许多互联网公司直接选用。它的代码结构兴义比较明晰,许多做移动端视频剖析的都应该触摸过,所以依据它来剖析应该跟简略了解。美拍直播的播映器并不是直接选用 ijkplayer 播映器,但也是依据 ffmpeg 来完结的,逻辑跟 ijkplayer 比较相似,原理上都是相通的,优化点也很相似,仅仅额定做了一些其他相关点的优化。所以依据 ijkplayer 翻开,也便利咱们从源码等级能够直接看到相关的要害点。

一、首屏时刻的影响要素

首屏时刻是指从用户从进入到直播间到直播画面出来的这部分时刻,这是观众最简略,直观的体会。它首要受直播播映器和CDN加快战略,以及移动端手机网络的影响。能够拆分为以下个方面:

  • 点击直播后,进入到直播间后,加载一些比方用户头像,观众列表,礼物之类的会占用网络带宽,影响到直播加载。
  • 移动端手机网络带宽的约束,现在一般直播的带宽都在1Mbps左右,所以假如下行带宽小于1Mbps,或许更小,对直播的体会影响就会很大。
  • 直播播映器拉流的速度,以及缓冲战略的操控,关于直播类,实时性的需求更高,需求动态的缓冲操控战略,能赶快的烘托出视频画面,减少用户等候时刻。
  • CDN是否有缓存直播流,以及缓存的战略对首屏影响也很大。
  • 直播拉流协议的影响,以及CDN对不同的协议优化支撑友爱程度不一样,当时盛行的拉流协议首要有 rtmp 和 htt手机动态壁纸p-flv。经过许多的测验发现,移动端拉流时在相同的CDN战略以及播映器操控战略的条件下,http-flv 协议比较rtmp 协议,首屏时刻要减少300~400ms 左右。首要是在 rtmp 协议建联过程中,与效劳端的交互耗时会更久,所以后边的剖析会直接在 http-flv 协议的根底上。

二、首屏耗时的“条分节解”

要想优化首屏时刻,就必须清楚的知道全部的耗时别离耗在哪里。下面咱们以移动版的 ffplay(ijkplayer)播映器为根底,逐步剖析直播拉流细节。下面咱们以 http-flv 协议为拉流协议剖析,http-flv 协议便是专门拉去flv文件流的 http 协议,所以它的恳求流程便是一个http 的下载流程,如下图:

美拍直播首屏耗时减少50%以上的优化实践

从上图中能够看出,首屏耗时的组成首要以下根本组成:

美拍直播首屏耗时减少50%以上的优化实践

1,DNS耗时

DNS解析,是全部网络恳求的榜首步,在咱们用依据ffmpeg完结的播映器ffplay中,全部的DNS解析恳求都是 ffmpeg 调用`getaddrinfo`办法来获取的。

  • 一般耗时多久?

假如在没有缓存的状况下,实测发现一次域名的解析会花费至少300ms 左右的时刻,有时分更长,假如本地缓存射中,耗时很短,几个ms左右,能够疏忽不武道巅峰计。缓存的有用时刻是在DNS 恳求包的时超级响马系统候,每个域名会装备对应的缓存 TTL 时刻,这个时刻不确定,依据各域名的装备,有些长有些短,不确定性比较大。

  • 为什么是这么久?

为什么DNS的恳求这么久呢,一般了解,DNS包的恳求,会先到邻近的运营商的DNS效劳器上查找,假如没有,会递归到根域名效劳器,这个耗时就好久。一般假如恳求过一次,这些效劳器都会有缓存,而且其他人也在不断的恳求,会继续更新,下次再恳求的时分就会比较快。有时分经过抓包发现每次恳求都会去恳求`A`和`AAAA` 查询,这是去恳求IPv6的地址,但由于咱们的域名没有IPv6的地址,所以每次都要回根域名效劳器去查询。为什么会恳求IP小雨V6的地址呢,由于 ffmpeg 在装备DNS恳求的时分是按如下装备的:

hints.ai_family = AF_UNSPEC;

它是一个兼容IPv4和IPv6的装备,假如修正成`AF_INET`,那么就不会有`AAAA`的查询包了。经过实测发现,假如只要IPv4的恳求,即使是榜初次,也会在100ms内完结,后边会更短。这个当地的优化空间很大。

  • 怎样计算?

以 ffmpeg 为例,能够在`libavformat/tcp.c`文件中,`tcp_open`办法中,按以下办法计算:

int64_t start = av_gettime();

if (!hostname[0])

ret = getaddrinfo(NULL, portstr, &hints, &ai);

else

ret = getaddrinfo(hostnam为什么尼彩卢洪波判刑e, portstr, &hints, &ai);

int64_t end = av_gettime(谷歌运用商铺);

2,TCP衔接耗时

TCP 衔接在这儿是只调用 Socket 的 connect 办法,并衔接成功的耗时,它是一个堵塞办法,它会一向等候TCP 的三次握手完结。它直接反响了客户端到CDN效劳器节点,点对点的延时状况,实测在一般的 wifi 网络环境下耗时在50ms以内。耗时较短,根本是没有什么优化空间的,不过它的时刻反响了客户端的网络状况或许客户端到节点的网络状况。

  • 怎样计算?

以ffmpeg为例,也是在`libavformat/tcp.c`文件中,`tcp_open`办法中,按以下办法计算:

int64_t start = av_gettim破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语e();

if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen,

s->open_timeout / 1000, h, !!cur_ai->ai_next)) < 0) {

if (ret == AVERROR_EXIT)

goto fail1;

else

goto fail;

}

int64_t end = av_gettime();

3,http呼应耗时

  • 什么是http呼应耗时?

http 呼应耗时是指客户端建议一个http request 恳求,然后等候http 呼应的header 回来这部分耗时。直播拉流http-flv协议也是一个http 恳求,客服端建议恳求后,效劳端会先将http的呼应头部回来,不带音视频流的数据,呼应码假如是200,标明视频流存在,紧接着就开端下发音视频数据。http 呼应耗时非常重要,它直接反响了CDN效劳节点处理恳求的才干。它与CDN节点是否有缓存这条流有关,假如在恳求之前有缓存这条流,节点就会直接呼应客户端,这个时刻一般也在50ms左右,最多不会超越200ms,假如没有缓存,节点则会回直播源站拉取直播流,耗时就会好久,至少都在200ms 以上,大部分时刻都会更长,所以它反响了这条直播流是否是冷流和暖流,以及CDN节点的缓存射中状况。

  • 怎样计算?

假如需求计算它的话,能够在`libavformat/http.c`文件中的,`http_open`办法

int64_t start = av_gettime();

ret = http破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语_open_cnx(h, options);

int64_t end = av_gettime();

4,音破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语视频流勘探耗时

  • 什么是音视频流勘探耗时?

这个界说比较含糊,它在 ffplay 中对应的是`avformat_find_stream_info`的耗时,它是一个同步的办法。在播映器中它会堵塞整个流程,由于它的作用是找到初始化音视频解码器的必要的数据。它有一些参数会形象到它的耗时,不过假如参数设置适宜的话,一般是100ms 内完结。

  • 怎样计算?

能够在 ijkplayer 的工程中`ff_ffplay.c`文件中,`read_thread`球球大作战直播办法

int64_t start = av_gettime();

avformat_find_stream_info(ic, opts);

int64_t end = av_gettime();

5,缓冲耗时

  • 什么是缓冲耗时?

缓冲耗时是指播映器的缓冲的数据到达了预先设定的阈值,能够开端播映视频了。这个值是能够动态设置的,所以不同的设置给首屏带来的影响是不一样的。咱们在美拍直播播映器最开端的设置是视频帧数和音频帧数都到达10帧以上,才干够开端播映。所以这部分一般的耗时都比较大,一起它还跟播映器里边的一个设置 `BUFFERING_CHECK_PER_MILLISECONDS` 值有关,由于播映器 check 缓冲区的数据是否到达目标值不是随意检测的,由于 check 本身会有必定的浮点数运算,所以 ijkplayer 开端给他设置了500ms 值,显着比较大,所以会对缓冲耗时有比较大的影响。

  • 怎样计算?

缓冲耗时的计算办法,不像前面几个那么简略,由于它涉及到的代码有多处,所以需求再多个当地计时。 开端计时能够直接早年面的find后边开端,完毕计时能够在榜首帧视频烘托出来的时分完毕计时。

avformat_find_stream_info(ic, opts);

start = av_gettime();

if (!ffp->first_video_frame_rendered) {

ffp->first_video_frame_rendered = 1;

ffp_notify_msg1(ffp, FFP_MSG_VIDEO_RENDERING_START);

end = av_gettime();

}

至此,首屏耗时的拆解就完结了,剩余的优化就从详细每个阶段着手优化。

三商、 首屏时刻的详细优化

在前面的分化之后,再来优化首屏时刻,思路就比较明晰了。由于流程是串行的,所以只需求做到部分最优,整体就会最优。

1,DNS的优化解析

  • 优化思路

DNS 的解析一向以来都是网络优化的首要问题,不只仅有时刻解析过长的问题,还有小运营商 DNS 绑架的问题,一般的解决计划都是选用 HttpDNS,但 HttpDNS 在部分地区也或许存在精确性问题,归纳各方面咱们选用了HTTPDNS 和 LocalDNS 结合的计划,来提高解析的速度和精确率。前面现已提到了,一般来说假如仅仅解析IPV4来说,LocalDNS 的耗时并不算长。但咱们也不能直接修正 ffmpeg,由于也要考虑到将来的 IPV6 的扩展问题。好在咱们内部有专门做 DNS 的 SDK,他们的大约思路是,APP 发动的时分就会先预解析咱们指定的先域名,由于拉流域名是固定的几个,所以完全能够先缓存起来。然后会依据各个域名解析的时分回来的有用时刻,过期后再去解析更新。至于 DNS绑架的问题,内部会有一个评价战略,假如 loacldns 出来的IP无法正常运用,或许延时太高,就会切换到 HttpDns 从头解析。这样就确保了每次真实去拉流的时分,DNS 的耗时简直为0,由于能够守时更新缓存池,使每次取得的 DNS 都是来自缓存池的。

  • 详细完结办法

怎样替换掉 ffmpeg 中`tcp.c`文件中的 `ret = getaddrinfo(hostname, portstr, &hints, &ai);` 办法,咱们最开端想到了两种计划:

计划A

比方咱们的拉流url是这样的 `http://a.meipai.com/m/c04.flv`,假如在传递url 给 ffmpeg 前将`a.meipai.com` 替换成DNS 预先解析出来的 ip 比方 `112.34.23.45` ,那替换后的url便是`http://112.34.23.45/m/c04.flv`。假如直接用这个url去建议破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语http恳求,在有些状况能够,许多状况是不可的。假如这个iP的机器只布置了 `a.meipai.com` 对应的效劳,就能解析出来。假如有多个域名的效劳,CDN 节点就无法正确的解析。所以这个时分一般是设置 http 恳求的 header里边的 Host 字段。一般能够经过以下代码传递给 ffmpeg 内部,这个参数的作用便是填充 http 的Host 邵武在线头部,详细的完结,能够 ffmpeg 源码,文件`http.c`中`http_connect` 办法中。

AVDictionary **dict = ffplayer_get_opt_dict(ffplayer, opt_category);

av_dict_set(dict, "headers", "Host: hdl-test-meipai.com", 0);

但这fork种计划有个 bug 便是,假如在宣布恳求 `http://a.meipai.com/m/c04.flv` 的时分,效劳端经过302调度办法回来了相似的成果 `http://112.34.23.45/a.meipei.com/m/c04.flv` ,指定了ip的url,这时客户端并不知道跳转的逻辑,由于http恳求都是在 ffmpeg 内部进行的。这个时分再设置了Host,就会呈现` http://112.34.23.45/a.meipai.com/a.meipai.com/m/c04.flv` 中心有两个 host 的状况,导致效劳端无法解析的 bug。这种状况也是在半途测验的时分偶然发作的,现在没有比较好的解决计划,除非让效劳端选用不下发302跳转,但这样就不通用了,会给将来留下危险,所以这种简略的计划不可行。

计划B

还有一种计划便是常常会用到的设置函数指针的办法,在 ffmpeg 中的 `tcp.c`顶用函数指针替换掉 `getaddreinfo` 办法,由于这个办法便是实践解析 DNS的办法,比方下面代码:

if(my_getaddreinfo) {

ret = my_getaddreinfo(hostname, portstr, &hints, &ai);

} else {

ret = getaddrinfo(hostname, portstr, &hints, &ai);

}

在` my_getaddreinf褐色o` 办法中,能够调用 DNS SDK的解析办法,获取到ip,然后填充到`ai`里边,就完结了咱们的需求。这种计划的优势很显着,便是灵敏,简略扩展,而且没有什么危险。不过有个下风是需求修正ffmpeg源码,这关于一个大的APP里边,有多个功用共用一个 `ffmpeg` 库的状况来讲,需求添加许多测验本钱。

整体来说,DNS优化后,依据线上的数据首屏时刻能减少 100ms~300ms 左右,特别是针对许多初次翻开,或许DNS本地缓存过期的状况下,能有很好的优化作用。

2,TCP衔接耗时的优化解析

TCP 衔接耗时,这个耗时可优化的空间首要是针对建连节点链路的优化,首要受限于三个要素影响:用户本身网络条件、用户到 CDN 边际节点中心链路的影响、CDN 边际节点的安稳性。由于用户网络条件有比较大的不可控性,所以优化首要会在后边两个点。咱们这边会结合着用户所对应的城市、运营商的状况,一起结合着效劳端的 CDN 多交融调度系统,能够给用户下发更适宜的 CDN 效劳域名,然后经过 HTTPDNS SDK 来优化 DNS 解析的成果。一起关于一些用户无上神脉被解析到比较偏僻的节点,或许质量不安稳的节点,那么咱们会经过监控机制来发现,并推进做些优化。。

3,http呼应耗时的优化解析

现在 HTTP 呼应耗时分两种状况:1. 假如 CDN 节点没有缓存流,CDN收到HTTP恳求后,就需求回源站去拉流,恳求呼应,并等候源站的呼应成果。这个耗时就比较久了,一般是400ms左右,这块和CDN内部的架构有关,有时更久,到达几秒的状况都有,所以这种状况,一般需求推进CDN厂商做一些优化;2. 假如 CDN 节点有缓存流,CDN 收到 HTTP 恳求后,会了解回来呼应头部,一般是在100ms 以内,呼应很快。这块比较受限于 CDN 边际节点分发战略,不同的 CDN 厂商的体现会有些差异,在端层面可做的东西较少,所以首要是推进多 CDN 的交融策破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语略来提高更好的体会。

4,音视频流勘探耗时的优化解析

音视频流的勘探耗时,在 ffmpeg 中能够对应函数 `avformat_find_stream_info`函数。在 ijkplayer 的完结中,这个办法的耗时一般会比较久。在 ffmpeg 中的`utils.c` 文件中的函数完结中有一行代码是 `int fps_analyze_framecount = 20;`,这行代码的大约用途是,假如外部没有额定设置这个值,那么 `avformat_find_stream_info ` 需求获取至少20帧视频数据,这关于首屏来说耗时就比较长了,一般都要1s左右。而且直播还有实时性的需求,所以没必要至少取20帧。这儿就有优化空间,能够去掉这个条件。设置办法:

av_dict_set_int(&ffp->format_opts, "fpsprobesize", 0, 0);

这样,`avformat_find_stream_info ` 的耗时就能够缩减到 100ms 以内。

5,buffer缓冲耗时的优化解析

这部分是朴实看播映器内部逻辑的完结,由于咱们是依据ijkplayer来修正的,就以 ijkplayer 来讲。先点出需求优化的两个当地:1. BUFFERING_CHECK_PER_MIL饺子馅怎样做好吃LISECONDS 值需求下降,2.MIN_MIN_FRAMES 值需求下降,3. CDN装备快启优化。下面详细剖析:

  • BUFFERING_CHECK_PER_MILLISECONDS

这部分逻辑首要是在ijkplayer工程中`ff_ffplay.c`文件中的`read_thread`办法中。用到的当地只要一处:

#define BUFFERING_CHECK_PER_MILLISECONDS (300)

if (ffp->packet_buffering) {

io_tick_counter = SDL_GetTickHR();

if (abs((int)(io_tick_counter - prev_io_tick_counter)) > BUFFERING_CHECK_PER_MILLISECONDS){

prev_io_tick_counter = io_tick_counter;

ffp_check_buffering_l(ffp);

}

}

从这个代码逻辑中能够看出,每次调用 `ffp_check_buffering_l` 去查看 buffer是否满意条件的时刻距离是 500ms 左右,假如刚好这次只差一帧数据就满意条件了,那么还需求再等 500ms 才干再次查看了。这个时刻,关于直播来说太长了。咱们当时的做法是下降到 50ms,理论上来说能够下降 150ms 左右,依据咱们线上灰度的数据来看,均匀能够减少 200ms 左右,契合预期值。

  • MIN_MIN_FRAMES

这部分代码完结是在`ffp_check_buffering_l(ffp)`函数中。

#define MIN_MIN_FRAMES 10

if (is->buffer_indicator_queue && is->buffer_indicator_queue->nb_packets > 0) {

if ( (is->audioq.nb_packets > MIN_MIN_FRAMES || is->audio_stream < 0 || is->audioq.abort_request)

&& (is->videoq.nb_packets > MIN_MIN_FRAMES || is->video_stream < 0 || is->videoq.abort_request)) {

printf("ffp_check_buffering_l buffering end \n");

ffp_toggle_buffering(ffp, 0);

}

}

这儿大约的意思需求缓冲的数据至少要有 11 帧视频,和 11 个音频数据包,才干脱离缓冲区,开端播映。咱们知道音频数据很简略满意条件,由于假如采样率是 44.1k 的收集音频话,那么1s,均匀有44个音频包。11 个音频包,适当于0.25s 数据。但关于视频,假如是24帧的帧率,至少需求0.4s左右的数据,关于大部分 android 直播来说,由于美颜、AR 方面的处理耗费,所以他们的收集编码帧率只要10~15s,那么就需求挨近1s的数据,这个耗时太长。缓冲区里需求怎样多数据,但实践上播映器现已下载了多少数据呢?咱们深化 ff_ffplay.c 源码能够看到视频解码后会放到一个 frame_queue 里边,用于烘托数据。能够看到视频数据的流程是这样的:下载到缓冲区->解码->烘托。其间烘托的缓冲红烧茄子的家常做法区便是 frame_queue。下载的数据会先经过解码线程将数据输出到 frame_queue 中,然后等 frame_queue 行列满了,才留在缓冲行列中。在 ff_ffplay.c 中,攫能够找到如下代码:

#define VIDEO_PICTURE_QUEUE_SIZE_MIN (3)

#define VIDEO_PICTURE_QUEUE_SIZE_MAX (16)

#define VIDEO_PICTURE_QUEUE_SIZE_DEFAULT (VIDEO_PICTURE_QUEUE_SIZE_MIN)

ffp->pictq_size = VIDEO_PICTURE_QUEUE_SIZE_DEFAULT; // option

/* start video display */

if (frame_queue_init(&is->pictq, &is->videoq, ffp->pictq_size, 1) < 0)

goto fail;

所以现在来看,假如设置10,播映器开端播映时至罕见14帧视频。关于低帧率的视频来说,也适当大了。在实践中咱们把它调整到5,首屏时刻减少了300ms左右,而且卡顿率只上升了2个百分点左右。

  • CDN边缘优化

CDN 边缘的优化首要包含 GOP 缓存技能及快启优化技能。这项两项技能根本原理是经过快速下发满足的视频帧以填充溢播映器的缓冲区然后让播映器在最短的时刻内到达播映条件以优化首屏时刻。视频缓存会以完好 GOP 为单位,这个首要是为了避免视频呈现花屏,快启优化则是会在 GOP 缓存根本上依据播映器缓冲区巨细设定必定的 GOP 数量用于填充播映器缓冲区。

这个优化项并不是客户端播映器来操控的,而是 CDN 下发视频数据的带宽和速度。由于缓冲区耗时不只跟缓冲需求的帧数有关,还跟下载数据的速度优化,以网宿 CDN 为例,他们能够装备快启后,在拉流时,前面缓存1s 的数据,效劳端将以 5 倍于平常带宽的速度下发。这样的作用除了首屏速度跟快以外,首屏也会更安稳,由于有固定 1s 的缓存快速下发。这个优化的作用是均匀能够更快 100ms 左右。

四、小结

至此,美拍直播的首屏作用,现已根本跟业界干流直播作用适当,后边咱们将在安稳性、卡顿率和卡顿时刻上面做进一步优化。

需求留意的是:根底数据的计算是全部优化的根底。比方首屏时刻优化的一个最根本的大前提便是需求有直播播映状况的各个阶段的计算数据,这在咱们作业展开的前期是不完善的,比方,DNS 的耗时和 http 呼应的耗时。这个由于种种原因导致一向都没有上报上来,所以开端是无法精准定位,只要一个大约的时刻。还有一些更丧命的问题是计算数据的不精确,由于破阵,美拍直播首屏耗时减少50%以上的优化实践,秋天的成语前史原因导致数据的精确性不行,所以往往会由于过错的数据导致过错的剖析。因而,咱们需求av天堂网2014注重根底数据计算的精确性和完善程度。

the end
向云而生,纵情向前,创业成长故事