WebRTC音视频同步原理与实现详解(上)
第四章、音视频同步实现详解
4.1 音视频同步标准
音视频做到什么程度才算是同步呢?
关于音画同步, 业界有3个标准:
1)ITU-R BT.1359(1998):国际电信联盟标准
2)ATSC IS/191(2003):美国的数字电视国家标准
3)EBU R37(2007):欧洲广播联盟标准
目前在音视频同步方面影响最大的国际标准是,ITU-R BT.1359-1,该标准的评测者既包括专家, 也包括一般人,采用5级评分标准,给出的答案是:


delay time是用视频延迟减去音频延迟,负数(-)表示音频延迟更大,正数(+)表示视频延迟更大。
4.2 同步器与延迟调整
4.2.1 音视频同步器
音视频同步器,就是负责将音频和视频流同步播放。

图中中间大框架里就是整个同步器,同步器输入包括三部分:
1)期望音频目标延迟,以该延迟播放,音频是流畅的
2)期望视频目标延迟,以该延迟播放,视频是流畅的
3)最近一对音视频包的相对延迟
同步器输出,包括两部分:
1)音频目标延迟
2)视频目标延迟
音视频相对延迟:音视频目标延迟差 - 最近一对音视频包相对延时

4.2.2 调整延迟
1)音视频目标延迟,取期望目标延迟与最小播放延迟的最大值。

最近一对音视频包的相对延迟与音视频的目标延迟差之和,得到当前时刻的音视频相对延迟,即音视频流目前的时间偏差,计算当时相对延迟,并使用滑动平均算法处理,减少噪声和干扰的影响。滑动平均算法公式:

其中,k表示平滑滤波器的窗口大小,用于计算滑动平均值的权重系数(代码中kFilterLength = 4),y表示平滑滤波器的滑动平均值,x表示当前样本值,这里是相对延迟
2)计算音视频的延迟
为了控制步长,相对延迟diff_ms是平滑的相对延迟的一半,并限制单次在80ms范围之内,如果是30ms以内,则认为是同步的,不需要调整。
当diff_ms > 0,说明视频比较慢,再进行视频延迟与基准(默认0)比较:

-
如果video_delay_.extra_ms > base_target_delay_ms_,减小视频流延迟,设置音频延迟为基准;
-
如果video_delay_.extra_ms <= base_target_delay_ms_,增大音频流延迟,设置视频延迟为基准。
当diff_ms < 0,说明音频比较慢,再进行音频延迟与基准(默认0)比较:

-
如果audio_delay_.extra_ms > base_target_delay_ms_,减小音频流延迟,设置视频延迟为基准;
-
如果audio_delay_.extra_ms <= base_target_delay_ms_,增大视频流延迟,设置音频延迟为基准。
3)同步策略
当视频相对音频存在播放延迟时,如果视频已经存在延迟,减小视频播放延迟,通过快放追上音频;如果视频没有延迟,无法再降低,增加音频延迟,让音频慢放等待视频。当音频相对视频存在播放延迟时,如果音频已经存在延迟,减小音频播放延迟,通过快放追上音频;如果音频没有延迟,无法再降低,增加视频延迟,让视频慢放等待音频。
经过了以上校准之后,输出了同步后音频、视频流的最小播放延迟audio_delay_.extra_ms和video_delay_.extra_ms。
4.3 设置音频延迟
前面计算出音频、视频流的最小播放延迟audio_delay_.extra_ms和video_delay_.extra_ms,extra_ms含义是音视频同步过程增加了多少的延迟,一开始是0,在同步的过程会慢慢收敛,不断累计。
理论上将这两个延迟分别施加到音频和视频流播放上,音视频就可同步,但是为了播放流畅,还要考虑网络延迟,因此,再进一步分别与音频期望目标延迟、视频期望目标延迟比较,取最大值。音频延时设置代码:

调用SetMinimumPlayoutDelay,会调用并设置到DelayManager中:

将delay_ms赋值给minimum_delay_ms_,这个值限制了最小播放延时,即限制 effective_minimum_delay_ms_的最小值。


其中,MinimumDelayUpperBound是控制delay不能超过75%的max packet buffer的大小。
那effective_minimum_delay_ms_的使用?
在计算网络延时使用,target_level_ms取target_level_ms_和 effective_minimum_delay_ms_的最大值。

4.4 音频输出控制
同步器输出了音频目标延迟后,设置到NetEQ中,参与NetEQ的Decision策略决策:

如果音频当前延迟小于3 / 4音频目标延迟,也就是缓存数据较少,需要减速播放等待目标延迟;如果音频当前延迟大于音频目标延迟,也就是缓存数据过多,需要加速播放追赶目标延迟;如果音频当前延迟大于4 * 音频目标延迟,返回快加速。
音频就是以缓存长度追赶目标延迟的方式达到延迟一定时间的效果,最终和视频的目标延迟对齐后,实现了音视频同步。代码实现:

target_level_ms_就是target_buffer_level,网络抖动延时
buffer_level_samples是当前jitter buffer size
1)首先计算网络延迟的最低和最高延时范围
将lower_limit设置为target_buffer_level的3/4与target_buffer_level - 85ms/2两者最大,higher_limit设置为target_buffer_level与lower_limit +20ms/packet_len_ms_两者最大。
2)比网络延迟的最大延迟的4倍要高,返回快加速。
3)抖动延时超过了网络延迟的最大延迟,表示抖动缓冲区包累积较多,返回加速播放。
4)抖动延时小于网络延迟的最小延迟,表示抖动缓冲区包较小,返回减速。
4.5 设置视频延迟
计算出目标延迟后,设置到视频同步(即视频接收流)。


