点播在线视频的秒开策略
前言:所以,在线观看视频已经成为人们生活中不可或缺的一部分。所以,我觉得在未来,音视频的领域会越来越广。本文中提到的优化策略不仅适用于短视频,更适用于文件较大的点播视频。结合我在项目中的探索,总结出以下几种方法(ps:写的不严谨的地方大神勿喷)。
较大的视频一分为二
一般说来,视频文件越小,需要解析的时间也就越短,这样一来,用户等待的时间也就大为减少。譬如,一个100M大小的视频,从视频开头我们可以把它分为两个视频:一个5M和95M。然后只需拿到两个视频的URL,就可以天衣无缝的合成一个视频,而且因为开始的视频大小只有5M,用户等待的时间大大缩短。关于视频合成的部分有不明白的同学可以看我另一文章短视频从无到有 (十二)视频中插入另外一个视频(优酷App视频广告效果)。
前置metadata
播放器在点播场景下去请求 MP4 视频数据,需要先获取到文件的 metadata,解析出该文件的编码、帧率等信息后才能开始播放。如果 MP4 的 metadata 数据块被编码在文件尾部,这种情况会导致播放器只有获取完整个文件后才能成功解析并播放这个视频。对于这种视频,我们最好能够在服务端将其重新编码,将 metadata 数据块转移到靠近文件头部的位置,保证播放器在线请求时能较快播放。比如 FFmpeg 的下列命令就可以支持这个操作:
ffmpeg -i test.mp4 -movflags faststart tested.mp4
选择合适的视频协议及优化参数
在播放视频时,我们可以选择合适的视频格式,譬如我们可以使用遵循HLS协议的m3u8视频来替代mp4等。在 iOS平台上,我们还可以优化播放参数。使用AVPlayer播放播放 HLS 这种流媒体视频时,可以设置player.automaticallyWaitsToMinimizeStalling =NO
。当设置值为 YES 时,AVPlayer 会努力尝试延迟开始播放,加载足够的数据来保证整个播放过程中尽量卡顿最少。需要注意的是,这个接口在 iOS 10 及以上版本才开放。基于 FFmpeg 实现的播放器,在播放视频时都会调用到一个 avformat_find_stream_info
(libavformat/utils.c) 函数,该函数的作用是读取一定长度的码流数据,来分析码流的基本信息,为视频中各个媒体流的 AVStream 结构体填充好相应的数据。这个函数中做了查找合适的解码器、打开解码器、读取一定的音视频帧数据、尝试解码音视频帧等工作,基本上完成了解码的整个流程。在不清楚视频数据的格式又要做到较好的兼容性时,这个过程是比较耗时的,从而会影响到播放器秒开。
在外部可以通过设置probesize
和 analyzeduration
两个参数来控制该函数读取的数据量大小和分析时长为比较小的值来降低avformat_find_stream_info
的耗时,从而优化播放器秒开。但是,需要注意的是这两个参数设置过小时,可能会造成预读数据不足,无法解析出码流信息,从而导致播放失败、无音频或无视频的情况。所以,在服务端对视频格式进行标准化转码,从而确定视频格式,进而再去推算 avformat_find_stream_info 分析码流信息所兼容的最小的 probesize 和 analyzeduration,就能在保证播放成功率的情况下最大限度地区优秒开。在我们能控制视频格式达到标准化后,我们可以直接修改 avformat_find_stream_info
的实现逻辑,针对该视频格式做优化,进而优化首屏秒开。比如,你可以试试将函数中用到的一个变量 fps_analyze_framecount 初始化为 0 试试效果。甚至,我们可以进一步直接去掉 avformat_find_stream_info
这个过程,自定义完成解码环境初始化。
相关参考资料:avformat_find_stream_info接口延迟降低
FFMPEG avformat_find_stream_info替换
对于avformat_find_stream_info
代码的分析,还可以看这里FFmpeg源代码简单分析:avformat_find_stream_info()。
CDN分发
找个合适的第三方CDN服务商也很重要。CDN节点部署,路由策略
缓存还是拉流,都会对延时产生影响。
有什么问题,欢迎大家留言讨论。