问题背景:
前两天看读者留言让再写写音视频问题排查方面的思路,前面大概写几篇:《音视频播放疑难杂症分析和解决 :序篇》、《音视频常见问题分析和解决:延时和抖动》、《记一次因为丢帧导致视频播放花屏问题的排查》。今天继续这个系列补充。由于移动互联网的快速发展,现在一些音视频IOT相关的智能设备如IPC、智能猫眼等,有很多移动端浏览器或者微信小程序的播放需求,这种情况我们用了HLS TS方案。
近期上线后,发现视频整体播放没有啥大问题,但是仔细看还是感觉有点卡顿,不仔细看不容易发现,就这个视频卡顿问题进行了一番排查,先说下结论:我们在读磁盘的TS切片文件时,没有把整个TS读完整,导致每个GOP最后有几帧丢了导致视频播放起来有稍微的卡顿感。
视频卡顿引起的原因很多,一般分为两大类:
一类是因为音视频时间戳打的不规范导致视频在解码渲染时顺序不对引起的;
另外一大类就是视频传输过程中因为网络问题导致的丢包进而产生的花屏和卡顿问题。一般具体问题需要具体分析,但是思路差不多。
问题排查:
1.排查问题前,大概画下流程处理示意图:
2. 分析思路:还是利用对比法和分段法进行定位问题出现在那个环节和模块。
上传码流从生产到消费的路径有两条:
第一条码流传输路径:
1-----2------6:这条路径主要是我们的私有协议,在自研移动端APP上进行观看播放码流,实际发现播放很顺畅,无卡顿感。
第二条码流传输路径:
1-----2-----3-----4------5:由于第一条没有问题,那说明问题只可能出现在3-----4-----5这三个环节。其中HLSTS服务是进行码流转化和切片的模块,第三方对象存储主要是借助公有云进行存储TS文件,HLSAPI是m3u8生成和码流分发模块。由于第三方对象存储都是大厂阿里,华为的,出问题概率比较低,所以先从HLSTS切片模块分析起来,逐渐向上层排查。
3. 为了复现该问题,我们在摄像头前面电脑上循环播放一段篮球投篮的小视频,如果出现卡顿问题很容易在浏览器上播放时发现,大家可以看下当时卡顿的情况。接着把HLSTS当时切片到磁盘上的一个个小TS合并成一个大文件播放,比较下到底是不是问题出现在把私有流传TS切片的过程,如果不是就继续分析上传到对象存储以及之后的下载分发情况。
结果发现把磁盘文件down到本地合并后播放,并无卡顿感播放挺顺利,那说明问题至少出在HLSTS服务上传第三方对象存储过程以后了。然后利用对象存储SDK将上传上去的TS片段拉下来分析发现视频的确卡顿,进而说明问题就出在HLSTS上传这块了。
4. 那到底什么原因导致从磁盘读文件再上传就少了一部分数据呢,少的数据又少了什么呢?然后把从对象存储拉下来的TS文件利用Elecard工具分析,发现每个GOP文件内少了几个P帧数据,由于摄像头是固定帧率,每4秒一个GOP,我们切片也是一个个GOP进行切成TS文件的。按道理一个TS应该100帧,实际发现总是在GOP的末尾少了几帧,既然丢帧了难怪播放起来不是很顺畅,如果丢帧5帧以上则播放TS时更明显,当时分析的文件:
这里帧率是25,一个GOP 4秒固定帧率算下来实际是100帧实际只有97帧,说明丢了3帧。
5. 后来发现从第三方对象存在下载下来的所有TS多少都存在丢帧情况,有些上传到OSS对象上丢了1、2帧有些则丢了4、5帧,那问题肯定出在HLSTS的上传文件模块中。为了验证实际将切到磁盘文件的大小和上传模块读的文件大小做了比较,的确上传模块上传文件都没有把文件读完整进行上传。
其中左侧是切出来文件写到磁盘上的实际大小,右侧是日志上传时读取的大小,明显发现没有把TS读完整进行上传。
6. 由于切片这块我们借助了FFMPEG,大概思路就是收到一个GOP时完成一个TS切片,切完后立即通知上传模块的线程进行读取文件上传对象存储。既然读的模块没有上传完整,大概想原因可能在读取文件时,实际切片还没完全写到磁盘的文件时,收到通知后发现有文件就开始上传了。后来也验证了猜想的正确,因为毕竟丢帧都丢在TS文件的末尾几帧数据上,那什么原因导致写磁盘的过程滞后读文件的线程呢,毕竟这里是同步操作的。再后来发现切片写文件我们用的FFmpeg接口是av_interleaved_write_frame 而不是av_write_frame,这样前面的接口为了交织的将音视频packet写的TS文件,会根据音视频的DTS进行缓存和排序,这样写文件时没有av_write_frame直接写得快,实际我们在调用这个接口时音视频的DTS我们上层是能控制的也是排好序的,完全没必要让FFmpeg接口取做缓存排序这件事,所以将接口切换到av_write_frame,后来切换后实际写完后通知上传文件线程就能读到完整文件。实际上传的大小也就是文件写磁盘的大小,视频卡顿也消失了。下面是分析结果和实际优化后的播放效果。
这里一个GOP就变成100帧,实际日志也显示上传的大小和磁盘文件最终的文件大小一致:
当然解决这个问题思路很多,我们就是通过换接口进行了解决,因为我们直接写TS不会存在问题,上层调用者对DTS排序问题已经做了处理。
思考总结:
音视频问题很多,常见的就有音视频卡顿、花屏、延时大,音画不同步等一系列问题。但是偏差这些问题无非就下面几点:
1. 分段分析,先利用二分法把问题一点点局限到一个过程或者一个服务中,这样缩小问题的排查范围;
2. 对比实验,利用一些路径上的对比实验也可以快速排查问题不是出在什么地方,也可以大幅度缩小问题排查。例如,直播时如大家APP播放同一主播的视频都出现问题,那问题大概率出现在主播端上行推流端,如果你的APP有问题,其他人能顺畅播放那说明问题出在你APP的下行端概率比较高,这样通过做一些简单的对比试验就可以把问题不会出现的路径去除掉
3. 写码流、分析码流、看日志、搭建环境复现问题成了排查问题根因的最后手段,线上问题一般先采用一些规避手段解决掉;
4. 专业的事交给专业的工具,视频码流是比较复杂的东西,分析时一定要借助专业工具,这些专业工具有些是现成的比如FFmpeg、Elecard、ParseFlv、Mp4Box,有些也需要自己平时积累开发一些工具出来,然后分析是传输、封装还是编解码层的问题。