- 音频信号压缩编码的标准主要有 G.7xx 系列、MPEG-x 系列、AC-x 系列。
- 音频编解码中常用的技术包括:AD/DA转换、压缩编码、数字信号处理、信道编码/调制。
- 经采样、编码但未压缩的语音信号(对应G.711编码)为:PCM。
- 音频编码方法包括三大类:波形编码、参数编码、混合编码。
1. 音视频不同步?
1.1 音视频同步算法
- 主要原因:显示时间戳 PTS 和解码时间戳 DTS
- 其他原因:采样率速度、设备支持的分辨率,码率,帧率、以及服务器拉流
1.2 解决音视频不同步的思路:从根源上解决
最成熟也是最复杂的解决音视频不同步的方法是修改时间戳,主要原理是:选择一个参考时间,在生成数据流时依据参考时间给每个数据块都打上时间戳;播放时,读取数据块上的时间戳,同时参考本地时间来安排播放。但如果源数据帧上打的时间戳本身就有问题,那么播放时再怎么调整也于事无补,所以解决音视频不同步问题,必须先从源上来解决。
1.3 同步视频到音频保证音视频同步
通常,解决同步问题有三钟选择:同步音频到视频,同步视频到音频,或者都同步到外部时钟(例如系统时钟)。悟空 TV 使用同步视频到音频方案来保障音视频的同步,实现流程如上图。
2. 编解码处理时遇到什么困难?
ffmpeg 在编解码的过程:
- 使用 ffmpeg 的 libavcoder,libavformat 的库及可能性编解码
- 编码过程:
- 采集出来的视频、音频数据使用 ffmpeg 进行压缩
- 进行按连续的视频,音频进行分组打包,为了区分各种包,也要包加上包头,包头写上显示时间戳 PTS,解码时间戳 DTS,通过网络传输到播放端
- 解码过程:
- 通过 TCP 协议接收到媒体流,FFmpeg 解封装,解码
- 最终获取到原始视频 YUV,音频 PCM 格式,利用播放器进行播放
3. 如何秒开视频?什么是秒开视频?
网易视频云:视频云播放器秒开和播放流畅度优化
3.1 什么是秒开视频?
秒开是指用户点击播放到看到画面的时间非常短,在 1 秒之内。
3.2 为什么需要秒开?
目前主流的直播协议是 RTMP,HTTP-FLV 和 HLS,都是基于 TCP 的长连接。在播放的过程中,若播放端所处的网络环境在一个较佳的状态,此时播放会很流畅。若网络环境不是很稳定,经常会发生抖动,如果播放端没有特殊处理,可能会经常发生卡顿,严重的甚至会出现黑屏。而移动直播由于其便捷性,用户可以随时随地发起和观看直播,我们无法保证用户的网络一直处于非常好的状态,所以,在网络不稳定的情况下保证播放的流畅度是非常重要的。
3.3 解决思路
3.3.1 获取关键帧后显示
改写播放器逻辑让播放器拿到第一个关键帧后就给予显示。
GOP 的第一个帧通常都是关键帧,由于加载的数据较少,可以达到 "首帧秒开"。如果直播服务器支持 GOP 缓存,意味着播放器在和服务器建立连接后可立即拿到数据,从而省却跨地域和跨运营商的回源传输时间。
GOP 体现了关键帧的周期,也就是两个关键帧之间的距离,即一个帧组的最大帧数。假设一个视频的恒定帧率是 24fps(即 1 秒 24 帧图像),关键帧周期为 2s,那么一个 GOP 就是 48 张图像。一般而言,每一秒视频至少需要使用一个关键帧。
增加关键帧个数可改善画质(GOP通常为 FPS 的倍数),但是同时增加了带宽和网络负载。这意味着,客户端播放器下载一个 GOP,毕竟该 GOP 存在一定的数据体积,如果播放端网络不佳,有可能不是能够快速在秒级以内下载完该 GOP,进而影响观感体验。
如果不能更改播放器行为逻辑为首帧秒开,直播服务器也可以做一些取巧处理,比如从缓存 GOP 改成缓存双关键帧(减少图像数量),这样可以极大程度地减少播放器加载 GOP 要传输的内容体积。
3.3.2 app 业务逻辑层面优化
比如提前做好 DNS 解析(省却几十毫秒),和提前做好测速选线(择取最优线路)。经过这样的预处理之后,在点击播放按钮时,将极大提高下载性能。
一方面,可以围绕传输层面做性能优化;另一方面,可以围绕客户播放行为做业务逻辑优化。两者可以有效的互为补充,作为秒开的优化空间。
3.4 秒开视频方案
3.4.1 优化服务器策略
播放器接入服务器请求数据的时间点的视频不一定是关键帧,那么需要等到下一个关键帧的到来,如果关键帧的周期是 2s 的话,那么等待的时间可能会在 0~2s 的范围内,这段等待的时间会影响首屏的加载时间。如果服务器有缓存,则播放端在接入的时候,服务器可以向前找最近的关键帧发给播放端,这样就可以省去等待的时间,可以大大的减少首屏的加载时间。
3.4.2 优化播放端策略
播放端请求到的第一帧数据肯定是关键帧,关键帧能够通过帧内参考进行解码。这样播放端就可以在接收到第一个关键帧的时候就立即开始解码显示,而不需要等到缓存一定数量的视频帧才开始解码,这样也能减少首屏画面显示的时间。
3.5 播放端首屏时长的优化
播放器的首屏过程中的几个步骤:
- 首屏时间,指的是从进入直播间开始到第一次看到直播画面的时间。首屏时间过长极易导致用户失去对直播的耐心,降低用户的留存。但游戏直播对画面质量和连贯性的要求高,对应推流端编码后的数据量和其他类型直播相比大的多,如何降低首屏时间是一个不小的难题。
- 在播放端的首屏过程中,主要有以下三个操作需要进行:加载直播间 UI(包括播放器本身)、下载直播数据流(未解码)和解码数据播放。其中数据解码播放又细分为以下几个步骤:
- 检测传输协议类型(RTMP、RTSP、HTTP 等)并与服务器建立连接接收数据;
- 视频流解复用得到音视频编码数据(H.264/H.265、AAC 等);
- 音视频数据解码,音频数据同步至外设,视频数据渲染都屏幕,至此,视频开始播放,首屏时间结束。
总结: 首先,加载 UI 可以以单例的方式进行,能够一定程度地提升首屏展示速度;其次,可以预设解码类型,减少数据类型检测时间;再次,设定合理的下载缓冲区大小,尽可能减少下载的数据量,当检测到 I 帧数据,立即开始解码单帧画面进行播放,提高首屏展示时间。
4. 如何降低延迟?如何保证流畅性?如何解决卡顿?解决网络抖动?
4.1 产生原因
保证直播的流畅性是指在直播过程中保证播放不发生卡顿,卡顿是指在播放过程中声音和画面出现停滞,非常影响用户体验。造成卡顿的原因有几种情况:
- 推流端网络抖动导致数据无法发送到服务器,造成播放端卡顿;
- 播放端网络抖动导致数据累计在服务器上拉不下来,造成博凡卡顿。
由于从服务器到播放器的网络情况复杂,尤其是在 3G 和带宽较差的 WIFI 环境下,抖动和延迟经常发生,导致播放不流畅,播放不流畅带来的负面影响就是延时增大。如何在网络抖动的情况下保证播放的流畅性和实时性是保障直播性能的难点。
4.2 流畅度优化
目前主流的直播协议是 RTMP、HTTP-FLV 和 HLS,都是基于 TCP 的长连接。在播放的过程中,若播放端所处的网络环境在一个较佳的状态,此时播放会很流畅。若网络环境不是很稳定,经常会发生抖动,如果播放端没有做特殊处理,可能会经常发生卡顿,严重的甚至会出现黑屏。而移动直播由于其便捷性,用户可以随时随地发起和观看直播,我们无法保证用户的网络一直处于一个非常好的状态,所以,在网络不稳定的情况下保证播放的流畅度是非常重要的。
为了解决这个问题,首先播放器需要将拉流线程和解码线程分开,并建立一个缓冲队列用于缓冲音视频数据。拉流线程将从服务器上获取到的音视频流放入队列,解码线程从队列中获取音视频数据进行解码播放,队列的长度可以调整。当网络发生抖动时,播放器无法从服务器上获取到数据或获取数据的速度较慢,此时队列中缓存的数据可以起到一个过渡的作用,让用户感觉不到网络发生了抖动。
当然这是对于网络发生抖动的情况所采取的策略,如果播放端的网络迟迟不能恢复或服务器的边缘结点出现宕机,则需要应用层进行重连或调度。
5. 丢包处理方案
第一种方案:重传
第一个策略时重传,很明确地丢什么数据重新传什么数据,不会浪费资源
第二种方案:前向纠错 FEC
定义
所谓前向纠错,其实是数据冗余,是解决丢包问题的主要方案之一。可以分成两种类型:多媒体无关的前向纠错和多媒体相关的。本文主要介绍多媒体无关的前向纠错,它更多应用在网络上,同时该技术在存储领域也有应用。
前向纠错简称 FEC(Forward Error Correction),其原理是:发送方将要发送的数据附加上一定的冗余纠错码一并发送,接收方则根据纠错码对数据进行差错检测,如发现差错,由接收方进行纠正,特点:使用纠错码(纠错码编码效率低且设备复杂)、单向信道、发送方无需设置缓冲器。
原理
分层数据保护是前向纠错对于分层的方案。分层指的是数据包里面有不同重要程度的数据,对于不同程度的数据分段对它进行保护。
前向纠错的数据包是基于 RTP 标准上设计的。前面是 RTP 包头,后面是前向纠错的数据包的格式。
FEC 算法其中一个称之为异或。假如有 4 个数据,那么它们可以取 4 个异或值,其中每一个数据都可以由另外 4 个异或值计算出来。还可以把 ABCD 和 E 想象成一个数据包,如果我们传输 ABCD 这四个数据包,第五个数据包传输的是 E,这五个数据包可以丢失任何 1 个数据包。接收方收到数据之后,能够把它丢的数据恢复出来。前向纠错算法能处理的是连续数据里只丢 1 个包。同时丢失 A 和 B,这个算法不能解决。
第三种方案:交叉传输 -- 处理连续丢包的情况
最后一个策略是交叉传输,我们日常看到多媒体可能是按照时序的,一个多媒体片断是由 1 到 10 组成。如果此过程当中有丢包,比如 3456 连续丢失,那么此次丢包的影响可能表现在视频播放出现停顿。若丢的是关键帧那么影响非常大,会导致后面一大片的花屏。因此当连续丢包对流媒体伤害特别大的情况下,可以采用交叉传输策略。1 到 10,原来是 3 个 3 个传,如 123、456、789 各传一次,那么现在可以改变传输策略,采用 147、280 和 369 的传输策略,这样一组数据丢掉,实际丢失在流媒体中间穿插的数据,播放程序可以在几乎不失真的状态下把视频恢复出来。