hls音频直播杂音分析

2021-08-12 16:14:31 浏览数 (1)

HTTP Live Streaming(HLS)是Apple制定的一套自适应多码率标准,用于切片式的分发,在直播领域应用非常广泛,但是在转封装的过程中,我们发现仅在苹果系统中,会伴有破音问题,本文主要内容就是如何分析直播过程中的破音产生的原因以及解决办法。

直播数据源一般有推流和回源两种模式,推流目前主流是rtmp协议 ott厂商会有TS协议,而回源,一般主流是rtmp源站或者flv源站 少量ott厂商会提供TS源站,而下行播放一般采用flv或者hls,如果有多码率自适应的需求,一般会采用hls,那这里就涉及了协议转封装问题,这里我们主要讨论ts转hls过程中遇到的问题分析。

        TS全称MPEG transport stream,是一种可以传输视频、音频、广告等节目信息的数字封装格式,多应用于电视广播系统,是一种字节流,被分割成188字节的TS分组(ts packet),结构如下:

  • ts 层:Transport Stream,是在 pes 层的基础上加入数据流的识别和传输必须的信息。
  • pes 层: Packet Elemental Stream,是在音视频数据上加了时间戳等对数据帧的说明信息。
  • es 层:Elementary Stream,即音视频数据。

ts packetts packet

         es层中,可以包含一个音频帧,也可以包含多个音频帧,ts头部 帧数据会被分割成多个188的包,被分割后,第一个包中会在头部加入pcr(节目时钟参考)类似音视频中的dts,这里也就是这次问题分析的重点。

          ts中的时间精度都是90Hz,即1s = 90000 time scale,这个我们平时常用的rtmp/flv协议中有所不同,rtmp中的时间戳都是毫秒单位 即1s = 1000 time sacle。一个音频帧即AAC frame一般有1024个采样样本,假设采样率为44100Hz,那么一个音频frame的播放时长=1024/44100 = 0.02321995s = 23.2199ms,前面我们已经提到,一般中间链路会使用rtmp,而rtmp时间戳是毫秒,这里取整后就变成了23ms,从而产生一个0.2ms的误差,转封装到hls时时间戳就变成了23 * 90 = 2070,而原始ts中的时间戳是90000 * 1024 / 44100 = 2089.795取整后为2089,那么问题来了,如果多个帧后,这个误差积累会变大,而hls就是ts的切片形式,苹果公司制定的标准,自然苹果系统的播放器对hls标准执行的就更加严格,Safari播放器对这个音频误差比较敏感,所以每过一小段时间就会听到噗噗的爆破音,对于音质要求较高的直播场景来说,这个就比较严重了。总结下破音的原因就是因为不同协议间的转换导致的精度降低而带来的时间戳误差。

        既然已经知道问题原因,那下一步就是怎么来解决,如果每帧都产生一个PES负载,那每个PES都会有自己的pcr,这样误差自然会积累,那如果把多个音频帧合并到一个PES中呢,这样只有一个pcr,后面的音频帧会根据采样率自行计算时长,而不是直接使用自己的pcr,这样就不会带来误差积累,通过分析ffmpeg的代码,也会发现,也是会进行音频帧合并输出的,默认合并时长为350ms,可以进行配置,一般200-400ms为最佳。

          结论:因精度降低带来误差时,尽量是想办法来减少误差积累带来的放大效应,对于音视频直播来说,如果音视频是一起输出的,因为有视频时间的参考,破音现象可能不怎么明显,甚至听不出来,但是对应音视频单独输出或者纯音频直播来说,破音效果会非常明显。

0 人点赞