IT笔记 · 2014年6月18日

视频直播,由于音频数据丢失引起的卡顿问题

  这几天解决了视频直播的一个问题,但是对音视频直播机制仍然很不清晰,记录下过程。

  问题现象:只有画面时能流畅观看直播,加入音频流之后,就开始出现一秒一次的卡顿。

  一开始以为是丢包,网络等原因,一一排除。观察久之后,发现卡顿规律实在太明显,每秒一次。再继续观察发现两次卡顿间的画面其实是连续的,也就是一秒时间的画面,直接用0.8秒就播放完了,然后就有了0.2秒的卡顿。

  为什么加入音频流之后会导致视频播放速率加快呢?网络上搜了搜,看见一段话:

最后,我猜测是否因为音频数据不足导致。因为我知道音频和视频播放不一样,它不会因为时间戳打得快就快放,它按照自己的频率计算时间匀速播放。如果音频数据不足或丢失,那么本来应该和它一起播放的视频帧会快进或跳过。

  所以猜测确实是音频数据不足导致的画面快进。

  猜测加入音频的播放过程是这样:因为需要音画同步,所以音频包与画面包都打了时间戳, 但是播放却不是直接由时间戳决定,而是累积一段时间的音频数据再播放,比如一秒,然后按音频数据的时间戳来播放对应时间戳的画面。此时如果音频数据时间少于一秒,就会导致播放速率变快的现象,同时也导致那1秒最后空余时间无数据的“卡顿”。

  所以回头仔细看了下代码,查找音频数据到底是怎么丢失的。最后发现问题出在ffmpeg的音频编码函数avcodec_encode_audio上,此函数每次处理的采样数据长度是固定的,然而每次我提供的音频采样数据长度不能被其整除,却没有保留,于是总有一小部分音频采样数据丢失,本地测试没问题,直播时就会发现出现以上所提的问题了。

  解决办法也很简单,每次把编码后剩余的采样数据保留连接在下一次采样数据之前,就OK了。

  以上都只是基于现象猜测而让问题得到解决,需要更进一步搞明白具体的格式与规范。