将delay_ms赋值给syncable_minimum_playout_delay_ms_,更新minimum_delay_ms为syncable_minimum_playout_delay_ms_(因为其他两个是0)

再设置到VCMTiming中:

即赋值给min_playout_delay_ms_。
最后,在render time中生效

Render time即是这帧数据渲染的时间:


4.6 视频渲染时间
视频渲染总框架:

1)视频目标延迟、视频当前延迟
2)视频最小播放延迟,来自同步器校准结果
3)期望接收时间,用于平滑渲染时间
视频帧渲染时间即是帧平滑时间与视频实际延迟之和。
4.7 期望接收时间
期望接收时间,即帧平滑时间。
FrameBuffer每获得一个可解码帧,都要更新其渲染时间,渲染时间通过TimestampExtrapolator类获得,是一个卡尔曼滤波器,其输入为帧的RTP时间戳和本地接收时间观测值,得到视频帧最优的期望接收时间,用于平滑网络的抖动。
TimestampExtrapolator会根据输入帧的时间戳的间隔计算输出渲染时间,目标是平滑输出帧的时间间隔。

1)每收到一帧,会记录该帧的RTP时间戳Tframe_rtp和本地接收时间Tframe_rcv,其中第一帧的RTP时间戳为Tfirst_frame_rtp和本地接收时间Tfirst_frame_rcv。
2)记帧RTP时间戳之差:Tframe_rtp_delta = Tframe_rtp - Tfirst_frame_rtp
3)帧本地接收时间之差:Tframe_recv_delta = Tframe_recv - Tfirst_frame_rcv
4)两者为线性关系,期望RTP时间戳之差Tframe_rtp_delta = _w[0] * Tframe_recv_delta + _w[1]
5)通过卡尔曼滤波器得到线性系数_w[0]、_w[1],进而得到期望接收时间的值:
Tframe_recv = Tfirst_frame_rcv + (Tframe_rtp_delta - _w[1]) / _w[0]
4.8 更新视频当前延迟
FrameBuffer每获得一个可解码帧会调用一次,更新当前延迟,最终用于计算渲染时间

render_time_ms为期望渲染时间,actual_decode_time_ms为实际解码时间。
获取目标延迟target_delay_ms,即抖动、解码时间、渲染时间与最小播放延迟的最大者,是播放当前帧总体的期望延迟,作为当前延迟的参考值。
期望解码时间为render_time_ms 与decode_time - render_time之差。
帧延迟delayed_ms 为actual_decode_time_ms与期望解码时间之差。
如果发生延迟,直接退出,不更新,如果有延迟,调整当时延迟,逼近目标延迟。
第五章、音画同步测量方法
本方介绍一种声控测量方法,需要购买辅助机搭建材料。
5.1 材料清单
PCB板:1块
LED灯:1个 长脚为正极
电阻:4个,分别是R1-2K、R2-1M、R3-10K、R4-100
电容:2个,分别是C1-1μ,C2-100μ, 长脚为正极
麦克风:1个
三极管:2个 S9013
电池和连接线若干
5.2 辅助板搭建图示

使用上面材料按这个电路图连接即可。
5.3 测试方法
1)下载标准音画同步视频"YHTB.MP4"到测试设备。
2)将接收画面与辅助机放在同一个画面里。
3)使用其他手机进行拍摄,帧率设置为240fps,进行拍摄录制。
4)将拍摄录制放到电脑中,使用播放器逐帧查看,比如AviDemux播放器。

5)计算同步时差
第一步,记录白色方块过"0"点的时间T1。

第二步,逐帧查看直到LED灯被点亮的第一帧,记录时间T2

两次时间差T2-T1,就是音画同步的延时T,即T=T2-T1。
第六章、总结
本文从RTP及NTP时间戳、音视频同步原理、目标延迟及同步实现4个方面,由简入繁地讲解WebRTC音视频同步的原理与实现。
1)RTP及NTP是WebRTC音视频同步的基石,没有这两个时间基准,通信的两端是无法进行同步的。
第一部分,介绍音频和视频RTP时间戳的不同计算和生成方法。
第二部分,介绍RTP与NTP的对应关系,如何通过SR包来获取RTP与NTP的线程关系,通过这个线程关系,可以通过RTP求对应的NTP时间戳。
2)介绍音视频的同步原理及常见的几种同步方法。
3)介绍如何求音视频的相对延迟、期望延迟、目标延迟,最小延迟。
4)介绍音视频同步的实现,以及代码实现。
5)介绍音画同步的测量方法。
总结一句就是通过求目标延迟,对音频的播放和视频的渲染施加各自的延迟,即可达到同步,也可达到流畅。
音视频同步总框图:

若出现了音画不同步的问题,先通过测量方法确认哪个源快,无论是音频还是视频快,需要分析一方慢的原因,可以从整条链路的各个环节去排查:录制、编码时间、Pacer、网络、JitterBuffer大小、解码时间、渲染时间等。若慢的一方无法再优化、加快,那只能将快的一方加延时放慢等待。为了低延迟和提升用户体验,我们优先去优化、加快慢的一方。
参考文献
(1)《RTCP协议与实战》
https://blog.csdn.net/weixin_38102771/article/details/121866968
(2)《WebRTC音视频同步》
https://blog.csdn.net/xiehuanbin/article/details/133810695
(3)《WebRTC音视频同步详解》
https://blog.csdn.net/sonysuqin/article/details/107297157
(4)WebRTC源码https://webrtc.googlesource.com
(5)RTP官方文档 https://datatracker.ietf.org/doc/html/rfc3551

往
期
推
荐
