短视频迎合了人们时间碎片化下的精神娱乐需求,或者现在追求“短平快”的大环境,我也有点短视频中毒,没事经常光顾某几个短视频APP,以至于冷落了某头条和某易新闻基本很少点开了,这些时间加起来holy bible估计都能读好几遍了。当然这是一篇技术文章,其他心理学,社会学问题,产品问题就不在这里讨论了,咱也没那个水平。

言归正传,我们也推出了短视频相关的产品。

在短视频的体验中,起播速度无疑是最影响体验的指标之一,因为短视频很短,十几秒到几分钟不等,如果一个十几秒的视频,加载时间都要3秒,肯定是一个很坏的体验;所以在产品定义之初,起播速度就设定了控制在1秒左右,大部分在1秒内,也就是业内说的“秒播”,这需要对播放流程进行优化。艾玛,终于绕到主题上了。

谈具体的优化之前我们先看下一个短视频播放的大概流程是怎样的?

再通过拆解流程,找到可以优化的模块或点,最终才能连成线,并给出优化方案。

如上图所示,移动设备的播放器通过某个视频url的域名,通过DNS服务请求到IP地址,通过这个IP地址与视频服务器建立TCP连接,然后在连接之上建立http协议,最终请求到数据,给到播放器进行解析音视频解码显示,用户看到画面听到声音,一个起播流程结束了。

为了更好的发现可优化的地方,我们对上图进行了拆解,结合实际情况给出了下边这张图

图中蓝色的部分是可以优化的,但由于实际情况是,flyme只在客户端接入了内容,内容都是放在CP的服务器上的,虽然有优化空间但是flyme这边优化不到,但在后边我们也会介绍有哪些优化空间可以操作。这个是行业现状,不过可以多接入几家内容选择岂不是更好。图中灰色部分是不能优化的,在流程上没有优化空间,而且这部分容易受到网络情况的影响,所以我们后续提到的优化,是基于大多数normal的网络情况的,虽然部分逻辑对极端网络情况也适用,但是这不是我们讨论的重点。图中绿色的部分是可以优化并且在项目现实中可以实施的。

下面对这些项目逐一进行介绍。

一、Domain name: 域名解析
耗时原因:

DNS请求包会先发到本地DNS服务器,如果查不到,会递归到根域名服务器,这个过程是比较耗时的,当然如果你请求过了,或者期间有其他人请求过相同的域名,那域名服务器就会有缓存,再次请求的时候就很快了;但是一般缓存的周期很短,需要有人不停地请求才能保持更新,所以具有很大的不确定性。

解决方案:

1.注意请求使用的IP协议版本,做播放的肯定都绕不过ffmpeg,在ffmpeg里为了兼容性,DNS请求的IP协议版本设置为AF_UNSPEC,这样在请求的时候会先请求IPv6的地址,如果没有再请求IPv4的地址,是很保险,但是在实际的项目中,没有IPv6的地址,造成一直递归到根域名服务器也查不到IPv6地址,极大的浪费了时间,可以使用AF_INET指定请求IPv4地址,节省一半以上的时间,首次请求或缓存过期后请求,耗时大概在大几十毫秒到100毫秒左右,可以通过监测getaddrinfo函数的耗时的到。

hints.ai_family = AF_INET;
getaddrinfo(hostname, portstr, &hints, &ai);

2.预置或预解析域名IP地址,100毫秒还是很大的一笔时间对于秒内播放来说,这个方案就是提前把域名解析出来,用的时候直接使用IP地址,但是这种方案有局限性,可能适合特定的音视频直播,对于短视频播放地址比较多样来说操作起来有一定难度,而且还存在CP切流和更换接入CP的情况,所以这个100毫秒目前只能先放在这里了。

二、Socket cache:socket buffer
耗时原因:

TCP connection在客户端的具体操作中基本都是通过socket实现的,在socket中有一个缓冲区的概念,发送端先把数据写到缓冲区,接收端数据也是先经过缓冲区,再从缓冲区读出,移动设备作为接收端,接收端缓冲区设置的太小,影响效率,接收端缓冲区设置的太大,会短时间内吃掉带宽,如果带宽不够会引起网络传输问题,还会造成流量的浪费。这些都会影响首屏数据的及时送达。

解决方案:

根据实际情况调整接收端缓冲区大小,通过计算和测试数据得到一个比较合理的值。可以在ffmpeg的network和tcp里进行调整,这是比较低层的修改了,为了通用性可以扩展http/tcp的options并通过ffmpeg提供的AVDictionary机制在avformat API这一层进行透传相关设置参数。
av_dict_set(&avdictionary, “param”, “value of param”);
setsockopt(fd, SOL_SOCKET, SO_RCVBUF,&len,sizeof(len));

三、Probe buffer
耗时原因:

在播放端,一开始并不知道要播放的视频的相关信息,比如封装格式,分辨率,音视频编码等信息,需要先读一段数据进来,再对这段数据进行探测,得出相应的信息,而存放这段探测数据需要一个buffer。这个buffer设置的太小可能导致分析不出信息导致重新探测,设置的太大就会增加收流的时间从而影响了首屏的播放,太小太大都会引入延迟。

解决方案:

根据实际情况调整这个buffer,通过计算和测试数据得到一个比较合理的值。可以通过ffmpeg的AVFormatContext结构体的probesize和max_analy_duration把对buffer的限制透传下去。可以通过观察avformat_find_stream_info这个函数来评价探测耗时。
AVFormatContext->probesize = n;
AVFormatContext->max_analyze_duration = m*AV_TIME_BASE;

四、Probe list
耗时原因:

同样是探测的流程,一开始播放端并不知道这段数据是什么格式,需要根据自己支持的格式通过探测得出一个分数,然后依据这个分数给出相应的格式,类似于android的sniff,所以如果ffmpeg设置的支持的格式越多这个探测list就越长,相应的探测时间也就越长。而对于短视频来说,CP的内容格式基本是确定的,基本都是MP4+H264/H265(不常见)+AAC。所以很多格式的探测是不必要的。

解决方案:

对于没有用的格式在ffmpeg build config里移除,只保留需要的格式,比如mp4,最大限度的减小probe list。可以通过观察avformat_find_stream_info这个函数来评价探测耗时。
disable avi
disable asf
disalbe mkv
and so on…

五、Player buffer
耗时原因:

对于非直播类的播放器,业内的一般做法是都会在player内设计一个缓冲buffer,这是为了播放流畅性和音视频同步的需要,尤其是在网络不稳定或较差的情况下,这个缓冲buffer显得尤为重要。一般这个缓冲buffer有按照帧数设置的,也有设置为1-2秒的,也有设置为3-5秒的,因为一般的播放比如在线电影,电视剧考虑的是整个播放过程几十分钟,甚至几个小时的体验,在开始缓冲个几秒是可以接受的,但是在短视频的场景下这是不可接受的。

解决方案:

策略性的优化,保证视频第一时间输出,把缓冲机制移到首屏播放之后,当然这里也要照顾到音频,保证音视频的同步,有些取舍要做。
这里其实是很重要的一个环节,Android的nuplayer框架设计上受限于这些因素起播速度就远达不到要求,又搞了个exoplayer,但是不做二次开发exoplayer还是不能满足需求。这个需要根据自己的播放框架来做设计,我们使用的是自研的Normandie播放框架,该框架已经上线将近两年,支持了多个音视频的业务,这里就不详细展开了。

六、MP4 Size:分辨率/QP/I帧位置
耗时原因:

分辨率这个不难理解,如果视频文件的分辨率很高,那它一帧的数据会很大,相应的传输时间就会变长。所以在内容产生的时候选择合适的分辨率录制或转码为合适的分辨率也是为播放端的负载在考虑,移动端720P左右足够了对于个人秀之类的短视频,内容聚合类的短视频分辨率可以更低。QP指的是图像质量,同一个分辨率的图像可以有很多级的QP,它是跟编码密切相关的,QP越高图像质量越高码率也越高,相应的传输时间也就越长。同样,不是QP越高越好,对于不是不同场景快速切换的720P视频,3M和5M码率的区别不大。选择合适的QP在画面质量和传输上找到一个平衡。



I帧位置,指的是视频I帧在视频文件开头的位置,播放器为了防止花屏之类的问题出现,一般在开始播放或seek时都会找到第一个I帧进行解码,一般视频文件一秒有25-30帧,很明显I帧放在第一帧和放在最后一帧对秒播是有影响的。

解决方案:

根据实际情况,在产品服务链条中选择合适的分辨率/QP。
把I帧放在文件开头第一帧的位置。

七、MP4 MOOV box position & Http re-connection
耗时原因:

如果在起播过程中发生了http re-connection耗时肯定会增加,而且http connection的耗时基本是不可优化的,所以要避免http re-connection的发生。但是mp4作为主流的短视频封装格式,它的MOOV box在文件中的位置直接影响了会否发生http re-connection,直接点说就是MOOV box放在文件的后面也就是MDAT box后,会产生http-reconnection,引入延时。

