Live-CheatSheet
本文节选自
Live CheatSheet | 直播技术理论基础与实践概论,很多内容非作者原创,而是对 Live Links 中列举出的多篇文章的盘点总结,更多直播相关内容可以前往 NGTE Website 交互式检索或 MushiChat 查看代码。
Live CheatSheet | 直播技术理论基础与实践概论
音视频直播的基本流程都是采集 → 编码推流 → 网络分发 → 解码 → 播放
这五大环节,其中又会涉及平台硬件、编解码、网络传输、服务并发、数字信号处理、在线学习等多方面技术。从交互模式上,又可以泛分为单对单模式与会议模式两大类;从实时性要求上,直播又可以分为伪实时、准实时与真实时三个等级
-
伪实时:视频消费延迟超过
3 秒,单向观看实时,通用架构是CDN + RTMP + HLS ,譬如很多的直播平台 -
准实时:视频消费延迟
1 ~ 3 秒,能进行双方互动但互动有障碍;可以通过TCP/UDP + FLV 已经实现了这类技术,譬如YY 直播等 -
真实时:视频消费延迟
< 1 秒,平均500 毫秒,譬如QQ 、微信、Skype 和WebRTC 等
编解码
视频封装格式就是我们通常所说的
视频压缩格式和视频格式具体的区别就是,它是将原始的视频码流变为可用的数字编码。首先,由原始数码设备提供相关的数字信号流,然后经由视频压缩算法,大幅度的减少流的大小,然后交给视频盒子,打上相应的

视频封装格式
常见的视频封装格式

AVI
这种视频格式的优点是图像质量好。由于无损
DV-AVI
数字摄像机就是使用这种格式记录视频数据的。它可以通过电脑的
MOV
具有较高的压缩比率和较完美的视频清晰度等特点,并可以保存
MPEG
WMV
Real Video
用户可以使用
FLV
MKV
视频编解码
视频实际上就是一帧一帧的图片,拼接起来进行播放;标准的图像格式使用
实时视频编码器需要考虑两个因素:编码计算量和码率带宽,实时视频会运行在移动端上,需要保证实时性就需要编码足够快,码率尽量小。基于这个原因现阶段一般认为
编码基础
总的来说,常用的编码方式分为三种:
-
变换编码:消除图像的帧内冗余。涉及到图像学里面的两个概念:空域和频域。空域就是我们物理的图片,频域就是将物理图片根据其颜色值等映射为数字大小。而变换编码的目的是利用频域实现去相关和能量集中。常用的正交变换有离散傅里叶变换,离散余弦变换等等。
-
运动估计和运动补偿:消除帧间冗余。视频压缩还存在时间上的关联性。例如,针对一些视频变化,背景图不变而只是图片中部分物体的移动,针对这种方式,可以只对相邻视频帧中变化的部分进行编码。
-
熵编码:提高压缩效率,熵编码主要是针对码节长度优化实现的。原理是针对信源中出现概率大的符号赋予短码,对于概率小的符号赋予长码,然后总的来说实现平均码长的最小值。编码方式(可变字长编码)有:霍夫曼编码、算术编码、游程编码等。
I 帧(I-frame): 学名叫做: Intra-coded picture
。也可以叫做独立帧。该帧是编码器随机挑选的参考图像,换句话说,一个I 帧本身就是一个静态图像。它是作为B,P 帧的参考点。对于它的压缩,只能使用熵
和变化编码
这两种方式进行帧内压缩。所以,它的运动学补偿基本没有。P 帧(P ‑frame): 又叫做Predicted picture
–前向预测帧。即,他会根据前面一张图像,来进行图片间的动态压缩,它的压缩率和I 帧比起来要高一些。B 帧(B ‑frame): 又叫做Bi-predictive picture
– 双向预测。它比P 帧来说,还多了后一张图像的预测,所以它的压缩率更高。

考虑到不同帧传输的无序性,我们还需要引入
-
PTS(presentation time stamps): 显示时间戳,显示器从接受到解码到显示的时间。 -
DTS(decoder timestamps): 解码时间戳。也表示该sample 在整个流中的顺序
H.26X
-
H.261:主要在老的视频会议和视频电话产品中使用。
-
H.263:主要用在视频会议、视频电话和网络视频上。
-
H.264:
H.264/MPEG-4 第十部分,或称AVC(Advanced Video Coding ,高级视频编码) ,是一种视频压缩标准,一种被广泛使用的高精度视频的录制、压缩和发布格式。 -
H.265:高效率视频编码
(High Efficiency Video Coding ,简称HEVC) 是一种视频压缩标准,H.264/MPEG-4 AVC 的继任者。HEVC 被认为不仅提升图像质量,同时也能达到H.264/MPEG-4 AVC 两倍之压缩率( 等同于同样画面质量下比特率减少了50%) ,可支持4K 分辨率甚至到超高画质电视,最高分辨率可达到8192×4320(8K 分辨率) ,这是目前发展的趋势。直至2013 年,Potplayer 添加了对于H.265 视频的解码,尚未有大众化编码软件出现。

