短视频秒播优化2

190 阅读7分钟

1,视频处理

1.1,视频采集的时候,会使用h264对视频流进行编码,h264压缩原理:帧内压缩和帧间压缩

1.1.1,帧内压缩,解决的是空域数据冗余问题。

由于我们拍摄的一帧图片,可能有很多相似或者相同的像素,帧内压缩就是保留一些有代表性的像素,解码的时候就是通过将这些有代表性的像素去填充没有保存的像素,经过帧内压缩的帧形成了i帧。

1.1.2,帧间压缩,解决的是时域数据冗徐问题。

比如对于一个一秒60帧的视频,这60帧可能都是相似的,每帧之间可能只有小部分的不同,我们就只保留一个I帧,这个i帧是可以直接解码的,其余的可以是p帧或者b帧,他们记录的只是和前面帧或者后面帧的差异,所以数据量小,但是解码的时候通过前面帧和当前帧的差异来解码。

经过h264压缩之后我们的视频大概是在30m左右,但是这对于我们短视频来说还是比较大的,所以我们又实用ffmpeg对视频的分辨率和帧率做了一个压缩,

1.2,FFmpeg视频压缩 调整码率 $ ffmpeg -i input.mp4 -b:v 2000k output.mp4

调整分辨率 $ ffmpeg -i input.mp4 -vf scale=640:360 output.mp4 720p

调整帧率 $ ffmpeg -i input.mp4 -r 30 output.mp4 30

60秒视频: 30M->12M,缩小3倍

经过ffmpeg的处理之后我们的视频大概是在15-20m左右,但是15-20m对于我们短视频来说,我们还是觉得有点大,但是不能调小参数了,再调小就卡或者糊,然后我们就又调研了一个阿里的窄带高清策略,它不是高保真策略是一个人的主观体验最好的策略

1.3,窄带高清 利用人眼视觉模型,强化人眼关注的地方,弱化人眼忽视的区域,对于人眼忽视的地方,可做进一步压缩。

60秒视频:12->7M,缩小1/3

1.3,视频MOOV头部处理 $ ffmpeg -i input.flv -c copy -movflags faststart output.mp4

另外我们还对某些视频做了一个处理,我们的视频都是mp4视频,播放mp4时,须先解析moov,视频才能播放,一般情况下,moov都是在视频头部,但是有些手机录制的视频moov在视频尾部,这时就需要收尾两次探测,才能解析出moov,拖慢视频播放速度,可以使用FFmpeg将视频的moov移到视频头部。

2,播放器优化 2.1,播放器选择: 对比了系统播放器,ijkplayer和exoplayer,实验发现ijk的起播速度是最快的。

2.2,播放器优化

2.2.1,起播参数配置 analyzedduration:播放前的探测时间 1s probsize :播放前的探测Size,3k, framedrop:跳帧处,放CPU处理较慢时,进行跳帧处理,保证播放流程,画面和声音同步

probesize & analyzeduration 同时存在 听谁的? 结论是: 谁先达到就听谁的。 以上的例子是读取50M的数据或100秒的数据,那个标准先达到,那就听谁的,停止probe。

2.2.2,播放器优化 除了配置起播参数外,我们还可以对播放器做一些优化

1,让播放器优先支持MP4格式的解封装 视频播放器播放视频之前,首先会对这个视频解封装,因为,没解封装前是不知道获取视频格式的,所以他会用他自带所有解封装器对这个视频一一探测,我们的视频都是mp4的,如果对于的mp4的extracctor排的比较靠后的话就会拖慢这个过程,所有我们可以让他只支持mp4的解封装器。

2,移除不必要的渲染器,如字幕 音频渲染器,视频渲染器,不需要字幕,加快速度

3,缓存优化

3.1,缓存的两种需求 3.1.1,边看边缓存 Androidvideocache原理

大概原理,他会构建一个本地代理服务器,视频播放器播放视频的时候,先向代理服务器请求数据,这时代理服务没数据,就会发起真正的网络请求,向服务器请求数据, 得到数据之后先写到本地缓存,然后在将本地数据返回给播放器,播放器播放。

只是解决了缓存问题,并没有预加载。那我门怎么实现预加载呢?

3.1.2,视频有预加载 视频预加载原理

代理服务器,只要向他请求数据,如果他本地没有数据,都会去请求真正的数据,然后写到本地,所以可以将这里的播放器替换成一个线程,让线程去请求数据,他也会去缓存数据。 视频播放的时候,先通过代理服务器,将本地数据进行读取播放,后面的数据再通过 代理服务器请求数据,缓存到本地,在返回给播放器播放。

3.2,缓存优化 3.2.1, 缓存大小设置

每个视频的时间,大小,码率都不同,如果设置一个固定值,可能对于某些视频的起播来说,缓存多了,,可能造成资源浪费,对于有的视频来说,缓存少了,不能立即播放,所以我们缓存大小是 MOOV大小+视频平均码率 * 预加载时长 ,对不同的视频,缓存不同的大小。(要搞清楚视频码率多少,给出一个确切大小)

3.2.2,预加载任务的管理 预加载视频是一次预加载一页,一页是8个视频,为了满足前面滑到的视频先缓存,又要满足快滑需求,所以我们需要一个并发的优先级队列,这里我们使用的是FixedThreadPool,核心线程数和最大线程数都是4,一次缓存一页(8个视频),前四个并发缓存,后4个顺序缓存。

3.2.3,保证视频优先播放 在添加预加载任务的时候和恢复预加载任务的时候,都会去判断当前视频是否应是播放状态了,如果不是播放状态就等待,等视频播放后在开始和恢复预加载任务。

3.2.4,滑倒一个视频的时候会暂停某些预加载任务 当我们滑动到一个已经预加载过的视频,我们只会去暂停这个视频前面视频的预加载任务,当我们滑动到一个没有预加载过的视频嘛,那么我们会去暂停所有的预加载任务,保证当前视频的网速嘛

3.2.4,预加载过的视频取消划过去的任务,没预加载的视频取消全部任务 滑动到一个视频时,为了保证这个视频尽快播放,会暂停某些预加载任务,快滑时暂停所有预加载任务,慢滑只暂停滑动方向之前的预加载任务,因为慢滑大概率滑到一个已经预加载的视频,快滑大概率滑到一个未预加载的视频。

3.2.5,尽量保证滑到的视频立即播放 等待下页(一页视频为8个)第一个视频预加载完成,才进入下一页视频,保证滑到的视频都是可以立马观看的。

3.2.5,限制网速 慢滑不会取消当前视频后面预加载任务,当前视频还没播放的时候,会限制预下载的网速,通过让下载线程sleep来实现。

4,网络优化 4.1,视频数据预加载&H5和NA数据共享

滑动到列表倒数第二个视频的时候就预加载下页数据,保证滑动流畅性,另外可提前加载下页视频的缓存

h5页面展示视频缩略图,点击缩略跳到视频播放页 可做h5页na缓存共享,h5滑动的视频数据缓存到本地,视频播放页获取视频数据的时候直接从本地读取,节省了视频数据的获取时间。

4.2,HttpDns进行IP预解析和IP直联

Http2升级

4.3,弱网环境 尽管已经做了很多优化,由于网络环境的限制,还是会卡顿,针对弱网环境,可以做一套低清视频适配,客户端通过Ping 检测网络延迟,定时给服务端上报,根据当前网络环境下发高清或者低清视频