解决方案:

1.在上传mp4文件的时候把MOOV box放在前面
2.在mp4文件上传到服务器之后,重新封装,把MOOV box放到前面

如果是传统音视频出身的工程师应该很清楚MOOV box,这里做下简单的介绍。mp4是由很多box组成的,其中MOOV box里存放的是音视频编码之类的对播放很重要的信息,先要拿到这些信息才能播放。所以MOOV box放在文件的前面通过一次http请求就可以直接读取到,解析,继续读取音视频数据播放。MOOV box放在文件的后边,但是播放器不知道它放在后面,需要先发起一次http请求读开头部分数据,发现没有MOOV box,它会seek到文件后边位置,读取MOOV box,读完之后再seek到文件前边位置,从开始位置读取音视频帧数据播放,每发生一次seek就重新发起一次http connetion请求。所以MOOV box放在后边比放在前边多了2次http connection,用时是放在前边方案的3倍。下边是两个短视频一个moov box放在了前边,一个放在了后边,放在了后边的通过NmdPlayer的log可以都看到会发生re-connection,请求文件最后一段数据来获取moov box。

八、Server/CDN
耗时原因:

CDN节点部署,路由策略
缓存还是拉流
都会对延时产生影响

解决方案:

server进行相关的优化。

九、TCP connection
耗时原因:

协议耗时,比如TCP的握手机制等,在稳定的网络下耗时基本是固定的,在较差网络下耗时会较长

解决方案:

CDN骨干网络的部署可以改善这种情况。

十、Http connection
耗时原因:

协议耗时,在稳定的网络下耗时基本是固定的,在较差网络下耗时会较长

解决方案:

CDN骨干网络的部署可以改善这种情况。

对于做技术的同学来说,并没有多么高深的东西,需要做的只是抓住问题的核心,把一个大问题拆解成一个个小问题,然后完成一个个小目标,最后水到渠成。其实很多事情都是这样的,你就把它看成一个技术问题,把它拆解成一个个小问题,完成一个个小目标,比如先赚它1个亿。

我们也完成了一个小目标,通过优化大多数的短视频起播速度都落在1秒内,达到了业内的“秒播”水平。

One more thing…
追求体验的极致,一直是我们追求的目标,而每个功能每个细节体验的极致累加起来就是最终产品的极致。
1.通过上边的分析,我们认为还有至少100~200ms的优化空间。
2.另外我们下一步计划用大数据来监控没有落在1秒内的情况,根据数据分析报告推动对这种情况的优化。这是我们下一个小目标。

很早之前录的一个视频,在线播放分辨率960x720的短视频,这算是比较高的分辨率了,以快手,抖音等为代表的个人秀类差不多是这个分辨率,抖音可能低一些;以西瓜等为代表的内容聚合类的,分辨率要更低些大多640x360或480P。

S70901-18153290
http://v.youku.com/v_show/id_XMzU0MTg3MzE0NA==.html

优化前(未解耦的框架android框架)

slow
http://v.youku.com/v_show/id_XMzU0MTg3NTU5Ng==.html

优化后(解耦的框架normandie+短视频定制优化)

fast
http://v.youku.com/v_show/id_XMzU0MTg3NTE0NA==.html

原创作者:Walker.Xu,原文链接:https://segmentfault.com/a/1190000014405913

欢迎关注我的微信公众号「码农突围」,分享Python、Java、大数据、机器学习、人工智能等技术,关注码农技术提升•职场突围•思维跃迁,20万+码农成长充电第一站,陪有梦想的你一起成长。

