播放器技术分享(3):音画同步

搞音视频开发好些年,分享过许多博客文章,比如:前几年发布的《FFmpeg技巧》系列,《Android音频开发》系列,《直播疑难杂症排查》系列等等。最近想把多年来开发和优化播放器的经验也分享出来,希望能帮助到音视频领域的初学者。第一期文章要推出的内容主要涉及到播放器比较核心的几个技术点,大概的目录如下:

1。播放器技术分享(1):架构设计

2。播放器技术分享(2):缓冲区管理

3。播放器技术分享(3):音画同步

4。播放器技术分享(4):首开时间

5。播放器技术分享(5):延时优化

本篇是系列文章的第三篇,主要聊一聊播放器的音画同步。

<强>

首先,我们给出音画同步的定义:

音画同步是指播放器正在渲染的每一帧画面和正在播放的每一段声音都是严格对应起来的,不存在人耳和肉眼可以分辨出来的偏差。

<强>

机器没有眼睛也没有耳朵,那它是如何去感知视频文件中的某一帧视频数据跟某一帧音频数据是属于<强>同一时间强劲的呢?

现实生活中,判断两件事情是否同一时刻发生的方法就是记录并且比较事件发生的日期时间,同样,我们可以在音频和视频数据“生产”出来的时候,为数据标记上一个“时间戳”,代表着它的出生时间。由此,播放器就知道如何判断了。

播放器技术分享(3):音画同步

如图所示,音视频在采集(生产)的时候,就给每一帧都打上“时间戳”(注意、音视频的时间戳需要使用一个共同的时间戳基准),假设以音频开始采集时刻的系统绝对时间点作为时间戳0点,假设音频20 ms采样一帧,视频帧率30 fps→即33女士产生一帧,那么,视频帧和音频帧的时间戳大致的递增规律为:

视频帧:10,43岁,76109142年……

音频帧:0,20岁,40岁,60岁,80120年……


注:实际上数据采集不会这么”均匀”,会有略微的浮动。

如此一来,播放器就可以通过附加在音频和视频帧上的时间戳信息,感知到音频帧和视频帧的“相对关系”,实现音画同步就轻而易举了,判断方法如下;

音画同步的方法:判断视频与音频帧的时间戳差值,是不是在一定的“阈值”范围内,如果是,则可以渲染/播放,否则就“等”到合适的时间。

<强>

由于音视频是分开采集的,所以它们的时间戳不可能完全对应得上,因此,只要在一个合理的“阈值”范围内即可认为是同步的。那么,这个“阈值”是怎么定义的呢?

播放器技术分享(3):音画同步

如图所示,这个“阈值”有一个国际标准定义了它,叫做:rfc - 1359,它是这么定义的:

1。无法察觉:音频和视频的时间戳差值在:-100 ms ~ + 25 ms之间

2。能够察觉:音频滞后了100 ms以上,或者超前了25女士以上

3。无法接受:音频滞后了185 ms以上,或者超前了90 ms以上

有了这个国际标准和经验值,我们做音画同步取的阈值就不用瞎猜了~ ~

<强>

音画同步的实现策略一般有3种:

1。视频同步到音频

2。音频同步到视频

3。音视频同步到外部时钟

比较常用的策略是:视频同步到音频。

因为音频是流式的,按照规律的匀速的速率去播放,才能显得更加“平滑”,而视频的播放其实是一张一张图片进行刷新显示,它的刷新时间的调整相对而言更容易一些,用户肉眼的敏感度也更弱一些。

下面就讲讲使用“视频同步到音频”的方式,如何实现播放器的音画同步:

播放器技术分享(3):音画同步

如图所示,一代表音频帧、p代表视频帧,音频帧持续送入扬声器以既定的速率播放,,视频帧则参考主时钟来决定自己是否渲染,何时渲染或者丢弃,算法如下:

1。假设最小为音画同步阈值(如:25 ms),则当前视频时间戳如果与主时钟的绝对差值在25 ms阈值范围内则都可以送入渲染

2。如果diff祝辞0,即分比;m-clock,则代表视频帧提前准备好了。这种情况下,是可以通过睡眠来等待主时钟的,但是为了防止异常时间戳导致睡眠时间过长,可以设置一个马克斯异常阈值(如:1000 ms),如果diff超过这个最大可以认为是异常帧,丢弃掉

播放器技术分享(3):音画同步