在实时视频当中最好不要加入
MPGA 系列
-
MPEG-1 第二部分(MPEG-1 第二部分主要使用在VCD 上,有些在线视频也使用这种格式。该编解码器的质量大致上和原有的VHS 录像带相当。) -
MPEG-2 第二部分(MPEG-2 第二部分等同于H.262 ,使用在DVD 、SVCD 和大多数数字视频广播系统和有线分布系统(cable distribution systems) 中。) -
MPEG-4 第二部分(MPEG-4 第二部分标准可以使用在网络传输、广播和媒体存储上。比起MPEG-2 和第一版的H.263 ,它的压缩性能有所提高。) -
MPEG-4 第十部分(MPEG-4 第十部分技术上和ITU-T H.264 是相同的标准,有时候也被叫做“AVC”) 最后这两个编码组织合作,诞生了H.264/AVC 标准。ITU-T 给这个标准命名为H.264 ,而ISO/IEC 称它为MPEG-4 高级视频编码(Advanced Video Coding ,AVC)。
音频编码器
实时音视频除了视频编码器以外还需要音频编码器,音频编码器只需要考虑编码延迟和丢包容忍度,所以一般的
同视频编码类似,将原始的音频流按照一定的标准进行编码,上传,解码,同时在播放器里播放,当然音频也有许多编码标准,例如
直播协议
常用的直播协议包括了
协议 | 优势 | 缺陷 | 延迟性 |
---|---|---|---|
HLS | 支持性广 | 延时巨高 | |
RTMP | 延时性好,灵活 | 量大的话,负载较高 | |
HTTP-FLV | 延时性好,游戏直播常用 | 只能在手机 |
HLS

#EXTM3U m3u文件头
#EXT-X-MEDIA-SEQUENCE 第一个TS分片的序列号
#EXT-X-TARGETDURATION 每个分片TS的最大的时长
#EXT-X-ALLOW-CACHE 是否允许cache
#EXT-X-ENDLIST m3u8文件结束符
#EXTINF 指定每个媒体段(ts)的持续时间(秒),仅对其后面的URI有效
mystream-12.ts
<video controls autoplay>
<source
src="http://devimages.apple.com/iphone/samples/bipbop/masterplaylist.m3u8"
type="application/vnd.apple.mpegurl"
/>
<p class="warning">Your browser does not support HTML5 video.</p>
</video>
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2855600,CODECS="avc1.4d001f,mp4a.40.2",RESOLUTION=960x540
live/medium.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=5605600,CODECS="avc1.640028,mp4a.40.2",RESOLUTION=1280x720
live/high.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1755600,CODECS="avc1.42001f,mp4a.40.2",RESOLUTION=640x360
live/low.m3u8
#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=545600,CODECS="avc1.42001e,mp4a.40.2",RESOLUTION=416x234
live/cellular.m3u8
以
#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:26
#EXTINF:9.901,
http://media.example.com/wifi/segment26.ts
#EXTINF:9.901,
http://media.example.com/wifi/segment27.ts
#EXTINF:9.501,
http://media.example.com/wifi/segment28.ts
该二级
live playlist: 动态列表。顾名思义,该列表是动态变化的,里面的ts 文件会实时更新,并且过期的ts 索引会被删除。默认,情况下都是使用动态列表。event playlist: 静态列表。它和动态列表主要区别就是,原来的ts 文件索引不会被删除,该列表是不断更新,而且文件大小会逐渐增大。它会在文件中,直接添加#EXT-X-PLAYLIST-TYPE:EVENT 作为标识。VOD playlist: 全量列表。它就是将所有的ts 文件都列在list 当中。如果,使用该列表,就和播放一整个视频没有啥区别了。它是使用#EXT-X-ENDLIST 表示文件结尾。
显而易见,
RTMP
RTMP,
-
纯
RTMP: 直接通过TCP 连接,端口为1935 -
RTMPS: RTMP + TLS/SSL,用于安全性的交流。
-
RTMPE: RTMP + encryption。在
RTMP 原始协议上使用,Adobe 自身的加密方法 -
RTMPT: RTMP + HTTP。使用
HTTP 的方式来包裹RTMP 流,这样能直接通过防火墙。不过,延迟性比较大。 -
RTMFP: RMPT + UDP。该协议常常用于
P2P 的场景中,针对延时有变态的要求。

