微视视频播放架构及优化实战
如果无法正常显示,请先停止浏览器的去广告插件。
1. 微视视频播放架构
及优化实战
柳永峰
高级技术专家
2. Senior Software
Michal Engineer
• 2010年年加⼊入腾讯,曾从事Web前端,后台开发⼯工作
• 现负责QQ空间,微视安卓客户端的视频播放业务
• 喜欢折腾智能硬件,cubian开源系统作者 (http://cubian.org)
• vim编辑器器多个知名插件作者,如sourcebeautify.vim, gvimim等
• 个⼈人⽹网站: http://hellohtml5.com/
• Github:@michalliu
3. • 短视频业务介绍
• 视频封装及编解码简介
• 不完美的安卓 - 视频播放业务的技术挑战
• 化繁为简 - 应对海量机型的高可用视频技术架构
• 极致体验 - 秒开优化实践
4.
5. • 短视频业务介绍
• 视频封装及编解码简介
• 不完美的安卓 - 视频播放业务的技术挑战
• 化繁为简 - 应对海量机型的高可用视频技术架构
• 极致体验 - 秒开优化实践
6. 视频封装格式 - MP4
FMP4
[1] QuickTime File Format [2] ISO Base Media File Format
常规MP4
7. 视频编解码基础
[1] ITU.H264编码标准 [2] GOP WiKi
8. • 短视频业务介绍
• 视频封装及编解码简介
• 不完美的安卓 - 视频播放业务的技术挑战
• 化繁为简 - 应对海量机型的高可用视频技术架构
• 极致体验 - 秒开优化实践
9. 安卓系统播放器器架构
Application
MediaPlayer
IPC Interface
MediaPlayerService
System Server
StageFright
AwesomePlayer NUPlayer
MediaExtractor OMX Codec
10. 安卓系统播放器器架构
缺点:
优点:
• 接⼝口简单,开箱即⽤用 • ⾸首帧渲染普遍较慢,华为⾼高端机型相对较好
• 视频播放不不消耗App进程的内存,CPU • 视频封装容器器⽀支持较少,仅对mp4⽀支持较完善
• 解码性能较好,耗电低 • 不不⽀支持扩展,⽆无法软解
• 不不⽀支持缓存
• 底层策略略优化⽋欠缺,播放成功率偏低
• 数据协议⽀支持有兼容性问题,例例如:https协议
8.x 4.x
13% 6%
5.x
21%
•
7.x
35%
6.0
25%
•
Crash/ANR问题较多,5.0及以下问题较突出,这部分⽤用
户⽬目前占⽐比18%
⿊黑箱,⽆无源码,出错难以定位
11. 安卓⾳音视频解码
相关API:
问题集锦:
• MediaCodec • MediaExtractor • 建议只绑定 Surface 使⽤用,单独解码YUV问题较多
AudioTrack • setOutputSurface (M版本以上) 调⽤用可能会抛异常或实现不不正确,谨慎使⽤用
• H264解码⼀一般⽆无问题,但某些机型解码器器对分辨率敏敏感
• H265解码存在兼容性问题,谨慎使⽤用
•
结论:
• 系统播放器器应⽤用极其有限,不不适合以短视频为核⼼心的应⽤用
• MediaExtractor不不适合做为通⽤用播放器器核⼼心模块,适合轻量量
编辑,信息读取等场景
• MediaCodec在控制得当的情况下是个解码⾳音视频的利利器器
• AudioTrack可⽤用来渲染裸⾳音频数据,没什什么问题
•
•
MediaCodec
MediaExtractor
• 只⽀支持mp4
• SEEK_TO_PREVIOUS_SYNC部分机型实现不不符合预期,建议使⽤用
SEEK_TO_CLOSEST_SYNC
12. ExoPlayer
DefaultExtractorsFactory extractorsFactory = new
DefaultExtractorsFactory();
Player API
MediaSource mediaSource = new
ExtractorMediaSource(Uri.parse("http://clips.vorwaerts-
gmbh.de/big_buck_bunny.mp4"),
mediaDataSourceFactory, extractorsFactory, null, null);
Player Logic
CustomMediaExtractor
Networking
Buffering
Extraction
MediaCodec
Decoding
AudioTrack
player.prepare(mediaSource);
Rendering
player.setPlayWhenReady(shouldAutoPlay);
13. IJKPlayer
FrameWork
Java
SurfaceFlinger
Player API
AudioFlinger
Surface
JNI Interface
FFPlay
Native
AVCodec
Decoding
ANativeWindow
MediaCodecWrapper
Decoding
Rendering
SDL
OpenSL
14. 应⽤用层播放器器
ExoPlayer
• Google主导开发
• API设计跟MediaPlayer不不⼀一致
• 性能及稳定性较好
• 安卓上唯⼀一⽀支持HLS 3.0标签
• 开源,易易扩展,社区活跃
IJKPlayer
• B站开发维护,基于FFMPEG,FFPLAY,SDL
• API设计跟MediaPlayer⼀一致
[1] ExoPlayer [2]IJKPlayer
15. • 短视频业务介绍
• 视频封装及编解码简介
• 不完美的安卓 - 视频播放业务的技术挑战
•
•
化繁为简 - 应对海量机型的高可用视频技术架构
极致体验 - 秒开优化实践
16. 产品运营数据
亿级播放量量 微视 QQ空间
运营数据
播放成功率 99.9% 99.9%
⾸首帧渲染耗时 300ms 700ms
平均秒开⽐比例例 98% 85%
(1秒以下)
⼆二次缓冲率 1.3% 0.45%
(播放卡顿率)
解码性能耗电 97%硬解 94%硬解
视频格式⽀支持度 MP4 MP4,HLS
Crash&ANR 极低 极低
17. 微视视频播放架构
数据源抽象 缓存管理理 PlayerService
Assets 增 OskExoPlayer
File
HTTPS
IO
接⼝口
删
IO
接⼝口
Local
HTTP
Proxy
IJKPlayer
读
MediaPlayer
HTTP
查
PLAYER
App
Logic
18. 本地代理理设计
功能:
•
http://127.0.0.1:{RandomPort}/?v={SourceURL}
&enableCache={IsEnableCache}
&priority={PriorityNumber}
&dataSourceType={DataSourceType}
&preferredContentType={PreferredContentType}
&uuid={PlayUUID}
&token={Token}
&extraUA={ExtraUA}
&eh={ExtraHeader}
数据协议转换(File/Assets/HTTPS等)
•
对缓存管理理层透明,理理论上可⽀支持任意协议的缓存
• ⽀支持⾼高级鉴权(VKey,Cookie,UA等)
• 关联播放器器与下载线程(UUID)
• 提⾼高播放性能及成功率
•
•
•
•
⾃自定义DNS解析
•
APP内⾃自动重新鉴权
• •
失败重连
多IP切换重连
播放质量量上报
HLS连接优化
• •
节省成本
•
流控
•
限速
•
TS缓存
TS重连
•
APP内⾃自动重新鉴权
调试(低速⽹网络,⽹网络断开等模拟)
19. 播放器器管理理架构
Operation
START
PAUSE
Application
STOP
PlayerService
SEEK_TO
GET_DURATION
GET_POSITION
GET_VIDEO_WIDTH
GET_VIDEO_HEIGHT
IS_PLAYING
StateMediaPlayer
IMediaPlayer
PlayerState
IDLE
INITIALIZED
PREPAREING
PREPARED
STARTED
PAUSED
SET_SURFACE
[1] OskExoPlayer
IJKPlayer
COMPLETED
ERROR
RELEASE
OskExoPlayer
SET_VOLUME RESET
SET_LOOPING
MediaPlayer
STOPPED
RELEASED
20. 缓存架构对⽐比
⽅方案⼀一
• Seek⽆无法落地缓存
•
⽆无数据
⽆无法直接缓存视频尾部数据
3M
30M
数据区
⽅方案⼆二
•
需要额外数据库或⽂文件⽀支持
1M
1M
30M
1M
物理理空洞洞
数据区
微视⽅方案
•
⾮非顺序缓存,⽀支持多进程共享
• 切⽚片存储,淘汰单位⼩小
• 缓存空间利利⽤用效率⾼高,缓存命中率⾼高
1M
1M
30M
1M
逻辑空洞洞
数据区
21. 缓存实现原理理
缓存分⽚片⽣生成通知
CacheKey
缓存Key
Cache Cache Free SinkSource
缓存分⽚片描述 缓存分⽚片描述 ⽆无锁 缓存落地算法
Lock
有锁
唯⼀一Key
FileSource HTTPSource
从⽂文件读取 HTTP下载
偏移量量
总⼤大⼩小
⽂文件类型
最后访问时间
HTTPSource
HTTP下载
22. 缓存淘汰策略略
梯度淘汰
• 按创建时间顺序淘汰(FIFO)
• ⽂文件中间的分⽚片先淘汰
•
1M
6.19
1M
6.19
按需淘汰,需要多少淘汰多少
1M
6.19
1M
6.19
⾼高优先级
较早观看
中优先级
最⼤大化利利⽤用缓存空间
低优先级
1M
6.20
优化效果
1M
6.20
1M
6.20
最近观看
• ⼤大盘⾸首缓时间降低200ms
• ⼆二次缓冲率从2%降低⾄至0.45%
• 秒进⽐比例例提升10个百分点,⽬目前微视达98%,QQ空间为85%
1M
6.20
最低优先级
23. • 短视频业务介绍
• 视频封装及编解码简介
• 不完美的安卓 - 视频播放业务的技术挑战
• 化繁为简 - 应对海量机型的高可用视频技术架构
• 极致体验 - 秒开优化实践
24. 秒开技术揭秘
理理论IO时间估算
理论IO耗时
MP4头部⼤大约是 512字节/s,按照视频 600Kbps 的码率
以800KB/s 的下载速度播放⼀一个 15s 的短视频,假定⾄至
少下载 5s 的数据才能开始播放,那么理理论上的最少缓冲
时⻓长为 0.47s
•
1s
0.92s
0.83s
0.75s
0.74s
0.65s
(512 * 15 + ((600 * 1000) / 8) * 5) / (800 * 1024) = 0.47s
mp4头部
下载数据量量
0.56s
0.5s
0.47s
下载速度
0.38s
0.28s
0.25s
0.19s
系统播放器器参数
•
•
0.10s
7.0以上NUPlayer⽆无限制
0s
1s
2s
3s
4s
5s
6s
7s
启动播放所需数据量
7.0以下 5s
AwesomePlayer.cpp
8s
9s
10s
25. 秒开技术揭秘
理论IO耗时
60%
缓冲时⻓长
缓冲概率
1
0.92s
0.83s
0.74s
0.75
0.65s
0.56s
(512 * 15 + ((600 * 1000) / 8) * 2.5) / (800 * 1024) = 0.24s
30%
0.47s
0.5
mp4头部
下载数据量量
下载速度
0.38s
0.28s
0.25
0.19s
10%
0.10s
5%
0%
0%
0%
0%
0%
0%
0
1s
2s
3s
4s
5s
6s
启动播放所需数据量
7s
8s
9s
10s
26. 秒开技术揭秘
LoadControl
MinBuffer Duration 15s
• MaxBuffer Duration 30s
• MinBuffer Start 2.5s
• MinBuffer Resume 5s
15
•
30
2.5
Time
27. 秒开技术揭秘
播放器器优化:
• 适当调整 analyzeduration 与 probsize
• 根据实际情况,尽量量减少Extractor 数量量
•
static {
try {
MediaCodecUtil.getDecoderInfo("video/hevc", false);
MediaCodecUtil.getDecoderInfo("video/avc", false);
MediaCodecUtil.getDecoderInfo(“audio/mp4a-latm", false);
} catch (MediaCodecUtil.DecoderQueryException ex) {
ex.printStackTrace(); // ignore
}
调整 Extractor 的排序,使最常⽤用的格式
排在前⾯面
• 预加载并缓存硬件解码器器信息
• 移除不不必要的渲染器器,如字幕
}
28. 秒开技术揭秘
播放器器优化:
•
⾸首屏⾳音视频并⾏行行渲染
29. 秒开技术揭秘
播放器器优化:
•
调整⾸首屏LoadControl检查步⻓长,默认为每次读取的Buffer为1M,⾸首屏未出前可适当增⼤大为2M
30. 组件开放计划
dependencies {
compile "com.qzone.oskplayer:player:1.5.4-oskplayer"
}
31.