短视频秒播优化实践(一)相关推荐

  1. 拒绝卡顿,揭秘盒马鲜生 Android 短视频秒播优化方案

    简介:短视频作为内容重要的承载方式,是吸引用户的重点,短视频的内容与体验直接关系到用户是否愿意长时停留.因此,体验的优化就显得尤为重要.上一篇我们分享了 iOS 短视频秒播优化,这篇我们来聊聊 And ...

  2. 在线短视频秒播优化之视频文件格式之MP4文件Moov box的位置

    之前我们介绍了在线短视频秒播优化的方方面面,从服务器,cdn部署接入,数据连接/获取,客户端缓存,出帧策略,到视频文件I帧位置等. 今天从视频文件格式的另外一个角度介绍,MP4文件的box排列顺序是如 ...

  3. 为什么要做短视频秒播优化

    最近在整理资料,翻到之前项目答辩ppt,盘了一下. 幸好有个记录,有时候一个事做完后就埋在记忆深处"忘得差不多了". 记录和复盘是个好习惯,好处多多: 1.初衷,事情多了,你就忘了 ...

  4. 华为开发者大会主题演讲:抖音短视频网络性能优化实践

    内容来源:华为开发者大会2021 HMS Core 6 System技术论坛,主题演讲<抖音短视频网络性能优化实践>. 演讲嘉宾:卡涛,抖音Android架构师 大家好!我是来自字节跳动抖 ...

  5. 新浪微博短视频服务的优化实践

    点击上方"程序员大咖",选择"置顶公众号" 关键时刻,第一时间送达! 先不说楚枫的这般年纪,能够踏入元武一重说明了什么,最主要的是,楚枫在刚刚踏入核心地带时,明 ...

  6. 【案例】新浪微博短视频服务的优化实践

    本文将分享新浪微博短视频如何提升用户体验.降低成本的思路与实践,包括提升短视频发布速度,降低长视频转码时间,通过新的 Codec 减少带宽成本等. 作者:李成亚来源:新浪微博|2018-08-06 1 ...

  7. 美拍短视频成本减半及毫秒起播优化实践

    本文是来自美图的黄及峰(阿不)在 GIAC 2018 深圳站分享的美拍短视频优化实践的演讲精华内容. 作者将从成本优化,成功率优化,播放体验优化等几个方面,整体介绍下美拍短视频成本减半以及毫秒起播优化 ...

  8. 音视频终端引擎优化实践

    本文由百度智能云-视频云终端技术架构师 --李明路,在百度开发者沙龙线上分享的演讲内容整理而成.内容从音视频终端引擎的概念出发,梳理了音视频终端引擎的发展和技术演进,重点介绍了音视频终端引擎的关键技术 ...

  9. 多目标排序在快手短视频推荐中的实践

    分享嘉宾:郑东博士 快手 推荐算法技术总监 编辑整理:于洋 出品平台:DataFunTalk 导读:快手是中国领先的短视频和直播社区,拥有超过3亿的DAU和丰富的社交数据.快手秉承的价值观是真实.多元 ...

  10. 亿级短视频社交美拍架构实践

    https://www.jianshu.com/p/b73dcd2c03e7 本文系麦俊生在BOSS直聘主办的直聘学院「对话架构师」活动上的精彩分享. 一.短视频市场的发展 近几年来,短视频应用在国内 ...

最新文章

  1. 传承or创新 ?解密分布式数据库自研修炼之路
  2. nuxt渲染html文件,Nuxt页面级缓存
  3. c# java数据类型不同点
  4. 使用谷歌浏览器模拟微信(android或ios)浏览器
  5. JavaScript实现字符串转换成驼峰表示法
  6. c语言多种选,教你轻松学会C语言系列之——一种更简洁、更经典的选择结构
  7. DDD中的聚合和UML中的聚合以及组合的关系
  8. 【车辆计数】基于matlab形态学停车场车辆计数【含Matlab源码 628期】
  9. ActiveMQ(三)——JMS消息结构、JMSReplyTo、面试题(消息丢失,消息重复,消息顺序)
  10. 使开发更便捷——Visual Studio 使用技巧——快捷键
  11. jquery文档modal_jQuery代码文档小工具
  12. 概率论和数理统计知识点汇总
  13. 我在51CTO微职位学PMP_飘过攻略及心得分享
  14. vue项目PC端移动端适配方案
  15. Error:Execution failed for task ':app:transformDexArchiveWithExternalLibsDexMergerForDebug'的解决办法
  16. RocketMq之一条消息在commitlog文件中如何存储验证
  17. IPhoneX全屏适配
  18. php插入数据含有特殊符号的处理方法
  19. VOIP+PSTN集成方案
  20. SASS的安装与使用(windows系统)

热门文章

  1. Git:操作报错:fatal: ‘origin‘ does not appear to be a git repository解决方案
  2. java继承与覆盖_Java-继承与覆盖【摘抄】
  3. sparse-to-dense.pytorch 代码主流程
  4. OWOD:开放世界目标检测,更贴近现实的检测场景 | CVPR 2021 Oral
  5. Hokuyo‘s first try
  6. html5,css3, bootstraps
  7. 阳明大神---容器时代
  8. C#设计模式--设配器模式
  9. (转)Tomcat目录结构
  10. Cocos2dx 3.0 交流篇