1.播放器首帧优化
1.1 网络建连
- 服务端提前下发视频链接域名
- HTTPDNS预解析或者预请求
- DNS IP缓存策略
- HTTP1.1 连接复用
- 如果是HTTPS的话,需要在TLS False Start设置session复用,这样既可以保证安全,又可以保证0RTT握手
- 自建服务端的话,可以引入QUIC协议,在弱网情况下效果更佳
1.2 视频格式
- 服务端将视频统一转码,然后通知客户端,或者服务器在下发视频链接的时候直接告诉客户端封装格式和编码格式,客户端减少嗅探逻辑。
- MP4视频,服务端需要保证moov信息在mdat信息之前。如果发现moov在mdat之后,需要服务端转一下。
- 服务端探测视频的首个GOP位置,下发给客户端,客户端预加载到首个GOP结束的位置
1.3 音视频解码
- 解码器异步初始化
- 解码器复用
1.4 预渲染
- 提前将视频画面渲染好,但是不必要显示出来,等会播放当前视频的时候直接展示就可以。
1.5 预加载
- 预加载策略要根据视频时长、网络速度、预加载视频的码率、预加载数量来决定。
- 预加载决策因素:
- 根据当前的播放器缓冲区buffer大小来决定是否继续预加载。
- 根据当前的网络带宽来决定是否继续预加载。
- 综合当前的播放器缓冲区buffer大小和网络带宽大小来决定是否继续预加载。
- 预加载采用本地代理方式用以将播放器的网络模块独立化。
1.6 多码率切换
- HLS和DASH都是多码率的格式,开始用低码率播放视频,后续根据网络状态切换到高码率的视频。
- 码率如何决策:
- 根据当前的播放器缓冲区buffer大小来决定是否继续预加载。
- 根据当前的网络带宽来决定是否继续预加载。
- 综合当前的播放器缓冲区buffer大小和网络带宽大小来决定是否继续预加载。
2.播放器成功率优化
2.1 网络导致失败
- 网络波动导致失败,网络重试
- 403问题,一般是客户端请求参数异常,request header确实或者不匹配
- 404问题,文件不存在,服务端调度调整一下,不能下发这样的链接
- 500问题,服务器过载问题,扩容或者调度优化
- 被劫持,采用HTTPDNS防劫持,或者自建代理,或者直接采用https
2.2 格式问题
- 不支持的封装格式
- 硬解码不支持的视频或者音频格式
采用FFmpeg音视频框架兼容不支持的封装格式、音视频解码格式
3.播放器seek优化
拖动进度条是一个比较重要的优化项,ffmpeg中的av_seek_frame有下面几种选项:
- AVSEEK_FLAG_BACKWARD:第一个 Flag 是 seek 到请求的时间戳之前最近的关键帧。通常情况下,seek 以 ms 为单位,若指定的 ms 时间戳刚好不是关键帧(大几率),会自动往回 seek 到最近的关键帧。虽然这种 flag 定位并不是非常精确,但能够较好地处理掉马赛克的问题,因为 BACKWARD 的方式会向回查找关键帧处,定位到关键帧处。
- AVSEEK_FLAG_BYTE :第二个 Flag 是 seek 到文件中对应的位置(字节表示),和 AVSEEK_FLAG_FRAME 完全一致,但查找算法不同。
- AVSEEK_FLAG_ANY:第三个 Flag 是可以 seek 到任意帧,不一定是关键帧,因此使用时可能出现花屏(马赛克),但进度和手滑完全一致。
- AVSEEK_FLAG_FRAME:第四个 Flag 是 seek 的时间戳对应 frame 序号,可以理解为向后找到最近的关键帧,与 BACKWARD 的方向是相反的。
当前播放时间点是cur_time,拖动到的时间点是seek_time,如果seek_time和cur_time在同一个GOP内部,那就不需要清空video frame queue中数据,优化seek性能。
4.播放器卡顿优化
4.1 解决渲染卡顿
播放帧渲染不能有耗时操作,例如视频播放中美颜、滤镜等操作不能耗时
4.2 加载Buffer优化
- 网络好的情况下缓冲Buffer调大点
- 网络差的情况下缓冲Buffer调小点
4.3 多码率适应
HLS多码率适应,弱网情况下计算load buffer自动切换到低码率
4.4 丢帧控制
极端情况下适当丢帧,丢帧要优先丢非参考帧,如果要丢参考帧需要丢整个GOP的数据,防止出现花屏
4.5 音视频同步
- 推流端推的视频timestamp和音频timestamp有问题,拉流端音视频同步存在问题,导致播放卡顿,需要推流端校准
- 拉流端缓冲设计要做好,解码队列中数据不够导致音视频解码时同步总是对不上。
- 特定视频中pts异常:视频中封装的音频和视频相差比较大,有时候会相差好几秒,这就是这个视频源有问题了。
5.播放器异常情况
5.1 视频渲染色差问题
目前大部分视频使用的颜色空间有:BT.601、BT.709、BT.2020,这里面还有 Limit Range 和 Full Range 的不同,在渲染时则可能涉及到颜色空间的转换,如果相关的转换矩阵参数不对或者没有从视频中获取到正确的颜色空间,在做转换时都可能出问题而最终造成渲染的视频出现色差问题。通常这样的问题不会直接报错造成视频无法播放,但是也会给用户带来异常的播放体验。
要优化这些问题,需要从视频中获取正确的颜色空间信息以及 Limit Range 和 Full Range 类型,并使用正确的转换矩阵来适配渲染支持的颜色格式。
5.2 视频画面比例问题
正常视频画面比例会根据width/height来决策,但是封装格式中width/height可能存在不准确的问题。有三个参考数据:
- DAR:显示宽高比
- PAR:单个像素的宽高比
- SAR:采样纵横比
PAR x SAR = DAR
最终要根据DAR来决定视频画面的比例,如果没有DAR则根据SAR来决策。
5.3 视频旋转角度
根据视频旋转角度在渲染视频的时候旋转画面。
5.4 花屏、黑屏、闪屏问题
- 主播没有打开摄像头权限,推流端没有做好权限校验处理。
- 采集Camera数据,就要开始编码,如果编码失败,没有推送数据,那就会黑屏。
- 拉流端遇到不支持的视频格式,或者解析出来的数据异常,出现解码失败,导致无法播放视频,出现黑屏。
- 推流过程中由于网络问题不得不丢帧处理,此时丢失了参考帧,导致后续拉流段解码的时候因为失去参考帧解码出来的数据出现花屏情况。如果需要丢帧,应该一次就丢掉整个GOP的数据,不然就可能出现花屏现象。
- 播放器拉流的时候首帧不是关键帧,导致花屏,一定要判断首帧是关键帧才开始处理,不然没有关键帧整个GOP的数据解出来都有问题的。
- 推流端直播size发生变化,拉流端没有重置解码器,导致拉流端解出来的数据异常。
- 硬解码的兼容性问题,出现编码器无法支持格式,例如相机采集的是NV21,但是编码器只能支持I420,那推出去的视频就会出现色差。