HTTP-FLV

每个
Content-Type:video/x-flv
Expires:Fri, 10 Feb 2017 05:24:03 GMT
Pragma:no-cache
Transfer-Encoding:chunked
网络传输
单对单模式主要是怎么通过路由路径优化手段达到两点之间最优,这方面
基础
推流
所谓推流,就是将我们已经编码好的音视频数据发往视频流服务器中。实时音视频系统都是一个客户端到其他一个或者多个客户端的通信行为,这就意味着需要将客户端编码后的音视频数据传输到其他实时音视频系统都是一个客户端到其他一个或者多个客户端的通信行为,这就意味着需要将客户端编码后的音视频数据传输到其他客户端上,一般做法是先将数据实时上传到服务器上,服务器再进行转发到其他客户端,客户端这个上传音视频数据行为称为推流。
我们可以通过
rtmp {
server {
listen 1935; #监听的端口
chunk_size 4000;
application hls { #rtmp推流请求路径
live on;
hls on;
hls_path /usr/local/var/www/hls;
hls_fragment 5s;
}
}
}
推流会受到客户端网络的影响,例如:
WebRTC
-
MediaStream:通过设备的摄像头及话筒获得视频、音频的同步流
-
PeerConnection: 用于构建点对点之间稳定、高效的流传输的组件 -
DataChannel:能够使得浏览器之间
( 点对点) 简历一个高吞吐量、低延时的信道,用于传输任何数据
实时网络传输优化
TCP 与UDP
在大规模实时多媒体传输网络中,
在实时传输中使用
-
报文冗余,报文冗余很好理解,就是一个报文在发送的时候发送
2 次或者多次。这个做的好处是简单而且延迟小,坏处就是需要额外N 倍(N 取决于发送的次数)的带宽。 -
FEC, Forward Error Correction,即向前纠错算法,常用的算法有纠删码技术(EC
) ,在分布式存储系统中比较常见。最简单的就是A B 两个报文进行XOR (与或操作)得到C ,同时把这三个报文发往接收端,如果接收端只收到AC, 通过A 和C 的XOR 操作就可以得到B 操作。 -
丢包重传,丢包重传有两种方式,一种是
push 方式,一种是pull 方式。Push 方式是发送方没有收到接收方的收包确认进行周期性重传,TCP 用的是push 方式。pull 方式是接收方发现报文丢失后发送一个重传请求给发送方,让发送方重传丢失的报文。丢包重传是按需重传,比较适合视频传输的应用场景,不会增加太对额外的带宽,但一旦丢包会引来至少一个RTT 的延迟。
拥塞控制
要评估一个网络通信质量的好坏和延迟一个重要的因素就是
-
发送端方一个带本地时间戳
T1 的ping 报文到接收端; -
接收端收到
ping 报文,以ping 中的时间戳T1 构建一个携带T1 的pong 报文发往发送端; -
发送端接收到接收端发了的
pong 时,获取本地的时间戳T2 ,用T2 –T1 就是本次评测的RTT 。
因为客户端有可能在弱网环境下进行推流,音视频数据如果某一时刻发多了,就会引起网络拥塞或者延迟,如果发少了,可能视频的清晰不好。在实时音视频传输过程会设计一个自动适应本地网络变化的拥塞控制算法,像
QoS 策略
客户端推流除了需要考虑网络上传能力以外,还需要考虑客户端的计算能力。如果在
媒体处理技术
回声消除
在实时音视频系统中,回声消除是一个难点,尽管
简单Web 实验
本部分的代码实验参考 MushiChat。
Media Source Extension
const vidElement = document.querySelector("video");
if (window.MediaSource) {
const mediaSource = new MediaSource();
vidElement.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener("sourceopen", sourceOpen);
} else {
console.log("The Media Source Extensions API is not supported.");
}
function sourceOpen(e) {
URL.revokeObjectURL(vidElement.src);
const mime = 'video/webm; codecs="opus, vp9"';
const mediaSource = e.target;
const sourceBuffer = mediaSource.addSourceBuffer(mime);
const videoUrl = "droid.webm";
fetch(videoUrl)
.then(function (response) {
return response.arrayBuffer();
})
.then(function (arrayBuffer) {
sourceBuffer.addEventListener("updateend", function (e) {
if (!sourceBuffer.updating && mediaSource.readyState === "open") {
mediaSource.endOfStream();
}
});
sourceBuffer.appendBuffer(arrayBuffer);
});
}
其中